svelte-plots-basic 3.4.0 → 4.1.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.
@@ -4,6 +4,7 @@
4
4
  Main properties:
5
5
  - `items` - array with text labels and their visual properties for each legend element.
6
6
  - `position` - position of the legend ("topleft", "top", "topright", "right", etc), default: `"topleft"`.
7
+ - `orientation` - arrangement of legend items (`"vertical"` or `"horizontal"`), default: `"vertical"`.
7
8
  - `lineColor` - color of the legend box line, default: `Colors.LEGEND`.
8
9
  - `lineWidth` - width (thickness) of the legend box line in pixels: `1`.
9
10
  - `faceColor` - color of the legend box background: `'#fff'`.
@@ -13,41 +14,47 @@
13
14
 
14
15
  ```svelte
15
16
  <script>
16
- import {Vector} from 'mdatools/array';
17
+ import { Vector } from 'mdatools/arrays';
18
+ import { Axes, Box, Legend, Lines, Points, XAxis, YAxis } from 'svelte-plots-basic/2d';
17
19
 
18
20
  const x = Vector.seq(-10, 10, 0.1);
19
21
  const y1 = x.apply(v => Math.cos(v));
20
22
  const y2 = x.apply(v => Math.sin(v));
23
+
24
+ const line1 = { lineType: 3, lineColor: 'red' };
25
+ const line2 = { lineType: 1, lineColor: 'blue' };
26
+ const point2 = { marker: 1, faceColor: 'white', lineColor: 'blue' };
27
+
28
+ const items = [
29
+ { label: 'cos(x)', line: line1 },
30
+ { label: 'sin(x)', line: line2, point: point2 }
31
+ ];
21
32
  </script>
22
33
 
23
34
  <Axes limX={[-10, 10]} limY={[-1.1, 1.1]} >
24
35
 
25
- <Lines xValues={x} yValues={y1} lineColor="red" lineType="3" />
26
- <Lines xValues={x} yValues={y2} lineColor="blue" lineType="1" />
27
- <Points xValues={x} yValues={y2} faceColor="white" borderColor="blue" />
36
+ <Lines xValues={x} yValues={y1} {...line1} />
37
+ <Lines xValues={x} yValues={y2} {...line2} />
38
+ <Points xValues={x} yValues={y2} {...point2} />
28
39
 
29
- <Legend
30
- position="topright"
31
- items = {[
32
- {"label": "cos(x)", "lineType": 1, "lineColor": "red"},
33
- {"label": "sin(x)", "lineType": 1, "lineColor": "blue", "marker": 1, "faceColor": "white", "borderColor": "blue"},
34
- ]}
35
- />
40
+ <Legend position="top" orientation="horizontal" {items} />
36
41
 
37
42
  <Box />
38
43
  <XAxis label="x" showGrid={true} />
39
44
  <YAxis label="f(x)" showGrid={true} />
40
45
  </Axes>
46
+ ```
41
47
  -->
42
48
  <script>
43
49
  import { getContext, onDestroy } from 'svelte';
44
50
  import { Colors, MARKER_SYMBOLS } from '../constants';
45
- import { text2svg } from '../methods';
51
+ import { text2svg, normalizeLineType } from '../methods';
46
52
 
47
53
  let {
48
54
  items, // array with text labels and their visual properties for each legend element.
49
55
  show = true, // logical, use to hide the element
50
- position = 'topleft', // position of the legend ("topleft", "top", "topright", "right", "bottomright", etc).
56
+ position = 'topleft', // position of the legend ("topleft", "top", "topright", "right", "bottomright", etc).
57
+ orientation = 'vertical', // arrangement of legend items ("vertical" or "horizontal")
51
58
  lineColor = Colors.LEGEND, // color of the legend box line
52
59
  lineWidth = 1, // width (thickness) of the legend box line
53
60
  faceColor = '#fff', // background color of the legend box
@@ -70,6 +77,21 @@
70
77
  return position;
71
78
  }
72
79
 
80
+ /* check if user provided orientation is correct */
81
+ function checkOrientation(orientation) {
82
+
83
+ if (typeof orientation !== 'string') {
84
+ console.error('Legend: value of "orientation" must be a string.');
85
+ return null;
86
+ }
87
+
88
+ if (!['vertical', 'horizontal'].includes(orientation)) {
89
+ console.error('Legend: wrong value of "orientation" property');
90
+ return null;
91
+ }
92
+ return orientation;
93
+ }
94
+
73
95
  /* check if user provided items are correct, transform text labels and set default values if they are absent */
