@stocksharp/diagram 0.5.0 → 0.6.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 +72 -11
- package/dist/esm/canvas-renderer.js +25 -20
- package/dist/esm/canvas-renderer.js.map +1 -1
- package/dist/esm/diagram/context-menu.js +66 -19
- package/dist/esm/diagram/context-menu.js.map +1 -1
- package/dist/esm/diagram/stocksharp-diagram.js +42 -8
- package/dist/esm/diagram/stocksharp-diagram.js.map +1 -1
- package/dist/esm/embed.js +7 -4
- package/dist/esm/embed.js.map +1 -1
- package/dist/esm/i18n.js +15 -4
- package/dist/esm/i18n.js.map +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/ssdiagram.js +124 -49
- package/dist/ssdiagram.js.map +2 -2
- package/dist/types/canvas-renderer.d.ts +1 -0
- package/dist/types/canvas-renderer.d.ts.map +1 -1
- package/dist/types/diagram/api.d.ts +7 -1
- package/dist/types/diagram/api.d.ts.map +1 -1
- package/dist/types/diagram/context-menu.d.ts +2 -0
- package/dist/types/diagram/context-menu.d.ts.map +1 -1
- package/dist/types/diagram/stocksharp-diagram.d.ts +7 -0
- package/dist/types/diagram/stocksharp-diagram.d.ts.map +1 -1
- package/dist/types/embed.d.ts.map +1 -1
- package/dist/types/i18n.d.ts +8 -0
- package/dist/types/i18n.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/canvas-renderer.ts +17 -11
- package/src/diagram/api.ts +7 -0
- package/src/diagram/context-menu.ts +83 -18
- package/src/diagram/stocksharp-diagram.ts +45 -8
- package/src/embed.ts +7 -4
- package/src/i18n.ts +34 -6
- package/src/index.ts +5 -0
package/README.md
CHANGED
|
@@ -154,7 +154,9 @@ missing type. Sites can localize that message through
|
|
|
154
154
|
`data-diagram-missing-element="Missing: {typeId}"` on the host.
|
|
155
155
|
|
|
156
156
|
Every text the embedded control shows comes from the host, so a translated page
|
|
157
|
-
carries no English leftovers
|
|
157
|
+
carries no English leftovers. These attributes are per-instance overrides on top
|
|
158
|
+
of the page's translation bundle (see *Translating the control* below); set them
|
|
159
|
+
when one diagram has to read differently from the rest of the page:
|
|
158
160
|
|
|
159
161
|
| Host attribute | What it renames |
|
|
160
162
|
|---|---|
|
|
@@ -163,7 +165,9 @@ carries no English leftovers:
|
|
|
163
165
|
| `data-diagram-missing-element="Missing: {typeId}"` | the placeholder for an element the palette lacks |
|
|
164
166
|
|
|
165
167
|
The same labels are available to custom integrations as the `fullscreenLabels`
|
|
166
|
-
option and `setFullscreenLabels()` on `StockSharpDiagram`.
|
|
168
|
+
option and `setFullscreenLabels()` on `StockSharpDiagram`. With neither the
|
|
169
|
+
attribute nor the option, the wording comes from the bundle, so a page that has
|
|
170
|
+
already been translated needs no per-diagram markup at all.
|
|
167
171
|
|
|
168
172
|
### Node actions and errors
|
|
169
173
|
|
|
@@ -190,10 +194,20 @@ the menu was opened over a socket.
|
|
|
190
194
|
|
|
191
195
|
### The context menu
|
|
192
196
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
+
Right-click opens the control's own menu, with an Export submenu. It is on by
|
|
198
|
+
default, because right-click suppresses the browser's menu either way and a
|
|
199
|
+
control that takes one away owes one back. It needs no stylesheet: it is styled
|
|
200
|
+
inline over `--ssdiagram-*` custom properties (`--ssdiagram-menu-background`,
|
|
201
|
+
`--ssdiagram-menu-border`, `--ssdiagram-menu-color`, `--ssdiagram-menu-hover`,
|
|
202
|
+
`--ssdiagram-menu-disabled-color`, `--ssdiagram-menu-font`), falling back to the
|
|
203
|
+
`--ssdiagram-control-*` values the fullscreen button uses. Its class names —
|
|
204
|
+
`ssdiagram-context-menu`, `-item`, `-label`, `-arrow`, `-submenu`, `-separator` —
|
|
205
|
+
are stable if you would rather use CSS.
|
|
206
|
+
|
|
207
|
+
To draw your own instead, pass `showContextMenu: false` (or call
|
|
208
|
+
`setContextMenuEnabled(false)`) and handle `contextMenuRequested`, which is
|
|
209
|
+
emitted either way — and emitted *before* the built-in menu opens, so a handler
|
|
210
|
+
can still switch it off.
|
|
197
211
|
|
|
198
212
|
`commands` is a tree in display order. An entry with a `group` is a submenu;
|
|
199
213
|
anything else is a command. `enabled` is computed for both — a submenu is off
|
|
@@ -209,8 +223,10 @@ diagram.on('contextMenuRequested', ({ x, y, commands }) => {
|
|
|
209
223
|
menu.on('pick', (command) => diagram.executeContextCommand(command));
|
|
210
224
|
```
|
|
211
225
|
|
|
212
|
-
`undo`, `redo`, `cut`, `copy`, `paste` and `
|
|
213
|
-
control itself.
|
|
226
|
+
`undo`, `redo`, `cut`, `copy`, `paste`, `delete` and `overview` are carried out
|
|
227
|
+
by the control itself. `overview` toggles the corner minimap, and reports its
|
|
228
|
+
current state as `checked` on the command so a menu can tick it rather than offer
|
|
229
|
+
a dead show/hide pair. The rest are requests it cannot answer alone: `open`,
|
|
214
230
|
`properties` and `help` raise `nodeOpen` / `nodeProperties` / `nodeHelp`, and
|
|
215
231
|
the `export` submenu raises `exportRequested` with the chosen format. Nothing
|
|
216
232
|
is produced until the host acts on it — only the host knows where the result
|
|
@@ -226,9 +242,54 @@ diagram.on('exportRequested', ({ format }) => {
|
|
|
226
242
|
```
|
|
227
243
|
|
|
228
244
|
Export is offered whenever the diagram has a node, including in read-only mode,
|
|
229
|
-
because it only reads.
|
|
230
|
-
|
|
231
|
-
|
|
245
|
+
because it only reads.
|
|
246
|
+
|
|
247
|
+
#### Translating the control
|
|
248
|
+
|
|
249
|
+
There is one mechanism, and it is `window.__designerI18n`: an object typed by the
|
|
250
|
+
exported `DesignerI18n`, holding every string the package renders itself — the
|
|
251
|
+
menu, the fullscreen button's tooltip, and the embed failure notes. It is read on
|
|
252
|
+
every lookup, so it can be assigned at any point, before or after the bundle
|
|
253
|
+
loads, and reassigned later to change language. A key that is missing or empty
|
|
254
|
+
falls back to English.
|
|
255
|
+
|
|
256
|
+
Per-instance settings — the `fullscreenLabels` option, `setFullscreenLabels()`,
|
|
257
|
+
and the `data-diagram-*` attributes above — override the bundle for one diagram.
|
|
258
|
+
Resolution is: explicit setting, then bundle, then the built-in English.
|
|
259
|
+
|
|
260
|
+
The context menu is rebuilt on every open and needs nothing after a language
|
|
261
|
+
change. The fullscreen button is drawn once, so call `refreshLabels()` to
|
|
262
|
+
re-read the bundle for it.
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
import type { DesignerI18n } from '@stocksharp/diagram';
|
|
266
|
+
|
|
267
|
+
const labels: DesignerI18n = { cut: 'Вырезать', ctxDelete: 'Удалить', /* … */ };
|
|
268
|
+
(window as unknown as { __designerI18n: DesignerI18n }).__designerI18n = labels;
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
The key is not always the command name, so here is the whole menu:
|
|
272
|
+
|
|
273
|
+
| command | key | English |
|
|
274
|
+
|---|---|---|
|
|
275
|
+
| `undo` / `redo` | `undo` / `redo` | Undo / Redo |
|
|
276
|
+
| `cut` / `copy` / `paste` | `cut` / `copy` / `paste` | Cut / Copy / Paste |
|
|
277
|
+
| `open` | `ctxOpen` | Open |
|
|
278
|
+
| `delete` | `ctxDelete` | Delete |
|
|
279
|
+
| *(the submenu)* | `ctxExportAs` | Export as |
|
|
280
|
+
| `exportDocument` | `ctxExportDocument` | Scheme |
|
|
281
|
+
| `exportPng` / `exportSvg` | `ctxExportPng` / `ctxExportSvg` | PNG image / SVG image |
|
|
282
|
+
| `overview` | `ctxOverview` | Overview |
|
|
283
|
+
| `properties` | `properties` | Properties |
|
|
284
|
+
| `help` | `ctxHelp` | Help |
|
|
285
|
+
| *(fullscreen button)* | `fullscreenEnter` / `fullscreenExit` | Enter / Exit fullscreen |
|
|
286
|
+
| *(embed failures)* | `embedErrorLoad` / `embedErrorEmpty` / `embedErrorDraw` | the three notes shown in place of a diagram |
|
|
287
|
+
| *(embed placeholder)* | `embedMissingElement` | the missing-element tooltip |
|
|
288
|
+
|
|
289
|
+
`ctxDelete` is separate from the solution explorer's `delete` on purpose: that
|
|
290
|
+
one removes a whole strategy, this one the selected nodes and links, and a
|
|
291
|
+
language that declines the object cannot serve both from one key. The same goes
|
|
292
|
+
for `ctxExportAs` against `ctxExport`.
|
|
232
293
|
|
|
233
294
|
Runtime failures flash the node border before leaving it red. Errors found
|
|
234
295
|
while loading a scheme use a red background. Hovering either state shows the
|
|
@@ -1876,6 +1876,26 @@ export class Diagram {
|
|
|
1876
1876
|
return added.map((node) => node.id);
|
|
1877
1877
|
}
|
|
1878
1878
|
// ---- input ------------------------------------------------------
|
|
1879
|
+
// Ends hover and everything hanging off it: highlight, cursor and the delayed tooltip.
|
|
1880
|
+
clearHover() {
|
|
1881
|
+
if (this.hoverPort !== null)
|
|
1882
|
+
this.emit('portHover', { node: this.hoverPort.node, port: this.hoverPort.port, hovering: false });
|
|
1883
|
+
if (this.hoverNode !== null)
|
|
1884
|
+
this.emit('nodeHover', { node: this.hoverNode, hovering: false });
|
|
1885
|
+
if (this.hoveredLink !== null)
|
|
1886
|
+
this.emit('linkHover', { link: this.hoveredLink, hovering: false });
|
|
1887
|
+
this.hoverPort = null;
|
|
1888
|
+
this.hoverNode = null;
|
|
1889
|
+
this.hoveredLink = null;
|
|
1890
|
+
this.tipTarget = null;
|
|
1891
|
+
this.tipShow = false;
|
|
1892
|
+
if (this.tipTimer !== null) {
|
|
1893
|
+
clearTimeout(this.tipTimer);
|
|
1894
|
+
this.tipTimer = null;
|
|
1895
|
+
}
|
|
1896
|
+
this.canvas.style.cursor = 'default';
|
|
1897
|
+
this.scheduleDraw();
|
|
1898
|
+
}
|
|
1879
1899
|
cancelLongPress() {
|
|
1880
1900
|
if (this.lpTimer !== null) {
|
|
1881
1901
|
clearTimeout(this.lpTimer);
|
|
@@ -1914,7 +1934,10 @@ export class Diagram {
|
|
|
1914
1934
|
this.relinking = null;
|
|
1915
1935
|
this.relinkCandidate = null;
|
|
1916
1936
|
this.linkSnap = null;
|
|
1917
|
-
this
|
|
1937
|
+
// A menu is about to cover this spot, and it opens under a cursor that has not moved --
|
|
1938
|
+
// which fires no boundary event, so nothing else would end the hover. Without this the
|
|
1939
|
+
// tooltip armed by the last pointermove appears 400ms later, through the open menu.
|
|
1940
|
+
this.clearHover();
|
|
1918
1941
|
this.emit('contextMenu', { x: pageX, y: pageY, link, node, port });
|
|
1919
1942
|
}
|
|
1920
1943
|
listen(target, type, listener, options) {
|
|
@@ -2292,25 +2315,7 @@ export class Diagram {
|
|
|
2292
2315
|
this.emitViewChanged(true);
|
|
2293
2316
|
this.scheduleDraw();
|
|
2294
2317
|
}, { passive: false });
|
|
2295
|
-
this.listen(this.canvas, 'pointerleave', () =>
|
|
2296
|
-
if (this.hoverPort !== null)
|
|
2297
|
-
this.emit('portHover', { node: this.hoverPort.node, port: this.hoverPort.port, hovering: false });
|
|
2298
|
-
if (this.hoverNode !== null)
|
|
2299
|
-
this.emit('nodeHover', { node: this.hoverNode, hovering: false });
|
|
2300
|
-
if (this.hoveredLink !== null)
|
|
2301
|
-
this.emit('linkHover', { link: this.hoveredLink, hovering: false });
|
|
2302
|
-
this.hoverPort = null;
|
|
2303
|
-
this.hoverNode = null;
|
|
2304
|
-
this.hoveredLink = null;
|
|
2305
|
-
this.tipTarget = null;
|
|
2306
|
-
this.tipShow = false;
|
|
2307
|
-
if (this.tipTimer !== null) {
|
|
2308
|
-
clearTimeout(this.tipTimer);
|
|
2309
|
-
this.tipTimer = null;
|
|
2310
|
-
}
|
|
2311
|
-
this.canvas.style.cursor = 'default';
|
|
2312
|
-
this.scheduleDraw();
|
|
2313
|
-
});
|
|
2318
|
+
this.listen(this.canvas, 'pointerleave', () => this.clearHover());
|
|
2314
2319
|
this.listen(this.canvas, 'dblclick', (e) => {
|
|
2315
2320
|
const [sx, sy] = localXY(e);
|
|
2316
2321
|
const [wx, wy] = this.toWorld(sx, sy);
|