@stocksharp/diagram 0.1.0 → 0.2.1
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 +24 -14
- package/dist/esm/canvas-renderer.js +34 -5
- package/dist/esm/canvas-renderer.js.map +1 -1
- package/dist/esm/diagram/stocksharp-diagram.js +2 -1
- package/dist/esm/diagram/stocksharp-diagram.js.map +1 -1
- package/dist/ssdiagram.js +30 -5
- package/dist/ssdiagram.js.map +2 -2
- package/dist/types/canvas-renderer.d.ts +5 -0
- package/dist/types/canvas-renderer.d.ts.map +1 -1
- package/dist/types/diagram/api.d.ts +3 -0
- package/dist/types/diagram/api.d.ts.map +1 -1
- package/dist/types/diagram/stocksharp-diagram.d.ts.map +1 -1
- package/package.json +5 -2
- package/src/canvas-renderer.ts +35 -5
- package/src/diagram/api.ts +3 -0
- package/src/diagram/stocksharp-diagram.ts +2 -0
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# StockSharp JS Strategy Diagram
|
|
2
2
|
|
|
3
3
|
[](https://github.com/StockSharp/Diagram/actions/workflows/ci.yml)
|
|
4
4
|
[](https://www.npmjs.com/package/@stocksharp/diagram)
|
|
@@ -11,6 +11,7 @@ renderer, read-only web embed, and versioned diagram document model.
|
|
|
11
11
|

|
|
12
12
|
|
|
13
13
|
[Live demo](https://stocksharp.github.io/Diagram/demo/) ·
|
|
14
|
+
[StockSharp website](https://stocksharp.com/) ·
|
|
14
15
|
[GitHub repository](https://github.com/StockSharp/Diagram) ·
|
|
15
16
|
[Issue tracker](https://github.com/StockSharp/Diagram/issues)
|
|
16
17
|
|
|
@@ -311,7 +312,9 @@ npm test
|
|
|
311
312
|
npm run build
|
|
312
313
|
npm run serve
|
|
313
314
|
npm run pack:check
|
|
314
|
-
npm run release:
|
|
315
|
+
npm run release:patch
|
|
316
|
+
npm run release:minor
|
|
317
|
+
npm run release:major
|
|
315
318
|
npm run api:check
|
|
316
319
|
npm run api:update # only after reviewing an intentional public API change
|
|
317
320
|
npm run test:browser
|
|
@@ -323,23 +326,30 @@ The browser suite covers Chromium smoke, interaction and lifecycle scenarios
|
|
|
323
326
|
at DPR 1 and 2.
|
|
324
327
|
|
|
325
328
|
CI verifies type checking, the reviewed declaration snapshot, unit/integration
|
|
326
|
-
tests,
|
|
327
|
-
|
|
329
|
+
tests, all bundles and tarball contents. The Playwright browser suite runs
|
|
330
|
+
locally via `npm run test:browser` (not in CI — the headless unit tests already
|
|
331
|
+
cover the same behaviour). GitHub Pages publishes the demo from `main`.
|
|
328
332
|
|
|
329
|
-
Publishing is
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
artifact to the release, and publishes that tarball to npm with provenance.
|
|
333
|
-
|
|
334
|
-
The first publication needs a short-lived npm granular access token in the
|
|
335
|
-
repository Actions secret `NPM_TOKEN`. After `@stocksharp/diagram` exists on npm,
|
|
336
|
-
configure tokenless trusted publishing, then remove the secret and revoke the
|
|
337
|
-
bootstrap token:
|
|
333
|
+
Publishing is driven by the version in `package.json`. `release.yml` runs on
|
|
334
|
+
every push to `main` and publishes only when that version is not yet on npm, so
|
|
335
|
+
an ordinary push is a no-op. To cut a release, bump the version and push:
|
|
338
336
|
|
|
339
337
|
```sh
|
|
340
|
-
npm
|
|
338
|
+
npm run release:patch # or release:minor / release:major
|
|
339
|
+
git push
|
|
341
340
|
```
|
|
342
341
|
|
|
342
|
+
The new version triggers `release.yml`, which rebuilds and tests the repository,
|
|
343
|
+
publishes to npm with provenance, then creates the `v<version>` tag and GitHub
|
|
344
|
+
Release. A failed publication can be retried from the workflow's `Run workflow`
|
|
345
|
+
action; already-published versions are detected and skipped.
|
|
346
|
+
|
|
347
|
+
Publishing authenticates through npm **trusted publishing (OIDC)** — there is no
|
|
348
|
+
`NPM_TOKEN` secret. The workflow grants `id-token: write`, and npm exchanges the
|
|
349
|
+
GitHub OIDC token for a short-lived publish token. The npm Trusted Publisher is
|
|
350
|
+
bound to the workflow filename `release.yml`, so do not rename that workflow
|
|
351
|
+
without updating the trusted publisher configuration on npmjs first.
|
|
352
|
+
|
|
343
353
|
## License
|
|
344
354
|
|
|
345
355
|
Copyright © 2010-present StockSharp Platform LLC and/or its affiliates. All
|
|
@@ -170,6 +170,7 @@ const RELINK_DRAG_THRESHOLD_PX = 4;
|
|
|
170
170
|
const PORT_SQ = 9; // socket square size — sits outside the node
|
|
171
171
|
const LINK_STUB = 22; // min horizontal lead-in/out before the elbow
|
|
172
172
|
const LINK_HOP = 5; // jump-over arc radius at crossings
|
|
173
|
+
const LINK_CORNER = 8; // corner rounding radius at elbows
|
|
173
174
|
const SNAP_PX = 32; // plug↔socket magnet radius (screen px)
|
|
174
175
|
const DEFAULT_GRID_SIZE = 28;
|
|
175
176
|
const ZOOM_MIN = 0.15;
|
|
@@ -1345,6 +1346,8 @@ export class Diagram {
|
|
|
1345
1346
|
this.opts.gridColor = t.gridColor;
|
|
1346
1347
|
if (t.linkMaxLightness !== undefined)
|
|
1347
1348
|
this.opts.linkMaxLightness = t.linkMaxLightness;
|
|
1349
|
+
if (t.typedLinkColors !== undefined)
|
|
1350
|
+
this.opts.typedLinkColors = t.typedLinkColors;
|
|
1348
1351
|
if (t.overviewBackground !== undefined)
|
|
1349
1352
|
this.opts.overviewBackground = t.overviewBackground;
|
|
1350
1353
|
if (t.overviewBorderColor !== undefined)
|
|
@@ -1455,6 +1458,16 @@ export class Diagram {
|
|
|
1455
1458
|
const base = map[type] ?? `hsl(${hashHue(type)}, 62%, 58%)`;
|
|
1456
1459
|
return maxL !== undefined ? clampLightness(base, maxL) : base;
|
|
1457
1460
|
}
|
|
1461
|
+
// Selection/hover accent. The dark-canvas blue washes out on a light canvas, so a light theme
|
|
1462
|
+
// (linkMaxLightness < 0.5) inverts to a darker, more saturated blue that stays clearly visible.
|
|
1463
|
+
selectionColor() {
|
|
1464
|
+
const maxL = this.opts.linkMaxLightness;
|
|
1465
|
+
return maxL !== undefined && maxL < 0.5 ? '#0d6efd' : '#4aa3ff';
|
|
1466
|
+
}
|
|
1467
|
+
linkHoverColor() {
|
|
1468
|
+
const maxL = this.opts.linkMaxLightness;
|
|
1469
|
+
return maxL !== undefined && maxL < 0.5 ? '#6aa9f0' : '#cfe3ff';
|
|
1470
|
+
}
|
|
1458
1471
|
// ---- hit testing (world coords) ---------------------------------
|
|
1459
1472
|
portAt(wx, wy) {
|
|
1460
1473
|
for (let i = this.nodes.length - 1; i >= 0; i -= 1) {
|
|
@@ -2379,14 +2392,16 @@ export class Diagram {
|
|
|
2379
2392
|
if (a === null || b === null)
|
|
2380
2393
|
continue;
|
|
2381
2394
|
const fp = this.nodes.find((n) => n.id === l.from)?.outPorts.find((p) => p.id === l.fromPort);
|
|
2382
|
-
const baseColor =
|
|
2395
|
+
const baseColor = (this.opts.typedLinkColors ?? false) && fp !== undefined
|
|
2396
|
+
? this.portColor(fp.type)
|
|
2397
|
+
: this.portColor('');
|
|
2383
2398
|
const state = options.selection && l === this.selectedLink
|
|
2384
2399
|
? 'sel'
|
|
2385
2400
|
: options.transient && (l === this.hoveredLink
|
|
2386
2401
|
|| (hoveredNode !== null && (l.from === hoveredNode.id || l.to === hoveredNode.id)))
|
|
2387
2402
|
? 'hov'
|
|
2388
2403
|
: 'norm';
|
|
2389
|
-
const color = state === 'sel' ?
|
|
2404
|
+
const color = state === 'sel' ? this.selectionColor() : state === 'hov' ? this.linkHoverColor() : baseColor;
|
|
2390
2405
|
const width = state === 'sel' ? 3 : state === 'hov' ? 2.6 : 2;
|
|
2391
2406
|
const pts = this.routeLink(a, b, new Set([l.from, l.to]));
|
|
2392
2407
|
this.strokeRoute(pts, color, width, prior);
|
|
@@ -2599,7 +2614,7 @@ export class Diagram {
|
|
|
2599
2614
|
ctx.fillStyle = hasLoadError ? ERROR_BACKGROUND : active ? '#ffd1dc' : n.color;
|
|
2600
2615
|
ctx.fill();
|
|
2601
2616
|
ctx.lineWidth = selected ? 2 : 1.5;
|
|
2602
|
-
ctx.strokeStyle = selected ?
|
|
2617
|
+
ctx.strokeStyle = selected ? this.selectionColor() : n.border;
|
|
2603
2618
|
ctx.stroke();
|
|
2604
2619
|
if (hasLoadError || hasRuntimeError) {
|
|
2605
2620
|
let alpha = 1;
|
|
@@ -2706,6 +2721,20 @@ export class Diagram {
|
|
|
2706
2721
|
ctx.beginPath();
|
|
2707
2722
|
ctx.moveTo(pts[0][0], pts[0][1]);
|
|
2708
2723
|
const H = LINK_HOP;
|
|
2724
|
+
// End a segment at its elbow with a rounded corner toward the next point (arcTo), clamped so it never
|
|
2725
|
+
// eats more than half of either adjacent segment. The final segment ends straight into the port.
|
|
2726
|
+
const finish = (i, x1, y1, x2, y2) => {
|
|
2727
|
+
if (i < pts.length - 1) {
|
|
2728
|
+
const nx = pts[i + 1][0];
|
|
2729
|
+
const ny = pts[i + 1][1];
|
|
2730
|
+
const seg1 = Math.abs(x2 - x1) + Math.abs(y2 - y1);
|
|
2731
|
+
const seg2 = Math.abs(nx - x2) + Math.abs(ny - y2);
|
|
2732
|
+
ctx.arcTo(x2, y2, nx, ny, Math.min(LINK_CORNER, seg1 / 2, seg2 / 2));
|
|
2733
|
+
}
|
|
2734
|
+
else {
|
|
2735
|
+
ctx.lineTo(x2, y2);
|
|
2736
|
+
}
|
|
2737
|
+
};
|
|
2709
2738
|
for (let i = 1; i < pts.length; i += 1) {
|
|
2710
2739
|
const [x1, y1] = pts[i - 1];
|
|
2711
2740
|
const [x2, y2] = pts[i];
|
|
@@ -2723,7 +2752,7 @@ export class Diagram {
|
|
|
2723
2752
|
else
|
|
2724
2753
|
ctx.arc(cx, y1, H, 0, Math.PI, true);
|
|
2725
2754
|
}
|
|
2726
|
-
|
|
2755
|
+
finish(i, x1, y1, x2, y2);
|
|
2727
2756
|
}
|
|
2728
2757
|
else if (x1 === x2 && y1 !== y2) {
|
|
2729
2758
|
const dir = y2 > y1 ? 1 : -1;
|
|
@@ -2739,7 +2768,7 @@ export class Diagram {
|
|
|
2739
2768
|
else
|
|
2740
2769
|
ctx.arc(x1, cy, H, Math.PI / 2, -Math.PI / 2, true);
|
|
2741
2770
|
}
|
|
2742
|
-
|
|
2771
|
+
finish(i, x1, y1, x2, y2);
|
|
2743
2772
|
}
|
|
2744
2773
|
else {
|
|
2745
2774
|
ctx.lineTo(x2, y2);
|