smithkit 0.5.0 → 0.7.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/README.md +47 -938
- package/dist/lib/OptionsValidation.d.ts +3 -3
- package/dist/lib/OptionsValidation.js +17 -13
- package/dist/lib/Smith.d.ts +3 -0
- package/dist/lib/Smith.js +42 -14
- package/dist/lib/appearance/SvgTheme.d.ts +1 -0
- package/dist/lib/appearance/SvgTheme.js +8 -7
- package/dist/lib/appearance/Theme.js +49 -52
- package/dist/lib/appearance/types.d.ts +75 -31
- package/dist/lib/grid/CircleLayerControl.d.ts +2 -2
- package/dist/lib/grid/CircleLayerControl.js +4 -4
- package/dist/lib/grid/ConstCircles.js +6 -6
- package/dist/lib/grid/ConstQCircles.js +4 -1
- package/dist/lib/grid/ConstSwrCircles.js +4 -1
- package/dist/lib/grid/GridLayerControl.d.ts +2 -2
- package/dist/lib/grid/GridLayerControl.js +10 -11
- package/dist/lib/grid/SmithGridLayer.js +3 -1
- package/dist/lib/index.d.ts +2 -2
- package/dist/lib/interaction/SmithCursor.js +6 -6
- package/dist/lib/layers.d.ts +28 -14
- package/dist/lib/math/Complex.d.ts +1 -1
- package/dist/lib/math/Complex.js +2 -2
- package/dist/lib/measurements.d.ts +20 -8
- package/dist/lib/options.d.ts +4 -4
- package/dist/lib/rendering/ChartHost.d.ts +5 -0
- package/dist/lib/rendering/ChartHost.js +14 -0
- package/dist/lib/rendering/SvgChartRenderer.d.ts +2 -2
- package/dist/lib/rendering/SvgChartRenderer.js +2 -2
- package/dist/lib/scales/SmithPeripheralScales.js +11 -11
- package/dist/lib/scales/SmithScales.d.ts +3 -0
- package/dist/lib/scales/SmithScales.js +39 -18
- package/dist/lib/svg/LabelLayout.js +9 -2
- package/dist/lib/traces/SmithData.d.ts +3 -3
- package/dist/lib/traces/SmithMarker.js +6 -5
- package/dist/lib/traces/TraceRenderer.d.ts +3 -3
- package/dist/lib/traces/TraceRenderer.js +19 -18
- package/package.json +24 -6
|
@@ -22,8 +22,8 @@ export class SmithCursor {
|
|
|
22
22
|
this.group = new SmithGroup().attr('pointer-events', 'none');
|
|
23
23
|
this.impedance = {
|
|
24
24
|
group: new SmithGroup({
|
|
25
|
-
stroke: 'var(--smithkit-cursor-
|
|
26
|
-
strokeWidth: 'var(--smithkit-cursor-
|
|
25
|
+
stroke: 'var(--smithkit-cursor-impedance-color)',
|
|
26
|
+
strokeWidth: 'var(--smithkit-cursor-line-width)',
|
|
27
27
|
fill: 'none',
|
|
28
28
|
}),
|
|
29
29
|
resistance: { circle: new SmithCircle({ p: [0, 0], r: 1 }) },
|
|
@@ -37,8 +37,8 @@ export class SmithCursor {
|
|
|
37
37
|
this.impedance.reactance.line.nonScalingStroke();
|
|
38
38
|
this.admittance = {
|
|
39
39
|
group: new SmithGroup({
|
|
40
|
-
stroke: 'var(--smithkit-cursor-
|
|
41
|
-
strokeWidth: 'var(--smithkit-cursor-
|
|
40
|
+
stroke: 'var(--smithkit-cursor-admittance-color)',
|
|
41
|
+
strokeWidth: 'var(--smithkit-cursor-line-width)',
|
|
42
42
|
fill: 'none',
|
|
43
43
|
}),
|
|
44
44
|
conductance: { circle: new SmithCircle({ p: [0, 0], r: 1 }) },
|
|
@@ -51,8 +51,8 @@ export class SmithCursor {
|
|
|
51
51
|
this.admittance.susceptance.arc.nonScalingStroke();
|
|
52
52
|
this.admittance.susceptance.line.nonScalingStroke();
|
|
53
53
|
this.point = new SmithLine([0, 0], [0, 0], {
|
|
54
|
-
stroke: 'var(--smithkit-cursor-
|
|
55
|
-
strokeWidth: 'var(--smithkit-cursor-
|
|
54
|
+
stroke: 'var(--smithkit-cursor-point-color)',
|
|
55
|
+
strokeWidth: 'var(--smithkit-cursor-point-size)',
|
|
56
56
|
fill: 'none',
|
|
57
57
|
});
|
|
58
58
|
this.point.nonScalingStroke();
|
package/dist/lib/layers.d.ts
CHANGED
|
@@ -1,19 +1,33 @@
|
|
|
1
1
|
import type { Complex } from './math/Complex.js';
|
|
2
2
|
export interface GridStyle {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
line: {
|
|
4
|
+
color: string;
|
|
5
|
+
/** Non-scaling stroke width in CSS pixels. */
|
|
6
|
+
majorWidth: number;
|
|
7
|
+
/** Non-scaling stroke width in CSS pixels. */
|
|
8
|
+
minorWidth: number;
|
|
9
|
+
};
|
|
10
|
+
text: {
|
|
11
|
+
color: string;
|
|
12
|
+
fontFamily: string;
|
|
13
|
+
/** Base font size in chart units; adaptive layout enforces a 9 CSS px minimum in the default view. */
|
|
14
|
+
fontSize: number;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/** A grid style patch. Omitted nested properties retain their existing values. */
|
|
18
|
+
export interface GridStyleOptions {
|
|
19
|
+
line?: Partial<GridStyle['line']>;
|
|
20
|
+
text?: Partial<GridStyle['text']>;
|
|
12
21
|
}
|
|
13
22
|
export interface CircleStyle {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
23
|
+
line: {
|
|
24
|
+
color: string;
|
|
25
|
+
/** Non-scaling stroke width in CSS pixels. */
|
|
26
|
+
width: number;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export interface CircleStyleOptions {
|
|
30
|
+
line?: Partial<CircleStyle['line']>;
|
|
17
31
|
}
|
|
18
32
|
export type GridDetail = 'basic' | 'standard' | 'detailed';
|
|
19
33
|
/** Grid styling uses SVG user units, except non-scaling stroke widths in screen pixels. */
|
|
@@ -23,11 +37,11 @@ export interface GridLayer {
|
|
|
23
37
|
setLabelsVisible(visible: boolean): void;
|
|
24
38
|
/** Default: standard. Basic shows only the principal normalized values. */
|
|
25
39
|
setDetail(detail: GridDetail): void;
|
|
26
|
-
setStyle(style:
|
|
40
|
+
setStyle(style: GridStyleOptions): void;
|
|
27
41
|
}
|
|
28
42
|
export interface CircleLayer {
|
|
29
43
|
setVisible(visible: boolean): void;
|
|
30
|
-
setStyle(style:
|
|
44
|
+
setStyle(style: CircleStyleOptions): void;
|
|
31
45
|
/** Replace the complete set after validation; duplicates are ignored and empty clears it. */
|
|
32
46
|
setValues(values: readonly number[]): void;
|
|
33
47
|
addValue(value: number): void;
|
|
@@ -117,7 +117,7 @@ export declare class Complex {
|
|
|
117
117
|
private static hyperbolicProduct;
|
|
118
118
|
private static hyperbolicReciprocal;
|
|
119
119
|
/**
|
|
120
|
-
* Elliptic coordinates for principal inverse functions (x
|
|
120
|
+
* Elliptic coordinates for principal inverse functions (non-negative x and y).
|
|
121
121
|
* With a = (|z+1| + |z-1|)/2, return acosh(a) and sqrt(a²-x²).
|
|
122
122
|
* Rationalized hypot differences retain tiny components near the branch cuts.
|
|
123
123
|
* Principal branches: https://dlmf.nist.gov/4.37
|
package/dist/lib/math/Complex.js
CHANGED
|
@@ -34,7 +34,7 @@ export class Complex {
|
|
|
34
34
|
}
|
|
35
35
|
if (args.length === 2) {
|
|
36
36
|
const arg0 = args[0];
|
|
37
|
-
const arg1 = args[1];
|
|
37
|
+
const arg1 = args[1] === undefined ? 0 : args[1];
|
|
38
38
|
if (typeof arg0 === 'number' && typeof arg1 === 'number') {
|
|
39
39
|
return new Complex(arg0, arg1);
|
|
40
40
|
}
|
|
@@ -598,7 +598,7 @@ export class Complex {
|
|
|
598
598
|
return Complex.reciprocal(denominator).mul(Math.exp(Math.LN2 - x));
|
|
599
599
|
}
|
|
600
600
|
/**
|
|
601
|
-
* Elliptic coordinates for principal inverse functions (x
|
|
601
|
+
* Elliptic coordinates for principal inverse functions (non-negative x and y).
|
|
602
602
|
* With a = (|z+1| + |z-1|)/2, return acosh(a) and sqrt(a²-x²).
|
|
603
603
|
* Rationalized hypot differences retain tiny components near the branch cuts.
|
|
604
604
|
* Principal branches: https://dlmf.nist.gov/4.37
|
|
@@ -3,14 +3,24 @@ import type { SmithReading } from './rf/RfCalculations.js';
|
|
|
3
3
|
export type TraceRenderMode = 'points' | 'line' | 'both';
|
|
4
4
|
export interface TraceStyle {
|
|
5
5
|
mode: TraceRenderMode;
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
line: {
|
|
7
|
+
/** Non-scaling SVG stroke width in CSS pixels. Default: 2. */
|
|
8
|
+
width: number;
|
|
9
|
+
/** Maximum additional line simplification error in CSS pixels. Zero disables it (default). */
|
|
10
|
+
tolerancePx: number;
|
|
11
|
+
};
|
|
12
|
+
point: {
|
|
13
|
+
/** Radius in CSS pixels; constant under chart zoom and container resize. Default: 2. */
|
|
14
|
+
radius: number;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/** A partial style patch; omitted nested properties retain their current values. */
|
|
18
|
+
export interface TraceStyleOptions {
|
|
19
|
+
mode?: TraceRenderMode;
|
|
20
|
+
line?: Partial<TraceStyle['line']>;
|
|
21
|
+
point?: Partial<TraceStyle['point']>;
|
|
22
|
+
}
|
|
23
|
+
export interface TraceOptions extends TraceStyleOptions {
|
|
14
24
|
name?: string;
|
|
15
25
|
/** A solid CSS color, such as '#2563eb' or 'orange'. */
|
|
16
26
|
color?: string;
|
|
@@ -29,6 +39,8 @@ export interface MarkerInfo {
|
|
|
29
39
|
readonly sampleIndex: number;
|
|
30
40
|
}
|
|
31
41
|
export interface TraceInfo extends Readonly<TraceStyle> {
|
|
42
|
+
readonly line: Readonly<TraceStyle['line']>;
|
|
43
|
+
readonly point: Readonly<TraceStyle['point']>;
|
|
32
44
|
readonly id: string;
|
|
33
45
|
readonly name: string;
|
|
34
46
|
readonly color: string;
|
package/dist/lib/options.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { SmithAppearance } from './appearance/types.js';
|
|
2
|
-
import type {
|
|
2
|
+
import type { CircleStyleOptions, GridDetail, GridStyleOptions } from './layers.js';
|
|
3
3
|
/** Settings for an individual impedance/admittance grid layer. */
|
|
4
4
|
export interface GridLayerOptions {
|
|
5
5
|
visible?: boolean;
|
|
6
6
|
detail?: GridDetail;
|
|
7
7
|
labelsVisible?: boolean;
|
|
8
|
-
style?:
|
|
8
|
+
style?: GridStyleOptions;
|
|
9
9
|
}
|
|
10
10
|
/** Shared settings for all four grids, followed by per-layer overrides. */
|
|
11
11
|
export interface GridOptions {
|
|
@@ -13,7 +13,7 @@ export interface GridOptions {
|
|
|
13
13
|
detail?: GridDetail;
|
|
14
14
|
/** Default: true. */
|
|
15
15
|
labelsVisible?: boolean;
|
|
16
|
-
style?:
|
|
16
|
+
style?: GridStyleOptions;
|
|
17
17
|
layers?: {
|
|
18
18
|
resistance?: GridLayerOptions;
|
|
19
19
|
reactance?: GridLayerOptions;
|
|
@@ -24,7 +24,7 @@ export interface GridOptions {
|
|
|
24
24
|
export interface CircleLayerOptions {
|
|
25
25
|
/** Default: false. */
|
|
26
26
|
visible?: boolean;
|
|
27
|
-
style?:
|
|
27
|
+
style?: CircleStyleOptions;
|
|
28
28
|
/** Replace the default values. Empty hides all circles; duplicate values are ignored. */
|
|
29
29
|
values?: readonly number[];
|
|
30
30
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** Recognize HTML hosts across windows without accessing browser globals at import time. */
|
|
2
|
+
export class ChartHost {
|
|
3
|
+
constructor() { }
|
|
4
|
+
static isElement(value) {
|
|
5
|
+
if (!value || typeof value !== 'object') {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
if (typeof HTMLElement !== 'undefined' && value instanceof HTMLElement) {
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
const elementType = value.ownerDocument?.defaultView?.HTMLElement;
|
|
12
|
+
return elementType !== undefined && value instanceof elementType;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -4,7 +4,7 @@ import type { SmithMarker } from '../traces/SmithMarker.js';
|
|
|
4
4
|
import { TraceInput } from '../samples.js';
|
|
5
5
|
import { Complex } from '../math/Complex.js';
|
|
6
6
|
import type { ChartLayers, PeripheralScales } from '../layers.js';
|
|
7
|
-
import type {
|
|
7
|
+
import type { TraceStyleOptions } from '../measurements.js';
|
|
8
8
|
/** Internal SVG backend. Owns chart elements, view transforms, and SVG gestures. */
|
|
9
9
|
export declare class SvgChartRenderer {
|
|
10
10
|
private onCursorChange;
|
|
@@ -64,6 +64,6 @@ export declare class SvgChartRenderer {
|
|
|
64
64
|
private cursorContainer;
|
|
65
65
|
private drawReactanceAxis;
|
|
66
66
|
/** Construct trace rendering without exposing chart containers or scalers to Smith. */
|
|
67
|
-
createTrace(values: TraceInput, color: string, style:
|
|
67
|
+
createTrace(values: TraceInput, color: string, style: TraceStyleOptions, onMarkerDrag: (marker: SmithMarker, dragging: boolean) => void): SmithData;
|
|
68
68
|
removeTrace(trace: SmithData): void;
|
|
69
69
|
}
|
|
@@ -93,7 +93,7 @@ export class SvgChartRenderer {
|
|
|
93
93
|
this.cursor = this.initCursor();
|
|
94
94
|
const cursorContainer = this.cursorContainer();
|
|
95
95
|
this.reactanceAxis = this.drawReactanceAxis({
|
|
96
|
-
stroke: 'var(--smithkit-boundary-
|
|
96
|
+
stroke: 'var(--smithkit-boundary-color)',
|
|
97
97
|
strokeWidth: 'var(--smithkit-boundary-width)',
|
|
98
98
|
fill: 'none',
|
|
99
99
|
});
|
|
@@ -356,7 +356,7 @@ export class SvgChartRenderer {
|
|
|
356
356
|
this.traces.forEach((d) => d.zoom(transform));
|
|
357
357
|
}
|
|
358
358
|
cursorContainer() {
|
|
359
|
-
const shape = this.drawReactanceAxis({ fill: 'transparent', stroke: 'none' });
|
|
359
|
+
const shape = this.drawReactanceAxis({ fill: 'transparent', stroke: 'none', strokeWidth: '0' });
|
|
360
360
|
shape.Element.style('pointer-events', 'all')
|
|
361
361
|
.on('pointermove.smithkit', (event) => {
|
|
362
362
|
this.cursorMove(d3.pointer(event));
|
|
@@ -44,7 +44,7 @@ export class SmithPeripheralScales extends SmithGroup {
|
|
|
44
44
|
.attr('cy', 250)
|
|
45
45
|
.attr('r', (radius) => radius)
|
|
46
46
|
.attr('fill', 'none')
|
|
47
|
-
.attr('stroke', 'var(--smithkit-scales-
|
|
47
|
+
.attr('stroke', 'var(--smithkit-scales-boundary-color)')
|
|
48
48
|
.attr('stroke-width', 1.1)
|
|
49
49
|
.attr('vector-effect', 'non-scaling-stroke');
|
|
50
50
|
this.axes.each(function (scale, index) {
|
|
@@ -62,7 +62,7 @@ export class SmithPeripheralScales extends SmithGroup {
|
|
|
62
62
|
.attr('cy', 250)
|
|
63
63
|
.attr('r', radius)
|
|
64
64
|
.attr('fill', 'none')
|
|
65
|
-
.attr('stroke', 'var(--smithkit-scales-
|
|
65
|
+
.attr('stroke', 'var(--smithkit-scales-line-color)')
|
|
66
66
|
.attr('stroke-width', 0.6)
|
|
67
67
|
.attr('vector-effect', 'non-scaling-stroke');
|
|
68
68
|
}
|
|
@@ -77,7 +77,7 @@ export class SmithPeripheralScales extends SmithGroup {
|
|
|
77
77
|
.attr('y1', y1)
|
|
78
78
|
.attr('x2', x2)
|
|
79
79
|
.attr('y2', y2)
|
|
80
|
-
.attr('stroke', 'var(--smithkit-scales-
|
|
80
|
+
.attr('stroke', 'var(--smithkit-scales-line-color)')
|
|
81
81
|
.attr('stroke-width', major ? 0.8 : 0.5)
|
|
82
82
|
.attr('vector-effect', 'non-scaling-stroke');
|
|
83
83
|
const captionDistance = Math.abs(((angle - captionAngle + 540) % 360) - 180);
|
|
@@ -93,9 +93,9 @@ export class SmithPeripheralScales extends SmithGroup {
|
|
|
93
93
|
.attr('transform', `rotate(${rotation},${x},${y})`)
|
|
94
94
|
.attr('text-anchor', 'middle')
|
|
95
95
|
.attr('dominant-baseline', 'central')
|
|
96
|
-
.attr('font-family', 'var(--smithkit-fontFamily)')
|
|
97
|
-
.attr('font-size', 'var(--smithkit-scales-
|
|
98
|
-
.attr('fill', 'var(--smithkit-scales-
|
|
96
|
+
.attr('font-family', 'var(--smithkit-text-fontFamily)')
|
|
97
|
+
.attr('font-size', 'var(--smithkit-scales-peripheral-fontSize)')
|
|
98
|
+
.attr('fill', 'var(--smithkit-scales-text-color)')
|
|
99
99
|
.text(scale.unit === 'λ' ? value.toFixed(2) : String(value));
|
|
100
100
|
}
|
|
101
101
|
}
|
|
@@ -118,11 +118,11 @@ export class SmithPeripheralScales extends SmithGroup {
|
|
|
118
118
|
.append('text')
|
|
119
119
|
.attr('class', 'peripheral-caption')
|
|
120
120
|
.attr('text-anchor', 'middle')
|
|
121
|
-
.attr('font-family', 'var(--smithkit-fontFamily)')
|
|
122
|
-
.attr('font-size', 'var(--smithkit-scales-
|
|
121
|
+
.attr('font-family', 'var(--smithkit-text-fontFamily)')
|
|
122
|
+
.attr('font-size', 'var(--smithkit-scales-peripheral-fontSize)')
|
|
123
123
|
.attr('font-weight', 500)
|
|
124
124
|
.attr('letter-spacing', 0.3)
|
|
125
|
-
.attr('fill', 'var(--smithkit-scales-
|
|
125
|
+
.attr('fill', 'var(--smithkit-scales-text-color)')
|
|
126
126
|
.append('textPath')
|
|
127
127
|
.attr('href', `#${pathId}`)
|
|
128
128
|
.attr('startOffset', '50%')
|
|
@@ -132,8 +132,8 @@ export class SmithPeripheralScales extends SmithGroup {
|
|
|
132
132
|
.attr('class', 'peripheral-indicator')
|
|
133
133
|
.attr('r', 3)
|
|
134
134
|
.attr('visibility', 'hidden')
|
|
135
|
-
.attr('fill', 'var(--smithkit-scales-
|
|
136
|
-
.attr('stroke', 'var(--smithkit-scales-
|
|
135
|
+
.attr('fill', 'var(--smithkit-scales-indicator-color)')
|
|
136
|
+
.attr('stroke', 'var(--smithkit-scales-indicator-outline)')
|
|
137
137
|
.attr('stroke-width', 1);
|
|
138
138
|
});
|
|
139
139
|
this.updateLabelVisibility();
|
|
@@ -9,7 +9,10 @@ export declare class SmithScales {
|
|
|
9
9
|
private readonly start;
|
|
10
10
|
private readonly length;
|
|
11
11
|
private readonly axes;
|
|
12
|
+
/** Configure independent scales for later mounting with draw(). */
|
|
12
13
|
constructor(appearance?: SmithAppearance);
|
|
14
|
+
/** Configure and mount immediately. String targets are CSS selectors, as in draw(). */
|
|
15
|
+
constructor(target: string | HTMLElement, appearance?: SmithAppearance);
|
|
13
16
|
/** Replace the preset and overrides without changing readings or layout. */
|
|
14
17
|
setAppearance(appearance: SmithAppearance): void;
|
|
15
18
|
draw(target: string | HTMLElement): void;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ImageExporter } from '../svg/ImageExporter.js';
|
|
2
|
+
import { ChartHost } from '../rendering/ChartHost.js';
|
|
2
3
|
import { Theme } from '../appearance/Theme.js';
|
|
3
4
|
import { SvgTheme } from '../appearance/SvgTheme.js';
|
|
4
5
|
import { select, format } from 'd3';
|
|
@@ -27,16 +28,27 @@ export class SmithScales {
|
|
|
27
28
|
.style('display', 'block')
|
|
28
29
|
.style('width', '100%')
|
|
29
30
|
.style('height', 'auto');
|
|
30
|
-
constructor(
|
|
31
|
+
constructor(targetOrAppearance = {}, configuration) {
|
|
32
|
+
const target = typeof targetOrAppearance === 'string' || ChartHost.isElement(targetOrAppearance)
|
|
33
|
+
? targetOrAppearance
|
|
34
|
+
: undefined;
|
|
35
|
+
if (target === undefined && configuration !== undefined) {
|
|
36
|
+
throw new TypeError('A container is required before the second appearance argument.');
|
|
37
|
+
}
|
|
38
|
+
const appearance = target === undefined
|
|
39
|
+
? targetOrAppearance
|
|
40
|
+
: configuration === undefined
|
|
41
|
+
? {}
|
|
42
|
+
: configuration;
|
|
31
43
|
this.setAppearance(appearance);
|
|
32
44
|
const labels = this.axes.append('g').attr('data-role', 'labels').attr('pointer-events', 'none');
|
|
33
45
|
labels
|
|
34
46
|
.append('text')
|
|
35
47
|
.attr('x', this.start)
|
|
36
48
|
.attr('y', 12)
|
|
37
|
-
.attr('font-family', 'var(--smithkit-fontFamily)')
|
|
38
|
-
.attr('font-size', 'var(--smithkit-scales-
|
|
39
|
-
.attr('fill', 'var(--smithkit-scales-
|
|
49
|
+
.attr('font-family', 'var(--smithkit-text-fontFamily)')
|
|
50
|
+
.attr('font-size', 'var(--smithkit-scales-title-fontSize)')
|
|
51
|
+
.attr('fill', 'var(--smithkit-scales-text-color)')
|
|
40
52
|
.text((scale) => scale.title);
|
|
41
53
|
labels
|
|
42
54
|
.append('text')
|
|
@@ -44,10 +56,10 @@ export class SmithScales {
|
|
|
44
56
|
.attr('data-role', 'scale-value')
|
|
45
57
|
.attr('x', this.start)
|
|
46
58
|
.attr('y', 25)
|
|
47
|
-
.attr('font-family', 'var(--smithkit-fontFamily)')
|
|
48
|
-
.attr('font-size', 'var(--smithkit-scales-
|
|
59
|
+
.attr('font-family', 'var(--smithkit-text-fontFamily)')
|
|
60
|
+
.attr('font-size', 'var(--smithkit-scales-value-fontSize)')
|
|
49
61
|
.attr('font-weight', 600)
|
|
50
|
-
.attr('fill', 'var(--smithkit-scales-
|
|
62
|
+
.attr('fill', 'var(--smithkit-scales-value-color)')
|
|
51
63
|
.text('—');
|
|
52
64
|
this.axes
|
|
53
65
|
.append('line')
|
|
@@ -56,7 +68,7 @@ export class SmithScales {
|
|
|
56
68
|
.attr('x2', this.start + this.length)
|
|
57
69
|
.attr('y1', 36)
|
|
58
70
|
.attr('y2', 36)
|
|
59
|
-
.attr('stroke', 'var(--smithkit-scales-
|
|
71
|
+
.attr('stroke', 'var(--smithkit-scales-line-color)')
|
|
60
72
|
.attr('stroke-width', 1);
|
|
61
73
|
const start = this.start;
|
|
62
74
|
const length = this.length;
|
|
@@ -70,7 +82,7 @@ export class SmithScales {
|
|
|
70
82
|
ticks
|
|
71
83
|
.append('line')
|
|
72
84
|
.attr('y2', 5)
|
|
73
|
-
.attr('stroke', 'var(--smithkit-scales-
|
|
85
|
+
.attr('stroke', 'var(--smithkit-scales-line-color)')
|
|
74
86
|
.attr('stroke-width', 1);
|
|
75
87
|
select(this)
|
|
76
88
|
.select('[data-role=labels]')
|
|
@@ -80,9 +92,9 @@ export class SmithScales {
|
|
|
80
92
|
.attr('transform', (value) => `translate(${start + length * scale.position(value)},36)`)
|
|
81
93
|
.append('text')
|
|
82
94
|
.attr('y', 17)
|
|
83
|
-
.attr('font-size', 'var(--smithkit-scales-fontSize)')
|
|
84
|
-
.attr('font-family', 'var(--smithkit-fontFamily)')
|
|
85
|
-
.attr('fill', 'var(--smithkit-scales-
|
|
95
|
+
.attr('font-size', 'var(--smithkit-scales-text-fontSize)')
|
|
96
|
+
.attr('font-family', 'var(--smithkit-text-fontFamily)')
|
|
97
|
+
.attr('fill', 'var(--smithkit-scales-text-color)')
|
|
86
98
|
.attr('text-anchor', (_, i) => i === 0 ? 'start' : i === scale.values.length - 1 ? 'end' : 'middle')
|
|
87
99
|
.text((value) => (value === Infinity ? '∞' : String(value)));
|
|
88
100
|
});
|
|
@@ -93,11 +105,20 @@ export class SmithScales {
|
|
|
93
105
|
.attr('cx', this.start)
|
|
94
106
|
.attr('cy', 36)
|
|
95
107
|
.attr('r', 4)
|
|
96
|
-
.attr('fill', 'var(--smithkit-scales-
|
|
97
|
-
.attr('stroke', 'var(--smithkit-scales-
|
|
108
|
+
.attr('fill', 'var(--smithkit-scales-indicator-color)')
|
|
109
|
+
.attr('stroke', 'var(--smithkit-scales-indicator-outline)')
|
|
98
110
|
.attr('stroke-width', 1);
|
|
99
111
|
labels.raise();
|
|
100
112
|
this.axes.append('title').text((scale) => scale.description ?? scale.title);
|
|
113
|
+
if (target !== undefined) {
|
|
114
|
+
try {
|
|
115
|
+
this.draw(target);
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
this.destroy();
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
101
122
|
}
|
|
102
123
|
/** Replace the preset and overrides without changing readings or layout. */
|
|
103
124
|
setAppearance(appearance) {
|
|
@@ -147,7 +168,7 @@ export class SmithScales {
|
|
|
147
168
|
.style('visibility', 'visible');
|
|
148
169
|
}
|
|
149
170
|
/** Export mounted scales, optionally with a separate reading and its description. */
|
|
150
|
-
toSvg(options) {
|
|
171
|
+
toSvg(options = {}) {
|
|
151
172
|
this.assertAlive();
|
|
152
173
|
const container = this.container.node();
|
|
153
174
|
const style = getComputedStyle(container);
|
|
@@ -157,11 +178,11 @@ export class SmithScales {
|
|
|
157
178
|
: undefined, readout?.label
|
|
158
179
|
? {
|
|
159
180
|
text: readout.label,
|
|
160
|
-
color: style.getPropertyValue('--smithkit-scales-
|
|
161
|
-
fontFamily: style.getPropertyValue('--smithkit-fontFamily').trim(),
|
|
181
|
+
color: style.getPropertyValue('--smithkit-scales-text-color').trim(),
|
|
182
|
+
fontFamily: style.getPropertyValue('--smithkit-text-fontFamily').trim(),
|
|
162
183
|
}
|
|
163
184
|
: undefined);
|
|
164
|
-
return
|
|
185
|
+
return ImageExporter.svg([source], options);
|
|
165
186
|
}
|
|
166
187
|
/** Export mounted scales as PNG without changing their live readings. */
|
|
167
188
|
async toPng(options = {}) {
|
|
@@ -81,7 +81,6 @@ export class LabelLayout {
|
|
|
81
81
|
label,
|
|
82
82
|
order,
|
|
83
83
|
scale,
|
|
84
|
-
matrix: matrix,
|
|
85
84
|
baseSize: parseFloat(style(label).fontSize),
|
|
86
85
|
priority: Number(label.dataset.labelPriority ?? 0),
|
|
87
86
|
},
|
|
@@ -93,10 +92,18 @@ export class LabelLayout {
|
|
|
93
92
|
this.resizedFonts.set(label, label.style.fontSize);
|
|
94
93
|
label.style.fontSize = `${9 / scale}px`;
|
|
95
94
|
}
|
|
95
|
+
// WebKit can retain the old em offset after the font size changes.
|
|
96
|
+
// Reapply it before measuring so live and exported SVG use the same position.
|
|
97
|
+
const dx = label.getAttribute('dx');
|
|
98
|
+
if (dx?.endsWith('em')) {
|
|
99
|
+
label.setAttribute('dx', dx);
|
|
100
|
+
}
|
|
96
101
|
}
|
|
97
102
|
const measured = candidates.map((entry) => ({
|
|
98
103
|
...entry,
|
|
99
|
-
|
|
104
|
+
// Screen bounds include the browser's glyph/paint envelope. Normalizing
|
|
105
|
+
// them keeps collision decisions independent of the current zoom.
|
|
106
|
+
box: LabelLayout.transformBox(entry.label.getBoundingClientRect(), normalize),
|
|
100
107
|
}));
|
|
101
108
|
measured.sort((a, b) => b.priority - a.priority || a.order - b.order);
|
|
102
109
|
const occupied = [];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { SmithGroup } from '../svg/SmithGroup.js';
|
|
2
|
-
import type { TraceStyle, MarkerSelectionStrategy } from '../measurements.js';
|
|
2
|
+
import type { TraceStyle, TraceStyleOptions, MarkerSelectionStrategy } from '../measurements.js';
|
|
3
3
|
import { SmithMarker } from './SmithMarker.js';
|
|
4
4
|
import { SmithScaler } from '../svg/SmithScaler.js';
|
|
5
5
|
import type { TraceInput, TraceSample } from '../samples.js';
|
|
@@ -22,7 +22,7 @@ export declare class SmithData {
|
|
|
22
22
|
private selectHandler;
|
|
23
23
|
private visible;
|
|
24
24
|
private handler;
|
|
25
|
-
constructor(data: TraceInput, color: string, transform: TraceTransform, container: SmithGroup, scaler: SmithScaler, markerDragHandler?: ((marker: SmithMarker, dragging: boolean) => void) | undefined, markerContainer?: SmithGroup, style?:
|
|
25
|
+
constructor(data: TraceInput, color: string, transform: TraceTransform, container: SmithGroup, scaler: SmithScaler, markerDragHandler?: ((marker: SmithMarker, dragging: boolean) => void) | undefined, markerContainer?: SmithGroup, style?: TraceStyleOptions);
|
|
26
26
|
setViewportScale(scale: number): void;
|
|
27
27
|
zoom(transform: TraceTransform): void;
|
|
28
28
|
addMarker(sampleIndex?: number): number;
|
|
@@ -40,7 +40,7 @@ export declare class SmithData {
|
|
|
40
40
|
path: string;
|
|
41
41
|
} | undefined;
|
|
42
42
|
get Style(): TraceStyle;
|
|
43
|
-
setStyle(options:
|
|
43
|
+
setStyle(options: TraceStyleOptions): void;
|
|
44
44
|
setVisible(visible: boolean): void;
|
|
45
45
|
private moveMarker;
|
|
46
46
|
private updateReading;
|
|
@@ -45,6 +45,7 @@ export class SmithMarker extends SmithShape {
|
|
|
45
45
|
.attr('fill', 'none')
|
|
46
46
|
.attr('pointer-events', 'all')
|
|
47
47
|
.attr('stroke', 'none')
|
|
48
|
+
.attr('stroke-width', 0)
|
|
48
49
|
.attr('aria-hidden', 'true');
|
|
49
50
|
this.focusRing = g
|
|
50
51
|
.append('g')
|
|
@@ -53,8 +54,8 @@ export class SmithMarker extends SmithShape {
|
|
|
53
54
|
.attr('pointer-events', 'none')
|
|
54
55
|
.attr('aria-hidden', 'true');
|
|
55
56
|
for (const [stroke, width] of [
|
|
56
|
-
['var(--smithkit-marker-
|
|
57
|
-
['var(--smithkit-marker-
|
|
57
|
+
['var(--smithkit-marker-focus-halo)', 5],
|
|
58
|
+
['var(--smithkit-marker-focus-color)', 2.5],
|
|
58
59
|
]) {
|
|
59
60
|
this.focusRing
|
|
60
61
|
.append('circle')
|
|
@@ -66,17 +67,17 @@ export class SmithMarker extends SmithShape {
|
|
|
66
67
|
this.triangle = g
|
|
67
68
|
.append('polygon')
|
|
68
69
|
.attr('stroke', 'none')
|
|
69
|
-
.attr('fill', 'var(--smithkit-marker-
|
|
70
|
+
.attr('fill', 'var(--smithkit-marker-outline-color)');
|
|
70
71
|
this.inner = g.append('polygon').attr('stroke', 'none').attr('fill', color);
|
|
71
72
|
this.text = g
|
|
72
73
|
.append('text')
|
|
73
74
|
.attr('pointer-events', 'none')
|
|
74
75
|
.attr('aria-hidden', 'true')
|
|
75
|
-
.attr('font-family', 'var(--smithkit-fontFamily)')
|
|
76
|
+
.attr('font-family', 'var(--smithkit-text-fontFamily)')
|
|
76
77
|
.attr('font-weight', 'normal')
|
|
77
78
|
.attr('text-anchor', 'middle')
|
|
78
79
|
.attr('dominant-baseline', 'middle')
|
|
79
|
-
.attr('fill', 'var(--smithkit-marker-
|
|
80
|
+
.attr('fill', 'var(--smithkit-marker-text-color)')
|
|
80
81
|
.text(marker.toString());
|
|
81
82
|
this.zoom(1);
|
|
82
83
|
const drag = d3
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SmithGroup } from '../svg/SmithGroup.js';
|
|
2
2
|
import { SmithScaler } from '../svg/SmithScaler.js';
|
|
3
|
-
import type { TraceStyle } from '../measurements.js';
|
|
3
|
+
import type { TraceStyle, TraceStyleOptions } from '../measurements.js';
|
|
4
4
|
import { TraceBuffer } from './TraceBuffer.js';
|
|
5
5
|
export interface TraceTransform {
|
|
6
6
|
x: number;
|
|
@@ -19,7 +19,7 @@ export declare class TraceRenderer {
|
|
|
19
19
|
private group;
|
|
20
20
|
private lineDetail;
|
|
21
21
|
private lineIndices;
|
|
22
|
-
constructor(data: TraceBuffer, color: string, transform: TraceTransform, container: SmithGroup, scaler: SmithScaler, style?:
|
|
22
|
+
constructor(data: TraceBuffer, color: string, transform: TraceTransform, container: SmithGroup, scaler: SmithScaler, style?: TraceStyleOptions);
|
|
23
23
|
private drawTrace;
|
|
24
24
|
private selectLineIndices;
|
|
25
25
|
private linePath;
|
|
@@ -35,7 +35,7 @@ export declare class TraceRenderer {
|
|
|
35
35
|
private zoomDataPoints;
|
|
36
36
|
setColor(color: string): void;
|
|
37
37
|
get Style(): TraceStyle;
|
|
38
|
-
setStyle(options:
|
|
38
|
+
setStyle(options: TraceStyleOptions): void;
|
|
39
39
|
private redraw;
|
|
40
40
|
setVisible(visible: boolean): void;
|
|
41
41
|
update(data: TraceBuffer): void;
|