@stocksharp/diagram 0.2.2 → 0.3.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.
Files changed (68) hide show
  1. package/README.md +12 -0
  2. package/dist/esm/canvas-renderer.js +28 -22
  3. package/dist/esm/canvas-renderer.js.map +1 -1
  4. package/dist/esm/core/action-registry.js +24 -0
  5. package/dist/esm/core/action-registry.js.map +1 -1
  6. package/dist/esm/core/document.js +85 -28
  7. package/dist/esm/core/document.js.map +1 -1
  8. package/dist/esm/core/json.js +17 -0
  9. package/dist/esm/core/json.js.map +1 -0
  10. package/dist/esm/core/model.js +4 -0
  11. package/dist/esm/core/model.js.map +1 -1
  12. package/dist/esm/core/state.js +16 -2
  13. package/dist/esm/core/state.js.map +1 -1
  14. package/dist/esm/diagram/catalog.js +17 -5
  15. package/dist/esm/diagram/catalog.js.map +1 -1
  16. package/dist/esm/diagram/event-emitter.js +10 -0
  17. package/dist/esm/diagram/event-emitter.js.map +1 -1
  18. package/dist/esm/diagram/stocksharp-diagram.js +69 -57
  19. package/dist/esm/diagram/stocksharp-diagram.js.map +1 -1
  20. package/dist/esm/diagram/types.js +2 -1
  21. package/dist/esm/diagram/types.js.map +1 -1
  22. package/dist/esm/embed.js +129 -39
  23. package/dist/esm/embed.js.map +1 -1
  24. package/dist/esm/index.js +1 -1
  25. package/dist/esm/index.js.map +1 -1
  26. package/dist/ssdiagram.js +314 -147
  27. package/dist/ssdiagram.js.map +4 -4
  28. package/dist/types/canvas-renderer.d.ts +3 -5
  29. package/dist/types/canvas-renderer.d.ts.map +1 -1
  30. package/dist/types/core/action-registry.d.ts +7 -0
  31. package/dist/types/core/action-registry.d.ts.map +1 -1
  32. package/dist/types/core/document.d.ts.map +1 -1
  33. package/dist/types/core/json.d.ts +11 -0
  34. package/dist/types/core/json.d.ts.map +1 -0
  35. package/dist/types/core/model.d.ts +10 -1
  36. package/dist/types/core/model.d.ts.map +1 -1
  37. package/dist/types/core/state.d.ts +24 -1
  38. package/dist/types/core/state.d.ts.map +1 -1
  39. package/dist/types/diagram/api.d.ts +13 -6
  40. package/dist/types/diagram/api.d.ts.map +1 -1
  41. package/dist/types/diagram/catalog.d.ts +2 -1
  42. package/dist/types/diagram/catalog.d.ts.map +1 -1
  43. package/dist/types/diagram/event-emitter.d.ts +6 -1
  44. package/dist/types/diagram/event-emitter.d.ts.map +1 -1
  45. package/dist/types/diagram/palette.d.ts +1 -1
  46. package/dist/types/diagram/palette.d.ts.map +1 -1
  47. package/dist/types/diagram/stocksharp-diagram.d.ts +32 -21
  48. package/dist/types/diagram/stocksharp-diagram.d.ts.map +1 -1
  49. package/dist/types/diagram/types.d.ts +4 -4
  50. package/dist/types/diagram/types.d.ts.map +1 -1
  51. package/dist/types/embed.d.ts.map +1 -1
  52. package/dist/types/index.d.ts +3 -3
  53. package/dist/types/index.d.ts.map +1 -1
  54. package/package.json +2 -2
  55. package/src/canvas-renderer.ts +26 -24
  56. package/src/core/action-registry.ts +25 -0
  57. package/src/core/document.ts +91 -31
  58. package/src/core/json.ts +16 -0
  59. package/src/core/model.ts +14 -1
  60. package/src/core/state.ts +41 -3
  61. package/src/diagram/api.ts +14 -5
  62. package/src/diagram/catalog.ts +18 -6
  63. package/src/diagram/event-emitter.ts +12 -1
  64. package/src/diagram/palette.ts +1 -1
  65. package/src/diagram/stocksharp-diagram.ts +91 -75
  66. package/src/diagram/types.ts +6 -5
  67. package/src/embed.ts +149 -40
  68. package/src/index.ts +4 -0
