layerchart 0.0.1 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -37
- package/components/Arc.svelte +77 -0
- package/components/Arc.svelte.d.ts +34 -0
- package/components/Area.svelte +47 -0
- package/components/Area.svelte.d.ts +31 -0
- package/components/AreaStack.svelte +40 -0
- package/components/AreaStack.svelte.d.ts +20 -0
- package/components/AxisX.svelte +52 -0
- package/components/AxisX.svelte.d.ts +23 -0
- package/components/AxisY.svelte +66 -0
- package/components/AxisY.svelte.d.ts +23 -0
- package/components/Bars.svelte +102 -0
- package/components/Bars.svelte.d.ts +35 -0
- package/components/Baseline.svelte +21 -0
- package/components/Baseline.svelte.d.ts +17 -0
- package/components/Chart.svelte +50 -0
- package/components/Chart.svelte.d.ts +24 -0
- package/components/Circle.svelte +15 -0
- package/components/Circle.svelte.d.ts +22 -0
- package/components/ConnectedPoints.svelte +68 -0
- package/components/ConnectedPoints.svelte.d.ts +18 -0
- package/components/Group.svelte +26 -0
- package/components/Group.svelte.d.ts +21 -0
- package/components/HighlightLine.svelte +52 -0
- package/components/HighlightLine.svelte.d.ts +17 -0
- package/components/HighlightRect.svelte +27 -0
- package/components/HighlightRect.svelte.d.ts +18 -0
- package/components/Labels.svelte +96 -0
- package/components/Labels.svelte.d.ts +22 -0
- package/components/Line.svelte +18 -0
- package/components/Line.svelte.d.ts +23 -0
- package/components/LinearGradient.svelte +27 -0
- package/components/LinearGradient.svelte.d.ts +27 -0
- package/components/Path.svelte +40 -0
- package/components/Path.svelte.d.ts +27 -0
- package/components/Points.svelte +58 -0
- package/components/Points.svelte.d.ts +19 -0
- package/components/Rect.svelte +25 -0
- package/components/Rect.svelte.d.ts +25 -0
- package/components/Text.svelte +129 -0
- package/components/Text.svelte.d.ts +28 -0
- package/components/Threshold.svelte +86 -0
- package/components/Threshold.svelte.d.ts +35 -0
- package/components/Tooltip.svelte +120 -0
- package/components/Tooltip.svelte.d.ts +33 -0
- package/components/index.d.ts +19 -0
- package/components/index.js +19 -0
- package/docs/Blockquote.svelte +7 -0
- package/docs/Blockquote.svelte.d.ts +23 -0
- package/docs/Code.svelte +6 -0
- package/docs/Code.svelte.d.ts +23 -0
- package/docs/Layout.svelte +20 -0
- package/docs/Layout.svelte.d.ts +29 -0
- package/docs/Link.svelte +7 -0
- package/docs/Link.svelte.d.ts +27 -0
- package/docs/Preview.svelte +23 -0
- package/docs/Preview.svelte.d.ts +21 -0
- package/index.d.ts +3 -0
- package/index.js +3 -0
- package/package.json +84 -26
- package/stores/motionStore.d.ts +8 -0
- package/stores/motionStore.js +16 -0
- package/utils/event.d.ts +4 -0
- package/utils/event.js +42 -0
- package/utils/genData.d.ts +32 -0
- package/utils/genData.js +59 -0
- package/utils/index.d.ts +1 -0
- package/utils/index.js +1 -0
- package/utils/math.d.ts +4 -0
- package/utils/math.js +6 -0
- package/utils/path.d.ts +5 -0
- package/utils/path.js +14 -0
- package/utils/pivot.d.ts +14 -0
- package/utils/pivot.js +36 -0
- package/utils/scales.d.ts +10 -0
- package/utils/scales.js +21 -0
- package/utils/stack.d.ts +14 -0
- package/utils/stack.js +69 -0
- package/utils/string.d.ts +4 -0
- package/utils/string.js +27 -0
- package/utils/ticks.d.ts +3 -0
- package/utils/ticks.js +157 -0
- package/.prettierrc +0 -6
- package/src/app.html +0 -12
- package/src/global.d.ts +0 -1
- package/src/routes/index.svelte +0 -2
- package/static/favicon.png +0 -0
- package/svelte.config.js +0 -15
- package/tsconfig.json +0 -31
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
[x: string]: any;
|
|
5
|
+
r?: number;
|
|
6
|
+
offsetX?: number | ((value: number, context: any) => number);
|
|
7
|
+
offsetY?: number | ((value: number, context: any) => number);
|
|
8
|
+
};
|
|
9
|
+
events: {
|
|
10
|
+
[evt: string]: CustomEvent<any>;
|
|
11
|
+
};
|
|
12
|
+
slots: {};
|
|
13
|
+
};
|
|
14
|
+
export declare type PointsProps = typeof __propDef.props;
|
|
15
|
+
export declare type PointsEvents = typeof __propDef.events;
|
|
16
|
+
export declare type PointsSlots = typeof __propDef.slots;
|
|
17
|
+
export default class Points extends SvelteComponentTyped<PointsProps, PointsEvents, PointsSlots> {
|
|
18
|
+
}
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
<script >import { getMotionStore } from '../stores/motionStore';
|
|
2
|
+
export let x;
|
|
3
|
+
export let y;
|
|
4
|
+
export let width;
|
|
5
|
+
export let height;
|
|
6
|
+
export let spring = undefined;
|
|
7
|
+
export let tweened = undefined;
|
|
8
|
+
let tweened_x = getMotionStore(x, { spring, tweened });
|
|
9
|
+
let tweened_y = getMotionStore(y, { spring, tweened });
|
|
10
|
+
let tweened_width = getMotionStore(width, { spring, tweened });
|
|
11
|
+
let tweened_height = getMotionStore(height, { spring, tweened });
|
|
12
|
+
$: tweened_x.set(x);
|
|
13
|
+
$: tweened_y.set(y);
|
|
14
|
+
$: tweened_width.set(width);
|
|
15
|
+
$: tweened_height.set(height);
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<rect
|
|
19
|
+
x={$tweened_x}
|
|
20
|
+
y={$tweened_y}
|
|
21
|
+
width={$tweened_width}
|
|
22
|
+
height={$tweened_height}
|
|
23
|
+
{...$$restProps}
|
|
24
|
+
on:click
|
|
25
|
+
/>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import type { spring as springStore, tweened as tweenedStore } from 'svelte/motion';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
[x: string]: any;
|
|
6
|
+
x: number;
|
|
7
|
+
y: number;
|
|
8
|
+
width: number;
|
|
9
|
+
height: number;
|
|
10
|
+
spring?: boolean | Parameters<typeof springStore>[1];
|
|
11
|
+
tweened?: boolean | Parameters<typeof tweenedStore>[1];
|
|
12
|
+
};
|
|
13
|
+
events: {
|
|
14
|
+
click: MouseEvent;
|
|
15
|
+
} & {
|
|
16
|
+
[evt: string]: CustomEvent<any>;
|
|
17
|
+
};
|
|
18
|
+
slots: {};
|
|
19
|
+
};
|
|
20
|
+
export declare type RectProps = typeof __propDef.props;
|
|
21
|
+
export declare type RectEvents = typeof __propDef.events;
|
|
22
|
+
export declare type RectSlots = typeof __propDef.slots;
|
|
23
|
+
export default class Rect extends SvelteComponentTyped<RectProps, RectEvents, RectSlots> {
|
|
24
|
+
}
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
<script >import { getStringWidth } from '../utils/string';
|
|
2
|
+
/*
|
|
3
|
+
TODO:
|
|
4
|
+
- [ ] Handle styled text (use <slot /> to measure?)
|
|
5
|
+
|
|
6
|
+
Reference:
|
|
7
|
+
- https://bl.ocks.org/mbostock/7555321
|
|
8
|
+
- https://github.com/airbnb/visx/blob/master/packages/visx-text/src/Text.tsx
|
|
9
|
+
- https://airbnb.io/visx/text
|
|
10
|
+
- https://github.com/airbnb/visx/blob/master/packages/visx-demo/src/pages/text.tsx
|
|
11
|
+
*/
|
|
12
|
+
/** text value */
|
|
13
|
+
export let value = 0;
|
|
14
|
+
/** Maximum width to occupy (approximate as words are not split). */
|
|
15
|
+
export let width = undefined;
|
|
16
|
+
/** x position of the text. */
|
|
17
|
+
export let x = 0;
|
|
18
|
+
/** y position of the text. */
|
|
19
|
+
export let y = 0;
|
|
20
|
+
/** dx offset of the text. */
|
|
21
|
+
export let dx = 0;
|
|
22
|
+
/** dy offset of the text. */
|
|
23
|
+
export let dy = 0;
|
|
24
|
+
/** Desired "line height" of the text, implemented as y offsets. */
|
|
25
|
+
export let lineHeight = '1em';
|
|
26
|
+
/** Cap height of the text. */
|
|
27
|
+
export let capHeight = '0.71em'; // Magic number from d3
|
|
28
|
+
/** Whether to scale the fontSize to accommodate the specified width. */
|
|
29
|
+
export let scaleToFit = false;
|
|
30
|
+
/** Horizontal text anchor. */
|
|
31
|
+
export let textAnchor = 'start';
|
|
32
|
+
/** Vertical text anchor. */
|
|
33
|
+
export let verticalAnchor = 'end'; // default SVG behavior
|
|
34
|
+
/** Rotational angle of the text. */
|
|
35
|
+
export let rotate = undefined;
|
|
36
|
+
let wordsByLines = [];
|
|
37
|
+
let wordsWithWidth = [];
|
|
38
|
+
let spaceWidth = 0;
|
|
39
|
+
let style = undefined; // TODO: read from DOM?
|
|
40
|
+
$: words = value ? value.toString().split(/(?:(?!\u00A0+)\s+)/) : [];
|
|
41
|
+
$: wordsWithWidth = words.map((word) => ({
|
|
42
|
+
word,
|
|
43
|
+
width: getStringWidth(word, style) || 0
|
|
44
|
+
}));
|
|
45
|
+
$: spaceWidth = getStringWidth('\u00A0', style) || 0;
|
|
46
|
+
$: wordsByLines = wordsWithWidth.reduce((result, item) => {
|
|
47
|
+
const currentLine = result[result.length - 1];
|
|
48
|
+
if (currentLine &&
|
|
49
|
+
(width == null || scaleToFit || (currentLine.width || 0) + item.width + spaceWidth < width)) {
|
|
50
|
+
// Word can be added to an existing line
|
|
51
|
+
currentLine.words.push(item.word);
|
|
52
|
+
currentLine.width = currentLine.width || 0;
|
|
53
|
+
currentLine.width += item.width + spaceWidth;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// Add first word to line or word is too long to scaleToFit on existing line
|
|
57
|
+
const newLine = { words: [item.word], width: item.width };
|
|
58
|
+
result.push(newLine);
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
}, []);
|
|
62
|
+
$: lines = wordsByLines.length;
|
|
63
|
+
/**
|
|
64
|
+
* Convert css value to pixel value (ex. 0.71em => 11.36)
|
|
65
|
+
*/
|
|
66
|
+
function getPixelValue(cssValue) {
|
|
67
|
+
// TODO: Properly measure pixel values using DOM (handle inherited font size, zoom, etc)
|
|
68
|
+
// console.log(cssValue);
|
|
69
|
+
const [match, value, units] = cssValue.match(/([\d.]+)(\D+)/);
|
|
70
|
+
// console.log({ value, units });
|
|
71
|
+
const number = Number(value);
|
|
72
|
+
switch (units) {
|
|
73
|
+
case 'px':
|
|
74
|
+
return number;
|
|
75
|
+
case 'em':
|
|
76
|
+
case 'rem':
|
|
77
|
+
return number * 16;
|
|
78
|
+
default:
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
let startDy = 0;
|
|
83
|
+
$: if (verticalAnchor === 'start') {
|
|
84
|
+
startDy = getPixelValue(capHeight);
|
|
85
|
+
}
|
|
86
|
+
else if (verticalAnchor === 'middle') {
|
|
87
|
+
startDy = ((lines - 1) / 2) * -getPixelValue(lineHeight) + getPixelValue(capHeight) / 2;
|
|
88
|
+
}
|
|
89
|
+
else {
|
|
90
|
+
startDy = (lines - 1) * -getPixelValue(lineHeight);
|
|
91
|
+
}
|
|
92
|
+
let scaleTransform = '';
|
|
93
|
+
$: if (scaleToFit &&
|
|
94
|
+
lines > 0 &&
|
|
95
|
+
typeof x == 'number' &&
|
|
96
|
+
typeof y == 'number' &&
|
|
97
|
+
typeof width == 'number') {
|
|
98
|
+
const lineWidth = wordsByLines[0].width || 1;
|
|
99
|
+
const sx = width / lineWidth;
|
|
100
|
+
const sy = sx;
|
|
101
|
+
const originX = x - sx * x;
|
|
102
|
+
const originY = y - sy * y;
|
|
103
|
+
scaleTransform = `matrix(${sx}, 0, 0, ${sy}, ${originX}, ${originY})`;
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
scaleTransform = '';
|
|
107
|
+
}
|
|
108
|
+
$: rotateTransform = rotate ? `rotate(${rotate}, ${x}, ${y})` : '';
|
|
109
|
+
$: transform = `${scaleTransform} ${rotateTransform}`;
|
|
110
|
+
function isValidXOrY(xOrY) {
|
|
111
|
+
return (
|
|
112
|
+
// number that is not NaN or Infinity
|
|
113
|
+
(typeof xOrY === 'number' && Number.isFinite(xOrY)) ||
|
|
114
|
+
// for percentage
|
|
115
|
+
typeof xOrY === 'string');
|
|
116
|
+
}
|
|
117
|
+
</script>
|
|
118
|
+
|
|
119
|
+
<svg x={dx} y={dy} style="overflow: visible">
|
|
120
|
+
{#if isValidXOrY(x) && isValidXOrY(y)}
|
|
121
|
+
<text {x} {y} {transform} text-anchor={textAnchor} {...$$restProps}>
|
|
122
|
+
{#each wordsByLines as line, index}
|
|
123
|
+
<tspan {x} dy={index === 0 ? startDy : lineHeight}>
|
|
124
|
+
{line.words.join(' ')}
|
|
125
|
+
</tspan>
|
|
126
|
+
{/each}
|
|
127
|
+
</text>
|
|
128
|
+
{/if}
|
|
129
|
+
</svg>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
[x: string]: any;
|
|
5
|
+
value?: string | number;
|
|
6
|
+
width?: number;
|
|
7
|
+
x?: string | number;
|
|
8
|
+
y?: string | number;
|
|
9
|
+
dx?: string | number;
|
|
10
|
+
dy?: string | number;
|
|
11
|
+
lineHeight?: string;
|
|
12
|
+
capHeight?: string;
|
|
13
|
+
scaleToFit?: boolean;
|
|
14
|
+
textAnchor?: 'start' | 'middle' | 'end' | 'inherit';
|
|
15
|
+
verticalAnchor?: 'start' | 'middle' | 'end' | 'inherit';
|
|
16
|
+
rotate?: number;
|
|
17
|
+
};
|
|
18
|
+
events: {
|
|
19
|
+
[evt: string]: CustomEvent<any>;
|
|
20
|
+
};
|
|
21
|
+
slots: {};
|
|
22
|
+
};
|
|
23
|
+
export declare type TextProps = typeof __propDef.props;
|
|
24
|
+
export declare type TextEvents = typeof __propDef.events;
|
|
25
|
+
export declare type TextSlots = typeof __propDef.slots;
|
|
26
|
+
export default class Text extends SvelteComponentTyped<TextProps, TextEvents, TextSlots> {
|
|
27
|
+
}
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
<script >/*
|
|
2
|
+
See also:
|
|
3
|
+
- https://observablehq.com/@d3/difference-chart
|
|
4
|
+
- https://github.com/airbnb/visx/issues/245
|
|
5
|
+
*/
|
|
6
|
+
import { getContext } from 'svelte';
|
|
7
|
+
import { area as d3Area, line as d3Line } from 'd3-shape';
|
|
8
|
+
const { data: contextData, xGet, yGet, yRange } = getContext('LayerCake');
|
|
9
|
+
// Properties to override what is used from context
|
|
10
|
+
export let data = undefined; // TODO: Update Type
|
|
11
|
+
export let x = undefined; // TODO: Update Type
|
|
12
|
+
export let y0 = undefined; // TODO: Update Type
|
|
13
|
+
export let y1 = undefined; // TODO: Update Type
|
|
14
|
+
export let curve = undefined;
|
|
15
|
+
export let defined = undefined;
|
|
16
|
+
export let id = Math.random().toString(16).slice(-4);
|
|
17
|
+
$: areaPath = d3Area()
|
|
18
|
+
.x(x ?? $xGet)
|
|
19
|
+
.y0(y0 ?? ((d) => $yGet(d)[0]))
|
|
20
|
+
.y1(y1 ?? ((d) => $yGet(d)[1]));
|
|
21
|
+
$: if (curve)
|
|
22
|
+
areaPath.curve(curve);
|
|
23
|
+
$: if (defined)
|
|
24
|
+
areaPath.defined(defined);
|
|
25
|
+
$: clipPathBelow = d3Area()
|
|
26
|
+
.x(x ?? $xGet)
|
|
27
|
+
.y0(y0 ?? ((d) => $yGet(d)[0]))
|
|
28
|
+
.y1(y1 ?? ((d) => $yRange[0]));
|
|
29
|
+
$: if (curve)
|
|
30
|
+
clipPathBelow.curve(curve);
|
|
31
|
+
$: if (defined)
|
|
32
|
+
clipPathBelow.defined(defined);
|
|
33
|
+
$: clipPathAbove = d3Area()
|
|
34
|
+
.x(x ?? $xGet)
|
|
35
|
+
.y0(y0 ?? ((d) => $yRange[0]))
|
|
36
|
+
.y1(y1 ?? ((d) => $yGet(d)[1]));
|
|
37
|
+
$: if (curve)
|
|
38
|
+
clipPathAbove.curve(curve);
|
|
39
|
+
$: if (defined)
|
|
40
|
+
clipPathAbove.defined(defined);
|
|
41
|
+
$: linePathAbove = d3Line()
|
|
42
|
+
.x(x ?? $xGet)
|
|
43
|
+
.y(y0 ?? ((d) => $yGet(d)[0]));
|
|
44
|
+
$: if (curve)
|
|
45
|
+
linePathAbove.curve(curve);
|
|
46
|
+
$: if (defined)
|
|
47
|
+
linePathAbove.defined(defined);
|
|
48
|
+
$: linePathBelow = d3Line()
|
|
49
|
+
.x(x ?? $xGet)
|
|
50
|
+
.y(y1 ?? ((d) => $yGet(d)[1]));
|
|
51
|
+
$: if (curve)
|
|
52
|
+
linePathBelow.curve(curve);
|
|
53
|
+
$: if (defined)
|
|
54
|
+
linePathBelow.defined(defined);
|
|
55
|
+
</script>
|
|
56
|
+
|
|
57
|
+
<!-- Recreate on curve change as otherwise is 1 state change behind for some reason -->
|
|
58
|
+
{#key curve}
|
|
59
|
+
<g class="clip-paths">
|
|
60
|
+
<defs>
|
|
61
|
+
<clipPath id="threshold-clip-below-{id}">
|
|
62
|
+
<path d={clipPathBelow(data ?? $contextData)} />
|
|
63
|
+
</clipPath>
|
|
64
|
+
<clipPath id="threshold-clip-above-{id}">
|
|
65
|
+
<path d={clipPathAbove(data ?? $contextData)} />
|
|
66
|
+
</clipPath>
|
|
67
|
+
</defs>
|
|
68
|
+
</g>
|
|
69
|
+
|
|
70
|
+
<slot
|
|
71
|
+
name="pathAbove"
|
|
72
|
+
areaPathData={areaPath(data ?? $contextData)}
|
|
73
|
+
clipPath="url(#threshold-clip-below-{id})"
|
|
74
|
+
linePathData={linePathAbove(data ?? $contextData)}
|
|
75
|
+
/>
|
|
76
|
+
|
|
77
|
+
<slot
|
|
78
|
+
name="pathBelow"
|
|
79
|
+
areaPathData={areaPath(data ?? $contextData)}
|
|
80
|
+
clipPath="url(#threshold-clip-above-{id})"
|
|
81
|
+
linePathData={linePathBelow(data ?? $contextData)}
|
|
82
|
+
/>
|
|
83
|
+
{/key}
|
|
84
|
+
|
|
85
|
+
<!-- Fix `<Threshold> received an unexpected slot "default".` warning -->
|
|
86
|
+
<slot />
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
import type { CurveFactory } from 'd3-shape';
|
|
3
|
+
declare const __propDef: {
|
|
4
|
+
props: {
|
|
5
|
+
data?: any;
|
|
6
|
+
x?: any;
|
|
7
|
+
y0?: any;
|
|
8
|
+
y1?: any;
|
|
9
|
+
curve?: CurveFactory;
|
|
10
|
+
defined?: (d: [number, number], index: number, data: [number, number][]) => boolean;
|
|
11
|
+
id?: string;
|
|
12
|
+
};
|
|
13
|
+
events: {
|
|
14
|
+
[evt: string]: CustomEvent<any>;
|
|
15
|
+
};
|
|
16
|
+
slots: {
|
|
17
|
+
pathAbove: {
|
|
18
|
+
areaPathData: string;
|
|
19
|
+
clipPath: string;
|
|
20
|
+
linePathData: string;
|
|
21
|
+
};
|
|
22
|
+
pathBelow: {
|
|
23
|
+
areaPathData: string;
|
|
24
|
+
clipPath: string;
|
|
25
|
+
linePathData: string;
|
|
26
|
+
};
|
|
27
|
+
default: {};
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
export declare type ThresholdProps = typeof __propDef.props;
|
|
31
|
+
export declare type ThresholdEvents = typeof __propDef.events;
|
|
32
|
+
export declare type ThresholdSlots = typeof __propDef.slots;
|
|
33
|
+
export default class Threshold extends SvelteComponentTyped<ThresholdProps, ThresholdEvents, ThresholdSlots> {
|
|
34
|
+
}
|
|
35
|
+
export {};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
<script >import { getContext, createEventDispatcher } from 'svelte';
|
|
2
|
+
import { spring } from 'svelte/motion';
|
|
3
|
+
import { fade } from 'svelte/transition';
|
|
4
|
+
import { writable } from 'svelte/store';
|
|
5
|
+
import { bisector } from 'd3-array';
|
|
6
|
+
import { Svg, Html } from './Chart.svelte';
|
|
7
|
+
import { localPoint } from '../utils/event';
|
|
8
|
+
import { isScaleBand, scaleBandInvert } from '../utils/scales';
|
|
9
|
+
const dispatch = createEventDispatcher();
|
|
10
|
+
const { flatData, x, xScale, xGet, yScale, yGet, width, height, padding } = getContext('LayerCake');
|
|
11
|
+
export let snapToDataX = false;
|
|
12
|
+
export let snapToDataY = false;
|
|
13
|
+
export let findTooltipData = 'closest';
|
|
14
|
+
export let topOffset = 10;
|
|
15
|
+
export let leftOffset = 10;
|
|
16
|
+
export let contained = 'container'; // TODO: Support 'window' using getBoundingClientRect()
|
|
17
|
+
export let animate = true;
|
|
18
|
+
let tooltip = null;
|
|
19
|
+
let tooltipWidth = 0;
|
|
20
|
+
let tooltipHeight = 0;
|
|
21
|
+
let top = animate ? spring(0) : writable(0);
|
|
22
|
+
$: if (tooltip) {
|
|
23
|
+
const containerHeight = $height + $padding.bottom;
|
|
24
|
+
if (contained === 'container' && tooltip.top + topOffset + tooltipHeight > containerHeight) {
|
|
25
|
+
// change side
|
|
26
|
+
$top = tooltip.top - (topOffset + tooltipHeight);
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
$top = tooltip.top + topOffset;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
let left = animate ? spring(0) : writable(0);
|
|
33
|
+
$: if (tooltip) {
|
|
34
|
+
const containerWidth = $width + $padding.right;
|
|
35
|
+
if (contained === 'container' && tooltip.left + leftOffset + tooltipWidth > containerWidth) {
|
|
36
|
+
// change side
|
|
37
|
+
$left = tooltip.left - (leftOffset + tooltipWidth);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
$left = tooltip.left + leftOffset;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function handleTooltip(event) {
|
|
44
|
+
const point = localPoint(event.target, event);
|
|
45
|
+
const localX = point?.x ?? 0;
|
|
46
|
+
const localY = point?.y ?? 0;
|
|
47
|
+
let tooltipData;
|
|
48
|
+
if (isScaleBand($xScale)) {
|
|
49
|
+
// `x` value at mouse coordinate
|
|
50
|
+
const xValue = scaleBandInvert($xScale)(localX);
|
|
51
|
+
tooltipData = $flatData.find((d) => $x(d) === xValue);
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
// `x` value at mouse coordinate
|
|
55
|
+
const xValue = $xScale.invert(localX);
|
|
56
|
+
const bisectX = bisector($x).left;
|
|
57
|
+
const index = bisectX($flatData, xValue, 1);
|
|
58
|
+
const data0 = $flatData[index - 1];
|
|
59
|
+
const data1 = $flatData[index];
|
|
60
|
+
switch (findTooltipData) {
|
|
61
|
+
case 'closest':
|
|
62
|
+
tooltipData =
|
|
63
|
+
Number(xValue) - Number($x(data0)) > Number($x(data1)) - Number(xValue) ? data1 : data0;
|
|
64
|
+
break;
|
|
65
|
+
case 'left':
|
|
66
|
+
tooltipData = data0;
|
|
67
|
+
break;
|
|
68
|
+
case 'right':
|
|
69
|
+
default:
|
|
70
|
+
tooltipData = data1;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (tooltipData) {
|
|
74
|
+
tooltip = {
|
|
75
|
+
left: snapToDataX ? $xGet(tooltipData) : localX,
|
|
76
|
+
top: snapToDataY ? $yGet(tooltipData) : localY,
|
|
77
|
+
data: tooltipData
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function hideTooltip(event) {
|
|
82
|
+
tooltip = null;
|
|
83
|
+
}
|
|
84
|
+
</script>
|
|
85
|
+
|
|
86
|
+
<Html>
|
|
87
|
+
<div
|
|
88
|
+
class="absolute"
|
|
89
|
+
style="width: {$width}px; height: {$height}px; background: _red; z-index: 9999"
|
|
90
|
+
on:touchstart={handleTooltip}
|
|
91
|
+
on:touchmove={handleTooltip}
|
|
92
|
+
on:mousemove={handleTooltip}
|
|
93
|
+
on:mouseleave={hideTooltip}
|
|
94
|
+
on:click={(e) => {
|
|
95
|
+
dispatch('click', { data: tooltip?.data });
|
|
96
|
+
}}
|
|
97
|
+
/>
|
|
98
|
+
</Html>
|
|
99
|
+
|
|
100
|
+
{#if tooltip}
|
|
101
|
+
<Html>
|
|
102
|
+
<div
|
|
103
|
+
class="absolute pointer-events-none z-50"
|
|
104
|
+
style="
|
|
105
|
+
top: {$top}px;
|
|
106
|
+
left: {$left}px;
|
|
107
|
+
max-width: {$width / 2}px;
|
|
108
|
+
"
|
|
109
|
+
transition:fade={{ duration: 100 }}
|
|
110
|
+
bind:clientWidth={tooltipWidth}
|
|
111
|
+
bind:clientHeight={tooltipHeight}
|
|
112
|
+
>
|
|
113
|
+
<slot data={tooltip?.data} />
|
|
114
|
+
</div>
|
|
115
|
+
</Html>
|
|
116
|
+
|
|
117
|
+
<Svg>
|
|
118
|
+
<slot name="highlight" data={tooltip?.data} />
|
|
119
|
+
</Svg>
|
|
120
|
+
{/if}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { SvelteComponentTyped } from "svelte";
|
|
2
|
+
declare const __propDef: {
|
|
3
|
+
props: {
|
|
4
|
+
snapToDataX?: boolean;
|
|
5
|
+
snapToDataY?: boolean;
|
|
6
|
+
findTooltipData?: 'closest' | 'left' | 'right';
|
|
7
|
+
topOffset?: number;
|
|
8
|
+
leftOffset?: number;
|
|
9
|
+
contained?: 'container' | false;
|
|
10
|
+
animate?: boolean;
|
|
11
|
+
};
|
|
12
|
+
events: {
|
|
13
|
+
click: CustomEvent<{
|
|
14
|
+
data: any;
|
|
15
|
+
}>;
|
|
16
|
+
} & {
|
|
17
|
+
[evt: string]: CustomEvent<any>;
|
|
18
|
+
};
|
|
19
|
+
slots: {
|
|
20
|
+
default: {
|
|
21
|
+
data: any;
|
|
22
|
+
};
|
|
23
|
+
highlight: {
|
|
24
|
+
data: any;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
export declare type TooltipProps = typeof __propDef.props;
|
|
29
|
+
export declare type TooltipEvents = typeof __propDef.events;
|
|
30
|
+
export declare type TooltipSlots = typeof __propDef.slots;
|
|
31
|
+
export default class Tooltip extends SvelteComponentTyped<TooltipProps, TooltipEvents, TooltipSlots> {
|
|
32
|
+
}
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export { default as Area } from './Area.svelte';
|
|
2
|
+
export { default as AreaStack } from './AreaStack.svelte';
|
|
3
|
+
export { default as AxisX } from './AxisX.svelte';
|
|
4
|
+
export { default as AxisY } from './AxisY.svelte';
|
|
5
|
+
export { default as Bars } from './Bars.svelte';
|
|
6
|
+
export { default as Baseline } from './Baseline.svelte';
|
|
7
|
+
export { default as Chart } from './Chart.svelte';
|
|
8
|
+
export { default as Circle } from './Circle.svelte';
|
|
9
|
+
export { default as ClevelandDotPlot } from './ClevelandDotPlot.svelte';
|
|
10
|
+
export { default as HighlightRect } from './HighlightRect.svelte';
|
|
11
|
+
export { default as HighlightLine } from './HighlightLine.svelte';
|
|
12
|
+
export { default as Labels } from './Labels.svelte';
|
|
13
|
+
export { default as Line } from './Line.svelte';
|
|
14
|
+
export { default as Path } from './Path.svelte';
|
|
15
|
+
export { default as Rect } from './Rect.svelte';
|
|
16
|
+
export { default as Scatter } from './Scatter.svelte';
|
|
17
|
+
export { default as Text } from './Text.svelte';
|
|
18
|
+
export { default as Threshold } from './Threshold.svelte';
|
|
19
|
+
export { default as Tooltip } from './Tooltip.svelte';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export { default as Area } from './Area.svelte';
|
|
2
|
+
export { default as AreaStack } from './AreaStack.svelte';
|
|
3
|
+
export { default as AxisX } from './AxisX.svelte';
|
|
4
|
+
export { default as AxisY } from './AxisY.svelte';
|
|
5
|
+
export { default as Bars } from './Bars.svelte';
|
|
6
|
+
export { default as Baseline } from './Baseline.svelte';
|
|
7
|
+
export { default as Chart } from './Chart.svelte';
|
|
8
|
+
export { default as Circle } from './Circle.svelte';
|
|
9
|
+
export { default as ClevelandDotPlot } from './ClevelandDotPlot.svelte';
|
|
10
|
+
export { default as HighlightRect } from './HighlightRect.svelte';
|
|
11
|
+
export { default as HighlightLine } from './HighlightLine.svelte';
|
|
12
|
+
export { default as Labels } from './Labels.svelte';
|
|
13
|
+
export { default as Line } from './Line.svelte';
|
|
14
|
+
export { default as Path } from './Path.svelte';
|
|
15
|
+
export { default as Rect } from './Rect.svelte';
|
|
16
|
+
export { default as Scatter } from './Scatter.svelte';
|
|
17
|
+
export { default as Text } from './Text.svelte';
|
|
18
|
+
export { default as Threshold } from './Threshold.svelte';
|
|
19
|
+
export { default as Tooltip } from './Tooltip.svelte';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** @typedef {typeof __propDef.props} BlockquoteProps */
|
|
2
|
+
/** @typedef {typeof __propDef.events} BlockquoteEvents */
|
|
3
|
+
/** @typedef {typeof __propDef.slots} BlockquoteSlots */
|
|
4
|
+
export default class Blockquote extends SvelteComponentTyped<{}, {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
}, {
|
|
7
|
+
default: {};
|
|
8
|
+
}> {
|
|
9
|
+
}
|
|
10
|
+
export type BlockquoteProps = typeof __propDef.props;
|
|
11
|
+
export type BlockquoteEvents = typeof __propDef.events;
|
|
12
|
+
export type BlockquoteSlots = typeof __propDef.slots;
|
|
13
|
+
import { SvelteComponentTyped } from "svelte";
|
|
14
|
+
declare const __propDef: {
|
|
15
|
+
props: {};
|
|
16
|
+
events: {
|
|
17
|
+
[evt: string]: CustomEvent<any>;
|
|
18
|
+
};
|
|
19
|
+
slots: {
|
|
20
|
+
default: {};
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
export {};
|
package/docs/Code.svelte
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/** @typedef {typeof __propDef.props} CodeProps */
|
|
2
|
+
/** @typedef {typeof __propDef.events} CodeEvents */
|
|
3
|
+
/** @typedef {typeof __propDef.slots} CodeSlots */
|
|
4
|
+
export default class Code extends SvelteComponentTyped<{}, {
|
|
5
|
+
[evt: string]: CustomEvent<any>;
|
|
6
|
+
}, {
|
|
7
|
+
default: {};
|
|
8
|
+
}> {
|
|
9
|
+
}
|
|
10
|
+
export type CodeProps = typeof __propDef.props;
|
|
11
|
+
export type CodeEvents = typeof __propDef.events;
|
|
12
|
+
export type CodeSlots = typeof __propDef.slots;
|
|
13
|
+
import { SvelteComponentTyped } from "svelte";
|
|
14
|
+
declare const __propDef: {
|
|
15
|
+
props: {};
|
|
16
|
+
events: {
|
|
17
|
+
[evt: string]: CustomEvent<any>;
|
|
18
|
+
};
|
|
19
|
+
slots: {
|
|
20
|
+
default: {};
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<script context="module">
|
|
2
|
+
// Custom components: https://mdsvex.com/docs#custom-components
|
|
3
|
+
import blockquote from './Blockquote.svelte';
|
|
4
|
+
import a from './Link.svelte';
|
|
5
|
+
|
|
6
|
+
export { a, blockquote };
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<script>
|
|
10
|
+
import { AppBar } from 'svelte-ux';
|
|
11
|
+
|
|
12
|
+
// frontmatter: https://mdsvex.com/docs#frontmatter-1
|
|
13
|
+
export let title;
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<AppBar {title} />
|
|
17
|
+
|
|
18
|
+
<main class="p-2">
|
|
19
|
+
<slot />
|
|
20
|
+
</main>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** @typedef {typeof __propDef.props} LayoutProps */
|
|
2
|
+
/** @typedef {typeof __propDef.events} LayoutEvents */
|
|
3
|
+
/** @typedef {typeof __propDef.slots} LayoutSlots */
|
|
4
|
+
export default class Layout extends SvelteComponentTyped<{
|
|
5
|
+
title: any;
|
|
6
|
+
}, {
|
|
7
|
+
[evt: string]: CustomEvent<any>;
|
|
8
|
+
}, {
|
|
9
|
+
default: {};
|
|
10
|
+
}> {
|
|
11
|
+
}
|
|
12
|
+
export type LayoutProps = typeof __propDef.props;
|
|
13
|
+
export type LayoutEvents = typeof __propDef.events;
|
|
14
|
+
export type LayoutSlots = typeof __propDef.slots;
|
|
15
|
+
import a from "./Link.svelte";
|
|
16
|
+
import blockquote from "./Blockquote.svelte";
|
|
17
|
+
import { SvelteComponentTyped } from "svelte";
|
|
18
|
+
declare const __propDef: {
|
|
19
|
+
props: {
|
|
20
|
+
title: any;
|
|
21
|
+
};
|
|
22
|
+
events: {
|
|
23
|
+
[evt: string]: CustomEvent<any>;
|
|
24
|
+
};
|
|
25
|
+
slots: {
|
|
26
|
+
default: {};
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
export { a, blockquote };
|