layerchart 2.0.0-next.53 → 2.0.0-next.54
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/components/Arc.svelte +8 -7
- package/dist/components/Arc.svelte.test.js +1 -1
- package/dist/components/ArcLabel.svelte +1 -1
- package/dist/components/ClipPath.svelte +1 -1
- package/dist/components/GeoClipPath.svelte +75 -0
- package/dist/components/GeoClipPath.svelte.d.ts +29 -0
- package/dist/components/Hull.svelte +20 -2
- package/dist/components/Hull.svelte.d.ts +2 -2
- package/dist/components/Pie.svelte +8 -2
- package/dist/components/Text.svelte +63 -16
- package/dist/components/Text.svelte.d.ts +10 -0
- package/dist/components/charts/BarChart.svelte.test.js +1 -1
- package/dist/components/charts/DefaultTooltip.svelte.test.js +18 -18
- package/dist/components/charts/LineChart.svelte.test.js +1 -1
- package/dist/components/charts/PieChart.svelte.test.js +2 -2
- package/dist/components/charts/__screenshots__/BarChart.svelte.test.ts/BarChart-series-tooltip-should-use-explicit-series-colors--not-color-scale-1.png +0 -0
- package/dist/components/charts/__screenshots__/BarChart.svelte.test.ts/BarChart-series-tooltip-should-use-explicit-series-colors--not-color-scale-2.png +0 -0
- package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-AreaChart--multi-series--quadtree-x-mode--should-fade-non-highlighted-tooltip-series-items-on-hover-1.png +0 -0
- package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-AreaChart--multi-series--quadtree-x-mode--should-fade-non-highlighted-tooltip-series-items-on-hover-2.png +0 -0
- package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-AreaChart--multi-series--quadtree-x-mode--should-show-header-and-all-series-items-1.png +0 -0
- package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-AreaChart--multi-series--quadtree-x-mode--should-show-header-and-all-series-items-2.png +0 -0
- package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-AreaChart--multi-series--quadtree-x-mode--should-show-series-colors-in-tooltip-items-1.png +0 -0
- package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-AreaChart--multi-series--quadtree-x-mode--should-show-series-colors-in-tooltip-items-2.png +0 -0
- package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-AreaChart--multi-series--quadtree-x-mode--should-show-single-series-without-total-1.png +0 -0
- package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-AreaChart--multi-series--quadtree-x-mode--should-show-single-series-without-total-2.png +0 -0
- package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-LineChart--multi-series--quadtree-x-mode--should-show-header-and-all-series-items-1.png +0 -0
- package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-LineChart--multi-series--quadtree-x-mode--should-show-header-and-all-series-items-2.png +0 -0
- package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-ScatterChart--single-point--quadtree-mode--should-show-series-header-for-multi-series-1.png +0 -0
- package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-ScatterChart--single-point--quadtree-mode--should-show-series-header-for-multi-series-2.png +0 -0
- package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-ScatterChart--single-point--quadtree-mode--should-show-x--y--and-r-items-when-r-is-configured-1.png +0 -0
- package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-ScatterChart--single-point--quadtree-mode--should-show-x--y--and-r-items-when-r-is-configured-2.png +0 -0
- package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-ScatterChart--single-point--quadtree-mode--should-show-x-and-y-items-in-tooltip-1.png +0 -0
- package/dist/components/charts/__screenshots__/DefaultTooltip.svelte.test.ts/DefaultTooltip-ScatterChart--single-point--quadtree-mode--should-show-x-and-y-items-in-tooltip-2.png +0 -0
- package/dist/components/charts/__screenshots__/LineChart.svelte.test.ts/LineChart-tooltip-should-prefer-cScale-color-over-default-series-color-when-cScale-is-explicitly-provided-1.png +0 -0
- package/dist/components/charts/__screenshots__/LineChart.svelte.test.ts/LineChart-tooltip-should-prefer-cScale-color-over-default-series-color-when-cScale-is-explicitly-provided-2.png +0 -0
- package/dist/components/charts/__screenshots__/PieChart.svelte.test.ts/PieChart-uses-hovered-slice-identity-for-implicit-tooltip-series-1.png +0 -0
- package/dist/components/charts/__screenshots__/PieChart.svelte.test.ts/PieChart-uses-hovered-slice-identity-for-implicit-tooltip-series-2.png +0 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.js +2 -0
- package/dist/components/tooltip/Tooltip.svelte +145 -29
- package/dist/components/tooltip/Tooltip.svelte.d.ts +16 -0
- package/dist/components/tooltip/Tooltip.svelte.test.d.ts +1 -0
- package/dist/components/tooltip/Tooltip.svelte.test.js +294 -0
- package/dist/components/tooltip/__screenshots__/Tooltip.svelte.test.ts/Tooltip-portal-should-portal-tooltip-to-a-custom-selector-target-1.png +0 -0
- package/dist/components/tooltip/__screenshots__/Tooltip.svelte.test.ts/Tooltip-portal-should-portal-tooltip-to-a-custom-selector-target-2.png +0 -0
- package/dist/components/tooltip/__screenshots__/Tooltip.svelte.test.ts/Tooltip-portal-should-render-tooltip-inline-when-portal-is-false-1.png +0 -0
- package/dist/components/tooltip/__screenshots__/Tooltip.svelte.test.ts/Tooltip-portal-should-render-tooltip-inline-when-portal-is-false-2.png +0 -0
- package/package.json +13 -13
|
@@ -254,7 +254,10 @@
|
|
|
254
254
|
const ctx = getChartContext();
|
|
255
255
|
|
|
256
256
|
const endAngle = $derived(
|
|
257
|
-
endAngleProp ??
|
|
257
|
+
endAngleProp ??
|
|
258
|
+
degreesToRadians(
|
|
259
|
+
(ctx.config.xRange ? max(ctx.config.xRange as number[]) : max(range))!
|
|
260
|
+
)
|
|
258
261
|
);
|
|
259
262
|
|
|
260
263
|
const motionEndAngle = createMotion(initialValue, () => value, motion);
|
|
@@ -279,13 +282,11 @@
|
|
|
279
282
|
}
|
|
280
283
|
}
|
|
281
284
|
|
|
282
|
-
const
|
|
283
|
-
|
|
284
|
-
);
|
|
285
|
+
const chartRadius = $derived((Math.min(ctx.width, ctx.height) ?? 0) / 2);
|
|
286
|
+
|
|
287
|
+
const outerRadius = $derived(getOuterRadius(outerRadiusProp, chartRadius));
|
|
285
288
|
const trackOuterRadius = $derived(
|
|
286
|
-
trackOuterRadiusProp
|
|
287
|
-
? getOuterRadius(trackOuterRadiusProp, (Math.min(ctx.xRange[1], ctx.yRange[0]) ?? 0) / 2)
|
|
288
|
-
: outerRadius
|
|
289
|
+
trackOuterRadiusProp ? getOuterRadius(trackOuterRadiusProp, chartRadius) : outerRadius
|
|
289
290
|
);
|
|
290
291
|
|
|
291
292
|
function getInnerRadius(innerRadius: number | undefined, outerRadius: number) {
|
|
@@ -383,7 +383,7 @@ describe(`Arc`, () => {
|
|
|
383
383
|
const el = page.getByTestId(componentTestId);
|
|
384
384
|
await expect.element(el).toBeInTheDocument();
|
|
385
385
|
const transform = el.element()?.getAttribute('transform');
|
|
386
|
-
expect(transform).toContain('translate(-
|
|
386
|
+
expect(transform).toContain('translate(1.2246467991473533e-15, 10)');
|
|
387
387
|
});
|
|
388
388
|
it('should apply zero offset by default', async () => {
|
|
389
389
|
render(TestHarness, {
|
|
@@ -222,7 +222,7 @@
|
|
|
222
222
|
y: offsetCentroid[1],
|
|
223
223
|
textAnchor: 'middle' as const,
|
|
224
224
|
verticalAnchor: 'middle' as const,
|
|
225
|
-
|
|
225
|
+
rotate: centroidRotation,
|
|
226
226
|
};
|
|
227
227
|
}
|
|
228
228
|
return getArcTextProps?.('centroid', { startOffset, outerPadding }) ?? {};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { GeoPermissibleObjects } from 'd3-geo';
|
|
3
|
+
import type { Snippet } from 'svelte';
|
|
4
|
+
|
|
5
|
+
import type { ClipPathPropsWithoutHTML } from './ClipPath.svelte';
|
|
6
|
+
import type { GeoPathPropsWithoutHTML } from './GeoPath.svelte';
|
|
7
|
+
import type { Without } from '../utils/types.js';
|
|
8
|
+
|
|
9
|
+
export type BaseGeoClipPathPropsWithoutHTML = {
|
|
10
|
+
/**
|
|
11
|
+
* A unique id for the clipPath.
|
|
12
|
+
*/
|
|
13
|
+
id?: string;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* GeoJSON data defining the clip boundary.
|
|
17
|
+
*/
|
|
18
|
+
geojson: GeoPermissibleObjects;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Whether to disable clipping (show all).
|
|
22
|
+
*
|
|
23
|
+
* @default false
|
|
24
|
+
*/
|
|
25
|
+
disabled?: boolean;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The children snippet to render content inside the clipPath.
|
|
29
|
+
*/
|
|
30
|
+
children?: ClipPathPropsWithoutHTML['children'];
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export type GeoClipPathPropsWithoutHTML = BaseGeoClipPathPropsWithoutHTML &
|
|
34
|
+
Without<GeoPathPropsWithoutHTML, BaseGeoClipPathPropsWithoutHTML>;
|
|
35
|
+
|
|
36
|
+
export type GeoClipPathProps = GeoClipPathPropsWithoutHTML;
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<script lang="ts">
|
|
40
|
+
import { geoPath as d3GeoPath } from 'd3-geo';
|
|
41
|
+
|
|
42
|
+
import ClipPath from './ClipPath.svelte';
|
|
43
|
+
import GeoPath from './GeoPath.svelte';
|
|
44
|
+
import { createId } from '../utils/createId.js';
|
|
45
|
+
import { extractLayerProps } from '../utils/attributes.js';
|
|
46
|
+
import { getGeoContext } from '../contexts/geo.js';
|
|
47
|
+
|
|
48
|
+
const uid = $props.id();
|
|
49
|
+
|
|
50
|
+
let {
|
|
51
|
+
id = createId('clipPath-', uid),
|
|
52
|
+
geojson,
|
|
53
|
+
disabled = false,
|
|
54
|
+
children,
|
|
55
|
+
...restProps
|
|
56
|
+
}: GeoClipPathProps = $props();
|
|
57
|
+
|
|
58
|
+
const geo = getGeoContext();
|
|
59
|
+
|
|
60
|
+
function canvasClip(ctx: CanvasRenderingContext2D) {
|
|
61
|
+
if (!geo.projection || !geojson) return;
|
|
62
|
+
const pathGen = d3GeoPath(geo.projection, ctx);
|
|
63
|
+
pathGen(geojson);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function canvasClipDeps() {
|
|
67
|
+
return [geojson, geo.projection];
|
|
68
|
+
}
|
|
69
|
+
</script>
|
|
70
|
+
|
|
71
|
+
<ClipPath {id} {disabled} {children} {canvasClip} {canvasClipDeps}>
|
|
72
|
+
{#snippet clip()}
|
|
73
|
+
<GeoPath {geojson} class="stroke-none" {...extractLayerProps(restProps, 'lc-clip-path-geo')} />
|
|
74
|
+
{/snippet}
|
|
75
|
+
</ClipPath>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { GeoPermissibleObjects } from 'd3-geo';
|
|
2
|
+
import type { ClipPathPropsWithoutHTML } from './ClipPath.svelte';
|
|
3
|
+
import type { GeoPathPropsWithoutHTML } from './GeoPath.svelte';
|
|
4
|
+
import type { Without } from '../utils/types.js';
|
|
5
|
+
export type BaseGeoClipPathPropsWithoutHTML = {
|
|
6
|
+
/**
|
|
7
|
+
* A unique id for the clipPath.
|
|
8
|
+
*/
|
|
9
|
+
id?: string;
|
|
10
|
+
/**
|
|
11
|
+
* GeoJSON data defining the clip boundary.
|
|
12
|
+
*/
|
|
13
|
+
geojson: GeoPermissibleObjects;
|
|
14
|
+
/**
|
|
15
|
+
* Whether to disable clipping (show all).
|
|
16
|
+
*
|
|
17
|
+
* @default false
|
|
18
|
+
*/
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* The children snippet to render content inside the clipPath.
|
|
22
|
+
*/
|
|
23
|
+
children?: ClipPathPropsWithoutHTML['children'];
|
|
24
|
+
};
|
|
25
|
+
export type GeoClipPathPropsWithoutHTML = BaseGeoClipPathPropsWithoutHTML & Without<GeoPathPropsWithoutHTML, BaseGeoClipPathPropsWithoutHTML>;
|
|
26
|
+
export type GeoClipPathProps = GeoClipPathPropsWithoutHTML;
|
|
27
|
+
declare const GeoClipPath: import("svelte").Component<GeoClipPathPropsWithoutHTML, {}, "">;
|
|
28
|
+
type GeoClipPath = ReturnType<typeof GeoClipPath>;
|
|
29
|
+
export default GeoClipPath;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<script lang="ts" module>
|
|
2
|
-
import type { Without } from '../utils/types.js';
|
|
2
|
+
import type { Without, CommonStyleProps } from '../utils/types.js';
|
|
3
3
|
import type { SVGAttributes } from 'svelte/elements';
|
|
4
4
|
import type { ComponentProps } from 'svelte';
|
|
5
5
|
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
* @bindable
|
|
48
48
|
*/
|
|
49
49
|
ref?: SVGGElement;
|
|
50
|
-
};
|
|
50
|
+
} & CommonStyleProps;
|
|
51
51
|
|
|
52
52
|
export type HullProps = HullPropsWithoutHTML & Without<GroupProps, HullPropsWithoutHTML>;
|
|
53
53
|
</script>
|
|
@@ -79,6 +79,12 @@
|
|
|
79
79
|
onpointermove,
|
|
80
80
|
onclick,
|
|
81
81
|
onpointerleave,
|
|
82
|
+
fill,
|
|
83
|
+
fillOpacity,
|
|
84
|
+
stroke,
|
|
85
|
+
strokeOpacity,
|
|
86
|
+
strokeWidth,
|
|
87
|
+
opacity,
|
|
82
88
|
class: className,
|
|
83
89
|
ref: refProp = $bindable(),
|
|
84
90
|
...restProps
|
|
@@ -112,6 +118,12 @@
|
|
|
112
118
|
<GeoPath
|
|
113
119
|
geojson={polygon}
|
|
114
120
|
{curve}
|
|
121
|
+
{fill}
|
|
122
|
+
{fillOpacity}
|
|
123
|
+
{stroke}
|
|
124
|
+
{strokeOpacity}
|
|
125
|
+
{strokeWidth}
|
|
126
|
+
{opacity}
|
|
115
127
|
class={['lc-hull-path', classes.path]}
|
|
116
128
|
onclick={(e) => onclick?.(e, { points, polygon })}
|
|
117
129
|
onpointermove={(e) => onpointermove?.(e, { points, polygon })}
|
|
@@ -125,6 +137,12 @@
|
|
|
125
137
|
x={(d) => d[0]}
|
|
126
138
|
y={(d) => d[1]}
|
|
127
139
|
{curve}
|
|
140
|
+
{fill}
|
|
141
|
+
{fillOpacity}
|
|
142
|
+
{stroke}
|
|
143
|
+
{strokeOpacity}
|
|
144
|
+
{strokeWidth}
|
|
145
|
+
{opacity}
|
|
128
146
|
class={['lc-hull-class', classes.path]}
|
|
129
147
|
onclick={(e) => onclick?.(e, { points, polygon })}
|
|
130
148
|
onpointermove={(e) => onpointermove?.(e, { points, polygon })}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Without } from '../utils/types.js';
|
|
1
|
+
import type { Without, CommonStyleProps } from '../utils/types.js';
|
|
2
2
|
import type { ComponentProps } from 'svelte';
|
|
3
3
|
export type HullPropsWithoutHTML = {
|
|
4
4
|
/**
|
|
@@ -32,7 +32,7 @@ export type HullPropsWithoutHTML = {
|
|
|
32
32
|
* @bindable
|
|
33
33
|
*/
|
|
34
34
|
ref?: SVGGElement;
|
|
35
|
-
};
|
|
35
|
+
} & CommonStyleProps;
|
|
36
36
|
export type HullProps = HullPropsWithoutHTML & Without<GroupProps, HullPropsWithoutHTML>;
|
|
37
37
|
import { Delaunay } from 'd3-delaunay';
|
|
38
38
|
import { type GroupProps } from './Group.svelte';
|
|
@@ -108,7 +108,10 @@
|
|
|
108
108
|
const ctx = getChartContext();
|
|
109
109
|
|
|
110
110
|
const endAngle = $derived(
|
|
111
|
-
endAngleProp ??
|
|
111
|
+
endAngleProp ??
|
|
112
|
+
degreesToRadians(
|
|
113
|
+
(ctx.config.xRange ? max(ctx.config.xRange as number[]) : max(range))!
|
|
114
|
+
)
|
|
112
115
|
);
|
|
113
116
|
|
|
114
117
|
const motionEndAngle = createMotion(0, () => endAngle, motion);
|
|
@@ -116,7 +119,10 @@
|
|
|
116
119
|
const pie = $derived.by(() => {
|
|
117
120
|
let _pie = d3pie<any>()
|
|
118
121
|
.startAngle(
|
|
119
|
-
startAngleProp ??
|
|
122
|
+
startAngleProp ??
|
|
123
|
+
degreesToRadians(
|
|
124
|
+
(ctx.config.xRange ? min(ctx.config.xRange as number[]) : min(range))!
|
|
125
|
+
)
|
|
120
126
|
)
|
|
121
127
|
.endAngle(motionEndAngle.current)
|
|
122
128
|
.padAngle(padAngle)
|
|
@@ -24,6 +24,11 @@
|
|
|
24
24
|
return false;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
export type TextSegment = {
|
|
28
|
+
value: string | number;
|
|
29
|
+
class?: string;
|
|
30
|
+
};
|
|
31
|
+
|
|
27
32
|
export type TextPropsWithoutHTML = {
|
|
28
33
|
/**
|
|
29
34
|
* Text value to render.
|
|
@@ -36,6 +41,13 @@
|
|
|
36
41
|
*/
|
|
37
42
|
value?: string | number | ((d: any) => string | number);
|
|
38
43
|
|
|
44
|
+
/**
|
|
45
|
+
* Array of styled text segments for inline mixed styling.
|
|
46
|
+
* Each segment has its own value and optional class.
|
|
47
|
+
* Mutually exclusive with `value`.
|
|
48
|
+
*/
|
|
49
|
+
segments?: TextSegment[];
|
|
50
|
+
|
|
39
51
|
/**
|
|
40
52
|
* Maximum width to occupy (approximate as words are not split)
|
|
41
53
|
*/
|
|
@@ -256,6 +268,7 @@
|
|
|
256
268
|
|
|
257
269
|
let {
|
|
258
270
|
value,
|
|
271
|
+
segments,
|
|
259
272
|
x = 0,
|
|
260
273
|
initialX,
|
|
261
274
|
y = 0,
|
|
@@ -670,14 +683,30 @@
|
|
|
670
683
|
const textAlign = textAnchor === 'middle' ? 'center' : textAnchor === 'end' ? 'end' : 'start';
|
|
671
684
|
ctx.textAlign = textAlign;
|
|
672
685
|
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
const
|
|
686
|
+
if (segments) {
|
|
687
|
+
let xOffset = baseX;
|
|
688
|
+
for (const segment of segments) {
|
|
689
|
+
const segStyles = getTextStyles(undefined, undefined, undefined, undefined, undefined, segment.class);
|
|
690
|
+
const text = String(segment.value);
|
|
691
|
+
// Set font before rendering and measuring so width is accurate
|
|
692
|
+
const segComputedStyles = getComputedStyles(ctx.canvas, segStyles);
|
|
693
|
+
const fontWeight = segComputedStyles.fontWeight || '';
|
|
694
|
+
const fontSize = segComputedStyles.fontSize || '10px';
|
|
695
|
+
const fontFamily = segComputedStyles.fontFamily || 'sans-serif';
|
|
696
|
+
ctx.font = `${fontWeight} ${fontSize} ${fontFamily}`.trim();
|
|
697
|
+
renderText(ctx, text, { x: xOffset, y: baseY }, segStyles);
|
|
698
|
+
xOffset += ctx.measureText(text).width;
|
|
699
|
+
}
|
|
700
|
+
} else {
|
|
701
|
+
for (let index = 0; index < wordsByLines.length; index++) {
|
|
702
|
+
const line = wordsByLines[index];
|
|
703
|
+
const text = line.words.join(' ');
|
|
676
704
|
|
|
677
|
-
|
|
678
|
-
|
|
705
|
+
const xPos = baseX;
|
|
706
|
+
const yPos = baseY + index * effectiveLineHeight;
|
|
679
707
|
|
|
680
|
-
|
|
708
|
+
renderText(ctx, text, { x: xPos, y: yPos }, styles);
|
|
709
|
+
}
|
|
681
710
|
}
|
|
682
711
|
|
|
683
712
|
ctx.restore();
|
|
@@ -708,6 +737,7 @@
|
|
|
708
737
|
dataMode,
|
|
709
738
|
dataMode ? resolvedItems : null,
|
|
710
739
|
value,
|
|
740
|
+
segments,
|
|
711
741
|
motionX.current,
|
|
712
742
|
motionY.current,
|
|
713
743
|
fillKey!.current,
|
|
@@ -806,15 +836,26 @@
|
|
|
806
836
|
opacity={staticOpacity}
|
|
807
837
|
class={['lc-text', staticClassName]}
|
|
808
838
|
>
|
|
809
|
-
{#
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
839
|
+
{#if segments}
|
|
840
|
+
{#each segments as segment, index (index)}
|
|
841
|
+
<tspan
|
|
842
|
+
dy={index === 0 ? startDy : 0}
|
|
843
|
+
class={['lc-text-tspan', segment.class]}
|
|
844
|
+
>
|
|
845
|
+
{segment.value}
|
|
846
|
+
</tspan>
|
|
847
|
+
{/each}
|
|
848
|
+
{:else}
|
|
849
|
+
{#each wordsByLines as line, index (index)}
|
|
850
|
+
<tspan
|
|
851
|
+
x={motionX.current}
|
|
852
|
+
dy={index === 0 ? startDy : getPixelValue(lineHeight)}
|
|
853
|
+
class="lc-text-tspan"
|
|
854
|
+
>
|
|
855
|
+
{line.words.join(' ')}
|
|
856
|
+
</tspan>
|
|
857
|
+
{/each}
|
|
858
|
+
{/if}
|
|
818
859
|
</text>
|
|
819
860
|
{/if}
|
|
820
861
|
</svg>
|
|
@@ -864,7 +905,13 @@
|
|
|
864
905
|
style:line-height={lineHeight}
|
|
865
906
|
class={['lc-text', staticClassName]}
|
|
866
907
|
>
|
|
867
|
-
{
|
|
908
|
+
{#if segments}
|
|
909
|
+
{#each segments as segment}
|
|
910
|
+
<span class={segment.class}>{segment.value}</span>
|
|
911
|
+
{/each}
|
|
912
|
+
{:else}
|
|
913
|
+
{textValue}
|
|
914
|
+
{/if}
|
|
868
915
|
</div>
|
|
869
916
|
{/if}
|
|
870
917
|
{/if}
|
|
@@ -9,6 +9,10 @@ import type { FormatType, FormatConfig } from '@layerstack/utils';
|
|
|
9
9
|
* Strings are data props unless they look like CSS values (e.g. "50%", "1em").
|
|
10
10
|
*/
|
|
11
11
|
export declare function isTextDataProp(value: any): boolean;
|
|
12
|
+
export type TextSegment = {
|
|
13
|
+
value: string | number;
|
|
14
|
+
class?: string;
|
|
15
|
+
};
|
|
12
16
|
export type TextPropsWithoutHTML = {
|
|
13
17
|
/**
|
|
14
18
|
* Text value to render.
|
|
@@ -20,6 +24,12 @@ export type TextPropsWithoutHTML = {
|
|
|
20
24
|
* @default 0
|
|
21
25
|
*/
|
|
22
26
|
value?: string | number | ((d: any) => string | number);
|
|
27
|
+
/**
|
|
28
|
+
* Array of styled text segments for inline mixed styling.
|
|
29
|
+
* Each segment has its own value and optional class.
|
|
30
|
+
* Mutually exclusive with `value`.
|
|
31
|
+
*/
|
|
32
|
+
segments?: TextSegment[];
|
|
23
33
|
/**
|
|
24
34
|
* Maximum width to occupy (approximate as words are not split)
|
|
25
35
|
*/
|
|
@@ -254,7 +254,7 @@ describe('BarChart', () => {
|
|
|
254
254
|
tooltipRect.dispatchEvent(new PointerEvent('pointerenter', eventInit));
|
|
255
255
|
tooltipRect.dispatchEvent(new PointerEvent('pointermove', eventInit));
|
|
256
256
|
await vi.waitFor(() => {
|
|
257
|
-
const colorDots =
|
|
257
|
+
const colorDots = document.querySelectorAll('.lc-tooltip-item-color');
|
|
258
258
|
expect(colorDots.length).toBe(4);
|
|
259
259
|
const colors = Array.from(colorDots).map((dot) => dot.style.getPropertyValue('--color'));
|
|
260
260
|
expect(colors).toEqual([
|
|
@@ -50,14 +50,14 @@ describe('DefaultTooltip', () => {
|
|
|
50
50
|
await expect.element(tooltipCtx).toBeInTheDocument();
|
|
51
51
|
triggerTooltip(tooltipCtx);
|
|
52
52
|
await vi.waitFor(() => {
|
|
53
|
-
// Should have a header
|
|
54
|
-
const header =
|
|
53
|
+
// Should have a header (portaled to body)
|
|
54
|
+
const header = document.querySelector('.lc-tooltip-header');
|
|
55
55
|
expect(header).not.toBeNull();
|
|
56
56
|
// Should have 4 tooltip items (3 series + 1 total)
|
|
57
|
-
const items =
|
|
57
|
+
const items = document.querySelectorAll('.lc-tooltip-item-root');
|
|
58
58
|
expect(items.length).toBe(4);
|
|
59
59
|
// Labels should match series keys + total
|
|
60
|
-
const labels =
|
|
60
|
+
const labels = document.querySelectorAll('.lc-tooltip-item-label');
|
|
61
61
|
expect(labels.length).toBe(4);
|
|
62
62
|
const labelTexts = Array.from(labels).map((l) => l.textContent?.trim());
|
|
63
63
|
expect(labelTexts).toEqual(['apples', 'bananas', 'oranges', 'total']);
|
|
@@ -75,7 +75,7 @@ describe('DefaultTooltip', () => {
|
|
|
75
75
|
await expect.element(tooltipCtx).toBeInTheDocument();
|
|
76
76
|
triggerTooltip(tooltipCtx);
|
|
77
77
|
await vi.waitFor(() => {
|
|
78
|
-
const colorDots =
|
|
78
|
+
const colorDots = document.querySelectorAll('.lc-tooltip-item-color');
|
|
79
79
|
expect(colorDots.length).toBe(3);
|
|
80
80
|
const colors = Array.from(colorDots).map((dot) => dot.style.getPropertyValue('--color'));
|
|
81
81
|
expect(colors).toEqual(['rgb(255, 0, 0)', 'rgb(0, 128, 0)', 'rgb(255, 165, 0)']);
|
|
@@ -93,11 +93,11 @@ describe('DefaultTooltip', () => {
|
|
|
93
93
|
await expect.element(tooltipCtx).toBeInTheDocument();
|
|
94
94
|
triggerTooltip(tooltipCtx);
|
|
95
95
|
await vi.waitFor(() => {
|
|
96
|
-
const items =
|
|
96
|
+
const items = document.querySelectorAll('.lc-tooltip-item-root');
|
|
97
97
|
expect(items.length).toBe(4);
|
|
98
98
|
});
|
|
99
|
-
const items = Array.from(
|
|
100
|
-
const labels = Array.from(
|
|
99
|
+
const items = Array.from(document.querySelectorAll('.lc-tooltip-item-root'));
|
|
100
|
+
const labels = Array.from(document.querySelectorAll('.lc-tooltip-item-label'));
|
|
101
101
|
triggerPointerEvent(items[0], 'pointerenter');
|
|
102
102
|
await vi.waitFor(() => {
|
|
103
103
|
expect(items[0].dataset.highlighted).toBe('true');
|
|
@@ -133,7 +133,7 @@ describe('DefaultTooltip', () => {
|
|
|
133
133
|
await expect.element(tooltipCtx).toBeInTheDocument();
|
|
134
134
|
triggerTooltip(tooltipCtx);
|
|
135
135
|
await vi.waitFor(() => {
|
|
136
|
-
const items =
|
|
136
|
+
const items = document.querySelectorAll('.lc-tooltip-item-root');
|
|
137
137
|
// 1 series item, no total
|
|
138
138
|
expect(items.length).toBe(1);
|
|
139
139
|
});
|
|
@@ -152,12 +152,12 @@ describe('DefaultTooltip', () => {
|
|
|
152
152
|
await expect.element(tooltipCtx).toBeInTheDocument();
|
|
153
153
|
triggerTooltip(tooltipCtx);
|
|
154
154
|
await vi.waitFor(() => {
|
|
155
|
-
const header =
|
|
155
|
+
const header = document.querySelector('.lc-tooltip-header');
|
|
156
156
|
expect(header).not.toBeNull();
|
|
157
157
|
// 3 series + 1 total = 4 items
|
|
158
|
-
const items =
|
|
158
|
+
const items = document.querySelectorAll('.lc-tooltip-item-root');
|
|
159
159
|
expect(items.length).toBe(4);
|
|
160
|
-
const labels =
|
|
160
|
+
const labels = document.querySelectorAll('.lc-tooltip-item-label');
|
|
161
161
|
const labelTexts = Array.from(labels).map((l) => l.textContent?.trim());
|
|
162
162
|
expect(labelTexts).toEqual(['apples', 'bananas', 'oranges', 'total']);
|
|
163
163
|
});
|
|
@@ -176,10 +176,10 @@ describe('DefaultTooltip', () => {
|
|
|
176
176
|
await expect.element(tooltipCtx).toBeInTheDocument();
|
|
177
177
|
triggerTooltip(tooltipCtx);
|
|
178
178
|
await vi.waitFor(() => {
|
|
179
|
-
const items =
|
|
179
|
+
const items = document.querySelectorAll('.lc-tooltip-item-root');
|
|
180
180
|
// Should show x and y items
|
|
181
181
|
expect(items.length).toBe(2);
|
|
182
|
-
const labels = Array.from(
|
|
182
|
+
const labels = Array.from(document.querySelectorAll('.lc-tooltip-item-label')).map((l) => l.textContent?.trim());
|
|
183
183
|
expect(labels).toEqual(['x', 'y']);
|
|
184
184
|
});
|
|
185
185
|
});
|
|
@@ -196,10 +196,10 @@ describe('DefaultTooltip', () => {
|
|
|
196
196
|
await expect.element(tooltipCtx).toBeInTheDocument();
|
|
197
197
|
triggerTooltip(tooltipCtx);
|
|
198
198
|
await vi.waitFor(() => {
|
|
199
|
-
const items =
|
|
199
|
+
const items = document.querySelectorAll('.lc-tooltip-item-root');
|
|
200
200
|
// Should show x, y, and r items
|
|
201
201
|
expect(items.length).toBe(3);
|
|
202
|
-
const labels = Array.from(
|
|
202
|
+
const labels = Array.from(document.querySelectorAll('.lc-tooltip-item-label')).map((l) => l.textContent?.trim());
|
|
203
203
|
expect(labels).toEqual(['x', 'y', 'size']);
|
|
204
204
|
});
|
|
205
205
|
});
|
|
@@ -219,11 +219,11 @@ describe('DefaultTooltip', () => {
|
|
|
219
219
|
triggerTooltip(tooltipCtx);
|
|
220
220
|
await vi.waitFor(() => {
|
|
221
221
|
// Should show a header with the series name
|
|
222
|
-
const header =
|
|
222
|
+
const header = document.querySelector('.lc-tooltip-header');
|
|
223
223
|
expect(header).not.toBeNull();
|
|
224
224
|
expect(header.textContent).not.toBe('');
|
|
225
225
|
// Should show x and y items
|
|
226
|
-
const items =
|
|
226
|
+
const items = document.querySelectorAll('.lc-tooltip-item-root');
|
|
227
227
|
expect(items.length).toBe(2);
|
|
228
228
|
});
|
|
229
229
|
});
|
|
@@ -33,7 +33,7 @@ describe('LineChart', () => {
|
|
|
33
33
|
tooltipRect.dispatchEvent(new PointerEvent('pointerenter', eventInit));
|
|
34
34
|
tooltipRect.dispatchEvent(new PointerEvent('pointermove', eventInit));
|
|
35
35
|
await vi.waitFor(() => {
|
|
36
|
-
const colorDot =
|
|
36
|
+
const colorDot = document.querySelector('.lc-tooltip-item-color');
|
|
37
37
|
expect(colorDot).not.toBeNull();
|
|
38
38
|
const color = colorDot.style.getPropertyValue('--color');
|
|
39
39
|
// Should NOT be the default series color
|
|
@@ -27,8 +27,8 @@ describe('PieChart', () => {
|
|
|
27
27
|
arc.dispatchEvent(new PointerEvent('pointerenter', eventInit));
|
|
28
28
|
arc.dispatchEvent(new PointerEvent('pointermove', eventInit));
|
|
29
29
|
await vi.waitFor(() => {
|
|
30
|
-
const tooltipLabel =
|
|
31
|
-
const tooltipValue =
|
|
30
|
+
const tooltipLabel = document.querySelector('.lc-tooltip-item-label');
|
|
31
|
+
const tooltipValue = document.querySelector('.lc-tooltip-item-value');
|
|
32
32
|
expect(tooltipLabel?.textContent).toContain('chrome');
|
|
33
33
|
expect(tooltipValue?.textContent).toContain('275');
|
|
34
34
|
});
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -66,6 +66,8 @@ export { default as GeoProjection } from './GeoProjection.svelte';
|
|
|
66
66
|
export * from './GeoProjection.svelte';
|
|
67
67
|
export { default as GeoEdgeFade } from './GeoEdgeFade.svelte';
|
|
68
68
|
export * from './GeoEdgeFade.svelte';
|
|
69
|
+
export { default as GeoClipPath } from './GeoClipPath.svelte';
|
|
70
|
+
export * from './GeoClipPath.svelte';
|
|
69
71
|
export { default as GeoPath } from './GeoPath.svelte';
|
|
70
72
|
export * from './GeoPath.svelte';
|
|
71
73
|
export { default as GeoPoint } from './GeoPoint.svelte';
|
package/dist/components/index.js
CHANGED
|
@@ -66,6 +66,8 @@ export { default as GeoProjection } from './GeoProjection.svelte';
|
|
|
66
66
|
export * from './GeoProjection.svelte';
|
|
67
67
|
export { default as GeoEdgeFade } from './GeoEdgeFade.svelte';
|
|
68
68
|
export * from './GeoEdgeFade.svelte';
|
|
69
|
+
export { default as GeoClipPath } from './GeoClipPath.svelte';
|
|
70
|
+
export * from './GeoClipPath.svelte';
|
|
69
71
|
export { default as GeoPath } from './GeoPath.svelte';
|
|
70
72
|
export * from './GeoPath.svelte';
|
|
71
73
|
export { default as GeoPoint } from './GeoPoint.svelte';
|