Compare commits

...

105 Commits

Author SHA1 Message Date
vargburz b3e7f943ad 0.7.8 && render segments if exists 2 months ago
vargburz a8408a748c 0.7.7 && handle context menu 3 months ago
vargburz 6e6fa7dc8e 0.7.6 && update vue with markers and conf 3 months ago
rozetko f67ce313dd 0.7.5 3 months ago
rozetko c1c3b77dac Merge pull request 'area generator: support `invert` option for y/y1 axes' (#70) from area-generator-fix-invert into main 3 months ago
rozetko 53c233b969 area generator: support `invert` option for y/y1 axes 3 months ago
vargburz ebcb3185cd 0.7.4 version 3 months ago
vargburz 6422b49bf0 Merge pull request 'update area render type' (#69) from update-area-type-render into main 3 months ago
vargburz 3f9342b5e1 remove log 3 months ago
vargburz bb46fe79be update area render type 3 months ago
rozetko 0c3b404155 0.7.3 4 months ago
rozetko 85cd952b9f hotfix 4 months ago
rozetko 701feaaf2f 0.7.2 4 months ago
rozetko ebb49adf82 markers: render tooltip in center 4 months ago
rozetko f38829787c 0.7.1 4 months ago
rozetko 6549415feb markers hotfix 4 months ago
rozetko 117c0af469 Merge pull request 'better tooltips for markers' (#68) from better-markers-tooltips into main 4 months ago
rozetko aac8f6f5ac bump version to `0.7.0` 4 months ago
rozetko f4354d7a77 better tooltips for markers 4 months ago
rozetko 529f439ac9 0.6.21 5 months ago
rozetko 121f7a0305 fix renderDots not working for right y-axis 5 months ago
rozetko 7e721ab880 0.6.20 5 months ago
rozetko 3663d3eaaa upd chartwerk core to 0.6.25 5 months ago
Coin de Gamma bd598d6a0b Merge pull request '0.6.19' (#64) from 0.6.19 into main 6 months ago
glitch4347 4620ef7aa9 0.6.19 6 months ago
rozetko 44a4e6ce74 Merge pull request 'segment select' (#63) from segment-select into main 6 months ago
glitch4347 04a01b75a1 opacity param 6 months ago
glitch4347 bf3aab2db1 segment select 6 months ago
Coin de Gamma 348a289f1a Merge pull request '0.6.18' (#61) from 0.6.18 into main 8 months ago
glitch4347 17a2fdf94e 0.6.18 8 months ago
Coin de Gamma dc89f6cbb9 Merge pull request 'basic react component implementatino is sep project' (#59) from better-react-component-#58 into main 8 months ago
glitch4347 547c15c0b6 optimise excludes in libs in webpack 8 months ago
glitch4347 32d122ba4d back dev build 8 months ago
glitch4347 9c165f4e1f basic react component implementatino is sep project 8 months ago
Coin de Gamma ec2bd27acd Merge pull request '0.6.17' (#54) from 0.6.17 into main 8 months ago
glitch4347 815144d209 update core 0.6.23 8 months ago
glitch4347 1a80ca2cab 0.6.17 8 months ago
Coin de Gamma ee08db2f54 Merge pull request 'use events instead of eventsCallbacks' (#53) from core-0.6.23 into main 8 months ago
glitch4347 884fed6582 use events instead of eventsCallbacks 8 months ago
glitch4347 8aca72ce04 zoom out with ranges logic 9 months ago
Coin de Gamma c62a1c386f Merge pull request 'rename demo->basic, live and vertical && update readme' (#47) from rename-examples into main 9 months ago
glitch4347 de6237891c rename demo->basic, live and vertical && update readme 9 months ago
rozetko 7bcd0d298a 0.6.16 10 months ago
rozetko ee2f02be96 upd core 10 months ago
rozetko 456b888fe1 0.6.15 10 months ago
rozetko a34c0574e4 hotfix 10 months ago
rozetko 73dbf0ea67 0.6.14 10 months ago
rozetko ff5973b106 Merge pull request 'updateData: update segments and markers' (#44) from update-segments-and-markers-on-update-data into main 10 months ago
rozetko 878e86d849 updateData: update segments and markers 10 months ago
vargburz 1e8f8d0cb3 0.6.13 10 months ago
rozetko 39412e5f65 Merge pull request 'roken shared crosshair #42' (#43) from broken-shared-crosshair-#42 into main 10 months ago
rozetko 37da147343 Merge pull request '0.6.19 core usdage' (#41) from build-fail-on-core-0.6.18-udpate-#40 into main 10 months ago
glitch4347 0dac1c390e fix 10 months ago
glitch4347 07f454fe51 0.6.19 core usdage 11 months ago
vargburz 88d6b2b24a Merge pull request 'click-event' (#39) from click-event into main 11 months ago
glitch4347 837004c2ad onclick 11 months ago
glitch4347 e46c7bdfb6 some commit 11 months ago
rozetko ee7a57685f 0.6.12 11 months ago
rozetko 963011b274 Merge pull request 'pod fix' (#37) from strange-updates into main 11 months ago
glitch4347 283f0995e8 pod fix 11 months ago
rozetko 19689a68cd Merge pull request 'mouse-over-and-react' (#36) from mouse-over-and-react into main 11 months ago
glitch4347 79b759569f simpler example 11 months ago
glitch4347 d66da50c1a rm line 11 months ago
glitch4347 d9d1b5e501 example with mouse over and refactor react component events 11 months ago
Coin de Gamma b8cd14e4b8 Merge pull request 'marker-callback-#25' (#35) from marker-callback-#25 into main 12 months ago
glitch4347 e470d58611 fx Marker callback type 12 months ago
glitch4347 26d5956c17 markers conf in react 12 months ago
glitch4347 43241bbcb7 markers conf + events 12 months ago
glitch4347 82fc9a10f1 markers conf + new example 12 months ago
rozetko 57ae85c20e Merge pull request 'react-component-marker-and-segment-feature-#28' (#33) from react-component-marker-and-segment-feature-#28 into main 12 months ago
glitch4347 98e4e42fc4 callbacks 12 months ago
glitch4347 6fbf833150 event callback back 12 months ago
glitch4347 a0e27d5efd rm My_CONST 12 months ago
glitch4347 727f8cac86 codefix 12 months ago
glitch4347 869488d405 codestyle 12 months ago
glitch4347 d97b0e9b0c markers++ 12 months ago
glitch4347 11ab01a7d2 markers++ 12 months ago
glitch4347 326c666435 component refactorinmg begin 12 months ago
rozetko 33cf970d5f Merge pull request 'basic segments impl' (#27) from segments-feature-#19 into main 12 months ago
glitch4347 03a562c0d2 codestytle fix 12 months ago
glitch4347 38b6eb2326 basic segments impl 12 months ago
rozetko af9aaf6d82 Merge pull request 'markers-feature-#18' (#23) from markers-feature-#18 into main 12 months ago
glitch4347 bf679019fc payload comment 12 months ago
glitch4347 86099c57b3 pointe events 12 months ago
glitch4347 9a6c5cd7f4 markers++ 12 months ago
glitch4347 aadcd013bf markers++ 12 months ago
glitch4347 a5c737fa81 marker data continue 12 months ago
rozetko c451df6e3b 0.6.11 12 months ago
rozetko 3ff6f7b8e8 crosshair hotfix 12 months ago
glitch4347 1d1a34f9bf markers begin 12 months ago
glitch4347 8346bceedf markers examples begin 12 months ago
vargburz 1ca84c53f8 Merge pull request '0.6.10 version' (#21) from version-0.6.10 into main 12 months ago
vargburz 85793a7965 0.6.10 version 12 months ago
vargburz 7e4a895e93 Merge pull request 'add copy-webpack-=plugin' (#20) from update-copy-webpack into main 12 months ago
glitch4347 f1c3ef6f1d add copy-webpack-=plugin 12 months ago
rozetko 6a0ea4303e Merge pull request 'add react component and build for that' (#16) from react-component-attempt-2 into main 12 months ago
glitch4347 08b128ea91 codestyle fixes 12 months ago
glitch4347 f1582fc610 rm comment 12 months ago
glitch4347 e98997995f add react component and build for that 12 months ago
rozetko e809046098 Merge pull request 'Developement how to and d3 resolution' (#14) from dev-how-to-#4 into main 12 months ago
glitch4347 833780105a fx type in conf 12 months ago
glitch4347 2e156ad46b add node_resolutinos for linking case & update readme 12 months ago
vargburz f100af0ee8 Merge pull request 'hotfix: call mouseOver and mouseMove to render crosshair on init and zoomin' (#10) from hidden-crosshair-on-first-render-and-zoomin into main 12 months ago
vargburz 927855ad45 Merge pull request 'set git repo in package.json' (#12) from set-git-package into main 12 months ago
glitch4347 5c39f741ff hotfix: call mouseOver and mouseMove to render crosshair on init and zoomin 1 year ago
  1. 2
      .gitignore
  2. 23
      README.md
  3. 14
      build/webpack.base.conf.js
  4. 42
      examples/area.html
  5. 0
      examples/basic.html
  6. 0
      examples/live.html
  7. 51
      examples/markers.html
  8. 47
      examples/markers_select.html
  9. 33
      examples/mouse_click.html
  10. 29
      examples/mouse_move.html
  11. 33
      examples/right_click.html
  12. 41
      examples/segments.html
  13. 46
      examples/segments_select.html
  14. 0
      examples/vertical.html
  15. 37
      examples/zoom_out.html
  16. 12
      package.json
  17. 26
      react/build/webpack.base.conf.js
  18. 8
      react/build/webpack.dev.conf.js
  19. 6
      react/build/webpack.prod.conf.js
  20. 23
      react/package.json
  21. 74
      react/src/index.tsx
  22. 23
      react/tsconfig.json
  23. 1322
      react/yarn.lock
  24. 139
      src/components/markers.ts
  25. 73
      src/components/segments.ts
  26. 260
      src/index.ts
  27. 5
      src/models/line_series.ts
  28. 19
      src/models/marker.ts
  29. 11
      src/models/segment.ts
  30. 38
      src/types.ts
  31. 5
      tsconfig.json
  32. 278
      yarn.lock

2
.gitignore vendored

@ -2,7 +2,7 @@ node_modules
dist
# yarn
.yarn/*
.yarn
!.yarn/patches
!.yarn/plugins
!.yarn/releases

23
README.md

@ -19,8 +19,25 @@
```
#### Other examples
[Static Chart](https://code.corpglory.net/chartwerk/line-pod/src/branch/main/examples/demo.html)
* [Basic](https://code.corpglory.net/chartwerk/line-pod/src/branch/main/examples/basic.html)
* [Live](https://code.corpglory.net/chartwerk/line-pod/src/branch/main/examples/live.html)
* [Vertical](https://code.corpglory.net/chartwerk/line-pod/src/branch/main/examples/vertical.html)
* [Segments](https://code.corpglory.net/chartwerk/line-pod/src/branch/main/examples/segments.html)
* [Markers](https://code.corpglory.net/chartwerk/line-pod/src/branch/main/examples/markers.html)
[Live Chart](https://code.corpglory.net/chartwerk/line-pod/src/branch/main/examples/demo_live.html)
### Development
[Vertical Chart](https://code.corpglory.net/chartwerk/line-pod/src/branch/main/examples/demo_vertical.html)
If you want to link `core` then clone it to same directory and then run
```
yarn link ../core
```
but don't add `resolutions` logic to `package.json`
then run
```
yarn install
yarn dev
```

14
build/webpack.base.conf.js

@ -1,4 +1,5 @@
const path = require('path');
const CopyPlugin = require("copy-webpack-plugin");
function resolve(dir) {
@ -8,7 +9,14 @@ function resolve(dir) {
module.exports = {
context: resolve('src'),
entry: './index.ts',
plugins: [],
plugins: [
new CopyPlugin({
patterns: [
{ from: "../react/dist/index.js", to: "react/index.js" },
{ from: "../react/dist/index.d.ts", to: "react/index.d.ts" },
],
})
],
module: {
rules: [
{
@ -25,6 +33,10 @@ module.exports = {
},
resolve: {
extensions: ['.ts', '.js'],
// this is necessary for resolution of external libs like d3 in dev mode
// when core is linked: webpack will take d3 from this node_modules but not from
// internal so you get one version of d3
modules: [path.resolve(__dirname, '../node_modules'), 'node_modules']
},
output: {
filename: 'index.js',

42
examples/area.html

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<script src="../dist/index.dev.js" type="text/javascript"></script>
</head>
<body>
<div id="chart" style="width: 50%; height: 500px;"></div>
<script type="text/javascript">
let options = {
renderLegend: false, usePanning: false,
axis: {
x: { format: 'numeric', range: [0, 100] },
y: { invert: true, range: [0, 100] },
y1: { isActive: true, format: 'numeric', range: [0, 1000] },
},
zoomEvents: {
mouse: { zoom: { isActive: false, orientation: 'horizontal' } },
scroll: { zoom: { isActive: false, orientation: 'horizontal' } }
},
}
const data1 = [[0,0], [35, 40], [65, 60], [100, 100]];
const data2 = [[0,0], [35, 50], [65, 65], [80, 100]];
const data3 = [[0,0], [35, 20], [65, 50], [100, 80]];
const data4 = [[0,900], [35, 800], [65, 700], [100, 600]];
var pod = new LinePod(
document.getElementById('chart'),
[
{ target: 'test1', datapoints: data1, color: 'green', renderArea: 'Above' },
{ target: 'test2', datapoints: data2, color: 'blue', renderArea: 'Below' },
{ target: 'test3', datapoints: data3, color: 'orange', renderArea: 'Below', yOrientation: 'right' },
{ target: 'test4', datapoints: data4, color: 'purple', renderArea: 'Above', yOrientation: 'right' },
],
options
);
pod.render();
</script>
</body>
</html>

0
examples/demo.html → examples/basic.html

0
examples/demo_live.html → examples/live.html

51
examples/markers.html

@ -0,0 +1,51 @@
<!DOCTYPE html>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<script src="../dist/index.dev.js" type="text/javascript"></script>
</head>
<body>
<div id="chart" style="width: 100%; height: 500px;"></div>
<script type="text/javascript">
const startTime = 1701790172908;
const timeSerieData = [5, 6, 3, 7, 5, 6, 8, 4, 5, 6, 4, 3, 5, 7, 8]
.map((el, idx) => [startTime + idx * 1000, el]);
const markersData1 = [3, 6, 9].map(el => ({
x: startTime + el * 1000,
color: 'red',
alwaysDisplay: false,
html: new Date(startTime).toISOString(),
}));
const markersData2 = [4, 11].map(el => ({
x: startTime + el * 1000,
color: 'blue',
alwaysDisplay: true,
html: new Date(startTime).toISOString(),
}));
let options = {
renderLegend: false,
axis: {
y: { range: [0, 10] },
x: { format: 'time' }
},
}
var pod = new LinePod(
document.getElementById('chart'),
[
{ datapoints: timeSerieData, color: 'black' },
],
options,
{
series: [
{ data: markersData1 },
{ data: markersData2 },
]
}
);
pod.render();
</script>
</body>
</html>

47
examples/markers_select.html

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<script src="../dist/index.dev.js" type="text/javascript"></script>
</head>
<body>
<div id="chart" style="width: 100%; height: 500px;"></div>
<script type="text/javascript">
const startTime = 1701790172908;
const timeSerieData = [5, 6, 3, 7, 5, 6, 8, 4, 5, 6, 4, 3, 5, 7, 8]
.map((el, idx) => [startTime + idx * 1000, el]);
const markersData = [3, 6, 9].map(el => ({
x: startTime + el * 1000,
payload: el,
color: 'red',
}));
let options = {
renderLegend: false,
axis: {
y: { range: [0, 10] },
x: { format: 'time' }
},
}
var pod = new LinePod(
document.getElementById('chart'),
[
{ datapoints: timeSerieData, color: 'black' },
],
options,
{
series: [
{ data: markersData },
],
events: {
onMouseMove: (el) => { console.log(el); },
onMouseOut: () => { console.log('mouse out'); }
}
}
);
pod.render();
</script>
</body>
</html>

33
examples/mouse_click.html

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<script src="../dist/index.dev.js" type="text/javascript"></script>
</head>
<body>
<div id="chart" style="width: 50%; height: 500px;"></div>
<script type="text/javascript">
const startTime = 1590590148;
const data = Array.from(
{ length: 20 },
(el, idx) => [startTime + idx * 10000, Math.floor(Math.random() * 30)]
);
let options = {
renderLegend: false, usePanning: false,
axis: { y: { range: [0, 50] } },
zoomEvents: { mouse: {
zoom: { isActive: false },
pan: { isActive: false },
} },
eventsCallbacks: { mouseClick: console.log }
}
var pod = new LinePod(
document.getElementById('chart'),
[{ datapoints: data }],
options
);
pod.render();
</script>
</body>
</html>

29
examples/mouse_move.html

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<script src="../dist/index.dev.js" type="text/javascript"></script>
</head>
<body>
<div id="chart" style="width: 50%; height: 500px;"></div>
<script type="text/javascript">
const startTime = 1590590148;
const data = Array.from(
{ length: 20 },
(el, idx) => [startTime + idx * 10000, Math.floor(Math.random() * 30)]
);
let options = {
renderLegend: false, usePanning: false,
axis: { y: { range: [0, 50] } },
eventsCallbacks: { mouseMove: console.log }
}
var pod = new LinePod(
document.getElementById('chart'),
[{ datapoints: data }],
options
);
pod.render();
</script>
</body>
</html>

33
examples/right_click.html

@ -0,0 +1,33 @@
<!DOCTYPE html>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<script src="../dist/index.dev.js" type="text/javascript"></script>
</head>
<body>
<div id="chart" style="width: 50%; height: 500px;"></div>
<script type="text/javascript">
const startTime = 1590590148;
const data = Array.from(
{ length: 20 },
(el, idx) => [startTime + idx * 10000, Math.floor(Math.random() * 30)]
);
let options = {
renderLegend: false, usePanning: false,
axis: { y: { range: [0, 50] } },
zoomEvents: { mouse: {
zoom: { isActive: false },
pan: { isActive: false },
} },
eventsCallbacks: { contextMenu: (position) => console.log('contextMenu', position) }
}
var pod = new LinePod(
document.getElementById('chart'),
[{ datapoints: data }],
options
);
pod.render();
</script>
</body>
</html>

41
examples/segments.html

@ -0,0 +1,41 @@
<!DOCTYPE html>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<script src="../dist/index.dev.js" type="text/javascript"></script>
</head>
<body>
<div id="chart" style="width: 100%; height: 500px;"></div>
<script type="text/javascript">
const startTime = 1701790172908;
const timeSerieData = [5, 6, 3, 7, 5, 6, 8, 4, 5, 6, 4, 3, 5, 7, 8]
.map((el, idx) => [startTime + idx * 1000, el]);
const segmentsData = [3, 6, 9].map(el => [startTime + el * 1000, startTime + (el + 1) * 1100]);
let options = {
renderLegend: false,
axis: {
y: { range: [0, 10] },
x: { format: 'time' }
},
}
var pod = new LinePod(
document.getElementById('chart'),
[
{ datapoints: timeSerieData, color: 'black' },
],
options,
undefined,
[
{
data: segmentsData,
color:'#FFE545'
}
]
);
pod.render();
</script>
</body>
</html>

46
examples/segments_select.html

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<script src="../dist/index.dev.js" type="text/javascript"></script>
</head>
<body>
<div id="chart" style="width: 100%; height: 500px;"></div>
<script type="text/javascript">
const startTime = 1701790172908;
const timeSerieData = [5, 6, 3, 7, 5, 6, 8, 4, 5, 6, 4, 3, 5, 7, 8]
.map((el, idx) => [startTime + idx * 1000, el]);
const segmentsData = [3, 6, 9].map(el => [startTime + el * 1000, startTime + (el + 1) * 1100]);
let options = {
renderLegend: false,
axis: {
y: { range: [0, 10] },
x: { format: 'time' }
},
}
var pod = new LinePod(
document.getElementById('chart'),
[
{ datapoints: timeSerieData, color: 'black' },
],
options,
undefined,
[
{
data: segmentsData,
color:'#FFE545',
select: true,
opacity: 0.4,
opacitySelect: 0.8,
onSelect: console.log,
onUnselect: console.log
}
]
);
pod.render();
</script>
</body>
</html>

0
examples/demo_vertical.html → examples/vertical.html

37
examples/zoom_out.html

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<meta content="utf-8" http-equiv="encoding">
<script src="../dist/index.dev.js" type="text/javascript"></script>
</head>
<body>
<div id="chart" style="width: 50%; height: 500px;"></div>
<script type="text/javascript">
const startTime = 1590590148;
const data = Array.from(
{ length: 20 },
(el, idx) => [startTime + idx * 10000, Math.floor(Math.random() * 30)]
);
let options = {
renderLegend: false, usePanning: false,
axis: { y: { range: [0, 50] } },
zoomEvents: { mouse: {
zoom: { isActive: true, orientation: "horizontal" },
pan: { isActive: false },
}},
events: {
zoomOut: function(centers, ranges) {
console.log('zoomOut', centers, ranges);
}
}
}
var pod = new LinePod(
document.getElementById('chart'),
[{ datapoints: data }],
options
);
pod.render();
</script>
</body>
</html>

12
package.json

@ -1,13 +1,13 @@
{
"name": "@chartwerk/line-pod",
"version": "0.6.9",
"version": "0.7.8",
"description": "Chartwerk line chart",
"main": "dist/index.js",
"files": [
"/dist"
],
"scripts": {
"build": "webpack --config build/webpack.prod.conf.js && webpack --config build/webpack.dev.conf.js",
"build": "rm -rf dist && cd react && yarn build && cd .. && webpack --config build/webpack.prod.conf.js && webpack --config build/webpack.dev.conf.js",
"dev": "webpack --watch --config build/webpack.dev.conf.js",
"test": "echo \"Error: no test specified\" && exit 1",
"update-core": "yarn up @chartwerk/core && yarn up @chartwerk/core@latest"
@ -19,9 +19,10 @@
"author": "CorpGlory",
"license": "ISC",
"dependencies": {
"@chartwerk/core": "latest"
"@chartwerk/core": "^0.6.26"
},
"devDependencies": {
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.8.1",
"style-loader": "^3.3.3",
"ts-loader": "^9.4.3",
@ -29,5 +30,8 @@
"webpack": "^5.87.0",
"webpack-cli": "^5.1.4"
},
"packageManager": "yarn@3.2.1"
"packageManager": "yarn@3.2.1",
"workspaces": [
"react/*"
]
}

26
react/build/webpack.base.conf.js

@ -0,0 +1,26 @@
const path = require('path');
module.exports = {
entry: './src/index.tsx',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
filename: 'index.js',
path: path.resolve(__dirname, '../dist'),
libraryTarget: 'umd',
umdNamedDefine: true,
},
externals: [
'@chartwerk/line-pod', 'react'
]
};

8
react/build/webpack.dev.conf.js

@ -0,0 +1,8 @@
const baseWebpackConfig = require('./webpack.base.conf');
var conf = baseWebpackConfig;
conf.devtool = 'inline-source-map';
conf.mode = 'development';
conf.output.filename = 'index.dev.js';
module.exports = conf;

6
react/build/webpack.prod.conf.js

@ -0,0 +1,6 @@
const baseWebpackConfig = require('./webpack.base.conf');
var conf = baseWebpackConfig;
conf.mode = 'production';
module.exports = baseWebpackConfig;

23
react/package.json

@ -0,0 +1,23 @@
{
"name": "line-pod-react",
"version": "0.0.1",
"description": "React wrapper around line-pod",
"main": "dist/index.js",
"repository": "http://code.corpglory.net/chartwerk/line-pod.git",
"author": "CorpGlory Inc.",
"license": "ISC",
"scripts": {
"build": "webpack --config build/webpack.prod.conf.js",
"dev": "webpack --config build/webpack.dev.conf.js"
},
"dependencies": {
"@chartwerk/line-pod": "workspace:*",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"ts-loader": "^9.5.1",
"typescript": "^5.4.3",
"webpack": "^5.87.0"
}
}

74
react/src/index.tsx

@ -0,0 +1,74 @@
import { LineTimeSerie, LineOptions, LinePod } from '@chartwerk/line-pod';
import { MarkersConf } from '@chartwerk/line-pod/dist/models/marker';
import { SegmentSerie } from '@chartwerk/line-pod/dist/models/segment';
import React, { useEffect, useRef, useState } from 'react';
import _ from 'lodash';
export type ChartwerkLinePodProps = {
id?: string;
series: LineTimeSerie[];
options?: LineOptions;
markersConf?: MarkersConf,
segments?: SegmentSerie[],
className?: string;
}
export function ChartwerkLinePod(props: ChartwerkLinePodProps) {
const [pod, setPod] = useState<LinePod | null>(null);
const [hack, setHack] = useState<number | null>(null);
const chartRef = useRef(null);
const chart = chartRef.current;
useEffect(() => {
// this function will be called on component unmount
return () => {
if(pod === null) { return; }
// @ts-ignore
pod.removeEventListeners();
}
}, []);
useEffect(() => {
if(chart === null) { return; }
if(pod === null) {
const newPod = new LinePod(
// @ts-ignore
chart,
props.series,
props.options,
props.markersConf,
props.segments
);
setPod(newPod);
newPod.render();
} else {
if(props.markersConf) {
pod.updateMarkers(props.markersConf);
}
if(props.segments) {
pod.updateSegments(props.segments);
}
// TODO: actually it's wrong logic with updates
// because it creates new pod anyway
pod.updateData(props.series, props.options);
}
}, [chart, props.id, props.options, props.markersConf, props.segments]);
// TODO: it's a hack to render the LinePod right after the div appears in DOM
setTimeout(() => {
if(hack === null) {
setHack(1);
}
}, 1);
return (
<div id={props.id} className={props.className} ref={chartRef}></div>
);
}
export default ChartwerkLinePod;

23
react/tsconfig.json

@ -0,0 +1,23 @@
{
"compilerOptions": {
"target": "es5",
"rootDir": "./src",
"module": "esnext",
"moduleResolution": "node",
"declaration": true,
"declarationDir": "dist",
"allowSyntheticDefaultImports": true,
"inlineSourceMap": false,
"sourceMap": true,
"noEmitOnError": false,
"emitDecoratorMetadata": false,
"experimentalDecorators": true,
"noImplicitReturns": true,
"noImplicitThis": false,
"noImplicitUseStrict": false,
"noImplicitAny": false,
"noUnusedLocals": false,
"baseUrl": "./src",
"jsx": "react"
}
}

1322
react/yarn.lock

File diff suppressed because it is too large Load Diff

139
src/components/markers.ts

@ -0,0 +1,139 @@
import { MarkerElem, MarkersConf, MarkerSerie } from '../models/marker';
import { LineTimeSerie, LineOptions } from '../types';
import { Margin, PodState } from '@chartwerk/core';
import d3 from 'd3';
export class Markers {
private _layerContainer = null;
private _chartHeight = 0;
constructor(
private _chartContainer: d3.Selection<HTMLElement, unknown, null, undefined>,
private _markerConf: MarkersConf,
private _state: PodState<LineTimeSerie, LineOptions>,
private _margin: Margin,
) { }
clear() {
if(this._layerContainer !== null) {
this._layerContainer.remove();
}
this._chartContainer.selectAll('.marker-content').remove();
}
render(metricContainer: d3.Selection<SVGGElement, unknown, null, undefined>, chartHeight: number) {
this._chartHeight = chartHeight;
this._layerContainer = metricContainer
.append('g')
.attr('class', 'markers-layer');
for(const serie of this._markerConf.series) {
this.renderSerie(serie);
}
}
private _getLinePosition(marker: MarkerElem): number {
return this._state.xScale(marker.x);
}
private _renderCircle(marker: MarkerElem) {
const linePosition = this._getLinePosition(marker);
let circle = this._layerContainer.append('circle')
.attr('class', 'gap-circle')
.attr('stroke', marker.color)
.attr('stroke-width', '2px')
.attr('r', 4)
.attr('cx', linePosition)
.attr('cy', 5)
circle
.attr('pointer-events', 'all')
.style('cursor', 'pointer')
.on('mousemove', () => {
const onMouseMove = this._markerConf.events?.onMouseMove;
if(onMouseMove) {
onMouseMove(marker);
return
}
if(marker.alwaysDisplay) {
return;
}
this._chartContainer
.selectAll(`.marker-content-${marker.x}`)
.style('visibility', 'visible')
.style('z-index', 9999);
})
.on('mouseout', () => {
const onMouseOut = this._markerConf.events?.onMouseOut;
if(onMouseOut) {
onMouseOut()
return
}
if(marker.alwaysDisplay) {
return;
}
this._chartContainer
.selectAll(`.marker-content-${marker.x}`)
.style('visibility', 'hidden')
.style('z-index', 1);
});
}
private _renderLine(marker: MarkerElem) {
const linePosition = this._getLinePosition(marker);
this._layerContainer.append('line')
.attr('class', 'gap-line')
.attr('stroke', marker.color)
.attr('stroke-width', '1px')
.attr('stroke-opacity', '0.3')
.attr('stroke-dasharray', '4')
.attr('x1', linePosition)
.attr('x2', linePosition)
.attr('y1', 0)
// @ts-ignore // TODO: remove ignore but boxParams are protected
.attr('y2', this._state.boxParams.height)
.attr('pointer-events', 'none');
}
private _renderTooltip(marker: MarkerElem) {
if(marker.html === undefined) {
return;
}
const linePosition = this._getLinePosition(marker);
const div = this._chartContainer
.append('div')
.attr('class', `marker-content marker-content-${marker.x}`)
// @ts-ignore // TODO: remove ignore but boxParams are protected
.style('top', `${this._state.boxParams.height - this._chartHeight}px`)
.style('visibility', marker.alwaysDisplay ? 'visible' : 'hidden')
.style('position', 'absolute')
.style('border', '1px solid black')
.style('background-color', 'rgb(33, 37, 41)')
.style('color', 'rgb(255, 255, 255)')
.style('line-height', '1.55')
.style('font-size', '0.875rem')
.style('border-radius', '0.5rem')
.style('padding', 'calc(0.3125rem) 0.625rem')
.style('position', 'absolute')
.style('white-space', 'nowrap')
.style('pointer-events', 'none')
.style('z-index', 1)
.html(marker.html);
// align tooltip: center (we need it to be rendered first)
div.style('left', `${linePosition + this._margin.left - div.node().getBoundingClientRect().width / 2}px`)
}
protected renderSerie(serie: MarkerSerie) {
serie.data.forEach((marker: MarkerElem) => {
this._renderLine(marker);
this._renderCircle(marker);
this._renderTooltip(marker);
});
}
}

73
src/components/segments.ts

@ -0,0 +1,73 @@
import { SegmentSerie, SegmentElement } from "../models/segment";
import { PodState } from "@chartwerk/core";
import { LineTimeSerie, LineOptions } from "../types";
import * as d3 from "d3";
const OPACITY = 0.3;
const OPACITY_SELECT = 0.3;
export class Segments {
// TODO: more semantic name
private _d3Holder = null;
private _metricCon = null;
constructor(
private _series: SegmentSerie[],
private _state: PodState<LineTimeSerie, LineOptions>
) {
}
render(metricContainer: d3.Selection<SVGGElement, unknown, null, undefined>, chartContainer: d3.Selection<SVGGElement, unknown, null, undefined>) {
if(this._d3Holder !== null) {
this._d3Holder.remove();
}
this._d3Holder = metricContainer.append('g').attr('class', 'markers-layer');
for (const s of this._series) {
this.renderSerie(chartContainer, s);
}
}
protected renderSerie(chartContainer: d3.Selection<SVGGElement, unknown, null, undefined>, serie: SegmentSerie) {
// TODO: it's hack with core, need to find a better way
const overlay = chartContainer.select('.overlay');
serie.data.forEach((d) => {
// @ts-ignore
const startPositionX = this._state.xScale(d[0]) as number;
// @ts-ignore
const endPositionX = this._state.xScale(d[1]) as number;
const width = endPositionX - startPositionX // Math.max(endPositionX - startPositionX, MIMIMUM_SEGMENT_WIDTH);
const opacity = serie.opacity || OPACITY;
const opacitySelect = serie.opacitySelect || OPACITY_SELECT;
this._d3Holder.append('rect')
.attr('class', 'segment')
.attr('x', startPositionX)
.attr('y', 0)
.attr('width', width)
// @ts-ignore // TODO: remove ignore but boxParams are protected
.attr('height', this._state.boxParams.height)
.attr('opacity', opacity)
.style('fill', serie.color)
.on('mouseover', function() {
if(serie.select === true) {
d3.select(this).attr('opacity', opacitySelect);
if(serie.onSelect) {
serie.onSelect(d);
}
}
})
.on('mouseout', function(e) {
if(serie.select === true) {
d3.select(this).attr('opacity', opacity);
if(serie.onUnselect) {
serie.onUnselect(d);
}
}
})
.on('mousemove', function(e) {
var event = new MouseEvent('mousemove', d3.event);
overlay.node().dispatchEvent(event)
})
});
}
}

260
src/index.ts

@ -1,7 +1,11 @@
import { ChartwerkPod, VueChartwerkPodMixin, TimeFormat, CrosshairOrientation, BrushOrientation, yAxisOrientation } from '@chartwerk/core';
import { LineTimeSerie, LineOptions } from './types';
import { LineTimeSerie, LineOptions, MouseObj, AreaType } from './types';
import { Markers } from './components/markers';
import { Segments } from './components/segments';
import { LineSeries } from './models/line_series';
import { MarkersConf } from './models/marker';
import { SegmentSerie } from './models/segment';
import * as d3 from 'd3';
import * as _ from 'lodash';
@ -10,64 +14,91 @@ const METRIC_CIRCLE_RADIUS = 1.5;
const CROSSHAIR_CIRCLE_RADIUS = 3;
const CROSSHAIR_BACKGROUND_RAIDUS = 9;
const CROSSHAIR_BACKGROUND_OPACITY = 0.3;
export class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
lineGenerator = null;
areaGenerator = null;
lineGeneratorY1 = null;
areaGeneratorY1 = null;
constructor(_el: HTMLElement, _series: LineTimeSerie[] = [], _options: LineOptions = {}) {
type Generator = d3.Line<[number, number]> | d3.Area<[number, number]>;
class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
private _markersLayer: Markers = null;
private _segmentsLayer: Segments = null;
constructor(
_el: HTMLElement,
_series: LineTimeSerie[] = [],
_options: LineOptions = {},
private _markersConf?: MarkersConf,
private _segmentSeries: SegmentSerie[] = [],
) {
super(_el, _series, _options);
this.series = new LineSeries(_series);
}
renderMetrics(): void {
override renderMetrics(): void {
this.clearAllMetrics();
this.updateCrosshair();
this.initLineGenerator();
this.initAreaGenerator();
this.updateEvents();
if(!this.series.isSeriesAvailable) {
this.renderNoDataPointsMessage();
return;
}
for(const serie of this.series.visibleSeries) {
this._renderMetric(serie);
const generator = this.getRenderGenerator(serie.renderArea, serie.yOrientation);
this._renderMetric(serie, generator);
}
if(!_.isEmpty(this._markersConf)) {
this._markersLayer = new Markers(this.d3Node, this._markersConf, this.state, this.margin);
this._markersLayer.render(this.metricContainer, this.height);
}
if(!_.isEmpty(this._segmentSeries)) {
this._segmentsLayer = new Segments(this._segmentSeries, this.state);
this._segmentsLayer.render(this.metricContainer, this.chartContainer);
}
}
clearAllMetrics(): void {
// TODO: temporary hack before it will be implemented in core.
this.chartContainer.selectAll('.metric-el').remove();
this._markersLayer?.clear();
}
initLineGenerator(): void {
this.lineGenerator = d3.line()
.x(d => this.state.xScale(d[0]))
.y(d => this.state.yScale(d[1]));
this.lineGeneratorY1 = d3.line()
.x(d => this.state.xScale(d[0]))
.y(d => this.state.y1Scale(d[1]));
}
initAreaGenerator(): void {
this.areaGenerator = d3.area()
.x(d => this.state.xScale(d[0]))
.y1(d => this.state.yScale(d[1]))
.y0(d => this.height);
this.areaGeneratorY1 = d3.area()
.x(d => this.state.xScale(d[0]))
.y1(d => this.state.y1Scale(d[1]))
.y0(d => this.height);
protected updateEvents(): void {
// overlay - core component that is used to handle mouse events
if(!this.overlay) {
return;
}
if(this.options._options.events?.contextMenu === undefined) {
return;
}
this.overlay.on('contextmenu', this.onContextMenu.bind(this));
}
getRenderGenerator(renderArea: boolean, yOrientation: yAxisOrientation): any {
if(renderArea) {
return yOrientation === yAxisOrientation.LEFT ? this.areaGenerator : this.areaGeneratorY1;
getRenderGenerator(renderArea: AreaType, yOrientation: yAxisOrientation): Generator {
const yScale = yOrientation === yAxisOrientation.LEFT ? this.state.yScale : this.state.y1Scale;
const yValueRange = yOrientation === yAxisOrientation.LEFT ? this.state.yValueRange : this.state.y1ValueRange;
const yAxisOptions = yOrientation === yAxisOrientation.LEFT ? this.options.axis.y : this.options.axis.y1;
const topChartBorder = !yAxisOptions.invert ? yScale(yValueRange[1]) : yScale(yValueRange[0]);
const bottomChartBorder = !yAxisOptions.invert ? yScale(yValueRange[0]) : yScale(yValueRange[1]);
switch(renderArea) {
case AreaType.NONE:
// return line generator
return d3.line()
.x(d => this.state.xScale(d[0]))
.y(d => yScale(d[1]));
case AreaType.ABOVE:
return d3.area()
.x(d => this.state.xScale(d[0]))
.y0(topChartBorder)
.y1(d => yScale(d[1]));
case AreaType.BELOW:
return d3.area()
.x(d => this.state.xScale(d[0]))
.y0(d => yScale(d[1]))
.y1(bottomChartBorder);
default:
throw new Error(`Unknown type of renderArea: ${renderArea}`);
}
return yOrientation === yAxisOrientation.LEFT ? this.lineGenerator : this.areaGeneratorY1;
}
_renderDots(serie: LineTimeSerie): void {
@ -80,12 +111,12 @@ export class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
.attr('r', METRIC_CIRCLE_RADIUS)
.style('pointer-events', 'none')
.attr('cx', d => this.state.xScale(d[0]))
.attr('cy', d => this.state.yScale(d[1]));
.attr('cy', d => this.state.getYScaleByOrientation(serie.yOrientation)(d[1]));
}
_renderLines(serie: LineTimeSerie): void {
const fillColor = serie.renderArea ? serie.color : 'none';
const fillOpacity = serie.renderArea ? 0.5 : 'none';
_renderLines(serie: LineTimeSerie, generator: Generator): void {
const fillColor = serie.renderArea !== AreaType.NONE ? serie.color : 'none';
const fillOpacity = serie.renderArea !== AreaType.NONE ? 0.5 : 'none';
this.metricContainer
.append('path')
@ -98,12 +129,12 @@ export class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
.attr('stroke-opacity', 0.7)
.attr('pointer-events', 'none')
.style('stroke-dasharray', serie.dashArray)
.attr('d', this.getRenderGenerator(serie.renderArea, serie.yOrientation));
.attr('d', generator);
}
_renderMetric(serie: LineTimeSerie): void {
_renderMetric(serie: LineTimeSerie, generator: Generator): void {
if(serie.renderLines === true) {
this._renderLines(serie);
this._renderLines(serie, generator);
}
if(serie.renderDots === true) {
@ -147,24 +178,16 @@ export class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
.style('pointer-events', 'none');
}
public renderSharedCrosshair(values: { x?: number, y?: number }): void {
this.onMouseOver(); // TODO: refactor to use it once
const eventX = this.state.xScale(values.x);
const eventY = this.state.yScale(values.y);
this.moveCrosshairLine(eventX, eventY);
const datapoints = this.findAndHighlightDatapoints(values.x, values.y);
this.options.callbackSharedCrosshairMove({
datapoints: datapoints,
eventX, eventY
});
}
public hideSharedCrosshair(): void {
this.crosshair.style('display', 'none');
}
// TODO: refactor to make xPosition and yPosition optional
// and trough error if they are provided for wrong orientation
moveCrosshairLine(xPosition: number, yPosition: number): void {
this.crosshair.style('display', null);
switch(this.options.crosshair.orientation) {
case CrosshairOrientation.VERTICAL:
this.crosshair.select('#crosshair-line-x')
@ -269,18 +292,17 @@ export class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
return _.max(intervals);
}
onMouseMove(): void {
getMouseObj(): MouseObj {
const eventX = d3.mouse(this.chartContainer.node())[0];
const eventY = d3.mouse(this.chartContainer.node())[1];
const xValue = this.state.xScale.invert(eventX); // mouse x position in xScale
const yValue = this.state.yScale.invert(eventY);
this.moveCrosshairLine(eventX, eventY);
const datapoints = this.findAndHighlightDatapoints(xValue, yValue);
// TDOO: is shift key pressed
// TODO: is shift key pressed
// TODO: need to refactor this object
this.options.callbackMouseMove({
return {
x: d3.event.pageX,
y: d3.event.pageY,
xVal: xValue,
@ -288,9 +310,40 @@ export class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
series: datapoints,
chartX: eventX,
chartWidth: this.width
};
}
override onMouseMove(): void {
const obj = this.getMouseObj();
const eventX = d3.mouse(this.chartContainer.node())[0];
const eventY = d3.mouse(this.chartContainer.node())[1];
this.moveCrosshairLine(eventX, eventY);
// TODO: is shift key pressed
// TODO: need to refactor this object
this.options.callbackMouseMove(obj);
}
public renderSharedCrosshair(values: { x?: number, y?: number }): void {
this.showCrosshair();
this.moveCrosshairLine(
values.x ? this.state.xScale(values.x) : 0,
values.y ? this.state.yScale(values.y) : 0
);
const datapoints = this.findAndHighlightDatapoints(values.x, values.y);
this.options.callbackSharedCrosshairMove({
datapoints: datapoints,
eventX: values.x ? this.state.xScale(values.x) : 0,
eventY: values.y ? this.state.yScale(values.y) : 0
});
}
override onMouseClick(): void {
this.options.callbackMouseClick(this.getMouseObj());
}
findAndHighlightDatapoints(xValue: number, yValue: number): { value: [number, number], color: string, label: string }[] {
if(!this.series.isSeriesAvailable) {
return [];
@ -320,21 +373,45 @@ export class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
return points;
}
onMouseOver(): void {
showCrosshair() {
this.crosshair.style('display', null);
this.crosshair.selectAll('.crosshair-circle')
.style('display', null);
}
onMouseOut(): void {
this.options.callbackMouseOut();
hideCrosshair() {
this.crosshair.style('display', 'none');
this.crosshair.selectAll('.crosshair-circle')
.style('display', 'none');
}
override onMouseOver(): void {
this.showCrosshair();
this.onMouseMove();
}
override onMouseOut(): void {
this.hideCrosshair();
this.options.callbackMouseOut();
}
isDoubleClickActive(): boolean {
return this.options.doubleClickEvent.isActive;
}
protected onBrushEnd(): void {
super.onBrushEnd();
this.onMouseOver();
}
updateMarkers(markersConf: MarkersConf): void {
this._markersConf = markersConf;
}
updateSegments(segments: SegmentSerie[]): void {
this._segmentSeries = segments;
}
// methods below rewrite s, (move more methods here)
protected zoomOut(): void {
if(d3.event.type === 'dblclick' && !this.isDoubleClickActive()) {
@ -376,13 +453,68 @@ export class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
x: xAxisMiddleValue,
y: yAxisMiddleValue
}
this.options.callbackZoomOut(centers);
// TODO: refactor core not to take _options explicitly
if(
this.options._options.events !== undefined &&
this.options._options.events.zoomOut !== undefined
) {
this.options._options.events.zoomOut(
centers,
[this.state.xValueRange, this.state.yValueRange]
);
}
}
protected onContextMenu(): void {
d3.event.preventDefault(); // do not open browser's context menu.
const eventX = d3.mouse(this.chartContainer.node())[0];
const eventY = d3.mouse(this.chartContainer.node())[1];
this.options._options.events.contextMenu({
x: this.state.xScale.invert(eventX),
y: this.state.yScale.invert(eventY),
});
}
// override parent updateData method to provide markers and segments
protected updateLineData(
series?: LineTimeSerie[],
options?: LineOptions,
markersConf?: MarkersConf,
segments?: SegmentSerie[],
shouldRerender = true
): void {
this.updateMarkers(markersConf);
this.updateSegments(segments);
this.updateData(series, options, shouldRerender);
}
}
// TODO: it should be moved to VUE folder
// it is used with Vue.component, e.g.: Vue.component('chartwerk-line-pod', VueChartwerkLinePod)
export const VueChartwerkLinePod = {
// alternative to `template: '<div class="chartwerk-line-pod" :id="id" />'`
props: {
markersConf: {
type: Object,
required: false,
default: function() { return {}; }
},
segments: {
type: Array,
required: false,
default: function() { return []; }
},
},
watch: {
markersConf() {
this.renderChart();
},
segments() {
this.renderChart();
},
},
render(createElement) {
return createElement(
'div',
@ -396,10 +528,10 @@ export const VueChartwerkLinePod = {
methods: {
render() {
if(this.pod === undefined) {
this.pod = new LinePod(document.getElementById(this.id), this.series, this.options);
this.pod = new LinePod(document.getElementById(this.id), this.series, this.options, this.markersConf, this.segments);
this.pod.render();
} else {
this.pod.updateData(this.series, this.options);
this.pod.updateLineData(this.series, this.options, this.markersConf, this.segments);
}
},
renderSharedCrosshair(values) {
@ -411,4 +543,4 @@ export const VueChartwerkLinePod = {
}
};
export { LineTimeSerie, LineOptions, TimeFormat };
export { LineTimeSerie, LineOptions, TimeFormat, LinePod, AreaType, MarkersConf, SegmentSerie };

5
src/models/line_series.ts

@ -1,5 +1,5 @@
import { CoreSeries, yAxisOrientation } from '@chartwerk/core';
import { LineTimeSerie } from '../types';
import { LineTimeSerie, AreaType } from '../types';
import * as _ from 'lodash';
@ -10,12 +10,11 @@ const LINE_SERIE_DEFAULTS = {
renderLines: true,
dashArray: '0',
class: '',
renderArea: false,
renderArea: AreaType.NONE,
yOrientation: yAxisOrientation.LEFT,
};
export class LineSeries extends CoreSeries<LineTimeSerie> {
constructor(series: LineTimeSerie[]) {
super(series, _.clone(LINE_SERIE_DEFAULTS));
}

19
src/models/marker.ts

@ -0,0 +1,19 @@
export type MarkerElem = {
x: number;
color: string;
html?: string;
alwaysDisplay?: boolean;
payload?: any;
}
export type MarkerSerie = {
data: MarkerElem[];
}
export type MarkersConf = {
series: MarkerSerie[],
events?: {
onMouseMove?: (el: MarkerElem) => void;
onMouseOut?: () => void;
}
}

11
src/models/segment.ts

@ -0,0 +1,11 @@
export type SegmentElement = [number, number, any?];
export type SegmentSerie = {
color: string;
data: SegmentElement[] // [from, to, payload?] payload is any data for tooltip,
select?: boolean,
opacity?: number,
opacitySelect?: number,
onSelect?: (SegmentElement) => void
onUnselect?: (SegmentElement) => void
}

38
src/types.ts

@ -1,13 +1,41 @@
import { Serie, Options } from '@chartwerk/core';
import { AxisRange } from '@chartwerk/core/dist/types';
type LineTimeSerieParams = {
maxLength: number,
renderDots: boolean,
renderLines: boolean, // TODO: refactor same as scatter-pod
maxLength: number;
renderDots: boolean;
renderLines: boolean; // TODO: refactor same as scatter-pod
dashArray: string; // dasharray attr, only for lines
class: string; // option to add custom class to each serie element
renderArea: boolean; // TODO: move to render type
renderArea: AreaType; // default is none
}
export enum AreaType {
NONE = 'None',
ABOVE = 'Above',
BELOW = 'Below',
}
export type LineTimeSerie = Serie & Partial<LineTimeSerieParams>;
export type LineOptions = Options;
export type LineOptions = Options & {
events? : {
zoomOut?: (centers: {
x: number;
y: number;
}, range: AxisRange[]) => void;
contextMenu?: (position: {
x: number;
y: number;
}) => void;
}
}
export type MouseObj = {
x: number,
y: number,
xVal: number,
yVal: number,
series: { value: [number, number], color: string, label: string }[],
chartX: number,
chartWidth: number
}

5
tsconfig.json

@ -17,6 +17,7 @@
"noImplicitUseStrict": false,
"noImplicitAny": false,
"noUnusedLocals": false,
"baseUrl": "./src"
}
"baseUrl": "./src",
},
"include": ["src/**/*"]
}

278
yarn.lock

@ -5,13 +5,13 @@ __metadata:
version: 6
cacheKey: 8
"@chartwerk/core@npm:latest":
version: 0.6.14
resolution: "@chartwerk/core@npm:0.6.14"
"@chartwerk/core@npm:^0.6.26":
version: 0.6.26
resolution: "@chartwerk/core@npm:0.6.26"
dependencies:
d3: ^5.16.0
lodash: ^4.17.21
checksum: 34888b555d91a96d5a279f43dc4b33f345d055574855e1c90cb22913f7e42b13b6c9abbd0af07e6531b6f872cdf8e04660c22a2c14938189b67b9c494c6a0bfb
checksum: d77ef83701dc13cf2b7fb36dc96448060b6301928bcc0730a7150930f83c51f295e176bcda4e1b8cb8f56d15fef5696edfe6f4e1033adbb5ef5d3487a02c3390
languageName: node
linkType: hard
@ -19,7 +19,8 @@ __metadata:
version: 0.0.0-use.local
resolution: "@chartwerk/line-pod@workspace:."
dependencies:
"@chartwerk/core": latest
"@chartwerk/core": ^0.6.26
copy-webpack-plugin: ^11.0.0
css-loader: ^6.8.1
style-loader: ^3.3.3
ts-loader: ^9.4.3
@ -95,6 +96,33 @@ __metadata:
languageName: node
linkType: hard
"@nodelib/fs.scandir@npm:2.1.5":
version: 2.1.5
resolution: "@nodelib/fs.scandir@npm:2.1.5"
dependencies:
"@nodelib/fs.stat": 2.0.5
run-parallel: ^1.1.9
checksum: a970d595bd23c66c880e0ef1817791432dbb7acbb8d44b7e7d0e7a22f4521260d4a83f7f9fd61d44fda4610105577f8f58a60718105fb38352baed612fd79e59
languageName: node
linkType: hard
"@nodelib/fs.stat@npm:2.0.5, @nodelib/fs.stat@npm:^2.0.2":
version: 2.0.5
resolution: "@nodelib/fs.stat@npm:2.0.5"
checksum: 012480b5ca9d97bff9261571dbbec7bbc6033f69cc92908bc1ecfad0792361a5a1994bc48674b9ef76419d056a03efadfce5a6cf6dbc0a36559571a7a483f6f0
languageName: node
linkType: hard
"@nodelib/fs.walk@npm:^1.2.3":
version: 1.2.8
resolution: "@nodelib/fs.walk@npm:1.2.8"
dependencies:
"@nodelib/fs.scandir": 2.1.5
fastq: ^1.6.0
checksum: 190c643f156d8f8f277bf2a6078af1ffde1fd43f498f187c2db24d35b4b4b5785c02c7dc52e356497b9a1b65b13edc996de08de0b961c32844364da02986dc53
languageName: node
linkType: hard
"@types/eslint-scope@npm:^3.7.3":
version: 3.7.4
resolution: "@types/eslint-scope@npm:3.7.4"
@ -129,6 +157,13 @@ __metadata:
languageName: node
linkType: hard
"@types/json-schema@npm:^7.0.9":
version: 7.0.15
resolution: "@types/json-schema@npm:7.0.15"
checksum: 97ed0cb44d4070aecea772b7b2e2ed971e10c81ec87dd4ecc160322ffa55ff330dace1793489540e3e318d90942064bb697cc0f8989391797792d919737b3b98
languageName: node
linkType: hard
"@types/node@npm:*":
version: 20.3.1
resolution: "@types/node@npm:20.3.1"
@ -352,6 +387,20 @@ __metadata:
languageName: node
linkType: hard
"ajv-formats@npm:^2.1.1":
version: 2.1.1
resolution: "ajv-formats@npm:2.1.1"
dependencies:
ajv: ^8.0.0
peerDependencies:
ajv: ^8.0.0
peerDependenciesMeta:
ajv:
optional: true
checksum: 4a287d937f1ebaad4683249a4c40c0fa3beed30d9ddc0adba04859026a622da0d317851316ea64b3680dc60f5c3c708105ddd5d5db8fe595d9d0207fd19f90b7
languageName: node
linkType: hard
"ajv-keywords@npm:^3.5.2":
version: 3.5.2
resolution: "ajv-keywords@npm:3.5.2"
@ -361,6 +410,17 @@ __metadata:
languageName: node
linkType: hard
"ajv-keywords@npm:^5.1.0":
version: 5.1.0
resolution: "ajv-keywords@npm:5.1.0"
dependencies:
fast-deep-equal: ^3.1.3
peerDependencies:
ajv: ^8.8.2
checksum: c35193940b853119242c6757787f09ecf89a2c19bcd36d03ed1a615e710d19d450cb448bfda407b939aba54b002368c8bff30529cc50a0536a8e10bcce300421
languageName: node
linkType: hard
"ajv@npm:^6.12.5":
version: 6.12.6
resolution: "ajv@npm:6.12.6"
@ -373,6 +433,18 @@ __metadata:
languageName: node
linkType: hard
"ajv@npm:^8.0.0, ajv@npm:^8.9.0":
version: 8.12.0
resolution: "ajv@npm:8.12.0"
dependencies:
fast-deep-equal: ^3.1.1
json-schema-traverse: ^1.0.0
require-from-string: ^2.0.2
uri-js: ^4.2.2
checksum: 4dc13714e316e67537c8b31bc063f99a1d9d9a497eb4bbd55191ac0dcd5e4985bbb71570352ad6f1e76684fb6d790928f96ba3b2d4fd6e10024be9612fe3f001
languageName: node
linkType: hard
"ansi-styles@npm:^4.1.0":
version: 4.3.0
resolution: "ansi-styles@npm:4.3.0"
@ -382,7 +454,7 @@ __metadata:
languageName: node
linkType: hard
"braces@npm:^3.0.1":
"braces@npm:^3.0.1, braces@npm:^3.0.2":
version: 3.0.2
resolution: "braces@npm:3.0.2"
dependencies:
@ -484,6 +556,22 @@ __metadata:
languageName: node
linkType: hard
"copy-webpack-plugin@npm:^11.0.0":
version: 11.0.0
resolution: "copy-webpack-plugin@npm:11.0.0"
dependencies:
fast-glob: ^3.2.11
glob-parent: ^6.0.1
globby: ^13.1.1
normalize-path: ^3.0.0
schema-utils: ^4.0.0
serialize-javascript: ^6.0.0
peerDependencies:
webpack: ^5.1.0
checksum: df4f8743f003a29ee7dd3d9b1789998a3a99051c92afb2ba2203d3dacfa696f4e757b275560fafb8f206e520a0aa78af34b990324a0e36c2326cefdeef3ca82e
languageName: node
linkType: hard
"cross-spawn@npm:^7.0.3":
version: 7.0.3
resolution: "cross-spawn@npm:7.0.3"
@ -844,6 +932,15 @@ __metadata:
languageName: node
linkType: hard
"dir-glob@npm:^3.0.1":
version: 3.0.1
resolution: "dir-glob@npm:3.0.1"
dependencies:
path-type: ^4.0.0
checksum: fa05e18324510d7283f55862f3161c6759a3f2f8dbce491a2fc14c8324c498286c54282c1f0e933cb930da8419b30679389499b919122952a4f8592362ef4615
languageName: node
linkType: hard
"electron-to-chromium@npm:^1.4.428":
version: 1.4.431
resolution: "electron-to-chromium@npm:1.4.431"
@ -924,13 +1021,26 @@ __metadata:
languageName: node
linkType: hard
"fast-deep-equal@npm:^3.1.1":
"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3":
version: 3.1.3
resolution: "fast-deep-equal@npm:3.1.3"
checksum: e21a9d8d84f53493b6aa15efc9cfd53dd5b714a1f23f67fb5dc8f574af80df889b3bce25dc081887c6d25457cce704e636395333abad896ccdec03abaf1f3f9d
languageName: node
linkType: hard
"fast-glob@npm:^3.2.11, fast-glob@npm:^3.3.0":
version: 3.3.2
resolution: "fast-glob@npm:3.3.2"
dependencies:
"@nodelib/fs.stat": ^2.0.2
"@nodelib/fs.walk": ^1.2.3
glob-parent: ^5.1.2
merge2: ^1.3.0
micromatch: ^4.0.4
checksum: 900e4979f4dbc3313840078419245621259f349950411ca2fa445a2f9a1a6d98c3b5e7e0660c5ccd563aa61abe133a21765c6c0dec8e57da1ba71d8000b05ec1
languageName: node
linkType: hard
"fast-json-stable-stringify@npm:^2.0.0":
version: 2.1.0
resolution: "fast-json-stable-stringify@npm:2.1.0"
@ -945,6 +1055,15 @@ __metadata:
languageName: node
linkType: hard
"fastq@npm:^1.6.0":
version: 1.15.0
resolution: "fastq@npm:1.15.0"
dependencies:
reusify: ^1.0.4
checksum: 0170e6bfcd5d57a70412440b8ef600da6de3b2a6c5966aeaf0a852d542daff506a0ee92d6de7679d1de82e644bce69d7a574a6c93f0b03964b5337eed75ada1a
languageName: node
linkType: hard
"fill-range@npm:^7.0.1":
version: 7.0.1
resolution: "fill-range@npm:7.0.1"
@ -971,6 +1090,24 @@ __metadata:
languageName: node
linkType: hard
"glob-parent@npm:^5.1.2":
version: 5.1.2
resolution: "glob-parent@npm:5.1.2"
dependencies:
is-glob: ^4.0.1
checksum: f4f2bfe2425296e8a47e36864e4f42be38a996db40420fe434565e4480e3322f18eb37589617a98640c5dc8fdec1a387007ee18dbb1f3f5553409c34d17f425e
languageName: node
linkType: hard
"glob-parent@npm:^6.0.1":
version: 6.0.2
resolution: "glob-parent@npm:6.0.2"
dependencies:
is-glob: ^4.0.3
checksum: c13ee97978bef4f55106b71e66428eb1512e71a7466ba49025fc2aec59a5bfb0954d5abd58fc5ee6c9b076eef4e1f6d3375c2e964b88466ca390da4419a786a8
languageName: node
linkType: hard
"glob-to-regexp@npm:^0.4.1":
version: 0.4.1
resolution: "glob-to-regexp@npm:0.4.1"
@ -978,6 +1115,19 @@ __metadata:
languageName: node
linkType: hard
"globby@npm:^13.1.1":
version: 13.2.2
resolution: "globby@npm:13.2.2"
dependencies:
dir-glob: ^3.0.1
fast-glob: ^3.3.0
ignore: ^5.2.4
merge2: ^1.4.1
slash: ^4.0.0
checksum: f3d84ced58a901b4fcc29c846983108c426631fe47e94872868b65565495f7bee7b3defd68923bd480582771fd4bbe819217803a164a618ad76f1d22f666f41e
languageName: node
linkType: hard
"graceful-fs@npm:^4.1.2":
version: 4.2.9
resolution: "graceful-fs@npm:4.2.9"
@ -1026,6 +1176,13 @@ __metadata:
languageName: node
linkType: hard
"ignore@npm:^5.2.4":
version: 5.3.0
resolution: "ignore@npm:5.3.0"
checksum: 2736da6621f14ced652785cb05d86301a66d70248597537176612bd0c8630893564bd5f6421f8806b09e8472e75c591ef01672ab8059c07c6eb2c09cefe04bf9
languageName: node
linkType: hard
"import-local@npm:^3.0.2":
version: 3.1.0
resolution: "import-local@npm:3.1.0"
@ -1054,6 +1211,22 @@ __metadata:
languageName: node
linkType: hard
"is-extglob@npm:^2.1.1":
version: 2.1.1
resolution: "is-extglob@npm:2.1.1"
checksum: df033653d06d0eb567461e58a7a8c9f940bd8c22274b94bf7671ab36df5719791aae15eef6d83bbb5e23283967f2f984b8914559d4449efda578c775c4be6f85
languageName: node
linkType: hard
"is-glob@npm:^4.0.1, is-glob@npm:^4.0.3":
version: 4.0.3
resolution: "is-glob@npm:4.0.3"
dependencies:
is-extglob: ^2.1.1
checksum: d381c1319fcb69d341cc6e6c7cd588e17cd94722d9a32dbd60660b993c4fb7d0f19438674e68dfec686d09b7c73139c9166b47597f846af387450224a8101ab4
languageName: node
linkType: hard
"is-number@npm:^7.0.0":
version: 7.0.0
resolution: "is-number@npm:7.0.0"
@ -1109,6 +1282,13 @@ __metadata:
languageName: node
linkType: hard
"json-schema-traverse@npm:^1.0.0":
version: 1.0.0
resolution: "json-schema-traverse@npm:1.0.0"
checksum: 02f2f466cdb0362558b2f1fd5e15cce82ef55d60cd7f8fa828cf35ba74330f8d767fcae5c5c2adb7851fa811766c694b9405810879bc4e1ddd78a7c0e03658ad
languageName: node
linkType: hard
"kind-of@npm:^6.0.2":
version: 6.0.3
resolution: "kind-of@npm:6.0.3"
@ -1155,6 +1335,13 @@ __metadata:
languageName: node
linkType: hard
"merge2@npm:^1.3.0, merge2@npm:^1.4.1":
version: 1.4.1
resolution: "merge2@npm:1.4.1"
checksum: 7268db63ed5169466540b6fb947aec313200bcf6d40c5ab722c22e242f651994619bcd85601602972d3c85bd2cc45a358a4c61937e9f11a061919a1da569b0c2
languageName: node
linkType: hard
"micromatch@npm:^4.0.0":
version: 4.0.4
resolution: "micromatch@npm:4.0.4"
@ -1165,6 +1352,16 @@ __metadata:
languageName: node
linkType: hard
"micromatch@npm:^4.0.4":
version: 4.0.5
resolution: "micromatch@npm:4.0.5"
dependencies:
braces: ^3.0.2
picomatch: ^2.3.1
checksum: 02a17b671c06e8fefeeb6ef996119c1e597c942e632a21ef589154f23898c9c6a9858526246abb14f8bca6e77734aa9dcf65476fca47cedfb80d9577d52843fc
languageName: node
linkType: hard
"mime-db@npm:1.52.0":
version: 1.52.0
resolution: "mime-db@npm:1.52.0"
@ -1204,6 +1401,13 @@ __metadata:
languageName: node
linkType: hard
"normalize-path@npm:^3.0.0":
version: 3.0.0
resolution: "normalize-path@npm:3.0.0"
checksum: 88eeb4da891e10b1318c4b2476b6e2ecbeb5ff97d946815ffea7794c31a89017c70d7f34b3c2ebf23ef4e9fc9fb99f7dffe36da22011b5b5c6ffa34f4873ec20
languageName: node
linkType: hard
"p-limit@npm:^2.2.0":
version: 2.3.0
resolution: "p-limit@npm:2.3.0"
@ -1250,6 +1454,13 @@ __metadata:
languageName: node
linkType: hard
"path-type@npm:^4.0.0":
version: 4.0.0
resolution: "path-type@npm:4.0.0"
checksum: 5b1e2daa247062061325b8fdbfd1fb56dde0a448fb1455453276ea18c60685bdad23a445dc148cf87bc216be1573357509b7d4060494a6fd768c7efad833ee45
languageName: node
linkType: hard
"picocolors@npm:^1.0.0":
version: 1.0.0
resolution: "picocolors@npm:1.0.0"
@ -1257,7 +1468,7 @@ __metadata:
languageName: node
linkType: hard
"picomatch@npm:^2.2.3":
"picomatch@npm:^2.2.3, picomatch@npm:^2.3.1":
version: 2.3.1
resolution: "picomatch@npm:2.3.1"
checksum: 050c865ce81119c4822c45d3c84f1ced46f93a0126febae20737bd05ca20589c564d6e9226977df859ed5e03dc73f02584a2b0faad36e896936238238b0446cf
@ -1362,6 +1573,13 @@ __metadata:
languageName: node
linkType: hard
"queue-microtask@npm:^1.2.2":
version: 1.2.3
resolution: "queue-microtask@npm:1.2.3"
checksum: b676f8c040cdc5b12723ad2f91414d267605b26419d5c821ff03befa817ddd10e238d22b25d604920340fd73efd8ba795465a0377c4adf45a4a41e4234e42dc4
languageName: node
linkType: hard
"randombytes@npm:^2.1.0":
version: 2.1.0
resolution: "randombytes@npm:2.1.0"
@ -1380,6 +1598,13 @@ __metadata:
languageName: node
linkType: hard
"require-from-string@npm:^2.0.2":
version: 2.0.2
resolution: "require-from-string@npm:2.0.2"
checksum: a03ef6895445f33a4015300c426699bc66b2b044ba7b670aa238610381b56d3f07c686251740d575e22f4c87531ba662d06937508f0f3c0f1ddc04db3130560b
languageName: node
linkType: hard
"resolve-cwd@npm:^3.0.0":
version: 3.0.0
resolution: "resolve-cwd@npm:3.0.0"
@ -1422,6 +1647,22 @@ __metadata:
languageName: node
linkType: hard
"reusify@npm:^1.0.4":
version: 1.0.4
resolution: "reusify@npm:1.0.4"
checksum: c3076ebcc22a6bc252cb0b9c77561795256c22b757f40c0d8110b1300723f15ec0fc8685e8d4ea6d7666f36c79ccc793b1939c748bf36f18f542744a4e379fcc
languageName: node
linkType: hard
"run-parallel@npm:^1.1.9":
version: 1.2.0
resolution: "run-parallel@npm:1.2.0"
dependencies:
queue-microtask: ^1.2.2
checksum: cb4f97ad25a75ebc11a8ef4e33bb962f8af8516bb2001082ceabd8902e15b98f4b84b4f8a9b222e5d57fc3bd1379c483886ed4619367a7680dad65316993021d
languageName: node
linkType: hard
"rw@npm:1":
version: 1.3.3
resolution: "rw@npm:1.3.3"
@ -1454,6 +1695,18 @@ __metadata:
languageName: node
linkType: hard
"schema-utils@npm:^4.0.0":
version: 4.2.0
resolution: "schema-utils@npm:4.2.0"
dependencies:
"@types/json-schema": ^7.0.9
ajv: ^8.9.0
ajv-formats: ^2.1.1
ajv-keywords: ^5.1.0
checksum: 26a0463d47683258106e6652e9aeb0823bf0b85843039e068b57da1892f7ae6b6b1094d48e9ed5ba5cbe9f7166469d880858b9d91abe8bd249421eb813850cde
languageName: node
linkType: hard
"semver@npm:^7.3.4, semver@npm:^7.3.8":
version: 7.5.1
resolution: "semver@npm:7.5.1"
@ -1465,7 +1718,7 @@ __metadata:
languageName: node
linkType: hard
"serialize-javascript@npm:^6.0.1":
"serialize-javascript@npm:^6.0.0, serialize-javascript@npm:^6.0.1":
version: 6.0.1
resolution: "serialize-javascript@npm:6.0.1"
dependencies:
@ -1499,6 +1752,13 @@ __metadata:
languageName: node
linkType: hard
"slash@npm:^4.0.0":
version: 4.0.0
resolution: "slash@npm:4.0.0"
checksum: da8e4af73712253acd21b7853b7e0dbba776b786e82b010a5bfc8b5051a1db38ed8aba8e1e8f400dd2c9f373be91eb1c42b66e91abb407ff42b10feece5e1d2d
languageName: node
linkType: hard
"source-map-js@npm:^1.0.2":
version: 1.0.2
resolution: "source-map-js@npm:1.0.2"

Loading…
Cancel
Save