package/README.md CHANGED
@@ -153,6 +153,18 @@ node is rendered as a transient red placeholder whose hover tooltip names the
153
153
  missing type. Sites can localize that message through
154
154
  `data-diagram-missing-element="Missing: {typeId}"` on the host.
155
155
 
156
+ Every text the embedded control shows comes from the host, so a translated page
157
+ carries no English leftovers:
158
+
159
+ | Host attribute | What it renames |
160
+ |---|---|
161
+ | `data-diagram-fullscreen="Enter\|Exit"` | the fullscreen button's tooltip, collapsed and expanded |
162
+ | `data-diagram-errors="Load\|Empty\|Draw"` | the three failure notes shown in place of a diagram |
163
+ | `data-diagram-missing-element="Missing: {typeId}"` | the placeholder for an element the palette lacks |
164
+
165
+ The same labels are available to custom integrations as the `fullscreenLabels`
166
+ option and `setFullscreenLabels()` on `StockSharpDiagram`.
167
+
156
168
  ### Node actions and errors
157
169
 
158
170
  Double-click handling is opt-in. Give only the node types controlled by the
@@ -5,6 +5,8 @@
5
5
  // selection, delete, zoom/pan, load/save round-trip.
6
6
  import { createDiagramDocument, parseDiagramDocument } from './core/document.js';
7
7
  import { DiagramCommandHistory } from './core/history.js';
8
+ import { setJsonKey } from './core/json.js';
9
+ import { toPortDynamicMode } from './core/model.js';
8
10
  import { cloneDiagramRuntimeState, createDiagramNodeRuntimeState, createDiagramPortRuntimeState, createDiagramRuntimeState, createEditableDiagramPermissions, createReadOnlyDiagramPermissions, } from './core/state.js';
9
11
  const SCREEN_RENDER_OPTIONS = {
10
12
  grid: true,
@@ -26,7 +28,7 @@ function copyJsonObject(value) {
26
28
  return {};
27
29
  const result = {};
28
30
  for (const [key, item] of Object.entries(value))
29
- result[key] = copyJsonValue(item);
31
+ setJsonKey(result, key, copyJsonValue(item));
30
32
  return result;
31
33
  }
32
34
  function copyParameters(value) {
@@ -65,7 +67,7 @@ export class PortModel {
65
67
  this.maxLinks = typeof init.maxLinks === 'number' ? init.maxLinks : 0;
66
68
  this.availableTypes = [...(init.availableTypes ?? [])];
67
69
  this.isDynamic = init.isDynamic ?? false;
68
- this.dynamicMode = init.dynamicMode ?? '';
70
+ this.dynamicMode = toPortDynamicMode(init.dynamicMode);
69
71
  this.isSibling = init.isSibling ?? false;
70
72
  this.metadata = copyJsonObject(init.metadata);
71
73
  }
@@ -161,10 +163,8 @@ export class LinkModel {
161
163
  };
162
164
  }
163
165
  }
164
- const HEADER_H = 22;
165
166
  const PORT_R = 6;
166
167
  const PORT_ROW_H = 20;
167
- const NODE_PAD = 10;
168
168
  const RELINK_HANDLE_PX = 8; // WPF relink adornment is an 8x8 diamond
169
169
  const RELINK_DRAG_THRESHOLD_PX = 4;
170
170
  const PORT_SQ = 9; // socket square size — sits outside the node
@@ -241,8 +241,6 @@ export class Diagram {
241
241
  this.dragNode = null;
242
242
  this.dragStart = []; // group-drag origin
243
243
  this.dragAnchor = { wx: 0, wy: 0 };
244
- this.dragDX = 0;
245
- this.dragDY = 0;
246
244
  this.panning = false;
247
245
  this.panX = 0;
248
246
  this.panY = 0;
@@ -894,7 +892,7 @@ export class Diagram {
894
892
  if (value === undefined)
895
893
  delete node.paramValues[name];
896
894
  else
897
- node.paramValues[name] = value;
895
+ setJsonKey(node.paramValues, name, value);
898
896
  });
899
897
  }
