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 dist
# yarn # yarn
.yarn/* .yarn
!.yarn/patches !.yarn/patches
!.yarn/plugins !.yarn/plugins
!.yarn/releases !.yarn/releases

23
README.md

@ -19,8 +19,25 @@
``` ```
#### Other examples #### 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 path = require('path');
const CopyPlugin = require("copy-webpack-plugin");
function resolve(dir) { function resolve(dir) {
@ -8,7 +9,14 @@ function resolve(dir) {
module.exports = { module.exports = {
context: resolve('src'), context: resolve('src'),
entry: './index.ts', 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: { module: {
rules: [ rules: [
{ {
@ -25,6 +33,10 @@ module.exports = {
}, },
resolve: { resolve: {
extensions: ['.ts', '.js'], 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: { output: {
filename: 'index.js', 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", "name": "@chartwerk/line-pod",
"version": "0.6.9", "version": "0.7.8",
"description": "Chartwerk line chart", "description": "Chartwerk line chart",
"main": "dist/index.js", "main": "dist/index.js",
"files": [ "files": [
"/dist" "/dist"
], ],
"scripts": { "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", "dev": "webpack --watch --config build/webpack.dev.conf.js",
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
"update-core": "yarn up @chartwerk/core && yarn up @chartwerk/core@latest" "update-core": "yarn up @chartwerk/core && yarn up @chartwerk/core@latest"
@ -19,9 +19,10 @@
"author": "CorpGlory", "author": "CorpGlory",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@chartwerk/core": "latest" "@chartwerk/core": "^0.6.26"
}, },
"devDependencies": { "devDependencies": {
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.8.1", "css-loader": "^6.8.1",
"style-loader": "^3.3.3", "style-loader": "^3.3.3",
"ts-loader": "^9.4.3", "ts-loader": "^9.4.3",
@ -29,5 +30,8 @@
"webpack": "^5.87.0", "webpack": "^5.87.0",
"webpack-cli": "^5.1.4" "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 { 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 { LineSeries } from './models/line_series';
import { MarkersConf } from './models/marker';
import { SegmentSerie } from './models/segment';
import * as d3 from 'd3'; import * as d3 from 'd3';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -10,64 +14,91 @@ const METRIC_CIRCLE_RADIUS = 1.5;
const CROSSHAIR_CIRCLE_RADIUS = 3; const CROSSHAIR_CIRCLE_RADIUS = 3;
const CROSSHAIR_BACKGROUND_RAIDUS = 9; const CROSSHAIR_BACKGROUND_RAIDUS = 9;
const CROSSHAIR_BACKGROUND_OPACITY = 0.3; const CROSSHAIR_BACKGROUND_OPACITY = 0.3;
type Generator = d3.Line<[number, number]> | d3.Area<[number, number]>;
export class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
lineGenerator = null; class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
areaGenerator = null; private _markersLayer: Markers = null;
lineGeneratorY1 = null; private _segmentsLayer: Segments = null;
areaGeneratorY1 = null;
constructor(
constructor(_el: HTMLElement, _series: LineTimeSerie[] = [], _options: LineOptions = {}) { _el: HTMLElement,
_series: LineTimeSerie[] = [],
_options: LineOptions = {},
private _markersConf?: MarkersConf,
private _segmentSeries: SegmentSerie[] = [],
) {
super(_el, _series, _options); super(_el, _series, _options);
this.series = new LineSeries(_series); this.series = new LineSeries(_series);
} }
renderMetrics(): void { override renderMetrics(): void {
this.clearAllMetrics(); this.clearAllMetrics();
this.updateCrosshair(); this.updateCrosshair();
this.initLineGenerator(); this.updateEvents();
this.initAreaGenerator();
if(!this.series.isSeriesAvailable) { if(!this.series.isSeriesAvailable) {
this.renderNoDataPointsMessage(); this.renderNoDataPointsMessage();
return; return;
} }
for(const serie of this.series.visibleSeries) { 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 { clearAllMetrics(): void {
// TODO: temporary hack before it will be implemented in core. // TODO: temporary hack before it will be implemented in core.
this.chartContainer.selectAll('.metric-el').remove(); this.chartContainer.selectAll('.metric-el').remove();
this._markersLayer?.clear();
} }
initLineGenerator(): void { protected updateEvents(): void {
this.lineGenerator = d3.line() // overlay - core component that is used to handle mouse events
.x(d => this.state.xScale(d[0])) if(!this.overlay) {
.y(d => this.state.yScale(d[1])); return;
this.lineGeneratorY1 = d3.line() }
.x(d => this.state.xScale(d[0])) if(this.options._options.events?.contextMenu === undefined) {
.y(d => this.state.y1Scale(d[1])); return;
} }
this.overlay.on('contextmenu', this.onContextMenu.bind(this));
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);
} }
getRenderGenerator(renderArea: boolean, yOrientation: yAxisOrientation): any { getRenderGenerator(renderArea: AreaType, yOrientation: yAxisOrientation): Generator {
if(renderArea) { const yScale = yOrientation === yAxisOrientation.LEFT ? this.state.yScale : this.state.y1Scale;
return yOrientation === yAxisOrientation.LEFT ? this.areaGenerator : this.areaGeneratorY1; 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 { _renderDots(serie: LineTimeSerie): void {
@ -80,12 +111,12 @@ export class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
.attr('r', METRIC_CIRCLE_RADIUS) .attr('r', METRIC_CIRCLE_RADIUS)
.style('pointer-events', 'none') .style('pointer-events', 'none')
.attr('cx', d => this.state.xScale(d[0])) .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 { _renderLines(serie: LineTimeSerie, generator: Generator): void {
const fillColor = serie.renderArea ? serie.color : 'none'; const fillColor = serie.renderArea !== AreaType.NONE ? serie.color : 'none';
const fillOpacity = serie.renderArea ? 0.5 : 'none'; const fillOpacity = serie.renderArea !== AreaType.NONE ? 0.5 : 'none';
this.metricContainer this.metricContainer
.append('path') .append('path')
@ -98,12 +129,12 @@ export class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
.attr('stroke-opacity', 0.7) .attr('stroke-opacity', 0.7)
.attr('pointer-events', 'none') .attr('pointer-events', 'none')
.style('stroke-dasharray', serie.dashArray) .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) { if(serie.renderLines === true) {
this._renderLines(serie); this._renderLines(serie, generator);
} }
if(serie.renderDots === true) { if(serie.renderDots === true) {
@ -147,24 +178,16 @@ export class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
.style('pointer-events', 'none'); .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 { public hideSharedCrosshair(): void {
this.crosshair.style('display', 'none'); 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 { moveCrosshairLine(xPosition: number, yPosition: number): void {
this.crosshair.style('display', null);
switch(this.options.crosshair.orientation) { switch(this.options.crosshair.orientation) {
case CrosshairOrientation.VERTICAL: case CrosshairOrientation.VERTICAL:
this.crosshair.select('#crosshair-line-x') this.crosshair.select('#crosshair-line-x')
@ -269,18 +292,17 @@ export class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
return _.max(intervals); return _.max(intervals);
} }
onMouseMove(): void { getMouseObj(): MouseObj {
const eventX = d3.mouse(this.chartContainer.node())[0]; const eventX = d3.mouse(this.chartContainer.node())[0];
const eventY = d3.mouse(this.chartContainer.node())[1]; const eventY = d3.mouse(this.chartContainer.node())[1];
const xValue = this.state.xScale.invert(eventX); // mouse x position in xScale const xValue = this.state.xScale.invert(eventX); // mouse x position in xScale
const yValue = this.state.yScale.invert(eventY); const yValue = this.state.yScale.invert(eventY);
this.moveCrosshairLine(eventX, eventY);
const datapoints = this.findAndHighlightDatapoints(xValue, yValue); const datapoints = this.findAndHighlightDatapoints(xValue, yValue);
// TDOO: is shift key pressed // TODO: is shift key pressed
// TODO: need to refactor this object // TODO: need to refactor this object
this.options.callbackMouseMove({ return {
x: d3.event.pageX, x: d3.event.pageX,
y: d3.event.pageY, y: d3.event.pageY,
xVal: xValue, xVal: xValue,
@ -288,9 +310,40 @@ export class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
series: datapoints, series: datapoints,
chartX: eventX, chartX: eventX,
chartWidth: this.width 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 }[] { findAndHighlightDatapoints(xValue: number, yValue: number): { value: [number, number], color: string, label: string }[] {
if(!this.series.isSeriesAvailable) { if(!this.series.isSeriesAvailable) {
return []; return [];
@ -320,21 +373,45 @@ export class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
return points; return points;
} }
onMouseOver(): void { showCrosshair() {
this.crosshair.style('display', null); this.crosshair.style('display', null);
this.crosshair.selectAll('.crosshair-circle') this.crosshair.selectAll('.crosshair-circle')
.style('display', null); .style('display', null);
} }
onMouseOut(): void { hideCrosshair() {
this.options.callbackMouseOut();
this.crosshair.style('display', 'none'); 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 { isDoubleClickActive(): boolean {
return this.options.doubleClickEvent.isActive; 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) // methods below rewrite s, (move more methods here)
protected zoomOut(): void { protected zoomOut(): void {
if(d3.event.type === 'dblclick' && !this.isDoubleClickActive()) { if(d3.event.type === 'dblclick' && !this.isDoubleClickActive()) {
@ -376,13 +453,68 @@ export class LinePod extends ChartwerkPod<LineTimeSerie, LineOptions> {
x: xAxisMiddleValue, x: xAxisMiddleValue,
y: yAxisMiddleValue 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) // it is used with Vue.component, e.g.: Vue.component('chartwerk-line-pod', VueChartwerkLinePod)
export const VueChartwerkLinePod = { export const VueChartwerkLinePod = {
// alternative to `template: '<div class="chartwerk-line-pod" :id="id" />'` // 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) { render(createElement) {
return createElement( return createElement(
'div', 'div',
@ -396,10 +528,10 @@ export const VueChartwerkLinePod = {
methods: { methods: {
render() { render() {
if(this.pod === undefined) { 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(); this.pod.render();
} else { } else {
this.pod.updateData(this.series, this.options); this.pod.updateLineData(this.series, this.options, this.markersConf, this.segments);
} }
}, },
renderSharedCrosshair(values) { 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 { CoreSeries, yAxisOrientation } from '@chartwerk/core';
import { LineTimeSerie } from '../types'; import { LineTimeSerie, AreaType } from '../types';
import * as _ from 'lodash'; import * as _ from 'lodash';
@ -10,12 +10,11 @@ const LINE_SERIE_DEFAULTS = {
renderLines: true, renderLines: true,
dashArray: '0', dashArray: '0',
class: '', class: '',
renderArea: false, renderArea: AreaType.NONE,
yOrientation: yAxisOrientation.LEFT, yOrientation: yAxisOrientation.LEFT,
}; };
export class LineSeries extends CoreSeries<LineTimeSerie> { export class LineSeries extends CoreSeries<LineTimeSerie> {
constructor(series: LineTimeSerie[]) { constructor(series: LineTimeSerie[]) {
super(series, _.clone(LINE_SERIE_DEFAULTS)); 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 { Serie, Options } from '@chartwerk/core';
import { AxisRange } from '@chartwerk/core/dist/types';
type LineTimeSerieParams = { type LineTimeSerieParams = {
maxLength: number, maxLength: number;
renderDots: boolean, renderDots: boolean;
renderLines: boolean, // TODO: refactor same as scatter-pod renderLines: boolean; // TODO: refactor same as scatter-pod
dashArray: string; // dasharray attr, only for lines dashArray: string; // dasharray attr, only for lines
class: string; // option to add custom class to each serie element 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 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, "noImplicitUseStrict": false,
"noImplicitAny": false, "noImplicitAny": false,
"noUnusedLocals": false, "noUnusedLocals": false,
"baseUrl": "./src" "baseUrl": "./src",
} },
"include": ["src/**/*"]
} }

