@fundar/data-chart-telling 0.0.35 → 0.0.37
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/dist/index.d.ts +1 -0
- package/dist/layout/coordinates/CameraFit.svelte +111 -0
- package/dist/layout/coordinates/CameraFit.svelte.d.ts +15 -0
- package/dist/layout/coordinates/CoordinatesLayout.svelte +169 -95
- package/dist/layout/coordinates/CoordinatesLayout.svelte.d.ts +1 -1
- package/dist/layout/coordinates/camera.svelte.d.ts +17 -0
- package/dist/layout/coordinates/camera.svelte.js +106 -0
- package/dist/layout/coordinates/resolveCameraTarget.d.ts +14 -0
- package/dist/layout/coordinates/resolveCameraTarget.js +19 -0
- package/dist/layout/coordinates/zoom.svelte.d.ts +11 -15
- package/dist/layout/coordinates/zoom.svelte.js +15 -12
- package/dist/layout/plot/BasePlotLayout.svelte +312 -282
- package/dist/plots/line/Plot.svelte +6 -18
- package/dist/plots/line/ValueLabels.svelte +46 -84
- package/dist/plots/line/ValueLabels.svelte.d.ts +1 -1
- package/dist/types/layout/coordinates.d.ts +11 -5
- package/dist/types/plots/camera.d.ts +42 -0
- package/dist/types/plots/camera.js +1 -0
- package/package.json +1 -1
|
@@ -1,308 +1,338 @@
|
|
|
1
|
-
<script
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
1
|
+
<script
|
|
2
|
+
lang="ts"
|
|
3
|
+
generics="TData extends Record<string, unknown>, TSeries extends Record<string, unknown> = TData"
|
|
4
|
+
>
|
|
5
|
+
import type { ComponentProps, Snippet } from 'svelte';
|
|
6
|
+
import { Plot, Pointer } from 'svelteplot';
|
|
7
|
+
import { getConfiguration } from '../../configuration/config.svelte';
|
|
8
|
+
import { AUTO_MARGIN_ESTIMATE, numericMargin } from './margins';
|
|
9
|
+
import { buildScale } from '../scales/buildScale';
|
|
10
|
+
import ScalesLayout from '../scales/ScalesLayout.svelte';
|
|
11
|
+
import GeometryLayout from '../geometry/GeometryLayout.svelte';
|
|
12
|
+
import CoordinatesLayout from '../coordinates/CoordinatesLayout.svelte';
|
|
13
|
+
import StylesLayout from '../styles/StylesLayout.svelte';
|
|
14
|
+
import { getHover, createHover } from '../tooltip/hover.svelte';
|
|
15
|
+
import { createHoverController } from '../tooltip/controller.svelte';
|
|
16
|
+
import TooltipLayout from '../tooltip/TooltipLayout.svelte';
|
|
17
|
+
import type { AxisValue, AxisBasedScalesConfig } from '../../types/layout/scales';
|
|
18
|
+
import type { CoordinatesConfig } from '../../types/layout/coordinates';
|
|
19
|
+
import type { StylesLayoutConfig } from '../../types/layout/styles';
|
|
20
|
+
import type { ScopedMarkerGroup } from '../../types/layout/geometry';
|
|
21
|
+
import type { HoverPoint } from '../../types/layout/tooltip';
|
|
22
|
+
import type { MarginConfig, HoverConfig } from '../../types/plots/props';
|
|
23
|
+
import type { MarkerConfig } from '../../types/markers/all';
|
|
24
|
+
import type { Series } from '../../types/plots/data/common';
|
|
25
|
+
import type { GeoFeature } from '../../types/plots/data/geo';
|
|
23
26
|
|
|
24
|
-
|
|
27
|
+
type SveltePlotProps = ComponentProps<typeof Plot>;
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Shared chrome around every plot kind's svelteplot markup: the
|
|
31
|
+
* pointer-event wrapper, the hover/tooltip state machine, and the floating
|
|
32
|
+
* tooltip. Composes the Coordinates and Styles layers around every plot
|
|
33
|
+
* kind's own content, plus `GeometryLayout` (which renders nothing extra
|
|
34
|
+
* when `markers` is empty/unset). `ScalesLayout` composes in
|
|
35
|
+
* independently, only when `scales` is passed. Every plot kind supplies
|
|
36
|
+
* its own `<Plot x y projection>` scale config, either directly via
|
|
37
|
+
* `x`/`y` or by leaving them unset so this component derives them from
|
|
38
|
+
* `scales`.
|
|
39
|
+
*/
|
|
40
|
+
let {
|
|
41
|
+
width,
|
|
42
|
+
height,
|
|
43
|
+
data,
|
|
44
|
+
getX,
|
|
45
|
+
getY,
|
|
46
|
+
hover,
|
|
47
|
+
x = undefined,
|
|
48
|
+
y = undefined,
|
|
49
|
+
scales = undefined,
|
|
50
|
+
coordinates = undefined,
|
|
51
|
+
margins,
|
|
52
|
+
marginEstimate = AUTO_MARGIN_ESTIMATE,
|
|
53
|
+
marginRemountKey = undefined,
|
|
54
|
+
xTickRotate = undefined,
|
|
55
|
+
styles = undefined,
|
|
56
|
+
markers = undefined,
|
|
57
|
+
seriesData = undefined,
|
|
58
|
+
scopedGroups = undefined,
|
|
59
|
+
geoAllFeatures = undefined,
|
|
60
|
+
containerEl = $bindable(undefined),
|
|
61
|
+
children
|
|
62
|
+
}: {
|
|
63
|
+
width: number;
|
|
64
|
+
height: number;
|
|
65
|
+
/** Flat rows fed to svelteplot's `<Pointer>` for nearest-point matching, and to `CoordinatesLayout` for a `domain: 'data'` projection auto-fit. */
|
|
66
|
+
data: TData[];
|
|
67
|
+
getX: (d: TData) => AxisValue;
|
|
68
|
+
getY: (d: TData) => AxisValue;
|
|
69
|
+
/** Every hover/tooltip prop this component's own hover machinery reads — see {@link HoverConfig}. */
|
|
70
|
+
hover: HoverConfig<TData>;
|
|
71
|
+
/** Explicit `<Plot x>` override — bypasses `scales`-derived resolution (e.g. GeoPlot's fixed lon/lat domain). */
|
|
72
|
+
x?: SveltePlotProps['x'];
|
|
73
|
+
/** Explicit `<Plot y>` override — see `x`. */
|
|
74
|
+
y?: SveltePlotProps['y'];
|
|
75
|
+
/** Scale config `x`/`y` are derived from when not given directly. */
|
|
76
|
+
scales?: AxisBasedScalesConfig<TData>;
|
|
77
|
+
/** This plot kind's coordinate system config — `GeoPlot` only (a projection + pan/zoom). */
|
|
78
|
+
coordinates?: CoordinatesConfig;
|
|
79
|
+
/** Partial margin override — merged on top of the theme. */
|
|
80
|
+
margins?: MarginConfig;
|
|
81
|
+
/** Numeric fallback for a margin side that resolved to `'auto'` — see `numericMargin`'s doc comment. */
|
|
82
|
+
marginEstimate?: Record<'top' | 'right' | 'bottom' | 'left', number>;
|
|
83
|
+
/**
|
|
84
|
+
* Forces svelteplot's own `<Plot>` to fully unmount/remount (via
|
|
85
|
+
* `{#key}`) whenever this changes, instead of reacting to a `margins`
|
|
86
|
+
* prop change on an already-mounted instance. Only needed by a caller
|
|
87
|
+
* (line's own `Plot.svelte`) whose `margins` grows *after* mount, from
|
|
88
|
+
* measuring rendered content (see `createLabelMarginTracker`) — handing
|
|
89
|
+
* svelteplot's `<Plot>` a live post-mount margin change (rather than the
|
|
90
|
+
* same final value from its very first mount) was observed to send its
|
|
91
|
+
* own internal auto-margin sizing into a permanent one-pixel
|
|
92
|
+
* bottom-margin oscillation for line's end-point value labels
|
|
93
|
+
* specifically, which in turn kept re-triggering the overflow watcher
|
|
94
|
+
* that grew the margin in the first place — an infinite effect loop
|
|
95
|
+
* that tripped Svelte's `effect_update_depth_exceeded` guard. A static
|
|
96
|
+
* `margins` prop (the common case — every other plot kind) never needs
|
|
97
|
+
* this; leave it unset there.
|
|
98
|
+
*/
|
|
99
|
+
marginRemountKey?: string | number;
|
|
100
|
+
/** Boosts the bottom margin for a rotated x tick label — axis-having plot kinds only. */
|
|
101
|
+
xTickRotate?: number;
|
|
102
|
+
/** This plot kind's own `styles` prop, forwarded to the Styles layer. */
|
|
103
|
+
styles?: StylesLayoutConfig;
|
|
104
|
+
/**
|
|
105
|
+
* This plot kind's own markers array. Accepts a plain array, or a
|
|
106
|
+
* builder function for a plot kind whose own marker construction needs
|
|
107
|
+
* `setHoverMatch`/`clearHoverMatch`, only available once this
|
|
108
|
+
* component's own hover controller is set up.
|
|
109
|
+
*/
|
|
110
|
+
markers?:
|
|
111
|
+
| MarkerConfig[]
|
|
112
|
+
| ((hover: {
|
|
113
|
+
setHoverMatch: (rows: TData[]) => void;
|
|
114
|
+
clearHoverMatch: () => void;
|
|
115
|
+
}) => MarkerConfig[]);
|
|
116
|
+
/** All resolved series, forwarded to `GeometryLayout` — axis-based kinds only. Independently generic over `TSeries` (defaults to `TData`). */
|
|
117
|
+
seriesData?: Series<TSeries>[];
|
|
118
|
+
/** Per-series `GeometryLayout` groups — axis-based kinds only, same `TSeries` as `seriesData`. */
|
|
119
|
+
scopedGroups?: ScopedMarkerGroup<TSeries>[];
|
|
120
|
+
/** `GeoPlot`'s own untouched, tagged features, forwarded to `GeometryLayout` — `inset` marker only. */
|
|
121
|
+
geoAllFeatures?: (GeoFeature<Record<string, unknown>> & { __id: string })[];
|
|
122
|
+
/** The wrapper div's own element — bind for a nested layout that needs it for its own gesture handling (e.g. `CoordinatesLayout`'s zoom/rotate). */
|
|
123
|
+
containerEl?: HTMLDivElement;
|
|
124
|
+
/**
|
|
125
|
+
* `matchedPoints` carries the source `row` alongside the display fields,
|
|
126
|
+
* so a template can resolve it straight off `row` instead of assuming
|
|
127
|
+
* which visual axis it landed on. `activePoint` is the one matched point
|
|
128
|
+
* under the cursor. `numericMargins` lets a nested layout align itself
|
|
129
|
+
* with the plot's own content box. `setHoverMatch`/`clearHoverMatch` let
|
|
130
|
+
* a plot kind drive the match itself instead of svelteplot's
|
|
131
|
+
* distance-based `<Pointer>` — see `hover.pointMatching`. When `markers`
|
|
132
|
+
* is given, this is `GeometryLayout`'s own `children` instead of raw
|
|
133
|
+
* plot content. Optional — a plot kind whose every mark is a `markers`
|
|
134
|
+
* entry has nothing left to render here.
|
|
135
|
+
*/
|
|
136
|
+
children?: Snippet<
|
|
137
|
+
[
|
|
138
|
+
{
|
|
139
|
+
matchedPoints: HoverPoint<TData>[];
|
|
140
|
+
activePoint: HoverPoint<TData> | null;
|
|
141
|
+
impliesCrosshairX: boolean;
|
|
142
|
+
impliesCrosshairY: boolean;
|
|
143
|
+
numericMargins: { top: number; right: number; bottom: number; left: number };
|
|
144
|
+
setHoverMatch: (rows: TData[]) => void;
|
|
145
|
+
clearHoverMatch: () => void;
|
|
146
|
+
}
|
|
147
|
+
]
|
|
148
|
+
>;
|
|
149
|
+
} = $props();
|
|
142
150
|
|
|
143
|
-
|
|
151
|
+
const cfg = $derived(getConfiguration());
|
|
144
152
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
153
|
+
/**
|
|
154
|
+
* Margins passed straight to `<Plot margin={…}>`. Each side defaults to
|
|
155
|
+
* `'auto'` (from the theme), which lets svelteplot size it to whatever it
|
|
156
|
+
* actually renders there — tick labels, an axis title, rotated ticks —
|
|
157
|
+
* rather than a fixed guess that either clips content or wastes space.
|
|
158
|
+
* `margins`/`cfg.margins` can still pin a side to an exact number.
|
|
159
|
+
*/
|
|
160
|
+
const computedMargins = $derived.by(() => {
|
|
161
|
+
const base = { ...cfg.margins, ...margins };
|
|
162
|
+
// Auto margins already measure the real (rotated) label bounding box, so
|
|
163
|
+
// this manual boost is only needed when the caller pinned bottom to a
|
|
164
|
+
// fixed number, which bypasses that measurement.
|
|
165
|
+
if (!xTickRotate || typeof base.bottom !== 'number') return base;
|
|
166
|
+
const rad = (Math.abs(xTickRotate) * Math.PI) / 180;
|
|
167
|
+
return {
|
|
168
|
+
...base,
|
|
169
|
+
bottom: base.bottom + Math.ceil(Math.sin(rad) * 20)
|
|
170
|
+
};
|
|
171
|
+
});
|
|
164
172
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
173
|
+
const numericMargins = $derived({
|
|
174
|
+
top: numericMargin('top', computedMargins.top, marginEstimate),
|
|
175
|
+
right: numericMargin('right', computedMargins.right, marginEstimate),
|
|
176
|
+
bottom: numericMargin('bottom', computedMargins.bottom, marginEstimate),
|
|
177
|
+
left: numericMargin('left', computedMargins.left, marginEstimate)
|
|
178
|
+
});
|
|
171
179
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
180
|
+
// Cast to svelteplot's own (narrower, axis-specific) scale option type:
|
|
181
|
+
// buildScale has already stripped the fields that don't exist there
|
|
182
|
+
// (grid, the vertical label config, BarPlot's series-layout knobs).
|
|
183
|
+
const resolvedX = $derived(
|
|
184
|
+
x !== undefined ? x : (buildScale(scales?.x, data, getX) as SveltePlotProps['x'])
|
|
185
|
+
);
|
|
186
|
+
const resolvedY = $derived(
|
|
187
|
+
y !== undefined ? y : (buildScale(scales?.y, data, getY) as SveltePlotProps['y'])
|
|
188
|
+
);
|
|
177
189
|
|
|
178
|
-
|
|
179
|
-
|
|
190
|
+
/** Only ever meaningful for `GeoPlot`. `none` while any interactive gesture (`zoom`/`pan`/`rotate`) is on. */
|
|
191
|
+
const touchAction = $derived(
|
|
192
|
+
(coordinates?.zoom !== false && coordinates?.zoom != null) ||
|
|
193
|
+
coordinates?.pan ||
|
|
194
|
+
coordinates?.rotate
|
|
195
|
+
? 'none'
|
|
196
|
+
: undefined
|
|
197
|
+
);
|
|
180
198
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
199
|
+
// ── Hover / tooltip ───────────────────────────────────────────────────────
|
|
200
|
+
const sharedHover = getHover();
|
|
201
|
+
const localHover = createHover();
|
|
202
|
+
const hoverStore = $derived(sharedHover ?? localHover);
|
|
185
203
|
|
|
186
|
-
|
|
187
|
-
|
|
204
|
+
/** Declared intent, defaulted — see {@link HoverConfig.pointMatching}. */
|
|
205
|
+
const pointMatchingStrategy = $derived(hover.pointMatching ?? 'nearest');
|
|
188
206
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
207
|
+
/**
|
|
208
|
+
* Which axes svelteplot's `<Pointer>` should search along, derived from
|
|
209
|
+
* the active strategy. `undefined` for an axis collapses every point to
|
|
210
|
+
* the same coordinate on that axis, excluding it from the match entirely.
|
|
211
|
+
*/
|
|
212
|
+
const pointerMatchX = $derived(hoverStore.strategy === 'y' ? undefined : getX);
|
|
213
|
+
const pointerMatchY = $derived(hoverStore.strategy === 'x' ? undefined : getY);
|
|
196
214
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
215
|
+
$effect(() => {
|
|
216
|
+
if (sharedHover) return;
|
|
217
|
+
localHover.strategy = hover.strategy ?? 'x';
|
|
218
|
+
localHover.sync = hover.sync ?? false;
|
|
219
|
+
});
|
|
202
220
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
221
|
+
const ctrl = createHoverController<TData>({
|
|
222
|
+
hover: () => hoverStore,
|
|
223
|
+
facetId: () => hover.tooltip?.facetId ?? '',
|
|
224
|
+
points: () => hover.points,
|
|
225
|
+
getX: () => getX,
|
|
226
|
+
getY: () => getY,
|
|
227
|
+
label: () => hover.label,
|
|
228
|
+
seriesFilter: () => hover.tooltip?.series,
|
|
229
|
+
width: () => width,
|
|
230
|
+
height: () => height
|
|
231
|
+
});
|
|
214
232
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
233
|
+
function onMove(e: PointerEvent) {
|
|
234
|
+
if (hover.exclude?.(e)) {
|
|
235
|
+
ctrl.onLeave();
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
ctrl.onMove(e);
|
|
239
|
+
}
|
|
222
240
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
241
|
+
const resolvedMarkers = $derived(
|
|
242
|
+
typeof markers === 'function'
|
|
243
|
+
? markers({ setHoverMatch: ctrl.onPointer, clearHoverMatch: ctrl.onLeave })
|
|
244
|
+
: markers
|
|
245
|
+
);
|
|
226
246
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
247
|
+
/** `hover.crosshair === false` forces both off, overriding the strategy-implied default — see {@link HoverConfig.crosshair}. */
|
|
248
|
+
const effectiveImpliesCrosshairX = $derived(
|
|
249
|
+
hover.crosshair === false ? false : ctrl.impliesCrosshairX
|
|
250
|
+
);
|
|
251
|
+
const effectiveImpliesCrosshairY = $derived(
|
|
252
|
+
hover.crosshair === false ? false : ctrl.impliesCrosshairY
|
|
253
|
+
);
|
|
230
254
|
</script>
|
|
231
255
|
|
|
232
256
|
<!-- svelte-ignore a11y_no_static_element_interactions -->
|
|
233
257
|
<div
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
258
|
+
class="dct-plot"
|
|
259
|
+
bind:this={containerEl}
|
|
260
|
+
style:color={cfg.axis.color}
|
|
261
|
+
style:touch-action={touchAction}
|
|
262
|
+
onpointermove={hover.active ? onMove : undefined}
|
|
263
|
+
onpointerleave={hover.active ? ctrl.onLeave : undefined}
|
|
240
264
|
>
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
265
|
+
<CoordinatesLayout
|
|
266
|
+
{width}
|
|
267
|
+
{height}
|
|
268
|
+
margin={computedMargins}
|
|
269
|
+
x={resolvedX}
|
|
270
|
+
y={resolvedY}
|
|
271
|
+
{coordinates}
|
|
272
|
+
{data}
|
|
273
|
+
{containerEl}
|
|
274
|
+
remountKey={marginRemountKey}
|
|
275
|
+
>
|
|
276
|
+
<StylesLayout {styles} {width} {height} {numericMargins} />
|
|
277
|
+
{#if scales !== undefined}
|
|
278
|
+
<ScalesLayout {data} {getX} {getY} {width} {height} {numericMargins} {scales} />
|
|
279
|
+
{/if}
|
|
280
|
+
<GeometryLayout
|
|
281
|
+
markers={resolvedMarkers}
|
|
282
|
+
seriesData={seriesData ?? []}
|
|
283
|
+
scopedGroups={scopedGroups ?? []}
|
|
284
|
+
matchedPoints={ctrl.points}
|
|
285
|
+
activePoint={ctrl.activePoint}
|
|
286
|
+
impliesCrosshairX={effectiveImpliesCrosshairX}
|
|
287
|
+
impliesCrosshairY={effectiveImpliesCrosshairY}
|
|
288
|
+
{width}
|
|
289
|
+
{height}
|
|
290
|
+
{numericMargins}
|
|
291
|
+
{data}
|
|
292
|
+
{geoAllFeatures}
|
|
293
|
+
tooltipAnchorX={hover.tooltip?.anchorX}
|
|
294
|
+
tooltipAnchorY={hover.tooltip?.anchorY}
|
|
295
|
+
>
|
|
296
|
+
{@render children?.({
|
|
297
|
+
matchedPoints: ctrl.points,
|
|
298
|
+
activePoint: ctrl.activePoint,
|
|
299
|
+
impliesCrosshairX: effectiveImpliesCrosshairX,
|
|
300
|
+
impliesCrosshairY: effectiveImpliesCrosshairY,
|
|
301
|
+
numericMargins,
|
|
302
|
+
setHoverMatch: ctrl.onPointer,
|
|
303
|
+
clearHoverMatch: ctrl.onLeave
|
|
304
|
+
})}
|
|
305
|
+
</GeometryLayout>
|
|
282
306
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
307
|
+
{#if hover.active && pointMatchingStrategy === 'nearest'}
|
|
308
|
+
<Pointer
|
|
309
|
+
{data}
|
|
310
|
+
x={pointerMatchX}
|
|
311
|
+
y={pointerMatchY}
|
|
312
|
+
maxDistance={400}
|
|
313
|
+
onupdate={ctrl.onPointer}
|
|
314
|
+
/>
|
|
315
|
+
{/if}
|
|
316
|
+
</CoordinatesLayout>
|
|
287
317
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
318
|
+
{#if hover.tooltip}
|
|
319
|
+
<TooltipLayout
|
|
320
|
+
visible={ctrl.showTooltip && ctrl.tooltipPosition != null}
|
|
321
|
+
x={ctrl.tooltipPosition?.x ?? 0}
|
|
322
|
+
y={ctrl.tooltipPosition?.y ?? 0}
|
|
323
|
+
bounds={{ width, height }}
|
|
324
|
+
rows={ctrl.matchedRows.map((p) => p.row)}
|
|
325
|
+
format={hover.tooltip.format}
|
|
326
|
+
content={hover.tooltip.content}
|
|
327
|
+
anchorX={hover.tooltip.anchorX}
|
|
328
|
+
anchorY={hover.tooltip.anchorY}
|
|
329
|
+
/>
|
|
330
|
+
{/if}
|
|
301
331
|
</div>
|
|
302
332
|
|
|
303
333
|
<style>
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
334
|
+
.dct-plot {
|
|
335
|
+
position: relative;
|
|
336
|
+
line-height: 0;
|
|
337
|
+
}
|
|
308
338
|
</style>
|