900
898
  setShowNodeMessages(show) {
@@ -985,7 +983,7 @@ export class Diagram {
985
983
  if (node.loadError.length === 0)
986
984
  continue;
987
985
  const state = createDiagramNodeRuntimeState();
988
- state.error = { kind: 'load', message: node.loadError, pulse: ++this.runtimePulse };
986
+ state.errors.load = { kind: 'load', message: node.loadError, pulse: ++this.runtimePulse };
989
987
  this.runtimeState.nodes[node.id] = state;
990
988
  }
991
989
  if (Object.keys(this.runtimeState.nodes).length > 0)
@@ -1190,14 +1188,16 @@ export class Diagram {
1190
1188
  else if (previous.globalError?.pulse !== this.runtimeState.globalError.pulse) {
1191
1189
  this.globalErrorFlashStart = performance.now();
1192
1190
  }
1193
- this.runtimePulse = Math.max(this.runtimePulse, this.runtimeState.globalError?.pulse ?? 0, ...Object.values(this.runtimeState.nodes).map((node) => node.error?.pulse ?? 0));
1191
+ this.runtimePulse = Math.max(this.runtimePulse, this.runtimeState.globalError?.pulse ?? 0, ...Object.values(this.runtimeState.nodes)
1192
+ .flatMap((node) => [node.errors.runtime?.pulse ?? 0, node.errors.load?.pulse ?? 0]));
1194
1193
  for (const node of this.nodes) {
1195
- const error = this.runtimeState.nodes[node.id]?.error ?? null;
1196
- const previousError = previous.nodes[node.id]?.error ?? null;
1197
- node.runtimeError = error?.kind === 'runtime' ? error.message : '';
1198
- node.loadError = error?.kind === 'load' ? error.message : '';
1199
- if (error?.kind === 'runtime') {
1200
- if (previousError?.kind !== 'runtime' || previousError.pulse !== error.pulse) {
1194
+ const errors = this.runtimeState.nodes[node.id]?.errors;
1195
+ const previousRuntime = previous.nodes[node.id]?.errors.runtime;
1196
+ const runtimeError = errors?.runtime;
1197
+ node.runtimeError = runtimeError?.message ?? '';
1198
+ node.loadError = errors?.load?.message ?? '';
1199
+ if (runtimeError !== undefined) {
1200
+ if (previousRuntime === undefined || previousRuntime.pulse !== runtimeError.pulse) {
1201
1201
  node.errorFlashStart = performance.now();
1202
1202
  }
1203
1203
  }
@@ -1257,7 +1257,14 @@ export class Diagram {
1257
1257
  const state = this.getRuntimeState();
1258
1258
  const nodeState = state.nodes[id] ?? createDiagramNodeRuntimeState();
1259
1259
  state.nodes[id] = nodeState;
1260
- nodeState.error = message.length === 0 ? null : { kind, message, pulse: ++this.runtimePulse };
1260
+ // Only this kind's slot is written, so an error of the other kind that is
1261
+ // already on the node survives.
1262
+ if (message.length === 0)
1263
+ delete nodeState.errors[kind];
1264
+ else if (kind === 'load')
1265
+ nodeState.errors.load = { kind, message, pulse: ++this.runtimePulse };
1266
+ else
1267
+ nodeState.errors.runtime = { kind, message, pulse: ++this.runtimePulse };
1261
1268
  this.runtimeState = state;
1262
1269
  this.emitRuntimeStateChanged();
1263
1270
  return true;
@@ -1274,12 +1281,11 @@ export class Diagram {
1274
1281
  node.loadError = '';
1275
1282
  const state = this.getRuntimeState();
1276
1283
  const nodeState = state.nodes[id];
1277
- if (nodeState !== undefined && (kind === undefined || nodeState.error?.kind === kind)) {
1278
- nodeState.error = node.runtimeError.length > 0
1279
- ? { kind: 'runtime', message: node.runtimeError, pulse: ++this.runtimePulse }
1280
- : node.loadError.length > 0
1281
- ? { kind: 'load', message: node.loadError, pulse: ++this.runtimePulse }
1282
- : null;
1284
+ if (nodeState !== undefined) {
1285
+ if (kind === undefined || kind === 'runtime')
1286
+ delete nodeState.errors.runtime;
1287
+ if (kind === undefined || kind === 'load')
1288
+ delete nodeState.errors.load;
1283
1289
  }
1284
1290
  this.runtimeState = state;
1285
1291
  this.emitRuntimeStateChanged();