@shumoku/core 0.2.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/dist/icons/build-icons.js +3 -3
- package/dist/icons/build-icons.js.map +1 -1
- package/dist/icons/generated-icons.js +10 -10
- package/dist/icons/generated-icons.js.map +1 -1
- package/dist/index.d.ts +3 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -8
- package/dist/index.js.map +1 -1
- package/dist/layout/hierarchical.d.ts +1 -1
- package/dist/layout/hierarchical.d.ts.map +1 -1
- package/dist/layout/hierarchical.js +82 -66
- package/dist/layout/hierarchical.js.map +1 -1
- package/dist/layout/index.d.ts +1 -1
- package/dist/layout/index.d.ts.map +1 -1
- package/dist/layout/index.js.map +1 -1
- package/dist/models/types.d.ts.map +1 -1
- package/dist/models/types.js +13 -13
- package/dist/models/types.js.map +1 -1
- package/dist/themes/dark.d.ts.map +1 -1
- package/dist/themes/dark.js +1 -1
- package/dist/themes/dark.js.map +1 -1
- package/dist/themes/index.d.ts +3 -3
- package/dist/themes/index.d.ts.map +1 -1
- package/dist/themes/index.js +4 -4
- package/dist/themes/index.js.map +1 -1
- package/dist/themes/modern.d.ts.map +1 -1
- package/dist/themes/modern.js.map +1 -1
- package/dist/themes/types.d.ts.map +1 -1
- package/dist/themes/utils.d.ts +1 -1
- package/dist/themes/utils.d.ts.map +1 -1
- package/dist/themes/utils.js +5 -4
- package/dist/themes/utils.js.map +1 -1
- package/package.json +88 -92
- package/src/constants.ts +35 -35
- package/src/icons/build-icons.ts +12 -6
- package/src/icons/generated-icons.ts +12 -12
- package/src/index.test.ts +66 -0
- package/src/index.ts +6 -13
- package/src/layout/hierarchical.ts +1251 -1221
- package/src/layout/index.ts +1 -1
- package/src/models/types.ts +47 -37
- package/src/themes/dark.ts +15 -15
- package/src/themes/index.ts +7 -7
- package/src/themes/modern.ts +22 -22
- package/src/themes/types.ts +26 -26
- package/src/themes/utils.ts +25 -24
- package/dist/renderer/index.d.ts +0 -6
- package/dist/renderer/index.d.ts.map +0 -1
- package/dist/renderer/index.js +0 -5
- package/dist/renderer/index.js.map +0 -1
- package/dist/renderer/svg.d.ts +0 -131
- package/dist/renderer/svg.d.ts.map +0 -1
- package/dist/renderer/svg.js +0 -1031
- package/dist/renderer/svg.js.map +0 -1
- package/src/renderer/index.ts +0 -6
- package/src/renderer/svg.ts +0 -1277
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* Build script to convert default SVG icons to TypeScript
|
|
3
3
|
* Run with: bun src/icons/build-icons.ts
|
|
4
4
|
*/
|
|
5
|
-
import * as fs from 'fs';
|
|
6
|
-
import * as path from 'path';
|
|
7
|
-
import { fileURLToPath } from 'url';
|
|
5
|
+
import * as fs from 'node:fs';
|
|
6
|
+
import * as path from 'node:path';
|
|
7
|
+
import { fileURLToPath } from 'node:url';
|
|
8
8
|
const __filename = fileURLToPath(import.meta.url);
|
|
9
9
|
const __dirname = path.dirname(__filename);
|
|
10
10
|
const ICONS_DIR = path.join(__dirname);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-icons.js","sourceRoot":"","sources":["../../src/icons/build-icons.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"build-icons.js","sourceRoot":"","sources":["../../src/icons/build-icons.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAA;AAC7B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AACjD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;AAE1C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;AACtC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAA;AAE9D,SAAS,iBAAiB,CAAC,UAAkB;IAC3C,MAAM,YAAY,GAAG,UAAU,CAAC,KAAK,CAAC,8BAA8B,CAAC,CAAA;IACrE,IAAI,CAAC,YAAY;QAAE,OAAO,EAAE,CAAA;IAC5B,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;AACpD,CAAC;AAED,SAAS,qBAAqB,CAAC,UAAkB;IAC/C,MAAM,KAAK,GAA2B,EAAE,CAAA;IAExC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,KAAK,CAAA;IACd,CAAC;IAED,MAAM,KAAK,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,CAAA;IAExC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YAAE,SAAQ;QAEpC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;QAC5C,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;QAClD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;QACzC,MAAM,UAAU,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAA;QAE7C,IAAI,UAAU,EAAE,CAAC;YACf,KAAK,CAAC,QAAQ,CAAC,GAAG,UAAU,CAAA;QAC9B,CAAC;IACH,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC;AAED,SAAS,kBAAkB,CAAC,KAA6B;IACvD,MAAM,KAAK,GAAa;QACtB,KAAK;QACL,4CAA4C;QAC5C,mDAAmD;QACnD,KAAK;QACL,EAAE;QACF,iDAAiD;QACjD,EAAE;QACF,6DAA6D;QAC7D,EAAE;QACF,8BAA8B;QAC9B,mBAAmB;QACnB,kBAAkB;QAClB,iBAAiB;QACjB,oBAAoB;QACpB,GAAG;QACH,EAAE;QACF,iCAAiC;QACjC,gDAAgD;KACjD,CAAA;IAED,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACpD,KAAK,CAAC,IAAI,CAAC,MAAM,IAAI,QAAQ,OAAO,KAAK,CAAC,CAAA;IAC5C,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACf,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAEd,qBAAqB;IACrB,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAA;IAC3C,KAAK,CAAC,IAAI,CAAC,wDAAwD,CAAC,CAAA;IACpE,KAAK,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAA;IAC9C,KAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAA;IACnD,KAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAA;IACnD,KAAK,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAA;IAClD,KAAK,CAAC,IAAI,CAAC,+CAA+C,CAAC,CAAA;IAC3D,KAAK,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAA;IAC9C,KAAK,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAA;IACzD,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAA;IAC5C,KAAK,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAA;IAClD,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAA;IACxC,KAAK,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAA;IAClD,KAAK,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAA;IAChD,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACf,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAEd,kBAAkB;IAClB,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjB,KAAK,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAA;IACvD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjB,KAAK,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAA;IACpF,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAA;IAC3C,KAAK,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAA;IACtD,KAAK,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAA;IAC9C,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAA;IAC5C,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACf,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAEd,iFAAiF;IACjF,KAAK,CAAC,IAAI,CAAC,oEAAoE,CAAC,CAAA;IAChF,KAAK,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAA;IACpF,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAEd,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjB,KAAK,CAAC,IAAI,CAAC,qDAAqD,CAAC,CAAA;IACjE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjB,KAAK,CAAC,IAAI,CACR,+FAA+F,CAChG,CAAA;IACD,KAAK,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAA;IAClD,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACf,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAEd,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjB,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAA;IACtC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjB,KAAK,CAAC,IAAI,CAAC,qCAAqC,CAAC,CAAA;IACjD,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;IAC/B,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAA;IAChC,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAA;IACjC,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAA;IACxC,KAAK,CAAC,IAAI,CAAC,0CAA0C,CAAC,CAAA;IACtD,KAAK,CAAC,IAAI,CACR,8FAA8F,CAC/F,CAAA;IACD,KAAK,CAAC,IAAI,CAAC,uDAAuD,CAAC,CAAA;IACnE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjB,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACd,KAAK,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAA;IAC9D,KAAK,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAA;IAClD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACd,KAAK,CAAC,IAAI,CAAC,6DAA6D,CAAC,CAAA;IACzE,KAAK,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAA;IAC9C,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;IAC7B,KAAK,CAAC,IAAI,CACR,wFAAwF,CACzF,CAAA;IACD,KAAK,CAAC,IAAI,CAAC,oDAAoD,CAAC,CAAA;IAChE,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;IAClC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjB,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;IAC5B,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACf,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAEd,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjB,KAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAA;IACnD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjB,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAA;IAC5C,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAA;IAC/B,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAA;IAChC,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;IAClC,KAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAA;IACnD,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAA;IACrC,KAAK,CAAC,IAAI,CAAC,+DAA+D,CAAC,CAAA;IAC3E,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAA;IAC5C,KAAK,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAA;IACpD,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACf,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAEd,SAAS;IACT,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAA;IACvC,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAA;IACtC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACf,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IAEd,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED,SAAS,IAAI;IACX,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAA;IAExC,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;IACrD,MAAM,KAAK,GAAG,qBAAqB,CAAC,aAAa,CAAC,CAAA;IAElD,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAA;QACtC,OAAM;IACR,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,gBAAgB,CAAC,CAAA;IAEjE,MAAM,MAAM,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAA;IACxC,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;IAE9C,OAAO,CAAC,GAAG,CAAC,aAAa,WAAW,EAAE,CAAC,CAAA;AACzC,CAAC;AAED,IAAI,EAAE,CAAA"}
|
|
@@ -6,17 +6,17 @@ import { DeviceType } from '../models/index.js';
|
|
|
6
6
|
// Default network device icons
|
|
7
7
|
const defaultIcons = {
|
|
8
8
|
'access-point': `<path d="M12 10a2 2 0 100 4 2 2 0 000-4zm-4.5-2.5a6.5 6.5 0 019 0l-1.4 1.4a4.5 4.5 0 00-6.2 0l-1.4-1.4zm-2.8-2.8a10 10 0 0114.6 0l-1.4 1.4a8 8 0 00-11.8 0L4.7 4.7z"/>`,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
cloud: `<path d="M19.4 10.6A7 7 0 006 12a5 5 0 00.7 9.9h11.8a4.5 4.5 0 00.9-8.9z"/>`,
|
|
10
|
+
database: `<path d="M12 4c-4.4 0-8 1.3-8 3v10c0 1.7 3.6 3 8 3s8-1.3 8-3V7c0-1.7-3.6-3-8-3zm0 2c3.3 0 6 .9 6 2s-2.7 2-6 2-6-.9-6-2 2.7-2 6-2zM6 10.5c1.4.7 3.5 1 6 1s4.6-.3 6-1V12c0 1.1-2.7 2-6 2s-6-.9-6-2v-1.5zm0 4c1.4.7 3.5 1 6 1s4.6-.3 6-1V16c0 1.1-2.7 2-6 2s-6-.9-6-2v-1.5z"/>`,
|
|
11
|
+
firewall: `<path d="M12 2L4 6v6c0 5.5 3.4 10.3 8 12 4.6-1.7 8-6.5 8-12V6l-8-4zm0 2.2l6 3v5.3c0 4.3-2.6 8.1-6 9.5-3.4-1.4-6-5.2-6-9.5V7.2l6-3z"/> <path d="M11 8h2v5h-2V8zm0 6h2v2h-2v-2z"/>`,
|
|
12
|
+
generic: `<path d="M4 4h16v16H4V4zm2 2v12h12V6H6zm2 2h8v2H8V8zm0 4h8v2H8v-2z"/>`,
|
|
13
|
+
internet: `<path d="M12 2a10 10 0 100 20 10 10 0 000-20zm0 2c.6 0 1.3.8 1.8 2H10.2c.5-1.2 1.2-2 1.8-2zm-3.2.7A8 8 0 005 10h2.5c.1-2 .5-3.7 1.3-5.3zm6.4 0c.8 1.6 1.2 3.3 1.3 5.3H19a8 8 0 00-3.8-5.3zM5 12h2.5c.1 2 .5 3.7 1.3 5.3A8 8 0 015 12zm4.5 0h5c0 1.5-.3 3-1 4h-3c-.7-1-1-2.5-1-4zm7 0H19a8 8 0 01-3.8 5.3c.8-1.6 1.2-3.3 1.3-5.3zM10.2 18h3.6c-.5 1.2-1.2 2-1.8 2s-1.3-.8-1.8-2z"/>`,
|
|
14
14
|
'l2-switch': `<path d="M3 8h18v8H3V8zm2 2v4h14v-4H5zm2 1h2v2H7v-2zm4 0h2v2h-2v-2zm4 0h2v2h-2v-2z"/>`,
|
|
15
15
|
'l3-switch': `<path d="M3 6h18v12H3V6zm2 2v8h14V8H5zm2 2h4v1H7v-1zm6 0h4v1h-4v-1zm-6 3h4v1H7v-1zm6 0h4v1h-4v-1z"/>`,
|
|
16
16
|
'load-balancer': `<path d="M12 4L4 8l8 4 8-4-8-4zm0 2.5L16 8l-4 2-4-2 4-1.5zM4 12l8 4 8-4v2l-8 4-8-4v-2zm0 4l8 4 8-4v2l-8 4-8-4v-2z"/>`,
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
router: `<path d="M4 8h16v8H4V8zm2 2v4h12v-4H6zm1 1h2v2H7v-2zm4 0h2v2h-2v-2zm4 0h2v2h-2v-2z"/>`,
|
|
18
|
+
server: `<path d="M4 4h16v4H4V4zm0 6h16v4H4v-4zm0 6h16v4H4v-4zm2-10v2h2V6H6zm0 6v2h2v-2H6zm0 6v2h2v-2H6zm10-12v2h2V6h-2zm0 6v2h2v-2h-2zm0 6v2h2v-2h-2z"/>`,
|
|
19
|
+
vpn: `<path d="M12 2L4 5v6.5c0 5.3 3.4 10 8 11.5 4.6-1.5 8-6.2 8-11.5V5l-8-3zm0 4a3 3 0 110 6 3 3 0 010-6zm-4 8h8v1c0 2-1.8 3-4 3s-4-1-4-3v-1z"/>`,
|
|
20
20
|
};
|
|
21
21
|
// Map DeviceType to icon key
|
|
22
22
|
const deviceTypeToIcon = {
|
|
@@ -45,7 +45,7 @@ export function getDeviceIcon(type) {
|
|
|
45
45
|
return defaultIcons[iconKey];
|
|
46
46
|
}
|
|
47
47
|
// Vendor icon registry (populated by @shumoku/icons if installed)
|
|
48
|
-
|
|
48
|
+
const vendorIconRegistry = {};
|
|
49
49
|
/**
|
|
50
50
|
* Register vendor icons (called by @shumoku/icons)
|
|
51
51
|
*/
|
|
@@ -66,7 +66,7 @@ export function getVendorIconEntry(vendor, service, resource) {
|
|
|
66
66
|
const key = resource ? `${service}/${resource}` : service;
|
|
67
67
|
const entry = vendorIcons[key];
|
|
68
68
|
if (!entry) {
|
|
69
|
-
const serviceKey = Object.keys(vendorIcons).find(k => k.startsWith(service
|
|
69
|
+
const serviceKey = Object.keys(vendorIcons).find((k) => k.startsWith(`${service}/`));
|
|
70
70
|
if (serviceKey)
|
|
71
71
|
return vendorIcons[serviceKey];
|
|
72
72
|
return undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generated-icons.js","sourceRoot":"","sources":["../../src/icons/generated-icons.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAW/C,+BAA+B;AAC/B,MAAM,YAAY,GAA2B;IAC3C,cAAc,EAAE,wKAAwK;IACxL,
|
|
1
|
+
{"version":3,"file":"generated-icons.js","sourceRoot":"","sources":["../../src/icons/generated-icons.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @shumoku/core - Network topology visualization core library
|
|
3
3
|
*/
|
|
4
|
-
export * from './
|
|
4
|
+
export * from './constants.js';
|
|
5
|
+
export * from './icons/index.js';
|
|
5
6
|
export * from './layout/index.js';
|
|
7
|
+
export * from './models/index.js';
|
|
6
8
|
export * from './themes/index.js';
|
|
7
|
-
export * from './icons/index.js';
|
|
8
|
-
export * from './renderer/index.js';
|
|
9
|
-
export * from './constants.js';
|
|
10
9
|
export declare const version = "0.0.0";
|
|
11
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,cAAc,gBAAgB,CAAA;AAE9B,cAAc,kBAAkB,CAAA;AAEhC,cAAc,mBAAmB,CAAA;AAEjC,cAAc,mBAAmB,CAAA;AAEjC,cAAc,mBAAmB,CAAA;AAGjC,eAAO,MAAM,OAAO,UAAU,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @shumoku/core - Network topology visualization core library
|
|
3
3
|
*/
|
|
4
|
-
//
|
|
5
|
-
export * from './
|
|
4
|
+
// Constants
|
|
5
|
+
export * from './constants.js';
|
|
6
|
+
// Icons
|
|
7
|
+
export * from './icons/index.js';
|
|
6
8
|
// Layout
|
|
7
9
|
export * from './layout/index.js';
|
|
10
|
+
// Models
|
|
11
|
+
export * from './models/index.js';
|
|
8
12
|
// Themes
|
|
9
13
|
export * from './themes/index.js';
|
|
10
|
-
// Icons
|
|
11
|
-
export * from './icons/index.js';
|
|
12
|
-
// Renderer
|
|
13
|
-
export * from './renderer/index.js';
|
|
14
|
-
// Constants
|
|
15
|
-
export * from './constants.js';
|
|
16
14
|
// Version
|
|
17
15
|
export const version = '0.0.0';
|
|
18
16
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,YAAY;AACZ,cAAc,gBAAgB,CAAA;AAC9B,QAAQ;AACR,cAAc,kBAAkB,CAAA;AAChC,SAAS;AACT,cAAc,mBAAmB,CAAA;AACjC,SAAS;AACT,cAAc,mBAAmB,CAAA;AACjC,SAAS;AACT,cAAc,mBAAmB,CAAA;AAEjC,UAAU;AACV,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAA"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Hierarchical Layout Engine
|
|
3
3
|
* Uses ELK.js for advanced graph layout with proper edge routing
|
|
4
4
|
*/
|
|
5
|
-
import { type
|
|
5
|
+
import { type LayoutDirection, type LayoutResult, type NetworkGraph } from '../models/index.js';
|
|
6
6
|
export interface HierarchicalLayoutOptions {
|
|
7
7
|
direction?: LayoutDirection;
|
|
8
8
|
nodeWidth?: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hierarchical.d.ts","sourceRoot":"","sources":["../../src/layout/hierarchical.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"hierarchical.d.ts","sourceRoot":"","sources":["../../src/layout/hierarchical.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAqBH,OAAO,EAGL,KAAK,eAAe,EAGpB,KAAK,YAAY,EAGjB,KAAK,YAAY,EAIlB,MAAM,oBAAoB,CAAA;AAwG3B,MAAM,WAAW,yBAAyB;IACxC,SAAS,CAAC,EAAE,eAAe,CAAA;IAC3B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAC7B;AAgBD,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,OAAO,CAAqC;IACpD,OAAO,CAAC,GAAG,CAA0B;gBAEzB,OAAO,CAAC,EAAE,yBAAyB;IAK/C;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAwC/B,OAAO,CAAC,mBAAmB;IAarB,WAAW,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC;IA8B7D;;OAEG;IACH,OAAO,CAAC,aAAa;IA+XrB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAuR3B,MAAM,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY;IAczC,OAAO,CAAC,cAAc;IAetB,OAAO,CAAC,mBAAmB;IAgE3B,OAAO,CAAC,oBAAoB;IAc5B,OAAO,CAAC,kBAAkB;IAiD1B,OAAO,CAAC,oBAAoB;IAqD5B,OAAO,CAAC,uBAAuB;IAwE/B,4CAA4C;IAC5C,OAAO,CAAC,aAAa;IAmBrB,kDAAkD;IAClD,OAAO,CAAC,sBAAsB;CAiB/B;AAGD,eAAO,MAAM,kBAAkB,oBAA2B,CAAA"}
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
* Uses ELK.js for advanced graph layout with proper edge routing
|
|
4
4
|
*/
|
|
5
5
|
import ELK from 'elkjs/lib/elk.bundled.js';
|
|
6
|
+
import { CHAR_WIDTH_RATIO, DEFAULT_ICON_SIZE, ESTIMATED_CHAR_WIDTH, ICON_LABEL_GAP, LABEL_LINE_HEIGHT, MAX_ICON_WIDTH_RATIO, MIN_PORT_SPACING, NODE_HORIZONTAL_PADDING, NODE_VERTICAL_PADDING, PORT_LABEL_FONT_SIZE, PORT_LABEL_PADDING, } from '../constants.js';
|
|
7
|
+
import { getDeviceIcon, getVendorIconEntry } from '../icons/index.js';
|
|
6
8
|
import { getNodeId, } from '../models/index.js';
|
|
7
|
-
import { getVendorIconEntry, getDeviceIcon } from '../icons/index.js';
|
|
8
|
-
import { DEFAULT_ICON_SIZE, ICON_LABEL_GAP, LABEL_LINE_HEIGHT, NODE_VERTICAL_PADDING, NODE_HORIZONTAL_PADDING, MIN_PORT_SPACING, PORT_LABEL_FONT_SIZE, CHAR_WIDTH_RATIO, PORT_LABEL_PADDING, ESTIMATED_CHAR_WIDTH, MAX_ICON_WIDTH_RATIO, } from '../constants.js';
|
|
9
9
|
// ============================================
|
|
10
10
|
// Helper Functions
|
|
11
11
|
// ============================================
|
|
@@ -20,7 +20,13 @@ function collectNodePorts(graph, haPairSet) {
|
|
|
20
20
|
const nodePorts = new Map();
|
|
21
21
|
const getOrCreate = (nodeId) => {
|
|
22
22
|
if (!nodePorts.has(nodeId)) {
|
|
23
|
-
nodePorts.set(nodeId, {
|
|
23
|
+
nodePorts.set(nodeId, {
|
|
24
|
+
all: new Set(),
|
|
25
|
+
top: new Set(),
|
|
26
|
+
bottom: new Set(),
|
|
27
|
+
left: new Set(),
|
|
28
|
+
right: new Set(),
|
|
29
|
+
});
|
|
24
30
|
}
|
|
25
31
|
return nodePorts.get(nodeId);
|
|
26
32
|
};
|
|
@@ -163,12 +169,12 @@ export class HierarchicalLayout {
|
|
|
163
169
|
// Build HA container map: node ID -> container ID
|
|
164
170
|
const nodeToHAContainer = new Map();
|
|
165
171
|
const haPairMap = new Map();
|
|
166
|
-
haPairs.
|
|
172
|
+
for (const [idx, pair] of haPairs.entries()) {
|
|
167
173
|
const containerId = `__ha_container_${idx}`;
|
|
168
174
|
nodeToHAContainer.set(pair.nodeA, containerId);
|
|
169
175
|
nodeToHAContainer.set(pair.nodeB, containerId);
|
|
170
176
|
haPairMap.set(containerId, pair);
|
|
171
|
-
}
|
|
177
|
+
}
|
|
172
178
|
// Create ELK node
|
|
173
179
|
const createElkNode = (node) => {
|
|
174
180
|
const portInfo = nodePorts.get(node.id);
|
|
@@ -199,7 +205,7 @@ export class HierarchicalLayout {
|
|
|
199
205
|
// Top ports (incoming)
|
|
200
206
|
const topPorts = Array.from(portInfo.top);
|
|
201
207
|
const topPositions = calcPortPositions(topPorts.length, width);
|
|
202
|
-
topPorts.
|
|
208
|
+
for (const [i, portName] of topPorts.entries()) {
|
|
203
209
|
elkNode.ports.push({
|
|
204
210
|
id: `${node.id}:${portName}`,
|
|
205
211
|
width: PORT_WIDTH,
|
|
@@ -209,11 +215,11 @@ export class HierarchicalLayout {
|
|
|
209
215
|
labels: [{ text: portName }],
|
|
210
216
|
layoutOptions: { 'elk.port.side': 'NORTH' },
|
|
211
217
|
});
|
|
212
|
-
}
|
|
218
|
+
}
|
|
213
219
|
// Bottom ports (outgoing)
|
|
214
220
|
const bottomPorts = Array.from(portInfo.bottom);
|
|
215
221
|
const bottomPositions = calcPortPositions(bottomPorts.length, width);
|
|
216
|
-
bottomPorts.
|
|
222
|
+
for (const [i, portName] of bottomPorts.entries()) {
|
|
217
223
|
elkNode.ports.push({
|
|
218
224
|
id: `${node.id}:${portName}`,
|
|
219
225
|
width: PORT_WIDTH,
|
|
@@ -223,11 +229,11 @@ export class HierarchicalLayout {
|
|
|
223
229
|
labels: [{ text: portName }],
|
|
224
230
|
layoutOptions: { 'elk.port.side': 'SOUTH' },
|
|
225
231
|
});
|
|
226
|
-
}
|
|
232
|
+
}
|
|
227
233
|
// Left ports (HA)
|
|
228
234
|
const leftPorts = Array.from(portInfo.left);
|
|
229
235
|
const leftPositions = calcPortPositions(leftPorts.length, height);
|
|
230
|
-
leftPorts.
|
|
236
|
+
for (const [i, portName] of leftPorts.entries()) {
|
|
231
237
|
elkNode.ports.push({
|
|
232
238
|
id: `${node.id}:${portName}`,
|
|
233
239
|
width: PORT_WIDTH,
|
|
@@ -237,11 +243,11 @@ export class HierarchicalLayout {
|
|
|
237
243
|
labels: [{ text: portName }],
|
|
238
244
|
layoutOptions: { 'elk.port.side': 'WEST' },
|
|
239
245
|
});
|
|
240
|
-
}
|
|
246
|
+
}
|
|
241
247
|
// Right ports (HA)
|
|
242
248
|
const rightPorts = Array.from(portInfo.right);
|
|
243
249
|
const rightPositions = calcPortPositions(rightPorts.length, height);
|
|
244
|
-
rightPorts.
|
|
250
|
+
for (const [i, portName] of rightPorts.entries()) {
|
|
245
251
|
elkNode.ports.push({
|
|
246
252
|
id: `${node.id}:${portName}`,
|
|
247
253
|
width: PORT_WIDTH,
|
|
@@ -251,7 +257,7 @@ export class HierarchicalLayout {
|
|
|
251
257
|
labels: [{ text: portName }],
|
|
252
258
|
layoutOptions: { 'elk.port.side': 'EAST' },
|
|
253
259
|
});
|
|
254
|
-
}
|
|
260
|
+
}
|
|
255
261
|
elkNode.layoutOptions = {
|
|
256
262
|
'elk.portConstraints': 'FIXED_POS',
|
|
257
263
|
'elk.spacing.portPort': String(MIN_PORT_SPACING),
|
|
@@ -261,14 +267,14 @@ export class HierarchicalLayout {
|
|
|
261
267
|
};
|
|
262
268
|
// Create HA container node
|
|
263
269
|
const createHAContainerNode = (containerId, pair) => {
|
|
264
|
-
const nodeA = graph.nodes.find(n => n.id === pair.nodeA);
|
|
265
|
-
const nodeB = graph.nodes.find(n => n.id === pair.nodeB);
|
|
270
|
+
const nodeA = graph.nodes.find((n) => n.id === pair.nodeA);
|
|
271
|
+
const nodeB = graph.nodes.find((n) => n.id === pair.nodeB);
|
|
266
272
|
if (!nodeA || !nodeB)
|
|
267
273
|
return null;
|
|
268
274
|
const childA = createElkNode(nodeA);
|
|
269
275
|
const childB = createElkNode(nodeB);
|
|
270
276
|
// Find HA link
|
|
271
|
-
const haLink = graph.links.find(link => {
|
|
277
|
+
const haLink = graph.links.find((link) => {
|
|
272
278
|
if (!link.redundancy)
|
|
273
279
|
return false;
|
|
274
280
|
const from = toEndpoint(link.from);
|
|
@@ -414,12 +420,12 @@ export class HierarchicalLayout {
|
|
|
414
420
|
for (const sg of subgraphMap.values()) {
|
|
415
421
|
edgesByContainer.set(sg.id, []);
|
|
416
422
|
}
|
|
417
|
-
graph.links.
|
|
423
|
+
for (const [index, link] of graph.links.entries()) {
|
|
418
424
|
const from = toEndpoint(link.from);
|
|
419
425
|
const to = toEndpoint(link.to);
|
|
420
426
|
// Skip HA links (they're inside HA containers)
|
|
421
427
|
if (link.redundancy && isHALink(from.node, to.node)) {
|
|
422
|
-
|
|
428
|
+
continue;
|
|
423
429
|
}
|
|
424
430
|
const sourceId = from.port ? `${from.node}:${from.port}` : from.node;
|
|
425
431
|
const targetId = to.port ? `${to.node}:${to.port}` : to.node;
|
|
@@ -438,10 +444,12 @@ export class HierarchicalLayout {
|
|
|
438
444
|
if (to.ip)
|
|
439
445
|
labelParts.push(to.ip);
|
|
440
446
|
if (labelParts.length > 0) {
|
|
441
|
-
edge.labels = [
|
|
447
|
+
edge.labels = [
|
|
448
|
+
{
|
|
442
449
|
text: labelParts.join('\n'),
|
|
443
|
-
layoutOptions: { 'elk.edgeLabels.placement': 'CENTER' }
|
|
444
|
-
}
|
|
450
|
+
layoutOptions: { 'elk.edgeLabels.placement': 'CENTER' },
|
|
451
|
+
},
|
|
452
|
+
];
|
|
445
453
|
}
|
|
446
454
|
// Find LCA and place edge in appropriate container
|
|
447
455
|
const lca = findLCA(from.node, to.node);
|
|
@@ -451,7 +459,7 @@ export class HierarchicalLayout {
|
|
|
451
459
|
}
|
|
452
460
|
const containerId = container && subgraphMap.has(container) ? container : 'root';
|
|
453
461
|
edgesByContainer.get(containerId).push(edge);
|
|
454
|
-
}
|
|
462
|
+
}
|
|
455
463
|
// Dynamic edge spacing
|
|
456
464
|
const edgeNodeSpacing = Math.max(10, Math.round(options.nodeSpacing * 0.4));
|
|
457
465
|
const edgeEdgeSpacing = Math.max(8, Math.round(options.nodeSpacing * 0.25));
|
|
@@ -575,7 +583,9 @@ export class HierarchicalLayout {
|
|
|
575
583
|
else {
|
|
576
584
|
side = 'right';
|
|
577
585
|
}
|
|
578
|
-
const portName = elkPort.id.includes(':')
|
|
586
|
+
const portName = elkPort.id.includes(':')
|
|
587
|
+
? elkPort.id.split(':').slice(1).join(':')
|
|
588
|
+
: elkPort.id;
|
|
579
589
|
layoutNode.ports.set(elkPort.id, {
|
|
580
590
|
id: elkPort.id,
|
|
581
591
|
label: portName,
|
|
@@ -596,9 +606,9 @@ export class HierarchicalLayout {
|
|
|
596
606
|
}
|
|
597
607
|
// Build link map for ID matching
|
|
598
608
|
const linkById = new Map();
|
|
599
|
-
graph.links.
|
|
609
|
+
for (const [index, link] of graph.links.entries()) {
|
|
600
610
|
linkById.set(link.id || `edge-${index}`, { link, index });
|
|
601
|
-
}
|
|
611
|
+
}
|
|
602
612
|
// Track processed edges to prevent duplicates
|
|
603
613
|
const processedEdgeIds = new Set();
|
|
604
614
|
// Check if container is an HA container
|
|
@@ -693,16 +703,16 @@ export class HierarchicalLayout {
|
|
|
693
703
|
// Process all edges (coordinates are absolute with edgeCoords=ROOT)
|
|
694
704
|
processEdgesInContainer(elkGraph);
|
|
695
705
|
// Fallback for any missing links
|
|
696
|
-
graph.links.
|
|
706
|
+
for (const [index, link] of graph.links.entries()) {
|
|
697
707
|
const id = link.id || `link-${index}`;
|
|
698
708
|
if (layoutLinks.has(id))
|
|
699
|
-
|
|
709
|
+
continue;
|
|
700
710
|
const fromEndpoint = toEndpoint(link.from);
|
|
701
711
|
const toEndpoint_ = toEndpoint(link.to);
|
|
702
712
|
const fromNode = layoutNodes.get(fromEndpoint.node);
|
|
703
713
|
const toNode = layoutNodes.get(toEndpoint_.node);
|
|
704
714
|
if (!fromNode || !toNode)
|
|
705
|
-
|
|
715
|
+
continue;
|
|
706
716
|
const startY = fromNode.position.y + fromNode.size.height / 2;
|
|
707
717
|
const endY = toNode.position.y - toNode.size.height / 2;
|
|
708
718
|
const points = this.generateOrthogonalPath({ x: fromNode.position.x, y: startY }, { x: toNode.position.x, y: endY });
|
|
@@ -715,7 +725,7 @@ export class HierarchicalLayout {
|
|
|
715
725
|
points,
|
|
716
726
|
link,
|
|
717
727
|
});
|
|
718
|
-
}
|
|
728
|
+
}
|
|
719
729
|
// Calculate bounds
|
|
720
730
|
const bounds = this.calculateTotalBounds(layoutNodes, layoutSubgraphs);
|
|
721
731
|
return {
|
|
@@ -730,25 +740,32 @@ export class HierarchicalLayout {
|
|
|
730
740
|
const options = this.getEffectiveOptions(graph);
|
|
731
741
|
const result = this.calculateFallbackLayout(graph, options.direction);
|
|
732
742
|
// Start async layout
|
|
733
|
-
this.layoutAsync(graph)
|
|
743
|
+
this.layoutAsync(graph)
|
|
744
|
+
.then((asyncResult) => {
|
|
734
745
|
Object.assign(result, asyncResult);
|
|
735
|
-
})
|
|
746
|
+
})
|
|
747
|
+
.catch(() => { });
|
|
736
748
|
return result;
|
|
737
749
|
}
|
|
738
750
|
toElkDirection(direction) {
|
|
739
751
|
switch (direction) {
|
|
740
|
-
case 'TB':
|
|
741
|
-
|
|
742
|
-
case '
|
|
743
|
-
|
|
744
|
-
|
|
752
|
+
case 'TB':
|
|
753
|
+
return 'DOWN';
|
|
754
|
+
case 'BT':
|
|
755
|
+
return 'UP';
|
|
756
|
+
case 'LR':
|
|
757
|
+
return 'RIGHT';
|
|
758
|
+
case 'RL':
|
|
759
|
+
return 'LEFT';
|
|
760
|
+
default:
|
|
761
|
+
return 'DOWN';
|
|
745
762
|
}
|
|
746
763
|
}
|
|
747
764
|
calculateNodeHeight(node, portCount = 0) {
|
|
748
765
|
const lines = Array.isArray(node.label) ? node.label.length : 1;
|
|
749
766
|
const labelHeight = lines * LABEL_LINE_HEIGHT;
|
|
750
767
|
const labels = Array.isArray(node.label) ? node.label : [node.label];
|
|
751
|
-
const maxLabelLength = Math.max(...labels.map(l => l.length));
|
|
768
|
+
const maxLabelLength = Math.max(...labels.map((l) => l.length));
|
|
752
769
|
const labelWidth = maxLabelLength * ESTIMATED_CHAR_WIDTH;
|
|
753
770
|
const portWidth = portCount > 0 ? (portCount + 1) * MIN_PORT_SPACING : 0;
|
|
754
771
|
const baseContentWidth = Math.max(labelWidth, portWidth);
|
|
@@ -764,10 +781,10 @@ export class HierarchicalLayout {
|
|
|
764
781
|
if (vendorIcon.startsWith('<svg')) {
|
|
765
782
|
const viewBoxMatch = vendorIcon.match(/viewBox="0 0 (\d+) (\d+)"/);
|
|
766
783
|
if (viewBoxMatch) {
|
|
767
|
-
const vbWidth = parseInt(viewBoxMatch[1]);
|
|
768
|
-
const vbHeight = parseInt(viewBoxMatch[2]);
|
|
784
|
+
const vbWidth = Number.parseInt(viewBoxMatch[1], 10);
|
|
785
|
+
const vbHeight = Number.parseInt(viewBoxMatch[2], 10);
|
|
769
786
|
const aspectRatio = vbWidth / vbHeight;
|
|
770
|
-
|
|
787
|
+
const iconWidth = Math.round(DEFAULT_ICON_SIZE * aspectRatio);
|
|
771
788
|
iconHeight = DEFAULT_ICON_SIZE;
|
|
772
789
|
if (iconWidth > maxIconWidth) {
|
|
773
790
|
iconHeight = Math.round(maxIconWidth / aspectRatio);
|
|
@@ -780,10 +797,10 @@ export class HierarchicalLayout {
|
|
|
780
797
|
else {
|
|
781
798
|
const vbMatch = viewBox.match(/(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/);
|
|
782
799
|
if (vbMatch) {
|
|
783
|
-
const vbWidth = parseInt(vbMatch[3]);
|
|
784
|
-
const vbHeight = parseInt(vbMatch[4]);
|
|
800
|
+
const vbWidth = Number.parseInt(vbMatch[3], 10);
|
|
801
|
+
const vbHeight = Number.parseInt(vbMatch[4], 10);
|
|
785
802
|
const aspectRatio = vbWidth / vbHeight;
|
|
786
|
-
|
|
803
|
+
const iconWidth = Math.round(DEFAULT_ICON_SIZE * aspectRatio);
|
|
787
804
|
iconHeight = DEFAULT_ICON_SIZE;
|
|
788
805
|
if (iconWidth > maxIconWidth) {
|
|
789
806
|
iconHeight = Math.round(maxIconWidth / aspectRatio);
|
|
@@ -816,7 +833,7 @@ export class HierarchicalLayout {
|
|
|
816
833
|
}
|
|
817
834
|
calculateNodeWidth(node, portInfo) {
|
|
818
835
|
const labels = Array.isArray(node.label) ? node.label : [node.label];
|
|
819
|
-
const maxLabelLength = Math.max(...labels.map(l => l.length));
|
|
836
|
+
const maxLabelLength = Math.max(...labels.map((l) => l.length));
|
|
820
837
|
const labelWidth = maxLabelLength * ESTIMATED_CHAR_WIDTH;
|
|
821
838
|
const topCount = portInfo?.top.size || 0;
|
|
822
839
|
const bottomCount = portInfo?.bottom.size || 0;
|
|
@@ -837,8 +854,8 @@ export class HierarchicalLayout {
|
|
|
837
854
|
if (vendorIcon.startsWith('<svg')) {
|
|
838
855
|
const viewBoxMatch = vendorIcon.match(/viewBox="0 0 (\d+) (\d+)"/);
|
|
839
856
|
if (viewBoxMatch) {
|
|
840
|
-
const vbWidth = parseInt(viewBoxMatch[1]);
|
|
841
|
-
const vbHeight = parseInt(viewBoxMatch[2]);
|
|
857
|
+
const vbWidth = Number.parseInt(viewBoxMatch[1], 10);
|
|
858
|
+
const vbHeight = Number.parseInt(viewBoxMatch[2], 10);
|
|
842
859
|
const aspectRatio = vbWidth / vbHeight;
|
|
843
860
|
iconWidth = Math.min(Math.round(DEFAULT_ICON_SIZE * aspectRatio), maxIconWidth);
|
|
844
861
|
}
|
|
@@ -846,8 +863,8 @@ export class HierarchicalLayout {
|
|
|
846
863
|
else {
|
|
847
864
|
const vbMatch = viewBox.match(/(\d+)\s+(\d+)\s+(\d+)\s+(\d+)/);
|
|
848
865
|
if (vbMatch) {
|
|
849
|
-
const vbWidth = parseInt(vbMatch[3]);
|
|
850
|
-
const vbHeight = parseInt(vbMatch[4]);
|
|
866
|
+
const vbWidth = Number.parseInt(vbMatch[3], 10);
|
|
867
|
+
const vbHeight = Number.parseInt(vbMatch[4], 10);
|
|
851
868
|
const aspectRatio = vbWidth / vbHeight;
|
|
852
869
|
iconWidth = Math.min(Math.round(DEFAULT_ICON_SIZE * aspectRatio), maxIconWidth);
|
|
853
870
|
}
|
|
@@ -858,36 +875,38 @@ export class HierarchicalLayout {
|
|
|
858
875
|
return Math.max(paddedIconLabelWidth, portWidth);
|
|
859
876
|
}
|
|
860
877
|
calculateTotalBounds(nodes, subgraphs) {
|
|
861
|
-
let minX =
|
|
862
|
-
let
|
|
863
|
-
|
|
878
|
+
let minX = Number.POSITIVE_INFINITY;
|
|
879
|
+
let minY = Number.POSITIVE_INFINITY;
|
|
880
|
+
let maxX = Number.NEGATIVE_INFINITY;
|
|
881
|
+
let maxY = Number.NEGATIVE_INFINITY;
|
|
882
|
+
for (const node of nodes.values()) {
|
|
864
883
|
let left = node.position.x - node.size.width / 2;
|
|
865
884
|
let right = node.position.x + node.size.width / 2;
|
|
866
885
|
let top = node.position.y - node.size.height / 2;
|
|
867
886
|
let bottom = node.position.y + node.size.height / 2;
|
|
868
887
|
if (node.ports) {
|
|
869
|
-
node.ports.
|
|
888
|
+
for (const port of node.ports.values()) {
|
|
870
889
|
const portX = node.position.x + port.position.x;
|
|
871
890
|
const portY = node.position.y + port.position.y;
|
|
872
891
|
left = Math.min(left, portX - port.size.width / 2);
|
|
873
892
|
right = Math.max(right, portX + port.size.width / 2);
|
|
874
893
|
top = Math.min(top, portY - port.size.height / 2);
|
|
875
894
|
bottom = Math.max(bottom, portY + port.size.height / 2);
|
|
876
|
-
}
|
|
895
|
+
}
|
|
877
896
|
}
|
|
878
897
|
minX = Math.min(minX, left);
|
|
879
898
|
minY = Math.min(minY, top);
|
|
880
899
|
maxX = Math.max(maxX, right);
|
|
881
900
|
maxY = Math.max(maxY, bottom);
|
|
882
|
-
}
|
|
883
|
-
subgraphs.
|
|
901
|
+
}
|
|
902
|
+
for (const sg of subgraphs.values()) {
|
|
884
903
|
minX = Math.min(minX, sg.bounds.x);
|
|
885
904
|
minY = Math.min(minY, sg.bounds.y);
|
|
886
905
|
maxX = Math.max(maxX, sg.bounds.x + sg.bounds.width);
|
|
887
906
|
maxY = Math.max(maxY, sg.bounds.y + sg.bounds.height);
|
|
888
|
-
}
|
|
907
|
+
}
|
|
889
908
|
const padding = 50;
|
|
890
|
-
if (minX ===
|
|
909
|
+
if (minX === Number.POSITIVE_INFINITY) {
|
|
891
910
|
return { x: 0, y: 0, width: 400, height: 300 };
|
|
892
911
|
}
|
|
893
912
|
return {
|
|
@@ -908,7 +927,9 @@ export class HierarchicalLayout {
|
|
|
908
927
|
haPairSet.add([pair.nodeA, pair.nodeB].sort().join(':'));
|
|
909
928
|
}
|
|
910
929
|
const nodePorts = collectNodePorts(graph, haPairSet);
|
|
911
|
-
let x = 100
|
|
930
|
+
let x = 100;
|
|
931
|
+
let y = 100;
|
|
932
|
+
let col = 0;
|
|
912
933
|
const maxCols = 4;
|
|
913
934
|
const rowHeight = this.options.nodeHeight + this.options.rankSpacing;
|
|
914
935
|
for (const node of graph.nodes) {
|
|
@@ -933,7 +954,7 @@ export class HierarchicalLayout {
|
|
|
933
954
|
x += colWidth;
|
|
934
955
|
}
|
|
935
956
|
}
|
|
936
|
-
graph.links.
|
|
957
|
+
for (const [index, link] of graph.links.entries()) {
|
|
937
958
|
const fromId = getNodeId(link.from);
|
|
938
959
|
const toId = getNodeId(link.to);
|
|
939
960
|
const from = layoutNodes.get(fromId);
|
|
@@ -949,7 +970,7 @@ export class HierarchicalLayout {
|
|
|
949
970
|
link,
|
|
950
971
|
});
|
|
951
972
|
}
|
|
952
|
-
}
|
|
973
|
+
}
|
|
953
974
|
const bounds = this.calculateTotalBounds(layoutNodes, layoutSubgraphs);
|
|
954
975
|
return {
|
|
955
976
|
nodes: layoutNodes,
|
|
@@ -989,12 +1010,7 @@ export class HierarchicalLayout {
|
|
|
989
1010
|
}
|
|
990
1011
|
// Use midpoint for orthogonal routing
|
|
991
1012
|
const midY = start.y + dy / 2;
|
|
992
|
-
return [
|
|
993
|
-
start,
|
|
994
|
-
{ x: start.x, y: midY },
|
|
995
|
-
{ x: end.x, y: midY },
|
|
996
|
-
end,
|
|
997
|
-
];
|
|
1013
|
+
return [start, { x: start.x, y: midY }, { x: end.x, y: midY }, end];
|
|
998
1014
|
}
|
|
999
1015
|
}
|
|
1000
1016
|
// Default instance
|