74
96
  function processItems(items) {
75
97
 
@@ -96,25 +118,35 @@
96
118
  // set default values for lines
97
119
  if (item.line) {
98
120
  item.line = {...item.line};
99
- if (!item.line.lineType) item.line.lineType = 1
100
- if (!(item.line.lineType > 0 && item.line.lineType <= 4)) {
101
- console.error('Legend: parameter "lineType" for legend item ' + (i + 1) + ' is incorrect.');
102
- }
121
+ item.line.lineType = normalizeLineType(
122
+ item.line.lineType ?? 1,
123
+ `Legend item ${i + 1}`
124
+ );
103
125
  item.line.lineColor = item.line.lineColor ? item.line.lineColor : Colors.PRIMARY;
104
- item.line.lineWidth = item.line.lineWidth ? item.line.lineWidth : 1;
126
+ item.line.lineWidth = item.line.lineWidth ?? 1;
105
127
  }
106
128
 
107
129
  // set default values for markers
108
130
  if (item.point) {
109
131
  item.point = {...item.point};
110
- if (!item.point.marker) item.point.marker = 1
111
- if (!(item.point.marker > 0 && item.point.marker <= MARKER_SYMBOLS.length)) {
112
- console.error('Legend: parameter "marker" for legend item ' + (i + 1) + ' is incorrect.');
132
+ const canConvertMarker =
133
+ typeof item.point.marker === 'number' ||
134
+ (typeof item.point.marker === 'string' && item.point.marker.trim() !== '');
135
+ const marker = item.point.marker == null ? 1 :
136
+ canConvertMarker ? Number(item.point.marker) : NaN;
137
+
138
+ if (!Number.isInteger(marker) || marker < 1 || marker > MARKER_SYMBOLS.length) {
139
+ console.error(
140
+ `Legend item ${i + 1}: parameter "marker" must be a whole number from 1 to ${MARKER_SYMBOLS.length}.`
141
+ );
142
+ item.point = null;
143
+ } else {
144
+ item.point.marker = marker;
145
+ item.point.faceColor = item.point.faceColor ? item.point.faceColor : 'transparent';
146
+ item.point.lineWidth = item.point.lineWidth ?? 1;
147
+ item.point.markerSize = item.point.markerSize ?? 1;
148
+ item.point.lineColor = item.point.lineColor ? item.point.lineColor : Colors.PRIMARY;
113
149
  }
114
- item.point.faceColor = item.point.faceColor ? item.point.faceColor : 'transparent';
115
- item.point.lineWidth = item.point.lineWidth ? item.point.lineWidth : 1;
116
- item.point.markerSize = item.point.markerSize ? item.point.markerSize : 1;
117
- item.point.lineColor = item.point.lineColor ? item.point.lineColor : Colors.PRIMARY;
118
150
  }
119
151
 
120
152
  result.push(item);
@@ -122,14 +154,26 @@
122
154
  return result;
123
155
  }
124
156
 
125
- // get context and update group legend parameters reactivey
157
+ // Validate and transform only when the corresponding input changes.
158
+ const processedItems = $derived(processItems(items));
159
+ const validPosition = $derived(checkPosition(position));
160
+ const validOrientation = $derived(checkOrientation(orientation));
161
+
162
+ // get context and update group legend parameters reactively
126
163
  const axes = getContext('axes');
127
164
  $effect(() => {
128
- const newItems = processItems(items);
129
- const newPosition = checkPosition(position);
130
165
  axes.setGroupLegend(
131
- newItems && newPosition ?
132
- {show, position, items: newItems, lineColor, faceColor, lineWidth, fontSize} :
166
+ processedItems && validPosition && validOrientation ?
167
+ {
168
+ show,
169
+ position: validPosition,
170
+ orientation: validOrientation,
171
+ items: processedItems,
172
+ lineColor,
173
+ faceColor,
174
+ lineWidth,
175
+ fontSize
176
+ } :
133
177
  {show: false, position: null, items: null}
134
178
  );
135
179
  });
@@ -2,10 +2,10 @@
2
2
  @component Adds a series of lines connecting points with provided coordinates (polyline).
3
3
 
4
4
  Main properties:
5
- - `xValues` - array of vector with x-coordinates of the points.
6
- - `yValues` - array of vector with y-coordinates of the points.
5
+ - `xValues` - array or vector with x-coordinates of the points.
6
+ - `yValues` - array or vector with y-coordinates of the points.
7
7
  - `lineColor` - lines color, default: `Colors.PRIMARY`.
8
- - `lineWidth` - width (thickness) of the lines in pixels, defailt: `1`.
8
+ - `lineWidth` - width (thickness) of the lines in pixels, default: `1`.
9
9
  - `lineType` - type of lines (`1` - solid, `2` - dashed, `3` - dotted, `4` - dashdot).
10
10
  - `onclick` - function (callback) to be called when user clicks on a polyline.
11
11
 
@@ -27,7 +27,7 @@
27
27
  <script>
28
28
  import { getContext } from 'svelte';
29
29
  import { Colors } from '../constants';
30
- import { val2p, checkCoords, handleClick } from '../methods';
30
+ import { val2p, checkCoords, handleClick, normalizeLineType } from '../methods';
31
31
  import { LINE_STYLES } from '../constants';
32
32
 
33
33
  let {
@@ -43,13 +43,14 @@
43
43
  // check user provided coordinates
44
44
  const xv = $derived(checkCoords(xValues, 'Lines'));
45
45
  const yv = $derived(xv ? checkCoords(yValues, 'Lines', xv.length) : null);
46
+ const validLineType = $derived(normalizeLineType(lineType, 'Lines'));
46
47
 
47
48
  // get axes context and compute coordinates of polyline
48
49
  const axes = getContext('axes');
49
50
  const p = $derived(xv && yv ? val2p(xv, yv, axes.tX(), axes.tY()) : null);
50
51
 
51
52
  // reactive variables for coordinates of data points in pixels
52
- const lineStyleStr = $derived(`fill:transparent;stroke:${lineColor};stroke-width: ${lineWidth}px; stroke-dasharray:${LINE_STYLES[axes.scales().plot][lineType-1]}`);
53
+ const lineStyleStr = $derived(`fill:transparent;stroke:${lineColor};stroke-width: ${lineWidth}px; stroke-dasharray:${LINE_STYLES[axes.scales().plot][validLineType - 1]}`);
53
54
  </script>
54
55
 
55
56
  {#if p}
@@ -2,10 +2,10 @@
2
2
  @component Adds a series of polylines (like `<Lines>` but with several of those).
3
3
 
4
4
  Main properties:
5
- - `xValues` - array of vector with x-coordinates of the points.
6
- - `yValues` - Matrix (object of class `Matrix` from `mdatools/array`) with y-coordinates of the points.
5
+ - `xValues` - array or vector with x-coordinates of the points.
6
+ - `yValues` - Matrix (object of class `Matrix` from `mdatools/arrays`) with y-coordinates of the points.
7
7
  - `lineColor` - lines color, default: `Colors.PRIMARY`.
8
- - `lineWidth` - width (thickness) of the lines in pixels, defailt: `1`.
8
+ - `lineWidth` - width (thickness) of the lines in pixels, default: `1`.
9
9
  - `lineType` - type of segment lines (`1` - solid, `2` - dashed, `3` - dotted, `4` - dashdot).
10
10
  - `onclick` - function (callback) to be called when user clicks on a polyline.
11
11
 
@@ -16,8 +16,8 @@
16
16
  import { Vector, cbind } from 'mdatools/arrays';
17
17
  import { Axes, Multilines } from 'svelte-plots-basic/2d';
18
18
 
19
- const xValues = Vector.seq(0, 100, 100);
20
- const YY = cbind(
19
+ const xValues = Vector.seq(0, 10, 0.1);
20
+ const yValues = cbind(
21
21
  xValues.apply(v => Math.sin(v)),
22
22
  xValues.apply(v => Math.sin(v + 0.5) + 0.1),
23
23
  xValues.apply(v => Math.sin(v - 0.5) - 0.1),
@@ -35,12 +35,12 @@
35
35
  import { getContext } from 'svelte';
36
36
  import { ismatrix } from 'mdatools/arrays';
37
37
  import { Colors } from '../constants';
38
- import { val2p, checkCoords, handleClick } from '../methods';
38
+ import { val2p, checkCoords, handleClick, normalizeLineType } from '../methods';
39
39
  import { LINE_STYLES } from '../constants';
40
40
 
41
41
  let {
42
42
  xValues, // vector or array with x-coordinates of the points
43
- yValues, // vector or array with y-coordinates of the points
43
+ yValues, // matrix with y-coordinates of the points
44
44
  lineColor = Colors.PRIMARY, // color of segment lines
45
45
  lineType = 1, // type of segment lines (1 - solid, 2 - dashed, 3 - dotted, 4 - dashdot)
46
46
  lineWidth = 1, // width (thickness) of segment lines
@@ -49,6 +49,7 @@
49
49
 
50
50
  // check user provided coordinates
51
51
  const xv = $derived(checkCoords(xValues, 'Multilines'));
52
+ const validLineType = $derived(normalizeLineType(lineType, 'Multilines'));
52
53
  const yv = $derived.by(() => {
53
54
 
54
55
  if (!xv) return null;
@@ -79,7 +80,7 @@
79
80
  });
80
81
 
81
82
  // reactive variables for coordinates of data points in pixels
82
- const lineStyleStr = $derived(`fill:transparent;stroke:${lineColor};stroke-width: ${lineWidth}px; stroke-dasharray:${LINE_STYLES[axes.scales().plot][lineType-1]}`);
83
+ const lineStyleStr = $derived(`fill:transparent;stroke:${lineColor};stroke-width: ${lineWidth}px; stroke-dasharray:${LINE_STYLES[axes.scales().plot][validLineType - 1]}`);
83
84
  </script>
84
85
 
85
86
  {#if pp && pp.length > 0}
@@ -2,13 +2,13 @@
2
2
  @component Adds a series of points.
3
3
 
4
4
  Main properties:
5
- - `xValues` - array of vector with x-coordinates of the points.
6
- - `yValues` - array of vector with y-coordinates of the points.
5
+ - `xValues` - array or vector with x-coordinates of the points.
6
+ - `yValues` - array or vector with y-coordinates of the points.
7
7
  - `marker` - index for a point symbol (from 1 - default - to 8): `"●", "◼", "▲", "▼", "⬥", "+", "*", "✕"`.
8
8
  - `faceColor` - face (fill) color of the markers, default: `'transparent'`.
9
9
  - `lineColor` - border color of the markers, default: `Colors.PRIMARY`.
10
- - `lineWidth` - width (thickness) of the markers' border in pixels, defailt: `1`.
11
- - `markerSize` - size of the markers in em, defailt: `1`.
10
+ - `lineWidth` - width (thickness) of the markers' border in pixels, default: `1`.
11
+ - `markerSize` - size of the markers in em, default: `1`.
12
12
  - `onclick` - function (callback) to be called when user clicks on a marker.
13
13
 
14
14
  Example:
@@ -32,8 +32,8 @@
32
32
  import { checkCoords, transformCoords, handleClick } from '../methods';
33
33
 
34
34
  let {
35
- xValues, // array of vector with x-coordinates of points
36
- yValues, // array of vector with y-coordinates of points
35
+ xValues, // array or vector with x-coordinates of points
36
+ yValues, // array or vector with y-coordinates of points
37
37
  marker = 1, // index for point symbol (from 1 to 8): "●", "◼", "▲", "▼", "⬥", "+", "*", "✕"
38
38
  faceColor = 'transparent', // face (fill) color of the points
39
39
  lineColor = Colors.PRIMARY, // border color of the points
@@ -45,8 +45,8 @@
45
45
 
46
46
  // select which symbol to use as a marker
47
47
  const markerSymbol = $derived.by(() => {
48
- if (typeof(marker) !== 'number' || marker < 1 || marker > MARKER_SYMBOLS.length) {
49
- console.error('Points: parameter "marker" must be a number from 1 to ' + MARKER_SYMBOLS.length + '.');
48
+ if (!Number.isInteger(marker) || marker < 1 || marker > MARKER_SYMBOLS.length) {
49
+ console.error('Points: parameter "marker" must be a whole number from 1 to ' + MARKER_SYMBOLS.length + '.');
50
50
  return null;
51
51
  }
52
52
  return MARKER_SYMBOLS[marker - 1]
@@ -70,7 +70,7 @@
70
70
  const className = $derived(['◼', '⬥', '+', '✳', '✕'].includes(markerSymbol) ? 'series-points2' : 'series-points1');
71
71
 
72
72
  // check if all coordinates are correct
73
- const isOk = $derived(x && y && x.length === y.length);
73
+ const isOk = $derived(markerSymbol && x && y && x.length === y.length);
74
74
  </script>
75
75
 
76
76
  {#if isOk}
@@ -3,20 +3,19 @@
3
3
 
4
4
  Main properties:
5
5
  - `left` - array or vector with world coordinates of left side of the rectangles.
6
- - `top` - array or vector with world coordinates of left side of the rectangles.
6
+ - `top` - array or vector with world coordinates of top side of the rectangles.
7
7
  - `width` - width of the rectangles (one value or array/vector with individual values).
8
8
  - `height` - height of the rectangles (one value or array/vector with individual values).
9
- - `facColor` - face color of the rectangles (same for all).
9
+ - `faceColor` - face color of the rectangles (same for all).
10
10
  - `lineColor` - border color of each rectangle.
11
11
  - `lineWidth` - width (thickness) of border lines in pixels.
12
- - `className`- CSS class name for the labels group, default: `'series-rect'`.
12
+ - `className` - CSS class name for the rectangles group, default: `'series-rect'`.
13
13
  - `onclick` - function (callback) to be called when user clicks on any rectangle.
14
14
 
15
15
 
16
16
  Example:
17
- ```jsx
17
+ ```svelte
18
18
  <script>
19
- import { Matrix } from 'mdatools/arrays';
20
19
  import { Axes, Rectangles } from 'svelte-plots-basic/2d';
21
20
 
22
21
  const left = [0, 10, 20, 30];
@@ -32,27 +31,58 @@
32
31
  -->
33
32
  <script>
34
33
  import { getContext } from 'svelte';
35
- import { Vector } from 'mdatools/arrays';
34
+ import { Vector, isvector } from 'mdatools/arrays';
36
35
  import { Colors } from '../constants';
37
36
  import { checkCoords, transformCoords, transformObjects, handleClick } from '../methods';
38
37
 
39
38
  let {
40
- left, // array of vector with coordinates of left sides of the bars
41
- top, // array of vector with coordinates of top sides of the bars
42
- width, // single value (same for all) or vector/array with bar width
43
- height, // single value (same for all) or vector/array with bar height
44
- faceColor = Colors.PRIMARY, // color of bar faces (fill)
45
- lineColor = faceColor, // color of bar borders
46
- lineWidth = 1, // width (thickness) of bar border lines
39
+ left, // array or vector with coordinates of left sides of the rectangles
40
+ top, // array or vector with coordinates of top sides of the rectangles
41
+ width, // single value (same for all) or vector/array with rectangle width
42
+ height, // single value (same for all) or vector/array with rectangle height
43
+ faceColor = Colors.PRIMARY, // color of rectangle faces (fill)
44
+ lineColor = faceColor, // color of rectangle borders
45
+ lineWidth = 1, // width (thickness) of rectangle border lines
47
46
  className = 'series-rect', // CSS class name of the SVG group
48
47
  onclick, // function to be called if onclick event fires
49
48
  } = $props();
50
49
 
50
+ function checkDimensions(value, name, len) {
51
+ const canConvert =
52
+ typeof value === 'number' ||
53
+ (typeof value === 'string' && value.trim() !== '');
54
+ let dimensions;
55
+
56
+ if (canConvert) {
57
+ const scalar = Number(value);
58
+ if (!Number.isFinite(scalar) || scalar < 0) {
59
+ console.error(`Rectangles: parameter "${name}" must contain only finite non-negative values.`);
60
+ return null;
61
+ }
62
+ dimensions = Vector.fill(scalar, len);
63
+ } else if (Array.isArray(value) || isvector(value)) {
64
+ dimensions = checkCoords(value, `Rectangles (${name})`, len);
65
+ if (!dimensions) return null;
66
+ } else {
67
+ console.error(`Rectangles: parameter "${name}" must be a number, array, or Vector.`);
68
+ return null;
69
+ }
70
+
71
+ for (let i = 0; i < dimensions.length; i++) {
72
+ if (dimensions.v[i] < 0) {
73
+ console.error(`Rectangles: parameter "${name}" must contain only finite non-negative values.`);
74
+ return null;
75
+ }
76
+ }
77
+
78
+ return dimensions;
79
+ }
80
+
51
81
  // process provided values and compute world coordinates of rectangles
52
82
  const l = $derived(checkCoords(left, 'Rectangles (left)'));
53
83
  const t = $derived(l ? checkCoords(top, 'Rectangles (top)', l.length) : null);
54
- const w = $derived(t ? (typeof width !== 'object' ? Vector.fill(width, l.length) : width) : null);
55
- const h = $derived(t ? (typeof height !== 'object' ? Vector.fill(height, l.length) : height) : null);
84
+ const w = $derived(t ? checkDimensions(width, 'width', l.length) : null);
85
+ const h = $derived(t ? checkDimensions(height, 'height', l.length) : null);
56
86
 
57
87
  // get axes context and compute screen coordinates
58
88
  const axes = getContext('axes');
@@ -62,11 +92,11 @@
62
92
  const rw = $derived(w ? transformObjects(w, axes.tX()) : null);
63
93
  const rh = $derived(h ? transformObjects(h, axes.tY()) : null);
64
94
 
65
- // styles for bars and labels
95
+ // styles for rectangles
66
96
  const barsStyleStr = $derived(`fill:${faceColor};stroke:${lineColor};stroke-width:${lineWidth}px;`);
67
97
 
68
98
  // check if all coordinates are correct
69
- const isOk = $derived(rx && ry && rw && rh && (rw.length === rx.length) && (rh.length === rx.length));
99
+ const isOk = $derived(rx && ry && rw && rh);
70
100
  </script>
71
101
 
72
102
  {#if isOk}
@@ -78,4 +108,3 @@
78
108
  {/each}
79
109
  </g>
80
110
  {/if}
81
-
@@ -31,7 +31,7 @@
31
31
  <script>
32
32
  import { getContext } from 'svelte';
33
33
  import { Colors } from '../constants';
34
- import { checkCoords, transformCoords, handleClick } from '../methods';
34
+ import { checkCoords, transformCoords, handleClick, normalizeLineType } from '../methods';
35
35
  import { LINE_STYLES } from '../constants';
36
36
 
37
37
  let {
@@ -51,6 +51,7 @@
51
51
  const sy = $derived(sx ? checkCoords(yStart, 'Segments', sx.length) : null);
52
52
  const ex = $derived(sy ? checkCoords(xEnd, 'Segments', sx.length) : null);
53
53
  const ey = $derived(ex ? checkCoords(yEnd, 'Segments', sx.length) : null);
54
+ const validLineType = $derived(normalizeLineType(lineType, 'Segments'));
54
55
 
55
56
  // get axes context and reactive variables needed to compute coordinates
56
57
  const axes = getContext('axes');
@@ -60,7 +61,7 @@
60
61
  const y2 = $derived(ey ? transformCoords(ey, axes.tY()) : null);
61
62
 
62
63
  // reactive variables for coordinates of data points in pixels (and line style)
63
- const lineStyleStr = $derived(`stroke:${lineColor};stroke-width: ${lineWidth}px;stroke-dasharray:${LINE_STYLES[axes.scales().plot][lineType-1]}`);
64
+ const lineStyleStr = $derived(`stroke:${lineColor};stroke-width: ${lineWidth}px;stroke-dasharray:${LINE_STYLES[axes.scales().plot][validLineType - 1]}`);
64
65
 
65
66
  // local status
66
67
  const isOk = $derived(x1 && x2 && y1 && y2);
@@ -75,4 +76,3 @@
75
76
  {/each}
76
77
  </g>
77
78
  {/if}
78
-
@@ -1,18 +1,20 @@
1
1
  <!--
2
- @component Adds a series with line segments.
2
+ @component Adds text labels at specified plot coordinates.
3
3
 
4
4
  Main properties:
5
- - `xValues`- vector or array with x-coordinates for each label.
6
- - `yValues`- vector or array with y-coordinates for each label.
7
- - `labels`- single string or array with labels (strings).
8
- - `pos`- position of labels related to coordinates (`0` - middle - default, `1` - bottom, `2` - left, `3` - top, `4` - right).
9
- - `faceColor`- face color of label symbols, default: `Colors.PRIMARY_TEXT`.
10
- - `lineColor`- border colors of label symbols, default: `'transparent'`.
11
- - `lineWidth`- border width of label symbols in pixels, default: `0`.
12
- - `textSize`- size of label symbols in em, default: `1`.
13
- - `rotateAngle`- angle to rotate labels, default: `0`.
5
+ - `xValues` - vector or array with x-coordinates for each label.
6
+ - `yValues` - vector or array with y-coordinates for each label.
7
+ - `labels` - single string used at every coordinate or array with one string per coordinate.
8
+ - `pos` - one position used for every label, or an array/typed array with one position per label (`0` - middle - default, `1` - bottom, `2` - left, `3` - top, `4` - right).
9
+ - `faceColor` - text fill color, default: `Colors.PRIMARY_TEXT`.
10
+ - `lineColor` - text outline color, default: `'transparent'`.
11
+ - `lineWidth` - text outline width in pixels, default: `0`.
12
+ - `textSize` - text size in em, default: `1`.
13
+ - `rotateAngle` - angle to rotate labels, default: `0`.
14
14
  - `onclick` - function (callback) to be called when user clicks on a label.
15
15
 
16
+ Values in `labels` are rendered as raw SVG/HTML markup. Only pass trusted content.
17
+
16
18
  Example:
17
19
 
18
20
  ```svelte
@@ -1,7 +1,38 @@
1
+ <!--
2
+ @component Adds a vertical text legend at a specified plot position.
3
+
4
+ Main properties:
5
+ - `left` - x-coordinate of the legend in plot units.
6
+ - `top` - y-coordinate of the legend in plot units.
7
+ - `elements` - non-empty array of text labels. SVG/HTML markup is supported.
8
+ - `dx` - horizontal text offset, default: `"0"`.
9
+ - `dy` - vertical spacing between labels, default: `"1.25em"`.
10
+ - `faceColor` - text fill color, default: `Colors.PRIMARY_TEXT`.
11
+ - `lineColor` - text outline color, default: `"transparent"`.
12
+ - `lineWidth` - text outline width in pixels, default: `0`.
13
+ - `textSize` - text size in em, default: `1`.
14
+
15
+ Values in `elements` are rendered as raw SVG/HTML markup. Only pass trusted content.
16
+
17
+ Example:
18
+
19
+ ```svelte
20
+ <script>
21
+ import { Axes, TextLegend } from 'svelte-plots-basic/2d';
22
+
23
+ const elements = ['First group', 'Second group'];
24
+ </script>
25
+
26
+ <Axes limX={[0, 10]} limY={[0, 10]}>
27
+ <TextLegend left={1} top={9} {elements} />
28
+ </Axes>
29
+ ```
30
+ -->
31
+
1
32
  <script>
2
33
  import { getContext } from 'svelte';
3
34
  import { Colors } from '../constants';
4
- import { transformCoords } from '../methods';
35
+ import { checkCoords, transformCoords } from '../methods';
5
36
 
6
37
  let {
7
38
  left, // vector/array with coordinates of lef side of each text box
@@ -16,24 +47,31 @@
16
47
  } = $props()
17
48
 
18
49
  const axes = getContext('axes');
19
- const x = $derived(
20
- left !== undefined && left !== null
21
- ? transformCoords([left], axes.tX())
22
- : null
50
+ const lx = $derived(
51
+ left !== undefined && left !== null ? checkCoords([left], 'TextLegend (left)') : null
23
52
  );
24
- const y = $derived(
25
- top !== undefined && top !== null
26
- ? transformCoords([top], axes.tY())
27
- : null
53
+ const ty = $derived(
54
+ top !== undefined && top !== null ? checkCoords([top], 'TextLegend (top)') : null
28
55
  );
56
+ const x = $derived(lx ? transformCoords(lx, axes.tX()) : null);
57
+ const y = $derived(ty ? transformCoords(ty, axes.tY()) : null);
58
+
59
+ const validElements = $derived.by(() => {
60
+ if (!Array.isArray(elements) || elements.length < 1) {
61
+ console.error('TextLegend: parameter "elements" must be a non-empty array.');
62
+ return null;
63
+ }
64
+
65
+ return elements;
66
+ });
29
67
 
30
68
  // styles for bars and labels
31
69
  const textStyleStr = $derived(`fill:${faceColor};stroke-width:${lineWidth}px;stroke:${lineColor};font-size:${textSize}em;`);
32
70
  </script>
33
71
 
34
- {#if x && y && elements.length > 0}
72
+ {#if x && y && validElements}
35
73
  <text style={textStyleStr} x={x} y={y} dx={dx} dy={dy} dominant-baseline="middle" text-anchor="start">
36
- {#each elements as el, i}
74
+ {#each validElements as el, i}
37
75
  <tspan {x} {dx} dy={i === 0 ? 0 : dy}>{@html el}</tspan>
38
76
  {/each}
39
77
  </text>
@@ -4,7 +4,7 @@
4
4
  Main properties:
5
5
  - `label` - text label for the axis (optional).
6
6
  - `showGrid` - logical, show or not horizontal grid lines, default: `false`.
7
- - `ticks` - array or vector with tick positions (by default will be generated automatically based on `limX`).
7
+ - `ticks` - array or vector with tick positions (by default will be generated automatically based on `limY`).
8
8
  - `tickLabels` - array with tick labels to show at each tick (by default will be generated automatically).
9
9
  - `las` - orientation of tick labels (`1` - horizontal - default, `2` - vertical).
10
10
  - `whole` - logical, show numeric tick labels as whole numbers (without decimals) or not, default: `false`.
@@ -4,7 +4,7 @@
4
4
  Main properties:
5
5
  - `limX` - array with limits for x-axis (in plot units), default: `[0, 1]`.
6
6
  - `limY` - array with limits for y-axis (in plot units), default: `[0, 1]`.
7
- - `limZ` - array with limits for y-axis (in plot units), default: `[0, 1]`.
7
+ - `limZ` - array with limits for z-axis (in plot units), default: `[0, 1]`.
8
8
  - `theta` - angle (in radians) for orientation of projection plane, default: `-10`.
9
9
  - `phi` - angle (in radians) for orientation of projection plane, default: `-10`.
10
10
  - `zoom` - zooming factor, default: `0.5`.
@@ -15,18 +15,16 @@
15
15
  - `pngWidth` - width of PNG image in cm, default `8`
16
16
  - `pngHeight` - height of PNG image in cm, default `8`.
17
17
  - `pngRes` - resolution of PNG image (pixels per inch), default `300`.
18
- - `clipboardWidth` - width of plot image to copy to clipboard in pixels.
19
- - `clipboardHeight` - height of plot image to copy to clipboard in pixels.
18
+ - `clipboardWidth` - width of plot image to copy to clipboard in pixels, default `1200`.
19
+ - `clipboardHeight` - height of plot image to copy to clipboard in pixels, default `800`.
20
20
 
21
21
  Example:
22
- ```jsx
22
+ ```svelte
23
23
  <script>
24
24
  import {Axes} from 'svelte-plots-basic/3d';
25
25
  </script>
26
26
 
27
- <Axes limX={[-10, 10]} limY={[-10, 10]} limZ={[-10, 10]}>
28
- //all other plotting components are here
29
- </Axes>
27
+ <Axes limX={[-10, 10]} limY={[-10, 10]} limZ={[-10, 10]} />
30
28
  ```
31
29
  -->
32
30
  <script>
@@ -1,5 +1,5 @@
1
1
  <!--
2
- @component draws line segments for axis elements (ticks. etc), not for manual use.
2
+ @component Draws line segments for axis elements (ticks, etc.); not intended for direct use.
3
3
  -->
4
4
  <script>
5
5
  import { getContext } from 'svelte';
@@ -13,9 +13,9 @@
13
13
  lineWidth = 1, // line width (thickness) in pixels.
14
14
  } = $props();
15
15
 
16
- // get axes context and and compute screen coordinates
16
+ // get axes context and compute screen coordinates
17
17
  const axes = getContext('axes');
18
- const s1 = $derived(lineCoords.length == 2 ? transform3D(lineCoords[0], axes.tM()) : null);
18
+ const s1 = $derived(lineCoords.length === 2 ? transform3D(lineCoords[0], axes.tM()) : null);
19
19
  const s2 = $derived(s1 ? transform3D(lineCoords[1], axes.tM()) : null);
20
20
 
21
21
  // line style
@@ -29,4 +29,3 @@
29
29
  {/each}
30
30
  </g>
31
31
  {/if}
32
-
@@ -1,5 +1,5 @@
1
1
  <!--
2
- @component shows tick labels.
2
+ @component Shows tick labels.
3
3
  -->
4
4
  <script>
5
5
 
@@ -34,4 +34,4 @@
34
34
  user-select: none;
35
35
  dominant-baseline: middle;
36
36
  }
37
- </style>
37
+ </style>