@mhkeller/layercake-annotations 0.3.2 → 0.4.0
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/README.md +12 -8
- package/dist/components/AnnotationEditor.svelte +15 -4
- package/dist/components/AnnotationsData.svelte +2 -2
- package/dist/components/ArrowZone.svelte +8 -4
- package/dist/modules/coordinates.js +6 -6
- package/dist/modules/newAnnotation.js +4 -2
- package/dist/types.d.ts +4 -6
- package/package.json +1 -1
package/dist/README.md
CHANGED
|
@@ -38,8 +38,10 @@ src/lib/
|
|
|
38
38
|
```typescript
|
|
39
39
|
{
|
|
40
40
|
id: number, // Unique identifier
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
data: { // User data values (nested to avoid key collisions)
|
|
42
|
+
[xKey]: any, // X data value (key from LayerCake config)
|
|
43
|
+
[yKey]: any // Y data value (key from LayerCake config)
|
|
44
|
+
},
|
|
43
45
|
dx: number, // X offset: -100 to 100 (percentage of chart width)
|
|
44
46
|
dy: number, // Y offset: -100 to 100 (percentage of chart height)
|
|
45
47
|
text: string, // Annotation text (supports line breaks)
|
|
@@ -62,8 +64,10 @@ src/lib/
|
|
|
62
64
|
dy: number // Pixels from annotation vertical center
|
|
63
65
|
},
|
|
64
66
|
target: {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
+
data: { // User data values (nested to avoid key collisions)
|
|
68
|
+
[xKey]: any, // X data value (same accessor as LayerCake)
|
|
69
|
+
[yKey]: any // Y data value
|
|
70
|
+
},
|
|
67
71
|
dx?: number, // 0-100: % offset within ordinal band (X)
|
|
68
72
|
dy?: number // 0-100: % offset within ordinal band (Y)
|
|
69
73
|
}
|
|
@@ -77,13 +81,13 @@ The library uses multiple coordinate systems:
|
|
|
77
81
|
### Annotation Position
|
|
78
82
|
|
|
79
83
|
```
|
|
80
|
-
Final position = scale(
|
|
84
|
+
Final position = scale(data[key]) + (dx/100 × chartDimension)
|
|
81
85
|
```
|
|
82
86
|
|
|
83
87
|
| Property | Unit | Range | Example |
|
|
84
88
|
|----------|------|-------|---------|
|
|
85
|
-
| `[xKey]` | Data value | Depends on data | `new Date('2024-01-15')` |
|
|
86
|
-
| `[yKey]` | Data value | Depends on data | `42` |
|
|
89
|
+
| `data.[xKey]` | Data value | Depends on data | `new Date('2024-01-15')` |
|
|
90
|
+
| `data.[yKey]` | Data value | Depends on data | `42` |
|
|
87
91
|
| `dx` | % of chart width | -100 to 100 | `5` = 5% right |
|
|
88
92
|
| `dy` | % of chart height | -100 to 100 | `-10` = 10% up |
|
|
89
93
|
|
|
@@ -100,7 +104,7 @@ Pixels relative to annotation box edge:
|
|
|
100
104
|
|
|
101
105
|
| Property | Unit | When used |
|
|
102
106
|
|----------|------|-----------|
|
|
103
|
-
| `[xKey]`, `[yKey]` | Data values | Always (same keys as LayerCake config) |
|
|
107
|
+
| `data.[xKey]`, `data.[yKey]` | Data values | Always (same keys as LayerCake config) |
|
|
104
108
|
| `dx`, `dy` | % within band (0-100) | Only for ordinal scales |
|
|
105
109
|
|
|
106
110
|
## Keyboard Shortcuts
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
/**
|
|
42
42
|
* Coordinates
|
|
43
43
|
*/
|
|
44
|
-
let left = $derived(`calc(${$xGet(d)}${units} + ${d.dx}%)`);
|
|
45
|
-
let top = $derived(`calc(${$yGet(d)}${units} + ${d.dy}%)`);
|
|
44
|
+
let left = $derived(`calc(${$xGet(d.data)}${units} + ${d.dx}%)`);
|
|
45
|
+
let top = $derived(`calc(${$yGet(d.data)}${units} + ${d.dy}%)`);
|
|
46
46
|
|
|
47
47
|
/**
|
|
48
48
|
* @param {Array} [position] - The x and y pixel coordinates of the draggable element.
|
|
@@ -52,10 +52,21 @@
|
|
|
52
52
|
const xVal = x ? invertScale($xScale, x) : [];
|
|
53
53
|
const yVal = y ? invertScale($yScale, y) : [];
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
// Build data object, preserving existing values and overlaying new ones
|
|
56
|
+
const newData = filterObject(
|
|
56
57
|
{
|
|
58
|
+
...d.data,
|
|
57
59
|
[$config.x]: xVal[0],
|
|
58
|
-
[$config.y]: yVal[0]
|
|
60
|
+
[$config.y]: yVal[0]
|
|
61
|
+
},
|
|
62
|
+
(d) => d !== undefined
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
/** @type {Record<string, unknown>} */
|
|
66
|
+
const newProps = filterObject(
|
|
67
|
+
{
|
|
68
|
+
// Only include data if it has values (avoid overwriting with empty object)
|
|
69
|
+
data: Object.keys(newData).length > 0 ? newData : undefined,
|
|
59
70
|
dx: xVal[1],
|
|
60
71
|
dy: yVal[1]
|
|
61
72
|
},
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
<div
|
|
22
22
|
class="static-wrapper"
|
|
23
23
|
data-id={i}
|
|
24
|
-
style:left={`calc(${$xGet(d)}${units} + ${d.dx || 0}%)`}
|
|
25
|
-
style:top={`calc(${$yGet(d)}${units} + ${d.dy || 0}%)`}
|
|
24
|
+
style:left={`calc(${$xGet(d.data)}${units} + ${d.dx || 0}%)`}
|
|
25
|
+
style:top={`calc(${$yGet(d.data)}${units} + ${d.dy || 0}%)`}
|
|
26
26
|
style:width={d.width}
|
|
27
27
|
>
|
|
28
28
|
<div class="layercake-annotation {d.class || ''}" style={d.style} style:text-align={d.align || 'left'}>
|
|
@@ -217,8 +217,10 @@
|
|
|
217
217
|
clockwise,
|
|
218
218
|
source: { dx: newSourceDx, dy: newSourceDy },
|
|
219
219
|
target: {
|
|
220
|
-
|
|
221
|
-
|
|
220
|
+
data: {
|
|
221
|
+
[$config.x]: targetDataX,
|
|
222
|
+
[$config.y]: targetDataY
|
|
223
|
+
},
|
|
222
224
|
dx: targetOffsetX,
|
|
223
225
|
dy: targetOffsetY
|
|
224
226
|
}
|
|
@@ -242,8 +244,10 @@
|
|
|
242
244
|
dy: arrow?.source?.dy ?? defaultSourceDy
|
|
243
245
|
},
|
|
244
246
|
target: {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
+
data: {
|
|
248
|
+
[$config.x]: targetDataX,
|
|
249
|
+
[$config.y]: targetDataY
|
|
250
|
+
},
|
|
247
251
|
dx: targetOffsetX,
|
|
248
252
|
dy: targetOffsetY
|
|
249
253
|
}
|
|
@@ -37,9 +37,9 @@ export function getAnnotationBox(anno, scales) {
|
|
|
37
37
|
const offsetX = ((anno.dx ?? 0) / 100) * width;
|
|
38
38
|
const offsetY = ((anno.dy ?? 0) / 100) * height;
|
|
39
39
|
|
|
40
|
-
// Calculate top-left position
|
|
41
|
-
const left = xScale(x(anno)) + offsetX;
|
|
42
|
-
const top = yScale(y(anno)) + offsetY;
|
|
40
|
+
// Calculate top-left position (data values are nested in anno.data)
|
|
41
|
+
const left = xScale(x(anno.data)) + offsetX;
|
|
42
|
+
const top = yScale(y(anno.data)) + offsetY;
|
|
43
43
|
|
|
44
44
|
// Get width (stored as "150px" string or use default)
|
|
45
45
|
const annoWidth = anno.width ? parseInt(anno.width) : DEFAULT_ANNOTATION_WIDTH;
|
|
@@ -90,9 +90,9 @@ export function getArrowSource(anno, arrow, scales, annoHeight = 0) {
|
|
|
90
90
|
export function getArrowTarget(arrow, scales) {
|
|
91
91
|
const { xScale, yScale, x, y, width, height } = scales;
|
|
92
92
|
|
|
93
|
-
// Target is in data space
|
|
94
|
-
const baseX = xScale(x(arrow.target));
|
|
95
|
-
const baseY = yScale(y(arrow.target));
|
|
93
|
+
// Target is in data space (data values are nested in arrow.target.data)
|
|
94
|
+
const baseX = xScale(x(arrow.target.data));
|
|
95
|
+
const baseY = yScale(y(arrow.target.data));
|
|
96
96
|
|
|
97
97
|
// Add percentage offsets (used for ordinal scales)
|
|
98
98
|
const offsetX = ((arrow.target?.dx ?? 0) / 100) * width;
|
|
@@ -15,8 +15,10 @@ export default function newAnnotation(e, id, { xScale, yScale, config }) {
|
|
|
15
15
|
|
|
16
16
|
return {
|
|
17
17
|
id,
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
data: {
|
|
19
|
+
[config.x]: xVal[0],
|
|
20
|
+
[config.y]: yVal[0]
|
|
21
|
+
},
|
|
20
22
|
dx: xVal[1],
|
|
21
23
|
dy: yVal[1],
|
|
22
24
|
text: 'New note...',
|
package/dist/types.d.ts
CHANGED
|
@@ -16,9 +16,8 @@ export interface ArrowSource {
|
|
|
16
16
|
* Arrow target position (data space coordinates)
|
|
17
17
|
*/
|
|
18
18
|
export interface ArrowTarget {
|
|
19
|
-
/**
|
|
20
|
-
|
|
21
|
-
/** Y data value (key varies based on LayerCake config) */
|
|
19
|
+
/** User data values (x/y keys match LayerCake config) */
|
|
20
|
+
data: Record<string, unknown>;
|
|
22
21
|
/** Percentage offset for ordinal X scales (0-100) */
|
|
23
22
|
dx?: number;
|
|
24
23
|
/** Percentage offset for ordinal Y scales (0-100) */
|
|
@@ -45,9 +44,8 @@ export interface Arrow {
|
|
|
45
44
|
export interface Annotation {
|
|
46
45
|
/** Unique identifier */
|
|
47
46
|
id: number;
|
|
48
|
-
/**
|
|
49
|
-
|
|
50
|
-
/** Y data value (key varies based on LayerCake config, e.g., 'value' or 'y') */
|
|
47
|
+
/** User data values (x/y keys match LayerCake config) */
|
|
48
|
+
data: Record<string, unknown>;
|
|
51
49
|
/** Percentage offset from data point in X direction */
|
|
52
50
|
dx: number;
|
|
53
51
|
/** Percentage offset from data point in Y direction */
|