278
yarn.lock

@ -5,13 +5,13 @@ __metadata:
version: 6 version: 6
cacheKey: 8 cacheKey: 8
"@chartwerk/core@npm:latest": "@chartwerk/core@npm:^0.6.26":
version: 0.6.14 version: 0.6.26
resolution: "@chartwerk/core@npm:0.6.14" resolution: "@chartwerk/core@npm:0.6.26"
dependencies: dependencies:
d3: ^5.16.0 d3: ^5.16.0
lodash: ^4.17.21 lodash: ^4.17.21
checksum: 34888b555d91a96d5a279f43dc4b33f345d055574855e1c90cb22913f7e42b13b6c9abbd0af07e6531b6f872cdf8e04660c22a2c14938189b67b9c494c6a0bfb checksum: d77ef83701dc13cf2b7fb36dc96448060b6301928bcc0730a7150930f83c51f295e176bcda4e1b8cb8f56d15fef5696edfe6f4e1033adbb5ef5d3487a02c3390
languageName: node languageName: node
linkType: hard linkType: hard
@ -19,7 +19,8 @@ __metadata:
version: 0.0.0-use.local version: 0.0.0-use.local
resolution: "@chartwerk/line-pod@workspace:." resolution: "@chartwerk/line-pod@workspace:."
dependencies: dependencies:
"@chartwerk/core": latest "@chartwerk/core": ^0.6.26
copy-webpack-plugin: ^11.0.0
css-loader: ^6.8.1 css-loader: ^6.8.1
style-loader: ^3.3.3 style-loader: ^3.3.3
ts-loader: ^9.4.3 ts-loader: ^9.4.3
@ -95,6 +96,33 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "@types/eslint-scope@npm:^3.7.3":
version: 3.7.4 version: 3.7.4
resolution: "@types/eslint-scope@npm:3.7.4" resolution: "@types/eslint-scope@npm:3.7.4"
@ -129,6 +157,13 @@ __metadata:
languageName: node languageName: node
linkType: hard 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:*": "@types/node@npm:*":
version: 20.3.1 version: 20.3.1
resolution: "@types/node@npm:20.3.1" resolution: "@types/node@npm:20.3.1"
@ -352,6 +387,20 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "ajv-keywords@npm:^3.5.2":
version: 3.5.2 version: 3.5.2
resolution: "ajv-keywords@npm:3.5.2" resolution: "ajv-keywords@npm:3.5.2"
@ -361,6 +410,17 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "ajv@npm:^6.12.5":
version: 6.12.6 version: 6.12.6
resolution: "ajv@npm:6.12.6" resolution: "ajv@npm:6.12.6"
@ -373,6 +433,18 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "ansi-styles@npm:^4.1.0":
version: 4.3.0 version: 4.3.0
resolution: "ansi-styles@npm:4.3.0" resolution: "ansi-styles@npm:4.3.0"
@ -382,7 +454,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"braces@npm:^3.0.1": "braces@npm:^3.0.1, braces@npm:^3.0.2":
version: 3.0.2 version: 3.0.2
resolution: "braces@npm:3.0.2" resolution: "braces@npm:3.0.2"
dependencies: dependencies:
@ -484,6 +556,22 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "cross-spawn@npm:^7.0.3":
version: 7.0.3 version: 7.0.3
resolution: "cross-spawn@npm:7.0.3" resolution: "cross-spawn@npm:7.0.3"
@ -844,6 +932,15 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "electron-to-chromium@npm:^1.4.428":
version: 1.4.431 version: 1.4.431
resolution: "electron-to-chromium@npm:1.4.431" resolution: "electron-to-chromium@npm:1.4.431"
@ -924,13 +1021,26 @@ __metadata:
languageName: node languageName: node
linkType: hard 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 version: 3.1.3
resolution: "fast-deep-equal@npm:3.1.3" resolution: "fast-deep-equal@npm:3.1.3"
checksum: e21a9d8d84f53493b6aa15efc9cfd53dd5b714a1f23f67fb5dc8f574af80df889b3bce25dc081887c6d25457cce704e636395333abad896ccdec03abaf1f3f9d checksum: e21a9d8d84f53493b6aa15efc9cfd53dd5b714a1f23f67fb5dc8f574af80df889b3bce25dc081887c6d25457cce704e636395333abad896ccdec03abaf1f3f9d
languageName: node languageName: node
linkType: hard 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": "fast-json-stable-stringify@npm:^2.0.0":
version: 2.1.0 version: 2.1.0
resolution: "fast-json-stable-stringify@npm:2.1.0" resolution: "fast-json-stable-stringify@npm:2.1.0"
@ -945,6 +1055,15 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "fill-range@npm:^7.0.1":
version: 7.0.1 version: 7.0.1
resolution: "fill-range@npm:7.0.1" resolution: "fill-range@npm:7.0.1"
@ -971,6 +1090,24 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "glob-to-regexp@npm:^0.4.1":
version: 0.4.1 version: 0.4.1
resolution: "glob-to-regexp@npm:0.4.1" resolution: "glob-to-regexp@npm:0.4.1"
@ -978,6 +1115,19 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "graceful-fs@npm:^4.1.2":
version: 4.2.9 version: 4.2.9
resolution: "graceful-fs@npm:4.2.9" resolution: "graceful-fs@npm:4.2.9"
@ -1026,6 +1176,13 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "import-local@npm:^3.0.2":
version: 3.1.0 version: 3.1.0
resolution: "import-local@npm:3.1.0" resolution: "import-local@npm:3.1.0"
@ -1054,6 +1211,22 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "is-number@npm:^7.0.0":
version: 7.0.0 version: 7.0.0
resolution: "is-number@npm:7.0.0" resolution: "is-number@npm:7.0.0"
@ -1109,6 +1282,13 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "kind-of@npm:^6.0.2":
version: 6.0.3 version: 6.0.3
resolution: "kind-of@npm:6.0.3" resolution: "kind-of@npm:6.0.3"
@ -1155,6 +1335,13 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "micromatch@npm:^4.0.0":
version: 4.0.4 version: 4.0.4
resolution: "micromatch@npm:4.0.4" resolution: "micromatch@npm:4.0.4"
@ -1165,6 +1352,16 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "mime-db@npm:1.52.0":
version: 1.52.0 version: 1.52.0
resolution: "mime-db@npm:1.52.0" resolution: "mime-db@npm:1.52.0"
@ -1204,6 +1401,13 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "p-limit@npm:^2.2.0":
version: 2.3.0 version: 2.3.0
resolution: "p-limit@npm:2.3.0" resolution: "p-limit@npm:2.3.0"
@ -1250,6 +1454,13 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "picocolors@npm:^1.0.0":
version: 1.0.0 version: 1.0.0
resolution: "picocolors@npm:1.0.0" resolution: "picocolors@npm:1.0.0"
@ -1257,7 +1468,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"picomatch@npm:^2.2.3": "picomatch@npm:^2.2.3, picomatch@npm:^2.3.1":
version: 2.3.1 version: 2.3.1
resolution: "picomatch@npm:2.3.1" resolution: "picomatch@npm:2.3.1"
checksum: 050c865ce81119c4822c45d3c84f1ced46f93a0126febae20737bd05ca20589c564d6e9226977df859ed5e03dc73f02584a2b0faad36e896936238238b0446cf checksum: 050c865ce81119c4822c45d3c84f1ced46f93a0126febae20737bd05ca20589c564d6e9226977df859ed5e03dc73f02584a2b0faad36e896936238238b0446cf
@ -1362,6 +1573,13 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "randombytes@npm:^2.1.0":
version: 2.1.0 version: 2.1.0
resolution: "randombytes@npm:2.1.0" resolution: "randombytes@npm:2.1.0"
@ -1380,6 +1598,13 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "resolve-cwd@npm:^3.0.0":
version: 3.0.0 version: 3.0.0
resolution: "resolve-cwd@npm:3.0.0" resolution: "resolve-cwd@npm:3.0.0"
@ -1422,6 +1647,22 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "rw@npm:1":
version: 1.3.3 version: 1.3.3
resolution: "rw@npm:1.3.3" resolution: "rw@npm:1.3.3"
@ -1454,6 +1695,18 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "semver@npm:^7.3.4, semver@npm:^7.3.8":
version: 7.5.1 version: 7.5.1
resolution: "semver@npm:7.5.1" resolution: "semver@npm:7.5.1"
@ -1465,7 +1718,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"serialize-javascript@npm:^6.0.1": "serialize-javascript@npm:^6.0.0, serialize-javascript@npm:^6.0.1":
version: 6.0.1 version: 6.0.1
resolution: "serialize-javascript@npm:6.0.1" resolution: "serialize-javascript@npm:6.0.1"
dependencies: dependencies:
@ -1499,6 +1752,13 @@ __metadata:
languageName: node languageName: node
linkType: hard 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": "source-map-js@npm:^1.0.2":
version: 1.0.2 version: 1.0.2
resolution: "source-map-js@npm:1.0.2" resolution: "source-map-js@npm:1.0.2"

Loading…
Cancel
Save