diff --git a/canvas/package-lock.json b/canvas/package-lock.json index 4016b28..24abe14 100644 --- a/canvas/package-lock.json +++ b/canvas/package-lock.json @@ -14,13 +14,45 @@ "reactflow": "^11.11.4" }, "devDependencies": { + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.3", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "@vitejs/plugin-react": "^4.3.4", + "jsdom": "^25.0.1", "typescript": "^5.6.3", - "vite": "^5.4.11" + "vite": "^5.4.11", + "vitest": "^2.1.9" } }, + "node_modules/@adobe/css-tools": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.5.0.tgz", + "integrity": "sha512-6OzddxPio9UiWTCemp4N8cYLV2ZN1ncRnV1cVGtve7dhPOtRkleRyx32GQCYSwDYgaHU3USMm84tNsvKzRCa1Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@asamuzakjp/css-color": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", + "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^2.1.3", + "@csstools/css-color-parser": "^3.0.9", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "lru-cache": "^10.4.3" + } + }, + "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, "node_modules/@babel/code-frame": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", @@ -255,6 +287,16 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", @@ -303,6 +345,121 @@ "node": ">=6.9.0" } }, + "node_modules/@csstools/color-helpers": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", + "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/css-calc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", + "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", + "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^5.1.0", + "@csstools/css-calc": "^2.1.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", + "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", + "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/@dagrejs/dagre": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/@dagrejs/dagre/-/dagre-1.1.8.tgz", @@ -1221,6 +1378,90 @@ "win32" ] }, + "node_modules/@testing-library/dom": { + "version": "10.4.2", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.2.tgz", + "integrity": "sha512-yzr2S9HyAIdhz2/6qHgbs665Q7PKVcDF05vsOlHPxG1mo36gKVesdYVeDLnXgfjJ03CrKRk08knc6+E/9m8v2Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "picocolors": "1.1.1", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@testing-library/jest-dom": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.9.1.tgz", + "integrity": "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "aria-query": "^5.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "picocolors": "^1.1.1", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@testing-library/react": { + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.3.tgz", + "integrity": "sha512-Uo193NgQbPMz6lrrhtRQQFcMC6Re/ELLFbbuVL30WDlZxlpZf9/lMHTAVxPRLw1q1iu9OJmR1c2BLiENRstdBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@testing-library/dom": "^10.0.0", + "@types/react": "^18.0.0 || ^19.0.0", + "@types/react-dom": "^18.0.0 || ^19.0.0", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@types/aria-query": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", + "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/@types/babel__core": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", @@ -1581,6 +1822,181 @@ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, + "node_modules/@vitest/expect": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.9.tgz", + "integrity": "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "2.1.9", + "@vitest/utils": "2.1.9", + "chai": "^5.1.2", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.9.tgz", + "integrity": "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "2.1.9", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.12" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz", + "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.9.tgz", + "integrity": "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "2.1.9", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.9.tgz", + "integrity": "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.1.9", + "magic-string": "^0.30.12", + "pathe": "^1.1.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.9.tgz", + "integrity": "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^3.0.2" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.9.tgz", + "integrity": "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.1.9", + "loupe": "^3.1.2", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, + "license": "MIT" + }, "node_modules/baseline-browser-mapping": { "version": "2.11.7", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.7.tgz", @@ -1628,6 +2044,30 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001806", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001806.tgz", @@ -1649,18 +2089,86 @@ ], "license": "CC-BY-4.0" }, + "node_modules/chai": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/check-error": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", + "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, "node_modules/classcat": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/classcat/-/classcat-5.0.5.tgz", "integrity": "sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==", "license": "MIT" }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/css.escape": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz", + "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cssstyle": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz", + "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^3.2.0", + "rrweb-cssom": "^0.8.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/cssstyle/node_modules/rrweb-cssom": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", + "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", + "dev": true, + "license": "MIT" }, "node_modules/csstype": { "version": "3.2.3", @@ -1774,6 +2282,20 @@ "node": ">=12" } }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -1792,6 +2314,66 @@ } } }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "dev": true, + "license": "MIT" + }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/dom-accessibility-api": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/electron-to-chromium": { "version": "1.5.398", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.398.tgz", @@ -1799,6 +2381,75 @@ "dev": true, "license": "ISC" }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/esbuild": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", @@ -1848,6 +2499,43 @@ "node": ">=6" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/expect-type": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -1863,6 +2551,16 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -1873,12 +2571,218 @@ "node": ">=6.9.0" } }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "license": "MIT" }, + "node_modules/jsdom": { + "version": "25.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-25.0.1.tgz", + "integrity": "sha512-8i7LzZj7BF8uplX+ZyOlIz86V6TAsSs+np6m1kpW9u0JWi4z/1t+FzcK1aek+ybTnAC4KhBL4uXCNT0wcUIeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssstyle": "^4.1.0", + "data-urls": "^5.0.0", + "decimal.js": "^10.4.3", + "form-data": "^4.0.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.5", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.12", + "parse5": "^7.1.2", + "rrweb-cssom": "^0.7.1", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.0.0", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^2.11.2" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -1917,6 +2821,13 @@ "loose-envify": "cli.js" } }, + "node_modules/loupe": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -1927,6 +2838,70 @@ "yallist": "^3.0.2" } }, + "node_modules/lz-string": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "lz-string": "bin/bin.js" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -1963,6 +2938,43 @@ "node": ">=18" } }, + "node_modules/nwsapi": { + "version": "2.2.28", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.28.tgz", + "integrity": "sha512-IlVB7OS7qrOsVYlpnFIkETjMwT9jwvmocJmmM+GZU/PAB3uGi9Ezd7vcWhWBUnSc0ya4ppmQITOyP1ez9gg8cg==", + "dev": true, + "license": "MIT" + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -1999,6 +3011,32 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/pretty-format": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz", + "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", @@ -2024,6 +3062,14 @@ "react": "^18.3.1" } }, + "node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true, + "license": "MIT", + "peer": true + }, "node_modules/react-refresh": { "version": "0.17.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", @@ -2052,6 +3098,20 @@ "react-dom": ">=17" } }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/rollup": { "version": "4.62.3", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.3.tgz", @@ -2097,6 +3157,33 @@ "fsevents": "~2.3.2" } }, + "node_modules/rrweb-cssom": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", + "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", + "dev": true, + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", @@ -2116,6 +3203,13 @@ "semver": "bin/semver.js" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -2126,6 +3220,130 @@ "node": ">=0.10.0" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "dev": true, + "license": "MIT" + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", + "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tldts": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", + "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^6.1.86" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", + "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tough-cookie": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/typescript": { "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", @@ -2240,6 +3458,212 @@ } } }, + "node_modules/vite-node": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.9.tgz", + "integrity": "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.7", + "es-module-lexer": "^1.5.4", + "pathe": "^1.1.2", + "vite": "^5.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.9.tgz", + "integrity": "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/expect": "2.1.9", + "@vitest/mocker": "2.1.9", + "@vitest/pretty-format": "^2.1.9", + "@vitest/runner": "2.1.9", + "@vitest/snapshot": "2.1.9", + "@vitest/spy": "2.1.9", + "@vitest/utils": "2.1.9", + "chai": "^5.1.2", + "debug": "^4.3.7", + "expect-type": "^1.1.0", + "magic-string": "^0.30.12", + "pathe": "^1.1.2", + "std-env": "^3.8.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.1", + "tinypool": "^1.0.1", + "tinyrainbow": "^1.2.0", + "vite": "^5.0.0", + "vite-node": "2.1.9", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/node": "^18.0.0 || >=20.0.0", + "@vitest/browser": "2.1.9", + "@vitest/ui": "2.1.9", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ws": { + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.22.0.tgz", + "integrity": "sha512-Ydggc987+RO0AnWtZ/7Wq9FtNvcrL1b/RO0ud9mWjUPgDrsAAwQSF51sm2hm1XofbU/4jkpGEsLFsZZxU+1DOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" + }, "node_modules/yallist": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", diff --git a/canvas/package.json b/canvas/package.json index 2eb5607..0abe96d 100644 --- a/canvas/package.json +++ b/canvas/package.json @@ -6,7 +6,9 @@ "scripts": { "dev": "vite", "build": "tsc --noEmit && vite build", - "typecheck": "tsc --noEmit" + "typecheck": "tsc --noEmit", + "test": "vitest run", + "test:watch": "vitest" }, "dependencies": { "@dagrejs/dagre": "^1.1.4", @@ -15,10 +17,14 @@ "reactflow": "^11.11.4" }, "devDependencies": { + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.3", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "@vitejs/plugin-react": "^4.3.4", + "jsdom": "^25.0.1", "typescript": "^5.6.3", - "vite": "^5.4.11" + "vite": "^5.4.11", + "vitest": "^2.1.9" } } diff --git a/canvas/src/api.ts b/canvas/src/api.ts index 7cdc107..ce123c3 100644 --- a/canvas/src/api.ts +++ b/canvas/src/api.ts @@ -185,15 +185,43 @@ export interface ImportResult { export const importModel = (format: string, content: string, dialect?: string) => post("/api/import", { format, content, dialect }); +/** A semantic diff of an import against the current model (the review view's ModelDiffDoc), + * WITHOUT writing — plus the import's change list + warnings, so the review can apply the + * selected objects afterwards. Powers "review before it lands" for erwin imports. */ +export type ImportPreviewDoc = ModelDiffDoc & { + changes: { op: string; payload: Record }[]; + warnings: string[]; +}; + +export const importPreview = (format: string, content: string) => + post("/api/import/preview", { format, content }); + +/** Fetch import content a host (VS Code) stashed by token — the webview can't read local + * files, so /sme?import= hands off the file this way. One-shot. */ +export const importStashGet = (token: string) => + get<{ ok: boolean; content?: string; error?: string }>( + `/api/import/stash/${encodeURIComponent(token)}`, + ); + /** Apply an imported change list to the working tree as one batch (direct-write * canvas). Each command is sent WITHOUT a fingerprint so the server's stale-model * check is skipped: the guard exists to catch an external edit between a human's - * view and their action, not to serialise a machine applying its own batch. */ + * view and their action, not to serialise a machine applying its own batch. + * + * `tolerateExisting` skips "already exists" errors (idempotent scaffolding): an import + * into an existing model re-emits shared domains / subject areas / categories, and a + * create for one already present is a no-op, not a failure. Any OTHER error still throws. */ export const applyImportBatch = async ( changes: { op: string; payload: Record }[], + tolerateExisting = false, ) => { for (const c of changes) { - await sendCommand(c.op, c.payload); // no fingerprint -> no stale-check + try { + await sendCommand(c.op, c.payload); // no fingerprint -> no stale-check + } catch (e) { + if (tolerateExisting && e instanceof Error && /already exists/i.test(e.message)) continue; + throw e; + } } }; diff --git a/canvas/src/sme/DiffView.test.tsx b/canvas/src/sme/DiffView.test.tsx new file mode 100644 index 0000000..575d23d --- /dev/null +++ b/canvas/src/sme/DiffView.test.tsx @@ -0,0 +1,104 @@ +import { fireEvent, render, screen, within } from "@testing-library/react"; +import { useState } from "react"; +import { describe, expect, it } from "vitest"; +import { makeDiff } from "../test/diffFixture"; +import { DiffView } from "./DiffView"; +import { allFieldKeys, fieldKey, includedUlids, toggleField } from "./reviewModel"; + +/** The list-pane row for an entity (its name also appears in the detail

, so scope + * to the .rv-list to disambiguate). */ +function listRow(name: string): HTMLElement { + const list = document.querySelector(".rv-list") as HTMLElement; + return within(list).getByText(name).closest(".rv-obj") as HTMLElement; +} + +/** A host harness mirroring how ReviewScreen would drive per-field selection: it owns the + * field-keyed Set and exposes the derived included ULIDs so a test can assert them. */ +function PerFieldHost() { + const diff = makeDiff(); + const [selected, setSelected] = useState>(() => allFieldKeys(diff)); + const included = includedUlids(diff, selected); + return ( +
+
{included.sort().join(",")}
+ setSelected((s) => toggleField(fieldKey(ulid, field), s))} + /> +
+ ); +} + +describe("DiffView — filters (view only)", () => { + it("shows all changes by default and filters visibility without dropping selection", () => { + render(); + const list = () => document.querySelector(".rv-list") as HTMLElement; + // all four objects present initially + expect(within(list()).getByText("counterparty")).toBeInTheDocument(); + expect(within(list()).getByText("instrument")).toBeInTheDocument(); + expect(within(list()).getByText("legacy")).toBeInTheDocument(); + + // click the Additions filter -> only the added entity is visible in the list + fireEvent.click(screen.getByRole("tab", { name: /Additions/ })); + expect(within(list()).getByText("instrument")).toBeInTheDocument(); + expect(within(list()).queryByText("counterparty")).not.toBeInTheDocument(); + expect(within(list()).queryByText("legacy")).not.toBeInTheDocument(); + + // filtering did NOT change selection: everything is still included + expect(screen.getByTestId("included")).toHaveTextContent("E_ADD,E_DEL,E_MOD,E_REN"); + + // back to All -> everything visible again + fireEvent.click(screen.getByRole("tab", { name: /^All/ })); + expect(within(list()).getByText("counterparty")).toBeInTheDocument(); + }); + + it("only offers filters that have matches", () => { + render(); + // the fixture has one of each, so every filter with count>0 shows + for (const label of ["All", "Additions", "Modifications", "Renames", "Deletions", "Conflicts"]) { + expect(screen.getByRole("tab", { name: new RegExp(label) })).toBeInTheDocument(); + } + }); +}); + +describe("DiffView — per-field selection", () => { + it("unchecking every field of an object excludes it from the action", () => { + render(); + // focus the modified entity (it has two field changes) + fireEvent.click(listRow("counterparty")); + // its two per-field checkboxes live in the detail pane + const defBox = screen.getByLabelText("include change: definition"); + const domBox = screen.getByLabelText("include change: domain"); + expect(defBox).toBeChecked(); + expect(domBox).toBeChecked(); + + // uncheck both -> E_MOD drops out, others stay + fireEvent.click(defBox); + fireEvent.click(domBox); + expect(screen.getByTestId("included")).toHaveTextContent("E_ADD,E_DEL,E_REN"); + expect(screen.getByTestId("included")).not.toHaveTextContent("E_MOD"); + }); + + it("the object header checkbox reflects a partial (indeterminate) selection", () => { + render(); + fireEvent.click(listRow("counterparty")); + // uncheck ONE field -> the object stays included, header is indeterminate + fireEvent.click(screen.getByLabelText("include change: definition")); + expect(screen.getByTestId("included")).toHaveTextContent("E_MOD"); + const row = listRow("counterparty"); + const header = within(row as HTMLElement).getByRole("checkbox") as HTMLInputElement; + expect(header.indeterminate).toBe(true); + }); + + it("the header checkbox toggles all of an object's fields at once", () => { + render(); + fireEvent.click(listRow("counterparty")); + const row = listRow("counterparty"); + const header = within(row as HTMLElement).getByRole("checkbox"); + // header on -> off excludes the whole object + fireEvent.click(header); + expect(screen.getByTestId("included")).not.toHaveTextContent("E_MOD"); + }); +}); diff --git a/canvas/src/sme/DiffView.tsx b/canvas/src/sme/DiffView.tsx index eaeff23..658624c 100644 --- a/canvas/src/sme/DiffView.tsx +++ b/canvas/src/sme/DiffView.tsx @@ -1,49 +1,111 @@ import { useMemo, useState } from "react"; import type { FieldChangeDoc, ModelDiffDoc, ObjectChangeDoc } from "../types"; +import { + type ObjectSelectionState, + type ReviewFilter, + REVIEW_FILTERS, + fieldKey, + filterCounts, + filterObjects, + objectSelectionState, +} from "./reviewModel"; -/** The changed-object list and detail pane (plan §M1/M2). +/** The changed-object list and detail pane (plan §M1/M2), Phase 1: display FILTERS + + * per-FIELD selection. * * One list of only what changed, grouped by object, each change a plain-language - * sentence produced server-side (mdl_core.diff builds the label and detail, so - * the CLI, the PR body and this screen never drift). */ + * sentence produced server-side (mdl_core.diff builds the label and detail, so the CLI, + * the PR body and this screen never drift). Filters are a VIEW concern — they change what + * is visible, never what is selected (a hidden change is never silently dropped). + * + * Selection has two modes, chosen by which callback the host passes: + * - per-FIELD (`onToggleField` / field-keyed `selected`): the new Phase 1 model — each + * change is independently checkable and the object header shows a tri-state. + * - per-OBJECT (`onToggle` / ulid-keyed `selected`): the original propose flow, kept so + * existing callers work unchanged. */ export function DiffView({ diff, selectable, selected, onToggle, + onToggleField, }: { diff: ModelDiffDoc; - /** per-object checkboxes for selective proposal; off when a create_* is staged */ + /** show selection checkboxes; off when a create_* is staged */ selectable?: boolean; + /** the selected set — object ULIDs (per-object mode) or field keys (per-field mode) */ selected?: Set; + /** per-OBJECT toggle (original mode). When set, checkboxes are whole-object. */ onToggle?: (ulid: string) => void; + /** per-FIELD toggle (Phase 1). When set, checkboxes are per-field with an object + * tri-state header; takes precedence over onToggle. */ + onToggleField?: (ulid: string, field: string) => void; }) { + const [filter, setFilter] = useState("all"); + const visible = useMemo(() => filterObjects(diff, filter), [diff, filter]); + const counts = useMemo(() => filterCounts(diff), [diff]); const [focus, setFocus] = useState(diff.objects[0]?.ulid ?? null); const obj = useMemo( - () => diff.objects.find((o) => o.ulid === focus) ?? diff.objects[0] ?? null, - [diff, focus], + () => visible.find((o) => o.ulid === focus) ?? visible[0] ?? diff.objects[0] ?? null, + [visible, diff, focus], ); + const perField = !!onToggleField; if (!diff.objects.length) { return

No model changes against {diff.base.label}.

; } return ( -
-
- {diff.objects.map((o) => ( - setFocus(o.ulid)} - onToggle={() => onToggle?.(o.ulid)} - /> - ))} +
+ {selectable !== undefined && ( +
+ {REVIEW_FILTERS.filter((f) => f.id === "all" || counts[f.id] > 0).map((f) => ( + + ))} +
+ )} +
+
+ {visible.length === 0 ? ( +

No changes match this filter.

+ ) : ( + visible.map((o) => ( + setFocus(o.ulid)} + onToggleObject={() => onToggle?.(o.ulid)} + onToggleField={onToggleField} + /> + )) + )} +
+
+ {obj && ( + + )} +
-
{obj && }
); } @@ -57,27 +119,50 @@ function badge(o: ObjectChangeDoc): string { function ObjectRow({ obj, active, - checked, selectable, + perField, + objState, + checkedObject, onSelect, - onToggle, + onToggleObject, + onToggleField, }: { obj: ObjectChangeDoc; active: boolean; - checked: boolean; selectable?: boolean; + perField: boolean; + /** the object's tri-state in per-field mode */ + objState?: ObjectSelectionState; + /** whole-object checked, in per-object mode */ + checkedObject: boolean; onSelect: () => void; - onToggle: () => void; + onToggleObject: () => void; + onToggleField?: (ulid: string, field: string) => void; }) { + // In per-field mode the header checkbox toggles ALL of the object's fields at once, and + // shows indeterminate when only some are selected. + const setIndeterminate = (el: HTMLInputElement | null) => { + if (el && perField) el.indeterminate = objState === "some"; + }; + const headerChecked = perField ? objState !== "none" : checkedObject; + const toggleHeader = () => { + if (!perField) return onToggleObject(); + // toggle every field key of this object via the field callback + for (const f of obj.fields) onToggleField?.(obj.ulid, f.field); + for (const c of obj.children) for (const f of c.fields) onToggleField?.(obj.ulid, `${c.ulid}.${f.field}`); + if (!obj.fields.length && !obj.children.length) onToggleField?.(obj.ulid, "*"); + }; + return (
{selectable && ( e.stopPropagation()} - onChange={onToggle} + onChange={toggleHeader} aria-label={`include ${obj.name_before ?? obj.name_after}`} /> )} @@ -104,10 +189,38 @@ function ObjectRow({ ); } -function Detail({ obj }: { obj: ObjectChangeDoc }) { +function Detail({ + obj, + selectable, + perField, + selected, + onToggleField, +}: { + obj: ObjectChangeDoc; + selectable?: boolean; + perField?: boolean; + selected?: Set; + onToggleField?: (ulid: string, field: string) => void; +}) { const children = obj.children.flatMap((c) => - c.fields.map((f) => ({ field: f, on: c.name_before ?? c.name_after ?? "" })), + c.fields.map((f) => ({ field: f, on: c.name_before ?? c.name_after ?? "", key: `${c.ulid}.${f.field}` })), ); + // one selectable row per field, only when the host wired per-field selection + const pick = (field: string, node: React.ReactNode) => { + if (!selectable || !perField) return node; + const key = fieldKey(obj.ulid, field); + return ( +
+ onToggleField?.(obj.ulid, field)} + aria-label={`include change: ${field}`} + /> +
{node}
+
+ ); + }; return ( <>

@@ -119,10 +232,10 @@ function Detail({ obj }: { obj: ObjectChangeDoc }) { {obj.path && · {obj.path}}

{obj.fields.map((f, i) => ( - +
{pick(f.field, )}
))} - {children.map(({ field, on }, i) => ( - + {children.map(({ field, on, key }, i) => ( +
{pick(key, )}
))} {obj.severity === "breaking" && (
diff --git a/canvas/src/sme/ImportExportMenu.tsx b/canvas/src/sme/ImportExportMenu.tsx index 3b01cb4..ac9a314 100644 --- a/canvas/src/sme/ImportExportMenu.tsx +++ b/canvas/src/sme/ImportExportMenu.tsx @@ -1,5 +1,12 @@ import { useEffect, useRef, useState } from "react"; -import { type ExportFormat, exportUrl, fetchExportFormats, importModel } from "../api"; +import { + type ExportFormat, + type ImportPreviewDoc, + exportUrl, + fetchExportFormats, + importModel, + importPreview, +} from "../api"; import type { Exec } from "../exec"; import "./ImportExportMenu.css"; @@ -17,11 +24,17 @@ export function ImportExportMenu({ buttonClass = "erd-action ghost", applyBatch, openImport = false, + prefillImport = "", + onPreview, }: { exec: Exec; canEdit: boolean; /** called after a successful import so the shell can jump to the review screen */ onImported?: (tables: number) => void; + /** when set, an erwin import is reviewed before it lands (see ImportPanel.onPreview) */ + onPreview?: (doc: ImportPreviewDoc) => void; + /** pre-fill the import content (a host-stashed .xml) */ + prefillImport?: string; /** the import button's label — "Import & review" in the staged (SME) app, plain * "Import" in the direct-write architect canvas where there is no review screen */ submitLabel?: string; @@ -126,6 +139,8 @@ export function ImportExportMenu({ setOpen(null); onImported?.(n); }} + onPreview={onPreview} + prefillImport={prefillImport} /> )}
@@ -146,6 +161,8 @@ function ImportPanel({ applyBatch, onClose, onImported, + onPreview, + prefillImport, }: { exec: Exec; submitLabel: string; @@ -153,14 +170,26 @@ function ImportPanel({ applyBatch?: (changes: { op: string; payload: Record }[]) => Promise; onClose: () => void; onImported: (tables: number) => void; + /** When set, an erwin import is sent for PRE-WRITE REVIEW instead of being applied: the + * parsed semantic diff is handed up so the host mounts the review screen with an "Apply + * import" action. Absent = apply immediately (today's behaviour / direct-write canvas). */ + onPreview?: (doc: ImportPreviewDoc) => void; + prefillImport?: string; }) { - const [format, setFormat] = useState("sql"); + // When opened for pre-write review (onPreview wired), default to erwin — the only format the + // review path supports today — so the VS Code "Review Erwin import" flow lands ready to paste. + const [format, setFormat] = useState(onPreview ? "erwin" : "sql"); const [dialect, setDialect] = useState("postgres"); - const [content, setContent] = useState(""); + const [content, setContent] = useState(prefillImport ?? ""); const [busy, setBusy] = useState(false); const [error, setError] = useState(null); const [warnings, setWarnings] = useState([]); + // Host-stashed content (a VS Code .xml) arrives after mount; fill the panel when it does. + useEffect(() => { + if (prefillImport) setContent(prefillImport); + }, [prefillImport]); + const onFile = (f: File | null) => { if (!f) return; f.text().then(setContent).catch(() => setError("could not read that file")); @@ -171,6 +200,21 @@ function ImportPanel({ setError(null); setWarnings([]); try { + // Pre-write review: for an erwin import in the SME app, fetch the semantic diff and hand + // it up for review BEFORE anything is written; the review's "Apply import" action does + // the write. Other formats / the direct-write canvas keep the apply-now path below. + if (onPreview && format === "erwin") { + const doc = await importPreview(format, content); + if (!doc.changes.length) { + setError(doc.warnings[0] ?? "nothing to import from that document"); + setBusy(false); + return; + } + onClose(); + onPreview(doc); + setBusy(false); + return; + } const res = await importModel(format, content, format === "sql" ? dialect : undefined); if (!res.changes.length) { setError(res.warnings[0] ?? "nothing to import from that document"); diff --git a/canvas/src/sme/ModelWorkspace.tsx b/canvas/src/sme/ModelWorkspace.tsx index 911b003..7864c0a 100644 --- a/canvas/src/sme/ModelWorkspace.tsx +++ b/canvas/src/sme/ModelWorkspace.tsx @@ -1,5 +1,6 @@ import { useCallback, useMemo, useRef, useState } from "react"; import { ReactFlowProvider } from "reactflow"; +import type { ImportPreviewDoc } from "../api"; import type { Capabilities, Exec } from "../exec"; import { ModelCanvas, type ModelCanvasHandle } from "../ModelCanvas"; import { LayersView, OntologyBrowser, type ReadOnlyPanelTab } from "../SidePanel"; @@ -54,6 +55,9 @@ export function ModelWorkspace({ direct = false, onSelectEntity, onImported, + onImportPreview, + openImport = false, + prefillImport = "", query = "", busy, }: { @@ -67,6 +71,12 @@ export function ModelWorkspace({ onSelectEntity?: (id: string) => void; /** after an import stages its changes, jump the shell to the review screen */ onImported?: (tables: number) => void; + /** when set, an erwin import is reviewed before it lands (the shell mounts the review) */ + onImportPreview?: (doc: ImportPreviewDoc) => void; + /** open the import panel on mount (VS Code "Review Erwin import" via /sme?import=1) */ + openImport?: boolean; + /** pre-fill the import panel with this content (a host-stashed .xml via /sme?import=) */ + prefillImport?: string; /** the top-bar search text — highlights matching entities and dims the rest */ query?: string; busy?: boolean; @@ -242,7 +252,14 @@ export function ModelWorkspace({
diff --git a/canvas/src/sme/SmeApp.tsx b/canvas/src/sme/SmeApp.tsx index eb98c46..b36b33b 100644 --- a/canvas/src/sme/SmeApp.tsx +++ b/canvas/src/sme/SmeApp.tsx @@ -1,9 +1,12 @@ -import { useCallback, useEffect, useMemo, useState } from "react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { + type ImportPreviewDoc, + applyImportBatch, classifyStaged, fetchGlossary, fetchGlossaryConfig, fetchModel, + importStashGet, previewChanges, sendCommand, } from "../api"; @@ -26,6 +29,7 @@ import { ModelWorkspace } from "./ModelWorkspace"; import { SubjectAreaEditor } from "./SubjectAreaEditor"; import { ProposalsList } from "./ProposalsList"; import { ProposeDialog } from "./ProposeDialog"; +import { allFieldKeys, fieldKey, filterImportChanges, includedEntityNames } from "./reviewModel"; import { ReviewScreen } from "./ReviewScreen"; import { TermCard } from "./TermCard"; import { TermEditor } from "./TermEditor"; @@ -51,13 +55,34 @@ export function SmeApp() { const [editing, setEditing] = useState(false); const [pending, setPending] = useState([]); const [proposeOpen, setProposeOpen] = useState(false); + // `?import=1` (VS Code "Review Erwin import") starts on the Model view with the import panel + // open, so an erwin import flows straight into the pre-write review. `?import=` (the + // host read a local .xml and stashed it) additionally pre-fills the panel with that content. + const importParam = useMemo( + () => new URLSearchParams(window.location.search).get("import"), + [], + ); + const openImport = !!importParam; + const importStashToken = importParam && importParam !== "1" ? importParam : null; + // content fetched from the host's one-shot stash (when ?import=) + const [prefillImport, setPrefillImport] = useState(""); + useEffect(() => { + if (!importStashToken) return; + importStashGet(importStashToken) + .then((r) => r.ok && r.content && setPrefillImport(r.content)) + .catch(() => {}); + }, [importStashToken]); // browse | review | proposals. Written to location.hash so a view is linkable // (app.py serves sme.html for `sme` and any `sme/...`, so no server change). const [view, setView] = useState<"browse" | "model" | "areas" | "review" | "proposals">( - window.location.hash === "#proposals" ? "proposals" : "browse", + openImport ? "model" : window.location.hash === "#proposals" ? "proposals" : "browse", ); // objects the SME has unticked in the review screen (selective proposal) const [excluded, setExcluded] = useState>(new Set()); + // When an erwin import is being reviewed BEFORE it lands, this holds its preview doc + + // change list; the review screen then shows an "Apply import" action instead of propose. + // Cleared when the review is left. (Reuses the "review" view, no new route.) + const [importReview, setImportReview] = useState(null); const [user, setUser] = useState(() => localStorage.getItem("mdl.sme.user") ?? ""); // Server-established identity (spec §17). When the source is proxy or git, the // acting user is known and trustworthy — the propose dialog greets them instead @@ -210,9 +235,17 @@ export function SmeApp() { }, []); // keep the view in step with the hash, so a deep link and the back button work + const firstHash = useRef(true); useEffect(() => { const onHash = () => { const h = window.location.hash; + // On the very first load with ?import=1 and no hash yet, stay on the Model view (set by + // the initializer) so the import panel opens; a hash navigation always wins thereafter. + if (firstHash.current && !h && openImport) { + firstHash.current = false; + return; + } + firstHash.current = false; setView( h === "#proposals" ? "proposals" @@ -355,24 +388,53 @@ export function SmeApp() { {view === "review" ? ( + onToggleField={(ulid, field) => setExcluded((prev) => { const next = new Set(prev); - if (next.has(u)) next.delete(u); - else next.add(u); + const key = fieldKey(ulid, field); + if (next.has(key)) next.delete(key); + else next.add(key); return next; }) } - onBack={() => goto("browse")} + onBack={() => { + setImportReview(null); + setExcluded(new Set()); + goto("browse"); + }} onSubmit={(cl) => { setRouteAdvice(cl); setProposeOpen(true); }} + action={ + importReview + ? { + id: "apply-import", + label: "Apply import →", + primary: true, + apply: async () => { + // write only the ENTITIES the reviewer kept ticked (by name — the diff doc + // carries remapped ULIDs, so name is the stable join to the import commands) + const diff = importReview as ModelDiffDoc; + const selected = new Set( + [...allFieldKeys(diff)].filter((k) => !excluded.has(k)), + ); + const keepNames = includedEntityNames(diff, selected); + const changes = filterImportChanges(importReview.changes, keepNames); + await applyImportBatch(changes, true); // tolerate shared scaffolding + setImportReview(null); + setExcluded(new Set()); + goto("browse"); + await fetchModel(subjectArea || undefined).then(setModelDoc); + }, + } + : undefined + } /> ) : view === "model" ? ( // The previewed model when anything is staged, so an edit is visible @@ -386,6 +448,13 @@ export function SmeApp() { canEdit={canEdit} direct={direct} onImported={() => goto("review")} + onImportPreview={(doc) => { + setExcluded(new Set()); + setImportReview(doc); + goto("review"); + }} + openImport={openImport} + prefillImport={prefillImport} query={query} busy={staging.busy} /> diff --git a/canvas/src/sme/reviewModel.test.ts b/canvas/src/sme/reviewModel.test.ts new file mode 100644 index 0000000..e6321b4 --- /dev/null +++ b/canvas/src/sme/reviewModel.test.ts @@ -0,0 +1,163 @@ +import { describe, expect, it } from "vitest"; +import { makeDiff } from "../test/diffFixture"; +import type { ModelDiffDoc, ObjectChangeDoc } from "../types"; +import { + allFieldKeys, + fieldKey, + filterCounts, + filterImportChanges, + filterObjects, + includedEntityNames, + includedUlids, + objectFieldKeys, + objectIncluded, + objectSelectionState, + toggleField, + toggleObject, +} from "./reviewModel"; + +describe("filters (view-only)", () => { + const diff = makeDiff(); + + it("counts each change category", () => { + const c = filterCounts(diff); + expect(c.all).toBe(4); + expect(c.additions).toBe(1); // E_ADD + expect(c.deletions).toBe(1); // E_DEL + expect(c.moves).toBe(1); // E_REN + expect(c.modifications).toBe(1); // E_MOD (renamed E_REN excluded) + expect(c.conflicts).toBe(1); // E_DEL is breaking + }); + + it("filters the visible list without touching anything else", () => { + expect(filterObjects(diff, "additions").map((o) => o.ulid)).toEqual(["E_ADD"]); + expect(filterObjects(diff, "conflicts").map((o) => o.ulid)).toEqual(["E_DEL"]); + expect(filterObjects(diff, "all")).toHaveLength(4); + }); +}); + +describe("per-field selection", () => { + const diff = makeDiff(); + + it("gives a modified object one key per field", () => { + const mod = diff.objects.find((o) => o.ulid === "E_MOD")!; + expect(objectFieldKeys(mod)).toEqual([ + fieldKey("E_MOD", "definition"), + fieldKey("E_MOD", "domain"), + ]); + }); + + it("gives an added object with no field rows a single '*' key", () => { + const add = diff.objects.find((o) => o.ulid === "E_ADD")!; + expect(objectFieldKeys(add)).toEqual([fieldKey("E_ADD", "*")]); + }); + + it("derives object state from its selected fields", () => { + const mod = diff.objects.find((o) => o.ulid === "E_MOD")!; + const [k1, k2] = objectFieldKeys(mod); + expect(objectSelectionState(mod, new Set([k1, k2]))).toBe("all"); + expect(objectSelectionState(mod, new Set([k1]))).toBe("some"); + expect(objectSelectionState(mod, new Set())).toBe("none"); + // included when ≥1 field selected + expect(objectIncluded(mod, new Set([k1]))).toBe(true); + expect(objectIncluded(mod, new Set())).toBe(false); + }); + + it("toggleField flips one field immutably", () => { + const k = fieldKey("E_MOD", "domain"); + const start = new Set(); + const on = toggleField(k, start); + expect(on.has(k)).toBe(true); + expect(start.has(k)).toBe(false); // input untouched + expect(toggleField(k, on).has(k)).toBe(false); + }); + + it("toggleObject turns all fields off when all on, else all on", () => { + const mod = diff.objects.find((o) => o.ulid === "E_MOD")!; + const keys = objectFieldKeys(mod); + const allOn = new Set(keys); + expect([...toggleObject(mod, allOn)]).toHaveLength(0); // all -> none + const someOn = new Set([keys[0]]); + expect(objectSelectionState(mod, toggleObject(mod, someOn))).toBe("all"); // some -> all + }); + + it("includedUlids reflects field-level exclusion", () => { + const all = allFieldKeys(diff); + expect(includedUlids(diff, all).sort()).toEqual(["E_ADD", "E_DEL", "E_MOD", "E_REN"]); + // deselect both fields of E_MOD -> it drops out, others stay + let sel = all; + for (const k of objectFieldKeys(diff.objects.find((o) => o.ulid === "E_MOD")!)) { + sel = toggleField(k, sel); + } + expect(includedUlids(diff, sel).sort()).toEqual(["E_ADD", "E_DEL", "E_REN"]); + }); +}); + +describe("import write-filter (apply only the kept entities, by name)", () => { + // a minimal import command list like model_to_commands emits + const changes = [ + { op: "create_subject_area", payload: { id: "SA1", name: "Core" } }, + { op: "create_entity", payload: { id: "e_cp", name: "counterparty" } }, + { op: "add_attribute", payload: { entity_id: "e_cp", id: "a1", name: "cp_id" } }, + { op: "create_entity", payload: { id: "e_tr", name: "trade" } }, + { op: "add_attribute", payload: { entity_id: "e_tr", id: "a2", name: "trade_id" } }, + { op: "create_relationship", payload: { id: "r1", from_entity: "e_tr", to_entity: "e_cp" } }, + ]; + + it("keeps scaffolding + the kept entity + its attributes; drops the rest", () => { + const out = filterImportChanges(changes, new Set(["counterparty"])); + const ids = out.map((c) => `${c.op}:${c.payload.id}`); + expect(ids).toContain("create_subject_area:SA1"); + expect(ids).toContain("create_entity:e_cp"); + expect(ids).toContain("add_attribute:a1"); // counterparty's attr (id a1) + // trade and its attribute are dropped + expect(ids).not.toContain("create_entity:e_tr"); + expect(ids).not.toContain("add_attribute:a2"); + // the relationship references trade (dropped) -> dropped + expect(out.some((c) => c.op === "create_relationship")).toBe(false); + }); + + it("keeps a relationship only when BOTH endpoints are kept", () => { + const out = filterImportChanges(changes, new Set(["counterparty", "trade"])); + expect(out.some((c) => c.op === "create_relationship")).toBe(true); + }); + + it("nothing selected writes nothing", () => { + expect(filterImportChanges(changes, new Set())).toHaveLength(0); + }); + + it("includedEntityNames reads kept logical-entity names from the diff", () => { + const entity = (ulid: string, name: string): ObjectChangeDoc => ({ + ulid, object_kind: "logical_entity", object_kind_label: "entity", + change: "added", name_before: null, name_after: name, renamed: false, + severity: "additive", path: null, + fields: [{ field: "*", kind: "added", severity: "additive", label: "", detail: "", before: null, after: null }], + children: [], + }); + const diff = { + ok: true, base: { ref: "", sha: "", label: "" }, head: { ref: null, label: "" }, + counts: {}, max_severity: "additive", has_breaking: false, + objects: [entity("x", "counterparty"), entity("y", "trade")], config: [], + } as unknown as ModelDiffDoc; + const all = allFieldKeys(diff); + expect([...includedEntityNames(diff, all)].sort()).toEqual(["counterparty", "trade"]); + }); + + it("includedEntityNames excludes a MODIFIED (already-existing) entity", () => { + const obj = (ulid: string, name: string, change: "added" | "modified"): ObjectChangeDoc => ({ + ulid, object_kind: "logical_entity", object_kind_label: "entity", + change, name_before: change === "added" ? null : name, name_after: name, renamed: false, + severity: "additive", path: null, + fields: [{ field: "*", kind: change, severity: "additive", label: "", detail: "", before: null, after: null }], + children: [], + }); + const diff = { + ok: true, base: { ref: "", sha: "", label: "" }, head: { ref: null, label: "" }, + counts: {}, max_severity: "additive", has_breaking: false, + objects: [obj("x", "counterparty", "modified"), obj("y", "trade", "added")], config: [], + } as unknown as ModelDiffDoc; + const all = allFieldKeys(diff); + // counterparty already exists (modified) -> not created; only the new entity is kept + expect([...includedEntityNames(diff, all)]).toEqual(["trade"]); + }); +}); diff --git a/canvas/src/sme/reviewModel.ts b/canvas/src/sme/reviewModel.ts new file mode 100644 index 0000000..78d0537 --- /dev/null +++ b/canvas/src/sme/reviewModel.ts @@ -0,0 +1,203 @@ +// Pure helpers behind the review view: change filtering and per-field selection. +// Kept out of the component so the semantics are unit-testable on their own. + +import type { ChangeType, ModelDiffDoc, ObjectChangeDoc } from "../types"; + +// The display filters (competitor parity): a VIEW concern only — filtering changes +// what is visible, never what is selected for the action (so a hidden change can +// never be silently dropped from a proposal). +export type ReviewFilter = "all" | "additions" | "modifications" | "moves" | "deletions" | "conflicts"; + +export const REVIEW_FILTERS: { id: ReviewFilter; label: string }[] = [ + { id: "all", label: "All" }, + { id: "additions", label: "Additions" }, + { id: "modifications", label: "Modifications" }, + { id: "moves", label: "Renames" }, + { id: "deletions", label: "Deletions" }, + { id: "conflicts", label: "Conflicts" }, +]; + +/** Does an object match the active filter? `conflicts` maps to breaking severity (the + * only conflict signal a 2-way diff carries); `moves` maps to a rename. */ +export function objectMatchesFilter(o: ObjectChangeDoc, f: ReviewFilter): boolean { + switch (f) { + case "all": + return true; + case "additions": + return o.change === "added"; + case "deletions": + return o.change === "removed"; + case "moves": + return o.renamed; + case "modifications": + return o.change === "modified" && !o.renamed; + case "conflicts": + return o.severity === "breaking"; + } +} + +/** The objects visible under a filter. Selection is untouched — this is view-only. */ +export function filterObjects(diff: ModelDiffDoc, f: ReviewFilter): ObjectChangeDoc[] { + return f === "all" ? diff.objects : diff.objects.filter((o) => objectMatchesFilter(o, f)); +} + +/** Count per filter, for filter chips that show how many changes each reveals. */ +export function filterCounts(diff: ModelDiffDoc): Record { + const out = {} as Record; + for (const { id } of REVIEW_FILTERS) { + out[id] = id === "all" ? diff.objects.length : diff.objects.filter((o) => objectMatchesFilter(o, id)).length; + } + return out; +} + +// --- per-field selection ----------------------------------------------------------- +// Selection is keyed by (object ulid, field). An object is INCLUDED when at least one +// of its fields is selected; unchecking every field excludes the object. The object +// header shows a tri-state derived from its fields. + +/** The stable key for one field change of one object. A whole-object change (added / + * removed, which carry object-level identity rather than a field) uses the "*" field. */ +export function fieldKey(ulid: string, field: string): string { + return `${ulid}\u0000${field}`; +} + +/** Every selectable field key of an object, including its children's fields. An + * added/removed object with no field rows still gets one "*" key so it is selectable. */ +export function objectFieldKeys(o: ObjectChangeDoc): string[] { + const keys = o.fields.map((f) => fieldKey(o.ulid, f.field)); + for (const c of o.children) { + for (const f of c.fields) keys.push(fieldKey(o.ulid, `${c.ulid}.${f.field}`)); + } + return keys.length ? keys : [fieldKey(o.ulid, "*")]; +} + +export type ObjectSelectionState = "all" | "some" | "none"; + +/** The tri-state of an object, derived from which of its field keys are selected. */ +export function objectSelectionState(o: ObjectChangeDoc, selected: Set): ObjectSelectionState { + const keys = objectFieldKeys(o); + const on = keys.filter((k) => selected.has(k)).length; + if (on === 0) return "none"; + if (on === keys.length) return "all"; + return "some"; +} + +/** An object is included in the action when ≥1 of its fields is selected. */ +export function objectIncluded(o: ObjectChangeDoc, selected: Set): boolean { + return objectSelectionState(o, selected) !== "none"; +} + +/** The ULIDs the action should apply to, given a field-level selection. */ +export function includedUlids(diff: ModelDiffDoc, selected: Set): string[] { + return diff.objects.filter((o) => objectIncluded(o, selected)).map((o) => o.ulid); +} + +/** The NEW logical-entity names the reviewer kept, for filtering an import's command list. + * Only `added` entities are returned: the import emits `create_entity` for each entity, which + * fails for one that already exists in the current model (a name-matched "modified" object), so + * an import applies only its genuinely-new entities — a modified existing entity is left as-is + * (shown in the review, not clobbered). Name is the stable join: the diff doc carries remapped + * ULIDs (base's ULID for a name-matched object) while the import commands carry fresh ULIDs. */ +export function includedEntityNames(diff: ModelDiffDoc, selected: Set): Set { + const names = new Set(); + for (const o of diff.objects) { + if (o.object_kind !== "logical_entity") continue; + if (o.change !== "added") continue; // only new entities can be created by the import + if (!objectIncluded(o, selected)) continue; + const n = o.name_after ?? o.name_before; + if (n) names.add(n); + } + return names; +} + +type ImportCommand = { op: string; payload: Record }; + +/** Filter an erwin import's command list to the entities the reviewer kept (by name). + * Scaffolding ops (subject areas, domains, categories, members) always apply; an entity and + * its attributes apply when the entity's name is kept; a relationship or key group applies + * only when EVERY entity it references is kept. `model_to_commands` emits entities before the + * attributes/relationships that reference them, so a single pass can track which entity ids + * survive. */ +export function filterImportChanges( + changes: ImportCommand[], + keepNames: Set, +): ImportCommand[] { + if (keepNames.size === 0) return []; // nothing selected -> write nothing + const keptEntityIds = new Set(); // import-ULIDs of entities we keep + const out: ImportCommand[] = []; + const refEntityIds = (p: Record): string[] => + [p.entity_id, p.from_entity, p.to_entity, p.from, p.to].filter( + (v): v is string => typeof v === "string", + ); + for (const c of changes) { + const p = c.payload; + switch (c.op) { + case "create_entity": { + const name = typeof p.name === "string" ? p.name : ""; + const id = typeof p.id === "string" ? p.id : ""; + if (keepNames.has(name)) { + keptEntityIds.add(id); + out.push(c); + } + break; + } + case "add_attribute": { + const eid = typeof p.entity_id === "string" ? p.entity_id : ""; + if (keptEntityIds.has(eid)) out.push(c); + break; + } + case "create_relationship": + case "create_key_group": { + const refs = refEntityIds(p); + if (refs.length > 0 && refs.every((id) => keptEntityIds.has(id))) out.push(c); + break; + } + default: + // scaffolding (create_subject_area, create_domain, create_category, + // set_subject_area_members, …) always applies + out.push(c); + } + } + return out; +} + +/** All field keys across the whole diff — the initial "everything selected" set. */ +export function allFieldKeys(diff: ModelDiffDoc): Set { + const s = new Set(); + for (const o of diff.objects) for (const k of objectFieldKeys(o)) s.add(k); + return s; +} + +/** Toggle every field of an object at once (the header checkbox): if all are on, turn + * them off; otherwise turn them all on. Returns a NEW set (never mutates the input). */ +export function toggleObject(o: ObjectChangeDoc, selected: Set): Set { + const next = new Set(selected); + const keys = objectFieldKeys(o); + const allOn = keys.every((k) => next.has(k)); + for (const k of keys) { + if (allOn) next.delete(k); + else next.add(k); + } + return next; +} + +/** Toggle one field key. Returns a NEW set. */ +export function toggleField(key: string, selected: Set): Set { + const next = new Set(selected); + if (next.has(key)) next.delete(key); + else next.add(key); + return next; +} + +// A pluggable action the review view offers (Propose / Accept / Reconcile / Apply +// import). The view stays source-agnostic; the host wires the label + what apply does. +export interface ReviewAction { + id: string; + label: string; + primary?: boolean; + /** disabled reason, or undefined when enabled */ + disabledReason?: string; + apply: (selectedUlids: string[]) => void; +} + +export type { ChangeType }; diff --git a/canvas/src/sme/sme.css b/canvas/src/sme/sme.css index 8fb12c9..4cfa000 100644 --- a/canvas/src/sme/sme.css +++ b/canvas/src/sme/sme.css @@ -202,10 +202,34 @@ body { font-family: var(--font); background: var(--bg); color: var(--text); } } .rv-tab.active { background: var(--bg-card); color: var(--text); border-color: var(--border-strong); } +.rv-wrap { flex: 1; display: flex; flex-direction: column; min-height: 0; } .rv-body { flex: 1; display: grid; grid-template-columns: 380px 1fr; min-height: 0; } .rv-list { border-right: 1px solid var(--border); overflow-y: auto; padding: 10px; } .rv-detail { overflow-y: auto; padding: 22px 28px; } +/* display filters — a view concern; change what is visible, not what is selected */ +.rv-filters { + display: flex; gap: 4px; flex-wrap: wrap; padding: 8px 10px; + border-bottom: 1px solid var(--border); +} +.rv-filter { + display: inline-flex; align-items: center; gap: 6px; + padding: 4px 10px; border-radius: 99px; border: 1px solid var(--border); + background: transparent; color: var(--text-dim); cursor: pointer; font-size: 12px; +} +.rv-filter:hover { color: var(--text); border-color: var(--border-strong); } +.rv-filter.active { color: var(--accent); border-color: var(--accent); } +.rv-filter-count { + font-size: 11px; color: var(--text-dim); background: var(--bg-card); + border-radius: 99px; padding: 0 6px; min-width: 16px; text-align: center; +} +.rv-filter.active .rv-filter-count { color: var(--accent); } + +/* per-field selection rows in the detail pane */ +.rv-field-pick { display: flex; gap: 10px; align-items: flex-start; } +.rv-field-pick > input[type="checkbox"] { margin-top: 16px; accent-color: var(--accent); cursor: pointer; } +.rv-field-body { flex: 1; min-width: 0; } + /* one changed object */ .rv-obj { border: 1px solid var(--border); border-radius: 10px; margin-bottom: 8px; diff --git a/canvas/src/test/diffFixture.ts b/canvas/src/test/diffFixture.ts new file mode 100644 index 0000000..9440402 --- /dev/null +++ b/canvas/src/test/diffFixture.ts @@ -0,0 +1,68 @@ +import type { ModelDiffDoc, ObjectChangeDoc } from "../types"; + +// A realistic ModelDiffDoc with one of each change kind, for the review-view tests. +// Shapes mirror mdl_core.diff_render.render_json exactly. + +function obj(o: Partial & Pick): ObjectChangeDoc { + return { + object_kind: "logical_entity", + object_kind_label: "Entity", + name_before: null, + name_after: null, + renamed: false, + severity: "additive", + path: null, + fields: [], + children: [], + ...o, + }; +} + +export function makeDiff(): ModelDiffDoc { + return { + ok: true, + base: { ref: "HEAD", sha: "abc", label: "on disk" }, + head: { ref: null, label: "your staged changes" }, + counts: { entities: 4 }, + max_severity: "breaking", + has_breaking: true, + config: [], + objects: [ + // a modified entity with TWO field changes (per-field selection target) + obj({ + ulid: "E_MOD", + change: "modified", + name_before: "counterparty", + name_after: "counterparty", + severity: "additive", + fields: [ + { field: "definition", kind: "definition_changed", severity: "cosmetic", label: "Definition changed", detail: "", before: "a party", after: "a trading party" }, + { field: "domain", kind: "attribute_domain_changed", severity: "additive", label: "Domain changed", detail: "", before: "string", after: "text" }, + ], + }), + // an added entity (additions filter) + obj({ ulid: "E_ADD", change: "added", name_after: "instrument", severity: "additive" }), + // a removed entity that BREAKS dbt models (deletions + conflicts filters) + obj({ + ulid: "E_DEL", + change: "removed", + name_before: "legacy", + severity: "breaking", + fields: [ + { + field: "entity", + kind: "entity_removed", + severity: "breaking", + label: "Entity removed", + detail: "", + before: "legacy", + after: null, + breaks: [{ name: "dim_legacy", target: "snowflake", materialization: "table" }], + }, + ], + }), + // a renamed entity (moves filter) + obj({ ulid: "E_REN", change: "modified", renamed: true, name_before: "old_name", name_after: "new_name", severity: "cosmetic" }), + ], + }; +} diff --git a/canvas/src/test/setup.ts b/canvas/src/test/setup.ts new file mode 100644 index 0000000..f149f27 --- /dev/null +++ b/canvas/src/test/setup.ts @@ -0,0 +1 @@ +import "@testing-library/jest-dom/vitest"; diff --git a/canvas/vitest.config.ts b/canvas/vitest.config.ts new file mode 100644 index 0000000..21450a5 --- /dev/null +++ b/canvas/vitest.config.ts @@ -0,0 +1,14 @@ +import react from "@vitejs/plugin-react"; +import { defineConfig } from "vitest/config"; + +// Component + interaction tests for the canvas (jsdom). Kept separate from the Vite +// app build; `npm test` runs these headless. +export default defineConfig({ + plugins: [react()], + test: { + environment: "jsdom", + globals: true, + setupFiles: ["./src/test/setup.ts"], + include: ["src/**/*.test.{ts,tsx}"], + }, +}); diff --git a/demos/fixtures/sample.erwin.xml b/demos/fixtures/sample.erwin.xml new file mode 100644 index 0000000..ddc1a1e --- /dev/null +++ b/demos/fixtures/sample.erwin.xml @@ -0,0 +1,108 @@ + + + + TradingModel + + + id_typeBIGINT + + + + + StewardText + + + + + PhysicalUPPER + 1 + + + LogicalLOWER + 1 + + + + + CounterpartyCOUNTERPARTY + A trading partner. + + Jane Doe + + + + + counterparty_idD1 + Not_Null + + + legal_nameVARCHAR(255) + + Bob + + + + + + pk_counterpartyPrimary_Key + + + + A_CP1 + + + + + + Trade + + trade_id + + counterparty_id + R1 + A_CP1 + + + + + pk_tradePrimary_Key + + A_TR1 + + + + + Institution + + counterparty_id + + + + + + trade_has_counterparty + E_CPE_TR + Zero_One_or_More + is party to + is with + + + cpty_is_institutionSubtype_Complete + E_CPE_INST + A_CP2 + + + + + Trading + + E_CP + E_TR + + + + v_active_trades + + Main + + diff --git a/packages/cli/src/mdl_cli/main.py b/packages/cli/src/mdl_cli/main.py index 7b2373b..cb614a4 100644 --- a/packages/cli/src/mdl_cli/main.py +++ b/packages/cli/src/mdl_cli/main.py @@ -3158,6 +3158,31 @@ def model_detail( typer.echo(json.dumps(entities_detail(_load(model_dir).model, limit=limit), default=str)) +@model_app.command("tree") +def model_tree_cmd( + model_dir: Path = typer.Option(Path("."), "--model-dir", "-m"), + subject_area: str = typer.Option(None, "--subject-area", help="Scope by area name or ULID"), + fmt: str = typer.Option("json", "--format", help="json (the VS Code Model tree consumes it)"), +) -> None: + """A navigable tree of the logical model — every entity with its attributes and the + source file each lives in — for an editor's Model Explorer (entity → attributes, click + to open the YAML). Uncapped, unlike `model detail`. `--format json` is what the VS Code + Model tree consumes.""" + from mdl_core.query import model_tree + + repo = _load(model_dir) + tree = model_tree(repo.model, path_for=repo.path_for_ulid, subject_area=subject_area) + if fmt == "json": + typer.echo(json.dumps(tree, default=str)) + return + # a terse text fallback for the terminal + for e in tree["entities"]: + typer.secho(e["name"], fg=typer.colors.CYAN) + for a in e["attributes"]: + key = " (pk)" if a["is_pk"] else "" + typer.echo(f" {a['name']}: {a['domain']}{key}") + + @app.command() def mcp( repo: Path = typer.Option( diff --git a/packages/cli/tests/test_model_tree_cli.py b/packages/cli/tests/test_model_tree_cli.py new file mode 100644 index 0000000..c23b206 --- /dev/null +++ b/packages/cli/tests/test_model_tree_cli.py @@ -0,0 +1,57 @@ +"""CLI: `mdl model tree` — the JSON the VS Code Model Explorer consumes (entity → +attributes, with a source file per entity for click-to-open).""" + +from __future__ import annotations + +import json + +from typer.testing import CliRunner + +from mdl_cli.main import app + +runner = CliRunner() + + +def _demo(tmp_path): + d = tmp_path / "proj" + assert runner.invoke(app, ["init", "--demo", str(d)]).exit_code == 0 + return d / "model" + + +def test_model_tree_json_shape(tmp_path): + model = _demo(tmp_path) + r = runner.invoke(app, ["model", "tree", "-m", str(model), "--format", "json"]) + assert r.exit_code == 0, r.output + tree = json.loads(r.stdout) + assert "entities" in tree and tree["entities"] + e = tree["entities"][0] + assert {"name", "attributes", "file"} <= set(e) + assert isinstance(e["attributes"], list) + + +def test_model_tree_files_resolve_on_disk(tmp_path): + # every entity's `file` must be a real path relative to the model dir — this is the + # exact path the extension opens when a user clicks an entity in the tree. + model = _demo(tmp_path) + tree = json.loads(runner.invoke(app, ["model", "tree", "-m", str(model)]).stdout) + for e in tree["entities"]: + assert e["file"], f"{e['name']} has no source file" + assert (model / e["file"]).exists(), f"{e['file']} does not exist" + + +def test_model_tree_attributes_have_pk_flag(tmp_path): + model = _demo(tmp_path) + tree = json.loads(runner.invoke(app, ["model", "tree", "-m", str(model)]).stdout) + # at least one entity should have a pk attribute (the demo has keyed entities) + all_attrs = [a for e in tree["entities"] for a in e["attributes"]] + assert any(a["is_pk"] for a in all_attrs) + # every attribute carries the fields the tree renders + for a in all_attrs: + assert {"name", "domain", "role", "nullable", "is_pk"} <= set(a) + + +def test_model_tree_text_format(tmp_path): + model = _demo(tmp_path) + r = runner.invoke(app, ["model", "tree", "-m", str(model), "--format", "text"]) + assert r.exit_code == 0, r.output + assert "(pk)" in r.output # the text fallback marks primary keys diff --git a/packages/core/src/mdl_core/diff.py b/packages/core/src/mdl_core/diff.py index 83b4eba..0bbd133 100644 --- a/packages/core/src/mdl_core/diff.py +++ b/packages/core/src/mdl_core/diff.py @@ -565,6 +565,16 @@ def diff_models_by_name( relationships and key groups by name), then delegates to the unchanged `diff_models` — so all the classification, severity and rendering are reused. Head-only names keep their own ULIDs and show as added; base-only names show as removed.""" + head = remap_head_by_name(base, head) + return diff_models(base, head, base_label=base_label, head_label=head_label) + + +def remap_head_by_name(base: Model, head: Model) -> Model: + """Return a COPY of `head` whose ULIDs are rewritten to `base`'s ULID for every same-named + object, so the two models can be diffed (or enriched) by shared ULID. This is the name-match + step behind `diff_models_by_name`, exposed so a caller that needs both the diff AND the + remapped head (e.g. the server's import-preview, which runs break-impact enrichment against + the head using the diff doc's ULIDs) can share one remapping instead of duplicating it.""" import copy head = copy.deepcopy(head) @@ -594,7 +604,7 @@ def diff_models_by_name( remap[a.id] = base_attr[key] _apply_remap(head, remap) - return diff_models(base, head, base_label=base_label, head_label=head_label) + return head def _apply_remap(model: Model, remap: dict[str, str]) -> None: diff --git a/packages/core/src/mdl_core/query.py b/packages/core/src/mdl_core/query.py index 6461c9b..c49202f 100644 --- a/packages/core/src/mdl_core/query.py +++ b/packages/core/src/mdl_core/query.py @@ -274,3 +274,66 @@ def _resolve_subject_area_id(model: Model, ref: str) -> str | None: if sa.name.lower() == lref: return sa.id return None + + +def model_tree( + model: Model, + *, + path_for=None, + subject_area: str | None = None, +) -> dict: + """A navigable tree of the LOGICAL model for an editor's Model Explorer: every entity + with its attributes and each object's source file. Unlike `list_entities` (counts + only) and `entities_detail` (chat-sized, capped), this is the full, uncapped structure + a tree view drills into, and it carries the source file per entity so a click can open + the YAML. `path_for(ulid) -> rel path | None` is threaded in by the CLI (the file map + lives on ModelRepo, not on the pure Model); when absent, `file` is null. + + Each entity: name, physical_name, subject_area, definition, pattern, file, and + attributes (name, physical_name, domain, role, nullable, is_pk). Attributes keep their + authored order. `is_pk` is true when the attribute is a member of a pk KeyGroup or, + failing a declared pk, carries the legacy `role: business_key`. + """ + # A requested-but-unknown area resolves to None; scope to NOTHING rather than + # silently ignoring the filter (which would show the whole model). + want_scope = subject_area is not None + sa_id = _resolve_subject_area_id(model, subject_area) if want_scope else None + sa_name = {sa.id: sa.name for sa in model.subject_areas.values()} + ce_sa = {ce.id: ce.subject_area for ce in model.conceptual_entities.values()} + + entities: list[dict] = [] + for le in sorted(model.logical_entities.values(), key=lambda e: e.name): + area_id = ce_sa.get(le.realises) if le.realises else None + if want_scope and area_id != sa_id: + continue + # pk membership: declared pk KeyGroup members, else legacy business_key attrs + pk_ids: set[str] = set() + declared_pk = False + for kg in model.key_groups.values(): + if kg.entity == le.id and kg.type == "pk": + declared_pk = True + pk_ids.update(kg.members) + attributes = [ + { + "name": a.name, + "physical_name": a.physical_name, + "domain": a.domain, + "role": a.role, + "nullable": a.nullable, + "is_pk": (a.id in pk_ids) if declared_pk else (a.role == "business_key"), + } + for a in le.attributes + ] + entities.append( + { + "name": le.name, + "physical_name": le.physical_name, + "subject_area": sa_name.get(area_id) if area_id else None, + "definition": le.definition, + "pattern": le.pattern, + "file": path_for(le.id) if path_for else None, + "attributes": attributes, + } + ) + + return {"project": model.config.name, "entities": entities} diff --git a/packages/core/tests/test_model_tree.py b/packages/core/tests/test_model_tree.py new file mode 100644 index 0000000..6c351a8 --- /dev/null +++ b/packages/core/tests/test_model_tree.py @@ -0,0 +1,58 @@ +"""The model_tree query — the navigable entity→attribute structure the VS Code Model +Explorer drills into, with the source file per entity for click-to-open.""" + +from __future__ import annotations + +from mdl_core.query import model_tree +from mdl_core.repo import ModelRepo + + +def _repo(model_dir): + return ModelRepo.load(model_dir) + + +def test_model_tree_entities_and_attributes(model_dir): + repo = _repo(model_dir) + tree = model_tree(repo.model, path_for=repo.path_for_ulid) + by_name = {e["name"]: e for e in tree["entities"]} + assert {"counterparty", "trade"} <= set(by_name) + + cp = by_name["counterparty"] + attr_names = [a["name"] for a in cp["attributes"]] + # attributes keep their authored order + assert attr_names == ["counterparty_id", "legal_name"] + + +def test_model_tree_marks_primary_key(model_dir): + tree = model_tree(_repo(model_dir).model, path_for=_repo(model_dir).path_for_ulid) + cp = next(e for e in tree["entities"] if e["name"] == "counterparty") + pk = next(a for a in cp["attributes"] if a["name"] == "counterparty_id") + other = next(a for a in cp["attributes"] if a["name"] == "legal_name") + # counterparty_id is a business_key → is_pk; legal_name is not + assert pk["is_pk"] is True + assert other["is_pk"] is False + assert other["role"] == "attribute" + + +def test_model_tree_carries_source_file_that_exists(model_dir): + # the `file` per entity is what a click opens; it must be a real relative path on disk + repo = _repo(model_dir) + tree = model_tree(repo.model, path_for=repo.path_for_ulid) + cp = next(e for e in tree["entities"] if e["name"] == "counterparty") + assert cp["file"] == "logical/entities/counterparty.yaml" + assert (model_dir / cp["file"]).exists() + + +def test_model_tree_without_path_for_has_null_file(model_dir): + # pure Model (no ModelRepo file map) → file is null, never crashes + tree = model_tree(_repo(model_dir).model) + assert all(e["file"] is None for e in tree["entities"]) + + +def test_model_tree_scopes_to_subject_area(model_dir): + repo = _repo(model_dir) + # both fixture entities are homed in Trading; an unknown area scopes to nothing + scoped = model_tree(repo.model, path_for=repo.path_for_ulid, subject_area="Trading") + assert scoped["entities"] + empty = model_tree(repo.model, subject_area="no-such-area") + assert empty["entities"] == [] diff --git a/packages/server/src/mdl_server/app.py b/packages/server/src/mdl_server/app.py index 8eb043c..9b12e05 100644 --- a/packages/server/src/mdl_server/app.py +++ b/packages/server/src/mdl_server/app.py @@ -81,6 +81,10 @@ def create_app( model_dir = Path(model_dir) app = FastAPI(title="Modelith", docs_url="/api/docs", openapi_url="/api/openapi.json") cache: dict = {"fingerprint": None, "repo": None} + # One-shot in-memory stash for import content handed from a host (VS Code reads a local + # .xml and POSTs it here; the canvas webview, which cannot read local files, fetches it by + # token). Consumed on read; this is a convenience channel, not durable state. + import_stash: dict[str, str] = {} # Identity is resolved per request from a trusted-proxy header (enterprise) or the # model dir's git config (solo), or falls back to anonymous — see identity.py. The @@ -260,6 +264,73 @@ def import_model(body: dict) -> JSONResponse: } ) + @app.post("/api/import/stash") + def import_stash_put(body: dict) -> JSONResponse: + """Stash import content (e.g. an erwin XML a VS Code host read from disk) and return a + one-shot token. The canvas opens /sme?import= and fetches it below — the webview + itself cannot read the host's filesystem.""" + import secrets + + content = body.get("content", "") + if not content: + return JSONResponse({"ok": False, "error": "content is empty"}, status_code=422) + token = secrets.token_urlsafe(12) + import_stash[token] = content + # cap the stash so a long-lived server can't accumulate; this is a transient handoff + if len(import_stash) > 32: + for k in list(import_stash)[:-16]: + import_stash.pop(k, None) + return JSONResponse({"ok": True, "token": token}) + + @app.get("/api/import/stash/{token}") + def import_stash_get(token: str) -> JSONResponse: + """Consume a stashed import content by token (one-shot).""" + content = import_stash.pop(token, None) + if content is None: + return JSONResponse({"ok": False, "error": "unknown or expired token"}, status_code=404) + return JSONResponse({"ok": True, "content": content}) + + @app.post("/api/import/preview") + def import_preview(body: dict) -> JSONResponse: + """Parse an import and return a SEMANTIC DIFF of it against the current model, WITHOUT + writing anything — so the change can be reviewed (filters, per-field selection, break + impact) before it lands. Returns the ModelDiffDoc shape (as /api/git/diff/model does) + plus the import's `changes` and `warnings`, so the client can apply the selected + objects afterwards without re-parsing. Erwin only for now (the flagship migration); + other formats 422 until wired.""" + from mdl_emit_erd.imports.model import model_to_commands + + from mdl_core.diff import diff_models, remap_head_by_name + from mdl_core.diff_render import render_json + from mdl_server.git_api import _attach_breaks, _attach_paths + + fmt = body.get("format", "") + content = body.get("content", "") + if not content: + return JSONResponse({"ok": False, "error": "content is empty"}, status_code=422) + if fmt != "erwin": + return JSONResponse( + {"ok": False, "error": f"import preview supports erwin only (got {fmt!r})"}, + status_code=422, + ) + from mdl_reverse.erwin import import_erwin + + result = import_erwin(content) + current = _load().model + # Imported ULIDs are fresh, so match by NAME; keep the remapped head to enrich break + # impact against the same ULIDs the diff doc carries. + head = remap_head_by_name(current, result.model) + diff = diff_models(current, head, base_label="current", head_label="import") + doc = render_json(diff) + doc["ok"] = True + doc["base"] = {"ref": "current", "sha": "", "label": "current model"} + doc["head"] = {"ref": None, "label": "erwin import"} + _attach_paths(model_dir, doc) + _attach_breaks(head, doc) + doc["changes"] = model_to_commands(result.model) + doc["warnings"] = result.warnings + return JSONResponse(doc) + @app.get("/api/entities/{ulid}") def get_entity(ulid: str) -> JSONResponse: repo = _load() diff --git a/packages/server/src/mdl_server/static/assets/ModelDiagram-oAb1enKe.js b/packages/server/src/mdl_server/static/assets/ModelDiagram-CRUBpPVn.js similarity index 83% rename from packages/server/src/mdl_server/static/assets/ModelDiagram-oAb1enKe.js rename to packages/server/src/mdl_server/static/assets/ModelDiagram-CRUBpPVn.js index 26d3511..2d6de82 100644 --- a/packages/server/src/mdl_server/static/assets/ModelDiagram-oAb1enKe.js +++ b/packages/server/src/mdl_server/static/assets/ModelDiagram-CRUBpPVn.js @@ -1 +1 @@ -import{r,j as s}from"./client-DOmNpTln.js";import{f as T,t as _,u as O,v as R,E as D,B as P,C as z,w as A}from"./styles-BtrhR1xb.js";const V={entity:D},$={relationship:R},l={breaking:"#f87171",additive:"#34d399",cosmetic:"#fcd34d"},N=["#5eead4","#fcd34d","#a78bfa","#fb923c","#38bdf8","#f472b6","#a3e635"],d="#64748b";function Y({subjectArea:u,severityByUlid:a,focusUlid:m,onSelect:c}){const[t,g]=r.useState(null),[f,w]=r.useState(null),[h,E]=r.useState(!0);r.useEffect(()=>{g(null),T(u).then(g).catch(n=>w(String(n)))},[u]);const{nodes:k,edges:M}=r.useMemo(()=>{if(!t)return{nodes:[],edges:[]};const n=new Map;t.subject_areas.forEach(e=>{let o=2166136261;for(let i=0;i[e.id,e])),b=a&&a.size>0,C=t.entities.map(e=>{var j;const o=(a==null?void 0:a.get(e.id))??(e.conceptual?a==null?void 0:a.get(e.conceptual.id):void 0),i=b?o?l[o]??d:d:(j=e.conceptual)!=null&&j.subject_area?n.get(e.conceptual.subject_area.id)??d:d;return{id:e.id,type:"entity",position:{x:0,y:0},data:{entity:e,color:i,dimmed:!!(b&&!o),highlighted:e.id===m,showTypes:h}}}),x=t.relationships.map(e=>({id:e.id,source:e.from.entity,target:e.to.entity,type:"relationship",data:{relationship:e,dimmed:!1}}));return{nodes:_(C,x,p),edges:x}},[t,a,m,h]);return f?s.jsx("p",{className:"sme-splash error",children:f}):t?t.entities.length?s.jsxs("div",{className:"erd-wrap",children:[s.jsxs("div",{className:"erd-bar",children:[s.jsxs("span",{className:"erd-count",children:[t.entities.length," entities · ",t.relationships.length," relationships",t.scope&&" · scoped"]}),s.jsxs("label",{className:"erd-toggle",children:[s.jsx("input",{type:"checkbox",checked:h,onChange:n=>E(n.target.checked)}),"show types"]}),a&&a.size>0&&s.jsxs("span",{className:"erd-legend",children:[s.jsx("span",{className:"sw",style:{background:l.breaking}})," breaking",s.jsx("span",{className:"sw",style:{background:l.additive}})," added",s.jsx("span",{className:"sw",style:{background:l.cosmetic}})," changed",s.jsx("span",{className:"sw",style:{background:d}})," unchanged"]})]}),s.jsx("div",{className:"erd-canvas",children:s.jsxs(O,{nodes:k,edges:M,nodeTypes:V,edgeTypes:$,fitView:!0,minZoom:.1,nodesConnectable:!1,onNodeClick:(n,p)=>c==null?void 0:c(p.id),onPaneClick:()=>c==null?void 0:c(null),onlyRenderVisibleElements:!0,proOptions:{hideAttribution:!0},children:[s.jsx(P,{gap:16,color:"#1f2937"}),s.jsx(z,{showInteractive:!1}),s.jsx(A,{pannable:!0,zoomable:!0})]})})]}):s.jsx("p",{className:"sme-placeholder",children:"Nothing to draw — this subject area has no entities in it yet."}):s.jsx("div",{className:"sme-splash",children:"◮ drawing the model…"})}export{Y as ModelDiagram}; +import{r,j as s}from"./client-DOmNpTln.js";import{f as T,u as _,v as O,w as R,E as D,B as P,C as z,x as A}from"./styles-B90OKxCj.js";const V={entity:D},$={relationship:R},l={breaking:"#f87171",additive:"#34d399",cosmetic:"#fcd34d"},N=["#5eead4","#fcd34d","#a78bfa","#fb923c","#38bdf8","#f472b6","#a3e635"],d="#64748b";function Y({subjectArea:u,severityByUlid:a,focusUlid:m,onSelect:c}){const[t,g]=r.useState(null),[f,w]=r.useState(null),[h,E]=r.useState(!0);r.useEffect(()=>{g(null),T(u).then(g).catch(n=>w(String(n)))},[u]);const{nodes:k,edges:M}=r.useMemo(()=>{if(!t)return{nodes:[],edges:[]};const n=new Map;t.subject_areas.forEach(e=>{let o=2166136261;for(let i=0;i[e.id,e])),x=a&&a.size>0,C=t.entities.map(e=>{var j;const o=(a==null?void 0:a.get(e.id))??(e.conceptual?a==null?void 0:a.get(e.conceptual.id):void 0),i=x?o?l[o]??d:d:(j=e.conceptual)!=null&&j.subject_area?n.get(e.conceptual.subject_area.id)??d:d;return{id:e.id,type:"entity",position:{x:0,y:0},data:{entity:e,color:i,dimmed:!!(x&&!o),highlighted:e.id===m,showTypes:h}}}),b=t.relationships.map(e=>({id:e.id,source:e.from.entity,target:e.to.entity,type:"relationship",data:{relationship:e,dimmed:!1}}));return{nodes:_(C,b,p),edges:b}},[t,a,m,h]);return f?s.jsx("p",{className:"sme-splash error",children:f}):t?t.entities.length?s.jsxs("div",{className:"erd-wrap",children:[s.jsxs("div",{className:"erd-bar",children:[s.jsxs("span",{className:"erd-count",children:[t.entities.length," entities · ",t.relationships.length," relationships",t.scope&&" · scoped"]}),s.jsxs("label",{className:"erd-toggle",children:[s.jsx("input",{type:"checkbox",checked:h,onChange:n=>E(n.target.checked)}),"show types"]}),a&&a.size>0&&s.jsxs("span",{className:"erd-legend",children:[s.jsx("span",{className:"sw",style:{background:l.breaking}})," breaking",s.jsx("span",{className:"sw",style:{background:l.additive}})," added",s.jsx("span",{className:"sw",style:{background:l.cosmetic}})," changed",s.jsx("span",{className:"sw",style:{background:d}})," unchanged"]})]}),s.jsx("div",{className:"erd-canvas",children:s.jsxs(O,{nodes:k,edges:M,nodeTypes:V,edgeTypes:$,fitView:!0,minZoom:.1,nodesConnectable:!1,onNodeClick:(n,p)=>c==null?void 0:c(p.id),onPaneClick:()=>c==null?void 0:c(null),onlyRenderVisibleElements:!0,proOptions:{hideAttribution:!0},children:[s.jsx(P,{gap:16,color:"#1f2937"}),s.jsx(z,{showInteractive:!1}),s.jsx(A,{pannable:!0,zoomable:!0})]})})]}):s.jsx("p",{className:"sme-placeholder",children:"Nothing to draw — this subject area has no entities in it yet."}):s.jsx("div",{className:"sme-splash",children:"◮ drawing the model…"})}export{Y as ModelDiagram}; diff --git a/packages/server/src/mdl_server/static/assets/main-DgsUduj_.js b/packages/server/src/mdl_server/static/assets/main-DScWOCuj.js similarity index 99% rename from packages/server/src/mdl_server/static/assets/main-DgsUduj_.js rename to packages/server/src/mdl_server/static/assets/main-DScWOCuj.js index 53d918f..08556aa 100644 --- a/packages/server/src/mdl_server/static/assets/main-DgsUduj_.js +++ b/packages/server/src/mdl_server/static/assets/main-DScWOCuj.js @@ -1,2 +1,2 @@ -import{j as e,r as a,c as ie,R as oe}from"./client-DOmNpTln.js";import{I as le,R as de,P as Y,f as J,a as Z,g as ee,s as he,A as ue,b as xe,M as je,S as pe}from"./styles-BtrhR1xb.js";function me(s){return{canEdit:!s,mode:"direct",canArbitrate:!s,canCommit:!s}}function l({size:s=16,children:i}){return e.jsx("svg",{width:s,height:s,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:1.7,strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",focusable:"false",children:i})}const fe=s=>e.jsx(l,{...s,children:e.jsx("path",{d:"M12 5v14M5 12h14"})}),ge=s=>e.jsx(l,{...s,children:e.jsx("path",{d:"M12 3l7.5 4.5v9L12 21l-7.5-4.5v-9L12 3z"})}),ye=s=>e.jsxs(l,{...s,children:[e.jsx("path",{d:"M12 3l9 5-9 5-9-5 9-5z"}),e.jsx("path",{d:"M3 12l9 5 9-5"}),e.jsx("path",{d:"M3 16l9 5 9-5"})]}),be=s=>e.jsxs(l,{...s,children:[e.jsx("circle",{cx:"6",cy:"6",r:"2.4"}),e.jsx("circle",{cx:"6",cy:"18",r:"2.4"}),e.jsx("circle",{cx:"18",cy:"18",r:"2.4"}),e.jsx("path",{d:"M6 8.4v7.2M8.4 6H14a3 3 0 0 1 3 3v6.6"})]}),we=s=>e.jsxs(l,{...s,children:[e.jsx("path",{d:"M12 4v16M6 8h12"}),e.jsx("path",{d:"M6 8l-2.5 5a2.5 2.5 0 0 0 5 0L6 8zM18 8l-2.5 5a2.5 2.5 0 0 0 5 0L18 8z"}),e.jsx("path",{d:"M9 20h6"})]}),ve=s=>e.jsx(l,{...s,children:e.jsx("path",{d:"M8 7l-4 5 4 5M16 7l4 5-4 5"})}),Me=s=>e.jsxs(l,{...s,children:[e.jsx("path",{d:"M8 8l4-4 4 4M8 16l4 4 4-4"}),e.jsx("path",{d:"M4 12h16"})]}),Ce=s=>e.jsxs(l,{...s,children:[e.jsx("rect",{x:"3",y:"4",width:"7",height:"7",rx:"1"}),e.jsx("rect",{x:"14",y:"4",width:"7",height:"7",rx:"1"}),e.jsx("rect",{x:"3",y:"15",width:"7",height:"5",rx:"1"}),e.jsx("rect",{x:"14",y:"15",width:"7",height:"5",rx:"1"})]}),Ne=s=>e.jsx(l,{...s,children:e.jsx("path",{d:"M4 8V5a1 1 0 0 1 1-1h3M16 4h3a1 1 0 0 1 1 1v3M20 16v3a1 1 0 0 1-1 1h-3M8 20H5a1 1 0 0 1-1-1v-3"})}),Ee=s=>e.jsxs(l,{...s,children:[e.jsx("path",{d:"M20 11a8 8 0 1 0-.5 4"}),e.jsx("path",{d:"M20 4v5h-5"})]}),ke=s=>e.jsxs(l,{...s,children:[e.jsx("rect",{x:"4",y:"4",width:"16",height:"16",rx:"2"}),e.jsx("path",{d:"M4 9h16"})]}),Se=s=>e.jsxs(l,{...s,children:[e.jsx("path",{d:"M4 7h9a4 4 0 0 1 4 4v3"}),e.jsx("path",{d:"M14 11l3 3 3-3"})]}),Ie=s=>e.jsxs(l,{...s,children:[e.jsx("circle",{cx:"12",cy:"12",r:"9"}),e.jsx("path",{d:"M8.5 12.5l2.5 2.5 4.5-5"})]}),Le=s=>e.jsxs(l,{...s,children:[e.jsx("path",{d:"M12 4l9 16H3l9-16z"}),e.jsx("path",{d:"M12 10v4M12 17.5v.5"})]}),Re=s=>e.jsxs(l,{...s,children:[e.jsx("circle",{cx:"12",cy:"12",r:"9"}),e.jsx("path",{d:"M15 9l-6 6M9 9l6 6"})]}),Te=s=>e.jsx(l,{...s,children:e.jsx("path",{d:"M4 6h16M4 12h16M4 18h16"})}),ze=s=>e.jsxs(l,{...s,children:[e.jsx("rect",{x:"3",y:"3",width:"7",height:"7",rx:"1.5"}),e.jsx("rect",{x:"14",y:"3",width:"7",height:"7",rx:"1.5"}),e.jsx("rect",{x:"3",y:"14",width:"7",height:"7",rx:"1.5"}),e.jsx("rect",{x:"14",y:"14",width:"7",height:"7",rx:"1.5"})]}),De=s=>e.jsx(l,{...s,children:e.jsx("path",{d:"M6 6l12 12M18 6L6 18"})}),Be=s=>e.jsx(l,{...s,children:e.jsx("path",{d:"M5 12h14M13 6l6 6-6 6"})});function Fe({doc:s,saColors:i,countByArea:f,activeAreas:d,onSetActive:g,open:v,onClose:y}){const x=s.subject_areas,j=d.size>0,m=c=>g(new Set([c])),M=c=>{const p=new Set(d);p.has(c)?p.delete(c):p.add(c),g(p)},o=f.get("")??0;return e.jsxs("aside",{className:"canvas-drawer"+(v?" open":""),"aria-hidden":!v,children:[e.jsxs("div",{className:"drawer-header",children:[e.jsxs("h2",{children:[e.jsx(ze,{size:16})," Subject areas"]}),e.jsx("button",{className:"icon-btn",onClick:y,title:"Close","aria-label":"Close drawer",children:e.jsx(De,{size:16})})]}),e.jsx("div",{className:"drawer-hint",children:j?`Showing ${d.size} of ${x.length} — click a domain to focus, tick to add.`:"Click a domain to show only it. Tick several to compare."}),e.jsx("button",{className:"sa-all"+(j?"":" active"),onClick:()=>g(new Set),disabled:!j,children:"Show all"}),e.jsxs("div",{className:"sa-list",children:[x.map(c=>{const p=d.has(c.id),D=f.get(c.id)??c.member_count??0;return e.jsxs("div",{className:"sa-row"+(p?" active":""),onClick:()=>m(c.id),role:"button",tabIndex:0,onKeyDown:w=>{(w.key==="Enter"||w.key===" ")&&(w.preventDefault(),m(c.id))},title:`Focus ${c.name}`,children:[e.jsx("input",{type:"checkbox",checked:p,onClick:w=>w.stopPropagation(),onChange:()=>M(c.id),"aria-label":`Include ${c.name}`}),e.jsx("span",{className:"sa-chip",style:{background:i.get(c.id)}}),e.jsx("span",{className:"sa-name",children:c.name}),e.jsx("span",{className:"sa-count",children:D})]},c.id)}),o>0&&e.jsxs("div",{className:"sa-row muted",title:"Entities with no subject area",children:[e.jsx("span",{className:"sa-chip none"}),e.jsx("span",{className:"sa-name",children:"No subject area"}),e.jsx("span",{className:"sa-count",children:o})]})]})]})}function Pe({doc:s,diagnostics:i,query:f,onQuery:d,onSubmitQuery:g,showTypes:v,onToggleTypes:y,collapseDetail:x,onToggleCollapse:j,onFitView:m,onRelayout:M,onRefresh:o,readOnly:c,dirty:p,panelTab:D,onPanelTab:w,onNewEntity:Q,exec:A,onImported:S,onImportBatch:I,openImport:_,onToggleDrawer:$,drawerOpen:k,filterCount:K}){const B=(i==null?void 0:i.items.filter(u=>u.severity==="error").length)??0,C=(i==null?void 0:i.items.filter(u=>u.severity==="warning").length)??0,L=(u,b,R,F,q)=>e.jsxs("button",{className:"grp-btn"+(D===u?" active":""),onClick:()=>w(u),title:F,children:[b,e.jsx("span",{children:R}),q&&e.jsx("span",{className:"grp-badge","aria-label":"uncommitted changes"})]});return e.jsxs("header",{className:"topbar",children:[e.jsxs("div",{className:"topbar-row context",children:[e.jsxs("button",{className:"hamburger"+(k?" active":""),onClick:$,title:k?"Hide subject areas & layout":"Subject areas & layout","aria-label":"Toggle subject-area & layout drawer","aria-expanded":k,children:[e.jsx(Te,{size:18}),K>0&&e.jsx("span",{className:"hamburger-badge",children:K})]}),e.jsxs("div",{className:"brand",children:[e.jsx("span",{className:"logo",children:"◮"}),e.jsx("span",{className:"brand-name",children:"Modelith"}),e.jsx("span",{className:"project-name",children:s.project.name}),c&&e.jsx("span",{className:"chip",children:"read-only"})]}),e.jsx("input",{className:"search",type:"search",placeholder:"Search entities & attributes… ( / , Enter jumps )",value:f,onChange:u=>d(u.target.value),onKeyDown:u=>{u.key==="Enter"&&g()},id:"mdl-search"}),e.jsxs("div",{className:"stats",children:[e.jsxs("span",{className:"stat-item",title:"entities",children:[e.jsx(ke,{size:14}),s.counts.entities]}),e.jsxs("span",{className:"stat-item",title:"relationships",children:[e.jsx(Se,{size:14}),s.counts.relationships]}),i&&e.jsx("span",{className:"diag-chip"+(B?" err":C?" warn":" ok"),title:i.items.map(u=>`${u.code} ${u.message}`).join(` +import{j as e,r as a,c as ie,R as oe}from"./client-DOmNpTln.js";import{I as le,R as de,P as Y,f as J,a as Z,g as ee,s as he,A as ue,b as xe,M as je,S as pe}from"./styles-B90OKxCj.js";function me(s){return{canEdit:!s,mode:"direct",canArbitrate:!s,canCommit:!s}}function l({size:s=16,children:i}){return e.jsx("svg",{width:s,height:s,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:1.7,strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",focusable:"false",children:i})}const fe=s=>e.jsx(l,{...s,children:e.jsx("path",{d:"M12 5v14M5 12h14"})}),ge=s=>e.jsx(l,{...s,children:e.jsx("path",{d:"M12 3l7.5 4.5v9L12 21l-7.5-4.5v-9L12 3z"})}),ye=s=>e.jsxs(l,{...s,children:[e.jsx("path",{d:"M12 3l9 5-9 5-9-5 9-5z"}),e.jsx("path",{d:"M3 12l9 5 9-5"}),e.jsx("path",{d:"M3 16l9 5 9-5"})]}),be=s=>e.jsxs(l,{...s,children:[e.jsx("circle",{cx:"6",cy:"6",r:"2.4"}),e.jsx("circle",{cx:"6",cy:"18",r:"2.4"}),e.jsx("circle",{cx:"18",cy:"18",r:"2.4"}),e.jsx("path",{d:"M6 8.4v7.2M8.4 6H14a3 3 0 0 1 3 3v6.6"})]}),we=s=>e.jsxs(l,{...s,children:[e.jsx("path",{d:"M12 4v16M6 8h12"}),e.jsx("path",{d:"M6 8l-2.5 5a2.5 2.5 0 0 0 5 0L6 8zM18 8l-2.5 5a2.5 2.5 0 0 0 5 0L18 8z"}),e.jsx("path",{d:"M9 20h6"})]}),ve=s=>e.jsx(l,{...s,children:e.jsx("path",{d:"M8 7l-4 5 4 5M16 7l4 5-4 5"})}),Me=s=>e.jsxs(l,{...s,children:[e.jsx("path",{d:"M8 8l4-4 4 4M8 16l4 4 4-4"}),e.jsx("path",{d:"M4 12h16"})]}),Ce=s=>e.jsxs(l,{...s,children:[e.jsx("rect",{x:"3",y:"4",width:"7",height:"7",rx:"1"}),e.jsx("rect",{x:"14",y:"4",width:"7",height:"7",rx:"1"}),e.jsx("rect",{x:"3",y:"15",width:"7",height:"5",rx:"1"}),e.jsx("rect",{x:"14",y:"15",width:"7",height:"5",rx:"1"})]}),Ne=s=>e.jsx(l,{...s,children:e.jsx("path",{d:"M4 8V5a1 1 0 0 1 1-1h3M16 4h3a1 1 0 0 1 1 1v3M20 16v3a1 1 0 0 1-1 1h-3M8 20H5a1 1 0 0 1-1-1v-3"})}),Ee=s=>e.jsxs(l,{...s,children:[e.jsx("path",{d:"M20 11a8 8 0 1 0-.5 4"}),e.jsx("path",{d:"M20 4v5h-5"})]}),ke=s=>e.jsxs(l,{...s,children:[e.jsx("rect",{x:"4",y:"4",width:"16",height:"16",rx:"2"}),e.jsx("path",{d:"M4 9h16"})]}),Se=s=>e.jsxs(l,{...s,children:[e.jsx("path",{d:"M4 7h9a4 4 0 0 1 4 4v3"}),e.jsx("path",{d:"M14 11l3 3 3-3"})]}),Ie=s=>e.jsxs(l,{...s,children:[e.jsx("circle",{cx:"12",cy:"12",r:"9"}),e.jsx("path",{d:"M8.5 12.5l2.5 2.5 4.5-5"})]}),Le=s=>e.jsxs(l,{...s,children:[e.jsx("path",{d:"M12 4l9 16H3l9-16z"}),e.jsx("path",{d:"M12 10v4M12 17.5v.5"})]}),Re=s=>e.jsxs(l,{...s,children:[e.jsx("circle",{cx:"12",cy:"12",r:"9"}),e.jsx("path",{d:"M15 9l-6 6M9 9l6 6"})]}),Te=s=>e.jsx(l,{...s,children:e.jsx("path",{d:"M4 6h16M4 12h16M4 18h16"})}),ze=s=>e.jsxs(l,{...s,children:[e.jsx("rect",{x:"3",y:"3",width:"7",height:"7",rx:"1.5"}),e.jsx("rect",{x:"14",y:"3",width:"7",height:"7",rx:"1.5"}),e.jsx("rect",{x:"3",y:"14",width:"7",height:"7",rx:"1.5"}),e.jsx("rect",{x:"14",y:"14",width:"7",height:"7",rx:"1.5"})]}),De=s=>e.jsx(l,{...s,children:e.jsx("path",{d:"M6 6l12 12M18 6L6 18"})}),Be=s=>e.jsx(l,{...s,children:e.jsx("path",{d:"M5 12h14M13 6l6 6-6 6"})});function Fe({doc:s,saColors:i,countByArea:f,activeAreas:d,onSetActive:g,open:v,onClose:y}){const x=s.subject_areas,j=d.size>0,m=c=>g(new Set([c])),M=c=>{const p=new Set(d);p.has(c)?p.delete(c):p.add(c),g(p)},o=f.get("")??0;return e.jsxs("aside",{className:"canvas-drawer"+(v?" open":""),"aria-hidden":!v,children:[e.jsxs("div",{className:"drawer-header",children:[e.jsxs("h2",{children:[e.jsx(ze,{size:16})," Subject areas"]}),e.jsx("button",{className:"icon-btn",onClick:y,title:"Close","aria-label":"Close drawer",children:e.jsx(De,{size:16})})]}),e.jsx("div",{className:"drawer-hint",children:j?`Showing ${d.size} of ${x.length} — click a domain to focus, tick to add.`:"Click a domain to show only it. Tick several to compare."}),e.jsx("button",{className:"sa-all"+(j?"":" active"),onClick:()=>g(new Set),disabled:!j,children:"Show all"}),e.jsxs("div",{className:"sa-list",children:[x.map(c=>{const p=d.has(c.id),D=f.get(c.id)??c.member_count??0;return e.jsxs("div",{className:"sa-row"+(p?" active":""),onClick:()=>m(c.id),role:"button",tabIndex:0,onKeyDown:w=>{(w.key==="Enter"||w.key===" ")&&(w.preventDefault(),m(c.id))},title:`Focus ${c.name}`,children:[e.jsx("input",{type:"checkbox",checked:p,onClick:w=>w.stopPropagation(),onChange:()=>M(c.id),"aria-label":`Include ${c.name}`}),e.jsx("span",{className:"sa-chip",style:{background:i.get(c.id)}}),e.jsx("span",{className:"sa-name",children:c.name}),e.jsx("span",{className:"sa-count",children:D})]},c.id)}),o>0&&e.jsxs("div",{className:"sa-row muted",title:"Entities with no subject area",children:[e.jsx("span",{className:"sa-chip none"}),e.jsx("span",{className:"sa-name",children:"No subject area"}),e.jsx("span",{className:"sa-count",children:o})]})]})]})}function Pe({doc:s,diagnostics:i,query:f,onQuery:d,onSubmitQuery:g,showTypes:v,onToggleTypes:y,collapseDetail:x,onToggleCollapse:j,onFitView:m,onRelayout:M,onRefresh:o,readOnly:c,dirty:p,panelTab:D,onPanelTab:w,onNewEntity:Q,exec:A,onImported:S,onImportBatch:I,openImport:_,onToggleDrawer:$,drawerOpen:k,filterCount:K}){const B=(i==null?void 0:i.items.filter(u=>u.severity==="error").length)??0,C=(i==null?void 0:i.items.filter(u=>u.severity==="warning").length)??0,L=(u,b,R,F,q)=>e.jsxs("button",{className:"grp-btn"+(D===u?" active":""),onClick:()=>w(u),title:F,children:[b,e.jsx("span",{children:R}),q&&e.jsx("span",{className:"grp-badge","aria-label":"uncommitted changes"})]});return e.jsxs("header",{className:"topbar",children:[e.jsxs("div",{className:"topbar-row context",children:[e.jsxs("button",{className:"hamburger"+(k?" active":""),onClick:$,title:k?"Hide subject areas & layout":"Subject areas & layout","aria-label":"Toggle subject-area & layout drawer","aria-expanded":k,children:[e.jsx(Te,{size:18}),K>0&&e.jsx("span",{className:"hamburger-badge",children:K})]}),e.jsxs("div",{className:"brand",children:[e.jsx("span",{className:"logo",children:"◮"}),e.jsx("span",{className:"brand-name",children:"Modelith"}),e.jsx("span",{className:"project-name",children:s.project.name}),c&&e.jsx("span",{className:"chip",children:"read-only"})]}),e.jsx("input",{className:"search",type:"search",placeholder:"Search entities & attributes… ( / , Enter jumps )",value:f,onChange:u=>d(u.target.value),onKeyDown:u=>{u.key==="Enter"&&g()},id:"mdl-search"}),e.jsxs("div",{className:"stats",children:[e.jsxs("span",{className:"stat-item",title:"entities",children:[e.jsx(ke,{size:14}),s.counts.entities]}),e.jsxs("span",{className:"stat-item",title:"relationships",children:[e.jsx(Se,{size:14}),s.counts.relationships]}),i&&e.jsx("span",{className:"diag-chip"+(B?" err":C?" warn":" ok"),title:i.items.map(u=>`${u.code} ${u.message}`).join(` `)||"model valid",children:B?e.jsxs(e.Fragment,{children:[e.jsx(Re,{size:14}),B]}):C?e.jsxs(e.Fragment,{children:[e.jsx(Le,{size:14}),C]}):e.jsxs(e.Fragment,{children:[e.jsx(Ie,{size:14}),"valid"]})})]})]}),e.jsxs("div",{className:"topbar-row actions",children:[!c&&e.jsxs("button",{className:"tool-btn primary",onClick:Q,title:"New entity (n)",children:[e.jsx(fe,{size:15}),e.jsx("span",{children:"Entity"})]}),e.jsxs("div",{className:"btn-group",role:"group","aria-label":"Panels",children:[e.jsx("span",{className:"grp-tag",children:"Panels"}),L("ontology",e.jsx(ge,{size:15}),"Ontology","Ontology browser"),L("layers",e.jsx(ye,{size:15}),"Layers","Four-layer stack & coverage"),L("changes",e.jsx(be,{size:15}),"Changes",p?"Uncommitted changes":"Changes",p),L("decisions",e.jsx(we,{size:15}),"Decisions","Decision ledger")]}),e.jsxs("div",{className:"btn-group",role:"group","aria-label":"View",children:[e.jsx("span",{className:"grp-tag",children:"View"}),e.jsx("button",{className:"grp-btn icon-only"+(v?" active":""),onClick:y,title:"Toggle data types","aria-label":"Toggle data types",children:e.jsx(ve,{size:15})}),e.jsx("button",{className:"grp-btn icon-only"+(x?" active":""),onClick:j,title:"Collapse to keys (PK + FK only) — readable for large models","aria-label":"Collapse to keys",children:e.jsx(Me,{size:15})}),e.jsx(_e,{onRelayout:M}),e.jsx("button",{className:"grp-btn icon-only",onClick:m,title:"Fit view","aria-label":"Fit view",children:e.jsx(Ne,{size:15})})]}),e.jsxs("div",{className:"btn-group",role:"group","aria-label":"Data",children:[e.jsx("span",{className:"grp-tag",children:"Data"}),e.jsx("button",{className:"grp-btn icon-only",onClick:o,title:"Refresh from disk (picks up terminal / external edits)","aria-label":"Refresh from disk",children:e.jsx(Ee,{size:15})}),e.jsx(le,{exec:A,canEdit:!c,onImported:S,submitLabel:"Import",buttonClass:"grp-btn",applyBatch:I,openImport:_})]})]})]})}const O=["LR","TB","RL","BT"],Ae={LR:0,TB:90,RL:180,BT:270},se={LR:"left → right",TB:"top → bottom",RL:"right → left",BT:"bottom → top"};function _e({onRelayout:s}){const[i,f]=a.useState(!1),[d,g]=a.useState("LR"),[v,y]=a.useState("auto"),x=a.useRef(null);a.useEffect(()=>{if(!i)return;const o=c=>{x.current&&!x.current.contains(c.target)&&f(!1)};return document.addEventListener("mousedown",o),()=>document.removeEventListener("mousedown",o)},[i]);const j=o=>{y(o),s(o,d)},m=o=>{j(o),f(!1)},M=()=>{const o=O[(O.indexOf(d)+1)%O.length];g(o),s(v,o)};return e.jsxs("div",{className:"layout-picker",ref:x,children:[e.jsx("button",{className:"grp-btn icon-only",onClick:()=>j("auto"),title:"Auto-layout","aria-label":"Auto-layout",children:e.jsx(Ce,{size:15})}),e.jsx("button",{className:"grp-btn icon-only caret"+(i?" active":""),onClick:()=>f(o=>!o),title:"Layout style","aria-label":"Layout style",children:"▾"}),e.jsx("button",{className:"grp-btn icon-only",onClick:M,title:`Flow direction: ${se[d]} (click to rotate)`,"aria-label":`Flow direction: ${se[d]}`,children:e.jsx("span",{className:"dir-arrow",style:{transform:`rotate(${Ae[d]}deg)`},children:e.jsx(Be,{size:15})})}),i&&e.jsxs("div",{className:"layout-menu",role:"menu",children:[e.jsx("button",{onClick:()=>m("auto"),children:"Auto (by size)"}),e.jsx("button",{onClick:()=>m("hierarchical"),children:"Hierarchical"}),e.jsx("button",{onClick:()=>m("clustered"),children:"Clustered (by area)"}),e.jsx("button",{onClick:()=>m("grid"),children:"Grid"})]})]})}function $e(){const[s,i]=a.useState(null),[f,d]=a.useState(null),[g,v]=a.useState(null),[y,x]=a.useState(null),[j,m]=a.useState(""),[M,o]=a.useState(!0),[c,p]=a.useState(!1),[D,w]=a.useState(()=>new Set),[Q,A]=a.useState(null),[S,I]=a.useState(null),[_,$]=a.useState(!1),[k,K]=a.useState(()=>new Set),[B,C]=a.useState(!1),[L,u]=a.useState(0),b=a.useRef(null),R=a.useRef(""),F=a.useRef(!1),q=a.useMemo(()=>{const t=new Map;return s==null||s.subject_areas.forEach((r,n)=>t.set(r.id,Y[n%Y.length])),t},[s]),U=a.useMemo(()=>{const t=new Map;if(!s)return t;const r=new Map;return s.subject_areas.forEach(n=>{(n.members??[]).forEach(h=>r.set(h,n.id))}),s.entities.forEach(n=>{var E,V,X;const P=((E=n.conceptual)!=null&&E.id?r.get(n.conceptual.id):void 0)??((X=(V=n.conceptual)==null?void 0:V.subject_area)==null?void 0:X.id)??"";t.set(n.id,P)}),t},[s]),te=a.useMemo(()=>{const t=new Map;return U.forEach(r=>t.set(r,(t.get(r)??0)+1)),t},[U]),T=(s==null?void 0:s.read_only)??!0,ne=a.useMemo(()=>me(T),[T]),H=a.useMemo(()=>new URLSearchParams(window.location.search),[]),z=H.get("minimal")==="1";a.useEffect(()=>{z&&p(!0)},[z]);const ae=a.useCallback(t=>{w(r=>{const n=new Set(r);return n.has(t)?n.delete(t):n.add(t),n})},[]),re=H.get("import")==="1",W=a.useRef(!1),N=a.useCallback(()=>{J().then(i).catch(t=>v(String(t))),Z().then(d).catch(()=>d(null)),ee().then(t=>C(!!(t.git&&!t.clean))).catch(()=>C(!1)),u(t=>t+1)},[]);a.useEffect(N,[N]),a.useEffect(()=>{const t=setInterval(()=>{J().then(r=>{i(n=>n&&r.fingerprint===n.fingerprint?n:(F.current||(R.current=r.fingerprint),z||(Z().then(d).catch(()=>d(null)),ee().then(h=>C(!!(h.git&&!h.clean))).catch(()=>C(!1))),u(h=>h+1),r))}).catch(()=>{})},3e3);return()=>clearInterval(t)},[z]),a.useEffect(()=>{s!=null&&s.fingerprint&&(R.current=s.fingerprint)},[s]);const G=a.useCallback(async(t,r)=>{if(s){F.current=!0;try{const n=await he(t,r,R.current||s.fingerprint);return n!=null&&n.fingerprint&&(R.current=n.fingerprint),N(),n}catch(n){throw n instanceof ue&&n.status===409?(x("Model changed on disk — view refreshed, please retry."),N()):x(n instanceof Error?n.message:String(n)),n}finally{F.current=!1}}},[s,N]);a.useEffect(()=>{if(!y)return;const t=setTimeout(()=>x(null),5e3);return()=>clearTimeout(t)},[y]),a.useEffect(()=>{if(!s||W.current)return;const t=H.get("focus");if(!t)return;const r=s.entities.find(n=>{var h;return n.name===t||((h=n.conceptual)==null?void 0:h.name)===t});r&&(W.current=!0,requestAnimationFrame(()=>{var n;return(n=b.current)==null?void 0:n.focusEntity(r.id)}))},[s,H]);const ce=a.useCallback(()=>{var n;if(!s)return;const t=j.trim().toLowerCase();if(!t)return;const r=s.entities.find(h=>{var E;return(h.name.toLowerCase()+" "+(((E=h.conceptual)==null?void 0:E.name.toLowerCase())??"")+" "+h.attributes.map(V=>V.name.toLowerCase()).join(" ")).includes(t)});r&&((n=b.current)==null||n.focusEntity(r.id))},[s,j]);return a.useEffect(()=>{const t=r=>{var h,P,E;const n=(h=document.activeElement)==null?void 0:h.tagName;n==="INPUT"||n==="TEXTAREA"||n==="SELECT"||(r.key==="/"&&(r.preventDefault(),(P=document.getElementById("mdl-search"))==null||P.focus()),r.key==="n"&&!T&&((E=b.current)==null||E.newEntity()),r.key==="Escape"&&(A(null),m(""),I(null)))};return window.addEventListener("keydown",t),()=>window.removeEventListener("keydown",t)},[T]),g?e.jsxs("div",{className:"splash error",children:[e.jsxs("h1",{children:["◮"," Modelith"]}),e.jsx("p",{children:"Could not load the model:"}),e.jsx("pre",{children:g}),e.jsxs("p",{children:["Is ",e.jsx("code",{children:"mdl serve"})," pointed at a model directory?"]})]}):s?e.jsxs("div",{className:"app",children:[!z&&e.jsx(Pe,{doc:s,diagnostics:f,query:j,onQuery:m,onSubmitQuery:ce,showTypes:M,onToggleTypes:()=>o(t=>!t),collapseDetail:c,onToggleCollapse:()=>p(t=>!t),onFitView:()=>{var t;return(t=b.current)==null?void 0:t.fitView()},onRelayout:(t,r)=>{var n;return(n=b.current)==null?void 0:n.relayout(t,r)},onRefresh:N,readOnly:T,dirty:B,panelTab:S,onPanelTab:t=>I(r=>r===t?null:t),onNewEntity:()=>{var t;return(t=b.current)==null?void 0:t.newEntity()},exec:G,onImported:N,onImportBatch:xe,openImport:re,onToggleDrawer:()=>$(t=>!t),drawerOpen:_,filterCount:k.size}),e.jsxs("div",{className:"canvas-wrap",children:[e.jsx(je,{doc:s,caps:ne,exec:G,selectedId:S?null:Q,onSelect:A,query:j,showTypes:M,collapseDetail:c,expandedEntities:D,onToggleExpand:ae,activeAreas:k,onError:x,handleRef:b}),!z&&e.jsx(Fe,{doc:s,saColors:q,countByArea:te,activeAreas:k,onSetActive:K,open:_,onClose:()=>$(!1)}),S&&e.jsx(pe,{tab:S,onClose:()=>I(null),readOnly:T,refreshKey:L,onModelChanged:N,onFocusEntity:t=>{var r;I(null),(r=b.current)==null||r.focusEntity(t)}}),y&&e.jsx("div",{className:"toast",children:y})]})]}):e.jsxs("div",{className:"splash",children:["◮"," loading model…"]})}function Ke(){return e.jsx(de,{children:e.jsx($e,{})})}ie.createRoot(document.getElementById("root")).render(e.jsx(oe.StrictMode,{children:e.jsx(Ke,{})})); diff --git a/packages/server/src/mdl_server/static/assets/mocks-DUwiNnjR.js b/packages/server/src/mdl_server/static/assets/mocks-AfcrRcE6.js similarity index 100% rename from packages/server/src/mdl_server/static/assets/mocks-DUwiNnjR.js rename to packages/server/src/mdl_server/static/assets/mocks-AfcrRcE6.js diff --git a/packages/server/src/mdl_server/static/assets/sme-C10_zE1B.css b/packages/server/src/mdl_server/static/assets/sme-C10_zE1B.css new file mode 100644 index 0000000..d643f9c --- /dev/null +++ b/packages/server/src/mdl_server/static/assets/sme-C10_zE1B.css @@ -0,0 +1 @@ +:root{--bg: #0e1218;--bg-raised: #161c26;--bg-card: #1b232f;--border: #2a3442;--border-strong: #3d4a5c;--text: #e6ecf3;--text-dim: #93a1b5;--accent: #5eead4;--pk: #fcd34d;--err: #f87171;--ok: #34d399;--font: "Inter", -apple-system, "Segoe UI", Roboto, sans-serif;--mono: ui-monospace, "SF Mono", Menlo, monospace}*{box-sizing:border-box}html,body,#root{height:100%;margin:0}body{font-family:var(--font);background:var(--bg);color:var(--text)}.sme{display:flex;flex-direction:column;height:100%}.sme-splash{height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;color:var(--text-dim)}.sme-splash.error pre{background:var(--bg-card);padding:12px;border-radius:8px;color:var(--err)}.sme-top{display:flex;align-items:center;gap:16px;padding:12px 20px;background:var(--bg-raised);border-bottom:1px solid var(--border)}.sme-brand{display:flex;align-items:baseline;gap:8px;font-weight:700;white-space:nowrap}.sme-logo{color:var(--accent);font-size:18px}.sme-project{color:var(--text-dim);font-weight:400;font-size:13px}.sme-search{flex:0 1 420px;padding:9px 14px;border-radius:9px;font-size:14px;border:1px solid var(--border);background:var(--bg-card);color:var(--text);outline:none}.sme-search:focus{border-color:var(--accent)}.sme-tray{margin-left:auto;padding:9px 16px;border-radius:99px;border:none;cursor:pointer;background:var(--pk);color:#1a1400;font-weight:700;font-size:13px}.sme-chip{display:inline-block;font-size:11px;padding:2px 9px;margin:0 4px 0 0;border-radius:99px;background:#94a3b824;color:var(--text-dim)}.sme-chip.catalog{background:#fbbf2429;color:#fbbf24}.sme-catalog-banner{border:1px solid rgba(251,191,36,.35);background:#fbbf2414;border-radius:8px;padding:10px 12px;font-size:13px;line-height:1.5;color:var(--text);margin:4px 0 10px}.sme-catalog-banner a{color:#fbbf24;font-weight:600}.sme-catalog-note{color:var(--text-dim);font-size:12px;margin-top:4px}.sme-readonly-value{margin:0;padding:8px 10px;border-radius:6px;background:#94a3b80f;border:1px dashed var(--border);color:var(--text-dim);font-size:14px;line-height:1.5}.sme-body{flex:1;display:grid;grid-template-columns:220px 340px 1fr;min-height:0}.sme-nav{border-right:1px solid var(--border);padding:12px;overflow-y:auto;display:flex;flex-direction:column;gap:4px}.sme-sa{text-align:left;background:none;border:none;color:var(--text-dim);cursor:pointer;padding:8px 10px;border-radius:8px;font-size:13px}.sme-sa:hover{background:var(--bg-card);color:var(--text)}.sme-sa.active{background:#5eead41f;color:var(--accent);font-weight:600}.sme-list{list-style:none;margin:0;padding:8px;overflow-y:auto;border-right:1px solid var(--border)}.sme-list-item{padding:10px 12px;border-radius:9px;cursor:pointer;margin-bottom:4px}.sme-list-item:hover{background:var(--bg-card)}.sme-list-item.active{background:#5eead41a;box-shadow:inset 2px 0 0 var(--accent)}.sme-term-name{font-weight:600;font-size:14px;margin-right:6px}.sme-kind{font-size:10px;color:var(--text-dim);text-transform:uppercase;letter-spacing:.05em}.sme-badge{font-size:10px;padding:1px 7px;border-radius:99px;margin-left:4px;background:#94a3b829;color:var(--text-dim)}.sme-badge.proposed{background:#fcd34d29;color:var(--pk)}.sme-term-def{display:block;color:var(--text-dim);font-size:12px;margin-top:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sme-empty{color:var(--text-dim);padding:12px;font-style:italic}.sme-detail{overflow-y:auto;padding:24px 32px}.sme-placeholder{color:var(--text-dim);margin-top:40px;text-align:center}.sme-card-head{display:flex;justify-content:space-between;align-items:flex-start;gap:16px}.sme-card-head h1,.sme-card-head h2{margin:0 0 6px;font-size:22px}.sme-card section,.sme-editor .sme-field{margin-top:22px}.sme-card h3,.sme-editor h3{font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-dim);margin:0 0 8px}.sme-definition{font-size:15px;line-height:1.6;color:var(--text)}.sme-kv{display:flex;gap:10px;align-items:baseline;margin:4px 0;font-size:13px}.sme-kv .k{color:var(--text-dim);min-width:70px}.sme-muted{color:var(--text-dim);font-size:13px}.sme-usage{list-style:none;margin:0;padding:0}.sme-usage li{display:flex;align-items:center;gap:8px;padding:8px 12px;background:var(--bg-card);border:1px solid var(--border);border-radius:8px;margin-bottom:6px;font-size:13px}.sme-usage-model{font-weight:600}.sme-usage-phys{color:var(--text-dim);font-family:var(--mono);font-size:11px}.sme-current-align{font-family:var(--mono);color:var(--accent);margin-right:8px}.sme-primary{padding:9px 18px;border-radius:9px;border:none;cursor:pointer;background:var(--accent);color:#06281f;font-weight:700;font-size:14px}.sme-primary:disabled{opacity:.45;cursor:default}.sme-secondary{padding:8px 14px;border-radius:9px;cursor:pointer;font-size:13px;background:var(--bg-card);border:1px solid var(--border);color:var(--text)}.sme-link{background:none;border:none;color:var(--accent);cursor:pointer;font-size:13px;margin-left:8px}.sme-link.danger{color:var(--err)}.sme-hint,.sme-note{color:var(--text-dim);font-size:13px;line-height:1.5}.sme-field{display:flex;flex-direction:column;gap:6px}.sme-field>span{font-size:12px;color:var(--text-dim)}.sme-field textarea,.sme-field input,.sme-field select{padding:9px 12px;border-radius:9px;border:1px solid var(--border);background:var(--bg-card);color:var(--text);font-family:var(--font);font-size:14px;outline:none;resize:vertical}.sme-field textarea:focus,.sme-field input:focus{border-color:var(--accent)}.sme-field-row{display:flex;gap:16px;margin-top:22px}.sme-field-row .sme-field{flex:1}.sme-syn-row{display:flex;flex-wrap:wrap;gap:6px;align-items:center}.sme-syn-row input{flex:1;min-width:120px}.sme-chip.removable{cursor:pointer;background:#5eead424;color:var(--accent)}.sme-align-results{display:flex;flex-direction:column;gap:6px;max-height:240px;overflow-y:auto;margin:8px 0}.sme-align-card{text-align:left;background:var(--bg-card);border:1px solid var(--border);border-radius:9px;padding:10px 12px;cursor:pointer;color:var(--text)}.sme-align-card:hover{border-color:var(--accent)}.sme-align-card code{color:var(--accent);font-size:11px;margin-left:6px}.sme-align-def{display:block;color:var(--text-dim);font-size:12px;margin-top:4px}.sme-modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background:#05080db8;z-index:50;display:flex;align-items:center;justify-content:center}.sme-modal{width:560px;max-height:84vh;overflow-y:auto;background:var(--bg-raised);border:1px solid var(--border-strong);border-radius:16px;padding:24px;box-shadow:0 24px 80px #0009}.sme-modal h2{margin:0 0 4px}.sme-modal .sme-field{margin-top:14px}.sme-diff{list-style:none;margin:8px 0 0;padding:0}.sme-diff li{background:var(--bg-card);border:1px solid var(--border);border-radius:10px;padding:10px 12px;margin-bottom:8px}.sme-diff-head{display:flex;justify-content:space-between;margin-bottom:6px}.sme-diff-before{color:var(--err);font-size:13px;text-decoration:line-through;opacity:.8}.sme-diff-after{color:var(--ok);font-size:13px}.sme-modal-foot{display:flex;gap:10px;justify-content:flex-end;margin-top:20px}.sme-error-line{color:var(--err);font-size:13px}.sme-signed-in{margin-top:14px;font-size:13px;color:var(--text-dim);background:var(--bg-card);border:1px solid var(--border);border-radius:10px;padding:10px 12px}.sme-signed-in strong{color:var(--text)}.sme-modal a{color:var(--accent)}:root{--sev-breaking: var(--err);--sev-additive: var(--ok);--sev-cosmetic: var(--text-dim);--sev-context: #4b5768}.rv-shell{flex:1;display:flex;flex-direction:column;min-height:0}.sme-tabs{display:flex;gap:4px;margin-left:12px}.sme-tab{background:none;border:none;color:var(--text-dim);cursor:pointer;padding:7px 12px;border-radius:8px;font-size:13px;font-family:var(--font)}.sme-tab:hover{color:var(--text)}.sme-tab.active{color:var(--accent);font-weight:600;background:#5eead41a}.git-banner{display:flex;align-items:center;gap:10px;padding:8px 20px;background:#94a3b80f;border-bottom:1px solid var(--border);font-size:12.5px;color:var(--text-dim)}.git-banner code{font-family:var(--mono);font-size:11.5px;color:var(--text);background:var(--bg-card);padding:2px 8px;border-radius:6px}.git-banner.warn{background:#fcd34d12;color:var(--pk)}.git-banner .dim{color:var(--text-dim)}.rv-chip-del{font-size:12px;padding:3px 10px;border-radius:99px;background:#f8717124;color:var(--err)}.pr-chip.declined{background:#94a3b824;color:var(--text-dim)}.rv-obj-head input[type=checkbox]{accent-color:var(--accent);cursor:pointer}.rv-head{padding:14px 24px;border-bottom:1px solid var(--border);display:flex;align-items:flex-start;gap:20px}.rv-back{background:none;border:none;color:var(--text-dim);cursor:pointer;font-size:13px;padding:4px 0;font-family:var(--font)}.rv-back:hover{color:var(--accent)}.rv-title{margin:0 0 3px;font-size:19px}.rv-sub{color:var(--text-dim);font-size:13px}.rv-sub .warn{color:var(--err);font-weight:600}.rv-tabs{margin-left:auto;display:flex;gap:4px}.rv-tab{background:none;border:1px solid var(--border);color:var(--text-dim);padding:7px 16px;border-radius:8px;cursor:pointer;font-size:13px;font-family:var(--font)}.rv-tab.active{background:var(--bg-card);color:var(--text);border-color:var(--border-strong)}.rv-wrap{flex:1;display:flex;flex-direction:column;min-height:0}.rv-body{flex:1;display:grid;grid-template-columns:380px 1fr;min-height:0}.rv-list{border-right:1px solid var(--border);overflow-y:auto;padding:10px}.rv-detail{overflow-y:auto;padding:22px 28px}.rv-filters{display:flex;gap:4px;flex-wrap:wrap;padding:8px 10px;border-bottom:1px solid var(--border)}.rv-filter{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:99px;border:1px solid var(--border);background:transparent;color:var(--text-dim);cursor:pointer;font-size:12px}.rv-filter:hover{color:var(--text);border-color:var(--border-strong)}.rv-filter.active{color:var(--accent);border-color:var(--accent)}.rv-filter-count{font-size:11px;color:var(--text-dim);background:var(--bg-card);border-radius:99px;padding:0 6px;min-width:16px;text-align:center}.rv-filter.active .rv-filter-count{color:var(--accent)}.rv-field-pick{display:flex;gap:10px;align-items:flex-start}.rv-field-pick>input[type=checkbox]{margin-top:16px;accent-color:var(--accent);cursor:pointer}.rv-field-body{flex:1;min-width:0}.rv-obj{border:1px solid var(--border);border-radius:10px;margin-bottom:8px;background:var(--bg-card);cursor:pointer;overflow:hidden}.rv-obj:hover{border-color:var(--border-strong)}.rv-obj.active{border-color:var(--accent);box-shadow:inset 2px 0 0 var(--accent)}.rv-obj-head{display:flex;align-items:baseline;gap:8px;padding:11px 13px}.rv-obj-name{font-weight:600;font-size:14px}.rv-obj-kind{font-size:10px;color:var(--text-dim);text-transform:uppercase;letter-spacing:.05em}.rv-obj-fields{list-style:none;margin:0;padding:0 13px 11px 26px}.rv-obj-fields li{font-size:12.5px;color:var(--text-dim);line-height:1.7;position:relative}.rv-obj-fields li:before{content:"└";position:absolute;left:-13px;color:var(--border-strong)}.sev{font-size:10px;padding:2px 8px;border-radius:99px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;margin-left:auto;white-space:nowrap}.sev.breaking{background:#f8717129;color:var(--sev-breaking)}.sev.additive{background:#34d39924;color:var(--sev-additive)}.sev.cosmetic{background:#94a3b829;color:var(--sev-cosmetic)}.sev.renamed{background:#fcd34d29;color:var(--pk)}.rv-detail h2{margin:0 0 4px;font-size:20px}.rv-detail-kind{color:var(--text-dim);font-size:13px;margin-bottom:22px}.rv-section{margin-top:24px}.rv-section h3{font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-dim);margin:0 0 9px}.rv-ba{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:var(--border);border:1px solid var(--border);border-radius:9px;overflow:hidden}.rv-ba-col{background:var(--bg-card);padding:12px 14px}.rv-ba-label{font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--text-dim);margin-bottom:7px}.rv-ba-text{font-size:13.5px;line-height:1.6}.rv-ba-text del{background:#f871712e;color:#fca5a5;text-decoration:none}.rv-ba-text ins{background:#34d39929;color:#6ee7b7;text-decoration:none}.rv-hint{color:var(--text-dim);font-size:11.5px;margin-top:7px;font-style:italic}.rv-scalar{display:flex;align-items:center;gap:10px;font-size:13.5px;background:var(--bg-card);border:1px solid var(--border);border-radius:9px;padding:11px 14px}.rv-scalar .from{color:var(--err)}.rv-scalar .to{color:var(--ok)}.rv-scalar .arrow{color:var(--text-dim)}.rv-chips{display:flex;flex-wrap:wrap;gap:6px}.rv-chip-add{font-size:12px;padding:3px 10px;border-radius:99px;background:#34d39924;color:var(--ok)}.rv-break{border:1px solid rgba(248,113,113,.4);background:#f871710f;border-radius:10px;padding:14px 16px}.rv-break-head{display:flex;align-items:baseline;gap:8px;color:var(--err);font-weight:700;font-size:14px;margin-bottom:4px}.rv-break-meta{color:var(--text-dim);font-size:12px;font-family:var(--mono);margin-left:auto}.rv-break-body{font-size:13.5px;line-height:1.6;margin:10px 0 12px}.rv-usage{list-style:none;margin:0;padding:0}.rv-usage li{display:flex;align-items:center;gap:9px;padding:8px 12px;background:var(--bg-card);border:1px solid var(--border);border-radius:8px;margin-bottom:6px;font-size:13px}.rv-usage .m{font-weight:600}.rv-usage .p{color:var(--text-dim);font-family:var(--mono);font-size:11px}.rv-note{display:flex;gap:9px;align-items:flex-start;margin-top:18px;color:var(--text-dim);font-size:13px;line-height:1.6}.rv-note .i{color:var(--accent)}.rv-foot{border-top:1px solid var(--border);background:var(--bg-raised);padding:13px 24px}.rv-route{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;font-size:13px}.rv-route-badge{font-weight:700;color:var(--pk);background:#fcd34d21;padding:3px 11px;border-radius:99px;font-size:12px}.rv-route .k{color:var(--text-dim)}.rv-src{color:var(--text-dim);font-size:11px;font-style:italic}.rv-gates{margin-top:6px;font-size:12.5px;color:var(--text-dim)}.rv-gates code{font-family:var(--mono);color:var(--text);background:var(--bg-card);padding:1px 6px;border-radius:5px;margin-right:5px;font-size:11.5px}.rv-conflict{margin-top:10px;font-size:13px;display:flex;align-items:center;gap:8px}.rv-conflict.ok{color:var(--ok)}.rv-conflict.bad{color:var(--err)}.rv-conflict .detail{color:var(--text-dim)}.rv-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:12px}.pr-wrap{padding:20px 24px;max-width:940px}.pr-head{display:flex;align-items:baseline;gap:12px;margin-bottom:16px}.pr-head h2{margin:0;font-size:19px}.pr-head .meta{color:var(--text-dim);font-size:13px;margin-left:auto}.pr-card{border:1px solid var(--border);border-radius:11px;background:var(--bg-card);padding:14px 16px;margin-bottom:10px}.pr-card.attention{border-color:#f8717173}.pr-top{display:flex;align-items:baseline;gap:12px}.pr-title{font-weight:600;font-size:14.5px}.pr-chip{font-size:11px;padding:3px 10px;border-radius:99px;margin-left:auto;white-space:nowrap;font-weight:600}.pr-chip.accepted{background:#34d39924;color:var(--ok)}.pr-chip.changes{background:#5eead421;color:var(--accent)}.pr-chip.attention{background:#f8717126;color:var(--err)}.pr-chip.awaiting,.pr-chip.local{background:#94a3b824;color:var(--text-dim)}.pr-branch{font-family:var(--mono);font-size:11px;color:var(--text-dim);margin-top:5px}.pr-summary{font-size:13px;margin-top:7px}.pr-detail{font-size:12.5px;color:var(--err);margin-top:6px;line-height:1.5}.pr-foot{display:flex;align-items:center;gap:10px;margin-top:11px}.pr-foot .pr-link{font-size:12.5px;color:var(--text-dim)}.pr-foot .pr-link a{color:var(--accent)}.pr-btns{margin-left:auto;display:flex;gap:8px}.pr-degrade{margin-top:14px;font-size:12.5px;color:var(--text-dim);line-height:1.6;border-left:2px solid var(--border-strong);padding-left:12px}.sub-advice{border:1px solid rgba(252,211,77,.35);background:#fcd34d12;border-radius:9px;padding:12px 14px;margin-top:16px;font-size:13px;line-height:1.6}.sub-advice .i{color:var(--pk)}.sub-split{background:none;border:none;color:var(--pk);cursor:pointer;font-size:13px;font-weight:600;padding:8px 0 0;font-family:var(--font)}.sub-dest{margin-top:16px;font-size:13px}.sub-dest .row{display:flex;gap:10px;margin:5px 0}.sub-dest .k{color:var(--text-dim);min-width:80px}.sub-dest code{font-family:var(--mono);font-size:12px;color:var(--accent)}.sme-model-view{flex:1;display:grid;grid-template-columns:220px 1fr;min-height:0}.sme-sa-count{float:right;font-size:10px;padding:1px 6px;border-radius:99px;background:#94a3b82e;color:var(--text-dim)}.erd-wrap{flex:1;display:flex;flex-direction:column;min-height:0}.erd-bar{display:flex;align-items:center;gap:16px;padding:8px 16px;border-bottom:1px solid var(--border);font-size:12px;color:var(--text-dim)}.erd-count{font-variant-numeric:tabular-nums}.erd-toggle{display:flex;align-items:center;gap:6px;cursor:pointer}.erd-toggle input{accent-color:var(--accent)}.erd-legend{margin-left:auto;display:flex;align-items:center;gap:8px}.erd-legend .sw{display:inline-block;width:10px;height:10px;border-radius:3px;margin-left:8px}.erd-canvas{flex:1;min-height:320px}.erd-canvas .react-flow__attribution{display:none}.erd-busy{color:var(--pk);font-size:11px}.erd-error{color:var(--err);font-size:11.5px;margin-left:auto}.sme-model-view .erd-canvas{position:relative;min-height:0}.erd-action{background:#5eead41f;border:1px solid rgba(94,234,212,.35);color:var(--accent);border-radius:7px;padding:3px 10px;cursor:pointer;font-size:12px;font-family:var(--font);font-weight:600}.erd-action:hover{background:#5eead433}.erd-hint{color:var(--text-dim);font-size:11.5px;font-style:italic}.sa-editor{flex:1;display:grid;grid-template-columns:220px 1fr;min-height:0}.sa-main{overflow-y:auto;padding:18px 24px;display:flex;flex-direction:column;gap:14px}.sa-head h2{margin:0 0 4px;font-size:19px}.sa-filter{flex:none;width:100%;margin-top:10px}.sa-nudge{border:1px solid rgba(252,211,77,.35);background:#fcd34d12;border-radius:8px;padding:9px 12px;font-size:13px;color:var(--text)}.sa-panes{display:grid;grid-template-columns:1fr auto 1fr;gap:12px;align-items:stretch}.sa-pane{border:1px solid var(--border);border-radius:10px;background:var(--bg-card);display:flex;flex-direction:column;min-height:260px;max-height:380px}.sa-pane h3{font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-dim);margin:0;padding:10px 12px;border-bottom:1px solid var(--border)}.sa-pane ul{list-style:none;margin:0;padding:6px;overflow-y:auto;flex:1}.sa-row{display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:7px;cursor:pointer;font-size:13px}.sa-row:hover{background:#94a3b814}.sa-row.picked{background:#5eead41f}.sa-row input{accent-color:var(--accent);pointer-events:none}.sa-row-name{flex:1}.sme-badge.borrowed{background:#94a3b824;color:var(--text-dim)}.sa-controls{display:flex;flex-direction:column;gap:6px;justify-content:center}.sa-controls button{min-width:44px}.sa-expand{border-top:1px solid var(--border);padding-top:14px}.sa-expand h3{font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-dim);margin:0 0 9px}.sa-expand-row{display:flex;gap:10px;align-items:center;flex-wrap:wrap}.sa-expand-row select{padding:7px 10px;border-radius:8px;border:1px solid var(--border);background:var(--bg-card);color:var(--text);font-size:13px}.sa-expand-row label{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--text-dim)}.sa-expand-row input[type=number]{width:56px;padding:6px 8px;border-radius:7px;border:1px solid var(--border);background:var(--bg-card);color:var(--text)}.sa-hops{margin-top:12px;display:flex;flex-direction:column;gap:4px}.sa-hop{display:flex;align-items:baseline;gap:9px;padding:7px 10px;border-radius:7px;background:var(--bg-card);border:1px solid var(--border);font-size:13px;cursor:pointer}.sa-hop input{accent-color:var(--accent)}.sa-hop-name{font-weight:600}.sa-hop-why{color:var(--text-dim);font-size:11.5px;font-family:var(--mono)}.sa-hop-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:10px}.erd-panels{display:flex;gap:6px}.erd-group{display:inline-flex;gap:6px}.erd-sep{width:1px;align-self:stretch;margin:2px;background:var(--border);flex:none}.erd-caret{opacity:.55;margin-left:1px}.erd-action.ghost{background:none;border-color:var(--border);color:var(--text-dim);font-weight:500;display:inline-flex;align-items:center;gap:5px}.erd-action.ghost:hover{color:var(--text);border-color:var(--border-strong);background:none}.erd-action.ghost.on{background:#5eead41f;border-color:#5eead459;color:var(--accent)}.sme-nav-head{display:flex;align-items:center;justify-content:space-between;font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-dim);padding:2px 10px 8px}.sme-nav-add{background:none;border:1px solid var(--border);color:var(--text-dim);width:20px;height:20px;line-height:1;border-radius:6px;cursor:pointer;font-size:14px;font-family:var(--font)}.sme-nav-add:hover{color:var(--accent);border-color:#5eead466}.sme-nav-new input{width:100%;padding:7px 10px;border-radius:8px;font-size:13px;border:1px solid var(--accent);background:var(--bg-card);color:var(--text);outline:none;font-family:var(--font)}.sme-sa{display:flex;align-items:center;gap:8px}.sme-sa>:first-child{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sme-sa .sme-sa-count{float:none;margin-left:auto;flex:none}.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.sa-modal{width:min(900px,92vw);max-height:88vh}.sa-modal .sa-panes{margin-top:14px}.sa-modal .sa-pane{min-height:200px;max-height:260px}.sa-modal .sa-filter{margin-top:14px}.sa-modal .sa-expand{margin-top:16px} diff --git a/packages/server/src/mdl_server/static/assets/sme-DYGKbOTM.css b/packages/server/src/mdl_server/static/assets/sme-DYGKbOTM.css deleted file mode 100644 index f0414a2..0000000 --- a/packages/server/src/mdl_server/static/assets/sme-DYGKbOTM.css +++ /dev/null @@ -1 +0,0 @@ -:root{--bg: #0e1218;--bg-raised: #161c26;--bg-card: #1b232f;--border: #2a3442;--border-strong: #3d4a5c;--text: #e6ecf3;--text-dim: #93a1b5;--accent: #5eead4;--pk: #fcd34d;--err: #f87171;--ok: #34d399;--font: "Inter", -apple-system, "Segoe UI", Roboto, sans-serif;--mono: ui-monospace, "SF Mono", Menlo, monospace}*{box-sizing:border-box}html,body,#root{height:100%;margin:0}body{font-family:var(--font);background:var(--bg);color:var(--text)}.sme{display:flex;flex-direction:column;height:100%}.sme-splash{height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:8px;color:var(--text-dim)}.sme-splash.error pre{background:var(--bg-card);padding:12px;border-radius:8px;color:var(--err)}.sme-top{display:flex;align-items:center;gap:16px;padding:12px 20px;background:var(--bg-raised);border-bottom:1px solid var(--border)}.sme-brand{display:flex;align-items:baseline;gap:8px;font-weight:700;white-space:nowrap}.sme-logo{color:var(--accent);font-size:18px}.sme-project{color:var(--text-dim);font-weight:400;font-size:13px}.sme-search{flex:0 1 420px;padding:9px 14px;border-radius:9px;font-size:14px;border:1px solid var(--border);background:var(--bg-card);color:var(--text);outline:none}.sme-search:focus{border-color:var(--accent)}.sme-tray{margin-left:auto;padding:9px 16px;border-radius:99px;border:none;cursor:pointer;background:var(--pk);color:#1a1400;font-weight:700;font-size:13px}.sme-chip{display:inline-block;font-size:11px;padding:2px 9px;margin:0 4px 0 0;border-radius:99px;background:#94a3b824;color:var(--text-dim)}.sme-chip.catalog{background:#fbbf2429;color:#fbbf24}.sme-catalog-banner{border:1px solid rgba(251,191,36,.35);background:#fbbf2414;border-radius:8px;padding:10px 12px;font-size:13px;line-height:1.5;color:var(--text);margin:4px 0 10px}.sme-catalog-banner a{color:#fbbf24;font-weight:600}.sme-catalog-note{color:var(--text-dim);font-size:12px;margin-top:4px}.sme-readonly-value{margin:0;padding:8px 10px;border-radius:6px;background:#94a3b80f;border:1px dashed var(--border);color:var(--text-dim);font-size:14px;line-height:1.5}.sme-body{flex:1;display:grid;grid-template-columns:220px 340px 1fr;min-height:0}.sme-nav{border-right:1px solid var(--border);padding:12px;overflow-y:auto;display:flex;flex-direction:column;gap:4px}.sme-sa{text-align:left;background:none;border:none;color:var(--text-dim);cursor:pointer;padding:8px 10px;border-radius:8px;font-size:13px}.sme-sa:hover{background:var(--bg-card);color:var(--text)}.sme-sa.active{background:#5eead41f;color:var(--accent);font-weight:600}.sme-list{list-style:none;margin:0;padding:8px;overflow-y:auto;border-right:1px solid var(--border)}.sme-list-item{padding:10px 12px;border-radius:9px;cursor:pointer;margin-bottom:4px}.sme-list-item:hover{background:var(--bg-card)}.sme-list-item.active{background:#5eead41a;box-shadow:inset 2px 0 0 var(--accent)}.sme-term-name{font-weight:600;font-size:14px;margin-right:6px}.sme-kind{font-size:10px;color:var(--text-dim);text-transform:uppercase;letter-spacing:.05em}.sme-badge{font-size:10px;padding:1px 7px;border-radius:99px;margin-left:4px;background:#94a3b829;color:var(--text-dim)}.sme-badge.proposed{background:#fcd34d29;color:var(--pk)}.sme-term-def{display:block;color:var(--text-dim);font-size:12px;margin-top:3px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sme-empty{color:var(--text-dim);padding:12px;font-style:italic}.sme-detail{overflow-y:auto;padding:24px 32px}.sme-placeholder{color:var(--text-dim);margin-top:40px;text-align:center}.sme-card-head{display:flex;justify-content:space-between;align-items:flex-start;gap:16px}.sme-card-head h1,.sme-card-head h2{margin:0 0 6px;font-size:22px}.sme-card section,.sme-editor .sme-field{margin-top:22px}.sme-card h3,.sme-editor h3{font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-dim);margin:0 0 8px}.sme-definition{font-size:15px;line-height:1.6;color:var(--text)}.sme-kv{display:flex;gap:10px;align-items:baseline;margin:4px 0;font-size:13px}.sme-kv .k{color:var(--text-dim);min-width:70px}.sme-muted{color:var(--text-dim);font-size:13px}.sme-usage{list-style:none;margin:0;padding:0}.sme-usage li{display:flex;align-items:center;gap:8px;padding:8px 12px;background:var(--bg-card);border:1px solid var(--border);border-radius:8px;margin-bottom:6px;font-size:13px}.sme-usage-model{font-weight:600}.sme-usage-phys{color:var(--text-dim);font-family:var(--mono);font-size:11px}.sme-current-align{font-family:var(--mono);color:var(--accent);margin-right:8px}.sme-primary{padding:9px 18px;border-radius:9px;border:none;cursor:pointer;background:var(--accent);color:#06281f;font-weight:700;font-size:14px}.sme-primary:disabled{opacity:.45;cursor:default}.sme-secondary{padding:8px 14px;border-radius:9px;cursor:pointer;font-size:13px;background:var(--bg-card);border:1px solid var(--border);color:var(--text)}.sme-link{background:none;border:none;color:var(--accent);cursor:pointer;font-size:13px;margin-left:8px}.sme-link.danger{color:var(--err)}.sme-hint,.sme-note{color:var(--text-dim);font-size:13px;line-height:1.5}.sme-field{display:flex;flex-direction:column;gap:6px}.sme-field>span{font-size:12px;color:var(--text-dim)}.sme-field textarea,.sme-field input,.sme-field select{padding:9px 12px;border-radius:9px;border:1px solid var(--border);background:var(--bg-card);color:var(--text);font-family:var(--font);font-size:14px;outline:none;resize:vertical}.sme-field textarea:focus,.sme-field input:focus{border-color:var(--accent)}.sme-field-row{display:flex;gap:16px;margin-top:22px}.sme-field-row .sme-field{flex:1}.sme-syn-row{display:flex;flex-wrap:wrap;gap:6px;align-items:center}.sme-syn-row input{flex:1;min-width:120px}.sme-chip.removable{cursor:pointer;background:#5eead424;color:var(--accent)}.sme-align-results{display:flex;flex-direction:column;gap:6px;max-height:240px;overflow-y:auto;margin:8px 0}.sme-align-card{text-align:left;background:var(--bg-card);border:1px solid var(--border);border-radius:9px;padding:10px 12px;cursor:pointer;color:var(--text)}.sme-align-card:hover{border-color:var(--accent)}.sme-align-card code{color:var(--accent);font-size:11px;margin-left:6px}.sme-align-def{display:block;color:var(--text-dim);font-size:12px;margin-top:4px}.sme-modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;background:#05080db8;z-index:50;display:flex;align-items:center;justify-content:center}.sme-modal{width:560px;max-height:84vh;overflow-y:auto;background:var(--bg-raised);border:1px solid var(--border-strong);border-radius:16px;padding:24px;box-shadow:0 24px 80px #0009}.sme-modal h2{margin:0 0 4px}.sme-modal .sme-field{margin-top:14px}.sme-diff{list-style:none;margin:8px 0 0;padding:0}.sme-diff li{background:var(--bg-card);border:1px solid var(--border);border-radius:10px;padding:10px 12px;margin-bottom:8px}.sme-diff-head{display:flex;justify-content:space-between;margin-bottom:6px}.sme-diff-before{color:var(--err);font-size:13px;text-decoration:line-through;opacity:.8}.sme-diff-after{color:var(--ok);font-size:13px}.sme-modal-foot{display:flex;gap:10px;justify-content:flex-end;margin-top:20px}.sme-error-line{color:var(--err);font-size:13px}.sme-signed-in{margin-top:14px;font-size:13px;color:var(--text-dim);background:var(--bg-card);border:1px solid var(--border);border-radius:10px;padding:10px 12px}.sme-signed-in strong{color:var(--text)}.sme-modal a{color:var(--accent)}:root{--sev-breaking: var(--err);--sev-additive: var(--ok);--sev-cosmetic: var(--text-dim);--sev-context: #4b5768}.rv-shell{flex:1;display:flex;flex-direction:column;min-height:0}.sme-tabs{display:flex;gap:4px;margin-left:12px}.sme-tab{background:none;border:none;color:var(--text-dim);cursor:pointer;padding:7px 12px;border-radius:8px;font-size:13px;font-family:var(--font)}.sme-tab:hover{color:var(--text)}.sme-tab.active{color:var(--accent);font-weight:600;background:#5eead41a}.git-banner{display:flex;align-items:center;gap:10px;padding:8px 20px;background:#94a3b80f;border-bottom:1px solid var(--border);font-size:12.5px;color:var(--text-dim)}.git-banner code{font-family:var(--mono);font-size:11.5px;color:var(--text);background:var(--bg-card);padding:2px 8px;border-radius:6px}.git-banner.warn{background:#fcd34d12;color:var(--pk)}.git-banner .dim{color:var(--text-dim)}.rv-chip-del{font-size:12px;padding:3px 10px;border-radius:99px;background:#f8717124;color:var(--err)}.pr-chip.declined{background:#94a3b824;color:var(--text-dim)}.rv-obj-head input[type=checkbox]{accent-color:var(--accent);cursor:pointer}.rv-head{padding:14px 24px;border-bottom:1px solid var(--border);display:flex;align-items:flex-start;gap:20px}.rv-back{background:none;border:none;color:var(--text-dim);cursor:pointer;font-size:13px;padding:4px 0;font-family:var(--font)}.rv-back:hover{color:var(--accent)}.rv-title{margin:0 0 3px;font-size:19px}.rv-sub{color:var(--text-dim);font-size:13px}.rv-sub .warn{color:var(--err);font-weight:600}.rv-tabs{margin-left:auto;display:flex;gap:4px}.rv-tab{background:none;border:1px solid var(--border);color:var(--text-dim);padding:7px 16px;border-radius:8px;cursor:pointer;font-size:13px;font-family:var(--font)}.rv-tab.active{background:var(--bg-card);color:var(--text);border-color:var(--border-strong)}.rv-body{flex:1;display:grid;grid-template-columns:380px 1fr;min-height:0}.rv-list{border-right:1px solid var(--border);overflow-y:auto;padding:10px}.rv-detail{overflow-y:auto;padding:22px 28px}.rv-obj{border:1px solid var(--border);border-radius:10px;margin-bottom:8px;background:var(--bg-card);cursor:pointer;overflow:hidden}.rv-obj:hover{border-color:var(--border-strong)}.rv-obj.active{border-color:var(--accent);box-shadow:inset 2px 0 0 var(--accent)}.rv-obj-head{display:flex;align-items:baseline;gap:8px;padding:11px 13px}.rv-obj-name{font-weight:600;font-size:14px}.rv-obj-kind{font-size:10px;color:var(--text-dim);text-transform:uppercase;letter-spacing:.05em}.rv-obj-fields{list-style:none;margin:0;padding:0 13px 11px 26px}.rv-obj-fields li{font-size:12.5px;color:var(--text-dim);line-height:1.7;position:relative}.rv-obj-fields li:before{content:"└";position:absolute;left:-13px;color:var(--border-strong)}.sev{font-size:10px;padding:2px 8px;border-radius:99px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;margin-left:auto;white-space:nowrap}.sev.breaking{background:#f8717129;color:var(--sev-breaking)}.sev.additive{background:#34d39924;color:var(--sev-additive)}.sev.cosmetic{background:#94a3b829;color:var(--sev-cosmetic)}.sev.renamed{background:#fcd34d29;color:var(--pk)}.rv-detail h2{margin:0 0 4px;font-size:20px}.rv-detail-kind{color:var(--text-dim);font-size:13px;margin-bottom:22px}.rv-section{margin-top:24px}.rv-section h3{font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-dim);margin:0 0 9px}.rv-ba{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:var(--border);border:1px solid var(--border);border-radius:9px;overflow:hidden}.rv-ba-col{background:var(--bg-card);padding:12px 14px}.rv-ba-label{font-size:10px;text-transform:uppercase;letter-spacing:.06em;color:var(--text-dim);margin-bottom:7px}.rv-ba-text{font-size:13.5px;line-height:1.6}.rv-ba-text del{background:#f871712e;color:#fca5a5;text-decoration:none}.rv-ba-text ins{background:#34d39929;color:#6ee7b7;text-decoration:none}.rv-hint{color:var(--text-dim);font-size:11.5px;margin-top:7px;font-style:italic}.rv-scalar{display:flex;align-items:center;gap:10px;font-size:13.5px;background:var(--bg-card);border:1px solid var(--border);border-radius:9px;padding:11px 14px}.rv-scalar .from{color:var(--err)}.rv-scalar .to{color:var(--ok)}.rv-scalar .arrow{color:var(--text-dim)}.rv-chips{display:flex;flex-wrap:wrap;gap:6px}.rv-chip-add{font-size:12px;padding:3px 10px;border-radius:99px;background:#34d39924;color:var(--ok)}.rv-break{border:1px solid rgba(248,113,113,.4);background:#f871710f;border-radius:10px;padding:14px 16px}.rv-break-head{display:flex;align-items:baseline;gap:8px;color:var(--err);font-weight:700;font-size:14px;margin-bottom:4px}.rv-break-meta{color:var(--text-dim);font-size:12px;font-family:var(--mono);margin-left:auto}.rv-break-body{font-size:13.5px;line-height:1.6;margin:10px 0 12px}.rv-usage{list-style:none;margin:0;padding:0}.rv-usage li{display:flex;align-items:center;gap:9px;padding:8px 12px;background:var(--bg-card);border:1px solid var(--border);border-radius:8px;margin-bottom:6px;font-size:13px}.rv-usage .m{font-weight:600}.rv-usage .p{color:var(--text-dim);font-family:var(--mono);font-size:11px}.rv-note{display:flex;gap:9px;align-items:flex-start;margin-top:18px;color:var(--text-dim);font-size:13px;line-height:1.6}.rv-note .i{color:var(--accent)}.rv-foot{border-top:1px solid var(--border);background:var(--bg-raised);padding:13px 24px}.rv-route{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap;font-size:13px}.rv-route-badge{font-weight:700;color:var(--pk);background:#fcd34d21;padding:3px 11px;border-radius:99px;font-size:12px}.rv-route .k{color:var(--text-dim)}.rv-src{color:var(--text-dim);font-size:11px;font-style:italic}.rv-gates{margin-top:6px;font-size:12.5px;color:var(--text-dim)}.rv-gates code{font-family:var(--mono);color:var(--text);background:var(--bg-card);padding:1px 6px;border-radius:5px;margin-right:5px;font-size:11.5px}.rv-conflict{margin-top:10px;font-size:13px;display:flex;align-items:center;gap:8px}.rv-conflict.ok{color:var(--ok)}.rv-conflict.bad{color:var(--err)}.rv-conflict .detail{color:var(--text-dim)}.rv-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:12px}.pr-wrap{padding:20px 24px;max-width:940px}.pr-head{display:flex;align-items:baseline;gap:12px;margin-bottom:16px}.pr-head h2{margin:0;font-size:19px}.pr-head .meta{color:var(--text-dim);font-size:13px;margin-left:auto}.pr-card{border:1px solid var(--border);border-radius:11px;background:var(--bg-card);padding:14px 16px;margin-bottom:10px}.pr-card.attention{border-color:#f8717173}.pr-top{display:flex;align-items:baseline;gap:12px}.pr-title{font-weight:600;font-size:14.5px}.pr-chip{font-size:11px;padding:3px 10px;border-radius:99px;margin-left:auto;white-space:nowrap;font-weight:600}.pr-chip.accepted{background:#34d39924;color:var(--ok)}.pr-chip.changes{background:#5eead421;color:var(--accent)}.pr-chip.attention{background:#f8717126;color:var(--err)}.pr-chip.awaiting,.pr-chip.local{background:#94a3b824;color:var(--text-dim)}.pr-branch{font-family:var(--mono);font-size:11px;color:var(--text-dim);margin-top:5px}.pr-summary{font-size:13px;margin-top:7px}.pr-detail{font-size:12.5px;color:var(--err);margin-top:6px;line-height:1.5}.pr-foot{display:flex;align-items:center;gap:10px;margin-top:11px}.pr-foot .pr-link{font-size:12.5px;color:var(--text-dim)}.pr-foot .pr-link a{color:var(--accent)}.pr-btns{margin-left:auto;display:flex;gap:8px}.pr-degrade{margin-top:14px;font-size:12.5px;color:var(--text-dim);line-height:1.6;border-left:2px solid var(--border-strong);padding-left:12px}.sub-advice{border:1px solid rgba(252,211,77,.35);background:#fcd34d12;border-radius:9px;padding:12px 14px;margin-top:16px;font-size:13px;line-height:1.6}.sub-advice .i{color:var(--pk)}.sub-split{background:none;border:none;color:var(--pk);cursor:pointer;font-size:13px;font-weight:600;padding:8px 0 0;font-family:var(--font)}.sub-dest{margin-top:16px;font-size:13px}.sub-dest .row{display:flex;gap:10px;margin:5px 0}.sub-dest .k{color:var(--text-dim);min-width:80px}.sub-dest code{font-family:var(--mono);font-size:12px;color:var(--accent)}.sme-model-view{flex:1;display:grid;grid-template-columns:220px 1fr;min-height:0}.sme-sa-count{float:right;font-size:10px;padding:1px 6px;border-radius:99px;background:#94a3b82e;color:var(--text-dim)}.erd-wrap{flex:1;display:flex;flex-direction:column;min-height:0}.erd-bar{display:flex;align-items:center;gap:16px;padding:8px 16px;border-bottom:1px solid var(--border);font-size:12px;color:var(--text-dim)}.erd-count{font-variant-numeric:tabular-nums}.erd-toggle{display:flex;align-items:center;gap:6px;cursor:pointer}.erd-toggle input{accent-color:var(--accent)}.erd-legend{margin-left:auto;display:flex;align-items:center;gap:8px}.erd-legend .sw{display:inline-block;width:10px;height:10px;border-radius:3px;margin-left:8px}.erd-canvas{flex:1;min-height:320px}.erd-canvas .react-flow__attribution{display:none}.erd-busy{color:var(--pk);font-size:11px}.erd-error{color:var(--err);font-size:11.5px;margin-left:auto}.sme-model-view .erd-canvas{position:relative;min-height:0}.erd-action{background:#5eead41f;border:1px solid rgba(94,234,212,.35);color:var(--accent);border-radius:7px;padding:3px 10px;cursor:pointer;font-size:12px;font-family:var(--font);font-weight:600}.erd-action:hover{background:#5eead433}.erd-hint{color:var(--text-dim);font-size:11.5px;font-style:italic}.sa-editor{flex:1;display:grid;grid-template-columns:220px 1fr;min-height:0}.sa-main{overflow-y:auto;padding:18px 24px;display:flex;flex-direction:column;gap:14px}.sa-head h2{margin:0 0 4px;font-size:19px}.sa-filter{flex:none;width:100%;margin-top:10px}.sa-nudge{border:1px solid rgba(252,211,77,.35);background:#fcd34d12;border-radius:8px;padding:9px 12px;font-size:13px;color:var(--text)}.sa-panes{display:grid;grid-template-columns:1fr auto 1fr;gap:12px;align-items:stretch}.sa-pane{border:1px solid var(--border);border-radius:10px;background:var(--bg-card);display:flex;flex-direction:column;min-height:260px;max-height:380px}.sa-pane h3{font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-dim);margin:0;padding:10px 12px;border-bottom:1px solid var(--border)}.sa-pane ul{list-style:none;margin:0;padding:6px;overflow-y:auto;flex:1}.sa-row{display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:7px;cursor:pointer;font-size:13px}.sa-row:hover{background:#94a3b814}.sa-row.picked{background:#5eead41f}.sa-row input{accent-color:var(--accent);pointer-events:none}.sa-row-name{flex:1}.sme-badge.borrowed{background:#94a3b824;color:var(--text-dim)}.sa-controls{display:flex;flex-direction:column;gap:6px;justify-content:center}.sa-controls button{min-width:44px}.sa-expand{border-top:1px solid var(--border);padding-top:14px}.sa-expand h3{font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-dim);margin:0 0 9px}.sa-expand-row{display:flex;gap:10px;align-items:center;flex-wrap:wrap}.sa-expand-row select{padding:7px 10px;border-radius:8px;border:1px solid var(--border);background:var(--bg-card);color:var(--text);font-size:13px}.sa-expand-row label{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--text-dim)}.sa-expand-row input[type=number]{width:56px;padding:6px 8px;border-radius:7px;border:1px solid var(--border);background:var(--bg-card);color:var(--text)}.sa-hops{margin-top:12px;display:flex;flex-direction:column;gap:4px}.sa-hop{display:flex;align-items:baseline;gap:9px;padding:7px 10px;border-radius:7px;background:var(--bg-card);border:1px solid var(--border);font-size:13px;cursor:pointer}.sa-hop input{accent-color:var(--accent)}.sa-hop-name{font-weight:600}.sa-hop-why{color:var(--text-dim);font-size:11.5px;font-family:var(--mono)}.sa-hop-actions{display:flex;gap:10px;justify-content:flex-end;margin-top:10px}.erd-panels{display:flex;gap:6px}.erd-group{display:inline-flex;gap:6px}.erd-sep{width:1px;align-self:stretch;margin:2px;background:var(--border);flex:none}.erd-caret{opacity:.55;margin-left:1px}.erd-action.ghost{background:none;border-color:var(--border);color:var(--text-dim);font-weight:500;display:inline-flex;align-items:center;gap:5px}.erd-action.ghost:hover{color:var(--text);border-color:var(--border-strong);background:none}.erd-action.ghost.on{background:#5eead41f;border-color:#5eead459;color:var(--accent)}.sme-nav-head{display:flex;align-items:center;justify-content:space-between;font-size:11px;text-transform:uppercase;letter-spacing:.08em;color:var(--text-dim);padding:2px 10px 8px}.sme-nav-add{background:none;border:1px solid var(--border);color:var(--text-dim);width:20px;height:20px;line-height:1;border-radius:6px;cursor:pointer;font-size:14px;font-family:var(--font)}.sme-nav-add:hover{color:var(--accent);border-color:#5eead466}.sme-nav-new input{width:100%;padding:7px 10px;border-radius:8px;font-size:13px;border:1px solid var(--accent);background:var(--bg-card);color:var(--text);outline:none;font-family:var(--font)}.sme-sa{display:flex;align-items:center;gap:8px}.sme-sa>:first-child{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.sme-sa .sme-sa-count{float:none;margin-left:auto;flex:none}.visually-hidden{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}.sa-modal{width:min(900px,92vw);max-height:88vh}.sa-modal .sa-panes{margin-top:14px}.sa-modal .sa-pane{min-height:200px;max-height:260px}.sa-modal .sa-filter{margin-top:14px}.sa-modal .sa-expand{margin-top:16px} diff --git a/packages/server/src/mdl_server/static/assets/sme-Zxw1Myjj.js b/packages/server/src/mdl_server/static/assets/sme-Zxw1Myjj.js new file mode 100644 index 0000000..1da7f69 --- /dev/null +++ b/packages/server/src/mdl_server/static/assets/sme-Zxw1Myjj.js @@ -0,0 +1,2 @@ +const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ModelDiagram-CRUBpPVn.js","assets/client-DOmNpTln.js","assets/styles-B90OKxCj.js","assets/styles-DxhL4SV-.css"])))=>i.map(i=>d[i]); +import{r as a,j as e,c as Ge,R as Ke}from"./client-DOmNpTln.js";import{p as xe,c as be,d as ge,e as Ve,h as ve,I as Ue,R as Fe,M as Te,O as Ye,L as Je,i as Qe,j as Xe,A as Ze,k as es,l as ss,m as ns,o as ts,n as as,s as rs,f as ie,q as is,r as ls,t as cs,b as os}from"./styles-B90OKxCj.js";/* empty css */const ds="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function he(s,n){let t="";for(let i=0;i>=5n;return t}function Ne(){const s=BigInt(Date.now())&(1n<<48n)-1n,n=new Uint8Array(10);crypto.getRandomValues(n);let t=0n;for(const i of n)t=t<<8n|BigInt(i);return he(s,10)+he(t,16)}const hs={create_entity:["id","conceptual_id"],create_relationship:["id","from_fk_id"],create_subject_area:["id"],create_term:["id"],create_domain:["id"],create_code_set:["id"],create_key_group:["id"],create_category:["id"],add_attribute:["id"]};function ms(s,n){const t=hs[s];if(!t)return n;const i={...n};for(const l of t)i[l]||(i[l]=Ne());return i}function ye(s,n){if(s.startsWith("create_")||s==="add_attribute")return`${s}:${n.id??n.attribute_id}`;const t=n.id??n.entity_id??"",i=n.attribute_id??"";return i?`${s}:${t}:${i}`:`${s}:${t}`}function us({subjectArea:s,describe:n}){const[t,i]=a.useState([]),[l,m]=a.useState(null),[c,r]=a.useState(!1),d=a.useRef(null),v=a.useCallback(async(o,f)=>{f=ms(o,f),o==="set_alignment"&&f.status===void 0&&(f={...f,status:"proposed"});const N=ye(o,f),{label:_,before:B,after:E}=n(o,f);return i(S=>{const C=S.filter(R=>R.key!==N);if(o.startsWith("delete_")){const R=f.id??f.entity_id;if(R&&S.some(w=>w.op.startsWith("create_")&&w.payload.id===R))return C.filter(w=>w.payload.id!==R)}return[...C,{op:o,payload:f,label:_,before:B,after:E,key:N}]}),{ok:!0,fingerprint:"",created_id:f.id??null,diagnostics:[]}},[n]);a.useEffect(()=>{if(!t.length){m(null);return}const o=setTimeout(()=>{var N;(N=d.current)==null||N.abort();const f=new AbortController;d.current=f,r(!0),xe(t.map(_=>({op:_.op,payload:_.payload})),s,f.signal).then(m).catch(_=>{_.name!=="AbortError"&&m(null)}).finally(()=>r(!1))},250);return()=>clearTimeout(o)},[t,s]);const j=a.useCallback(o=>{i(f=>f.filter(N=>N.key!==o))},[]),b=a.useCallback(()=>i([]),[]);return a.useMemo(()=>({pending:t,previewDoc:(l==null?void 0:l.model)??null,previewDiff:(l==null?void 0:l.diff)??null,diagnostics:(l==null?void 0:l.diagnostics)??[],failure:l&&l.failed_index!==null?{index:l.failed_index,error:l.error??"invalid change"}:null,busy:c,exec:v,drop:j,clear:b}),[t,l,c,v,j,b])}function ps(s){const n=new Map;for(const i of s)for(const l of["id","conceptual_id","from_fk_id"]){const m=i.payload[l];i.op.startsWith("create_")&&typeof m=="string"&&n.set(m,i.key)}if(!n.size)return new Set;const t=new Set;for(const i of s)if(!i.op.startsWith("create_"))for(const l of Object.values(i.payload))typeof l=="string"&&n.has(l)&&(t.add(i.key),t.add(n.get(l)));return t}function js({user:s}){const[n,t]=a.useState(null);return a.useEffect(()=>{be(s).then(t).catch(()=>{})},[s]),!(n!=null&&n.ok)||!n.git?null:n.read_only?e.jsxs("div",{className:"git-banner",children:[e.jsx("code",{children:n.branch}),e.jsx("span",{children:"browse only — editing is disabled on this deployment"})]}):n.dirty?e.jsxs("div",{className:"git-banner warn",children:[e.jsx("code",{children:n.branch}),e.jsx("span",{children:"uncommitted changes in the working tree — a proposal will be refused until they are committed or discarded"})]}):n.on_base?e.jsxs("div",{className:"git-banner",children:[e.jsx("code",{children:n.branch}),e.jsx("span",{children:"protected — your edits become a pull request"})]}):e.jsxs("div",{className:"git-banner",children:[e.jsx("code",{children:n.branch}),e.jsx("span",{children:"your proposal branch"}),n.behind?e.jsxs("span",{className:"dim",children:["· ",n.base_branch," is ",n.behind," ahead"]}):null]})}function fs({exec:s,canEdit:n,stagedMembers:t}){const[i,l]=a.useState([]),[m,c]=a.useState(""),[r,d]=a.useState(null),[v,j]=a.useState(""),[b,o]=a.useState(new Set),[f,N]=a.useState("ancestors"),[_,B]=a.useState(1),[E,S]=a.useState(null),[C,R]=a.useState(new Set),[A,w]=a.useState(null);a.useEffect(()=>{ge().then(h=>{l(h.subject_areas),c(k=>{var D;return k||((D=h.subject_areas[0])==null?void 0:D.id)||""})}).catch(h=>w(String(h)))},[]),a.useEffect(()=>{m&&(S(null),o(new Set),Ve(m).then(d).catch(h=>w(String(h))))},[m]);const $=a.useMemo(()=>t[m]??(r==null?void 0:r.members)??[],[t,m,r]),I=a.useMemo(()=>{const h=new Map;for(const k of[...(r==null?void 0:r.included)??[],...(r==null?void 0:r.available)??[]])h.set(k.id,k);return h},[r]),g=v.trim().toLowerCase(),O=h=>!g||h.name.toLowerCase().includes(g),u=a.useMemo(()=>new Set($),[$]),M=a.useMemo(()=>$.map(h=>I.get(h)).filter(h=>!!h&&O(h)),[$,I,g]),z=a.useMemo(()=>[...I.values()].filter(h=>!u.has(h.id)&&O(h)),[I,u,g]),W=a.useCallback(h=>{if(!r)return;const k=h.filter(q=>!(r.members??[]).includes(q)).length,D=(r.members??[]).filter(q=>!h.includes(q)).length;s("set_subject_area_members",{id:r.id,members:h,__label:`${r.name}: ${h.length} objects (+${k} −${D})`})},[r,s]),H=(h,k)=>{const D=k?[...$,...h.filter(q=>!u.has(q))]:$.filter(q=>!h.includes(q));W(D),o(new Set)},G=(h,k,D)=>{const q=new Set(h);q.has(k)?q.delete(k):q.add(k),D(q)},T=()=>{if(!r)return;const h=b.size?[...b]:$;if(!h.length){w("add an object first, or select one to expand from");return}w(null),ve(r.id,{seeds:h,direction:f,levels:_}).then(k=>{S(k.hops),R(new Set(k.added))}).catch(k=>w(String(k)))},J=()=>{H([...C],!0),S(null)};if(A&&!r)return e.jsx("p",{className:"sme-splash error",children:A});if(!i.length)return e.jsx("p",{className:"sme-placeholder",children:"No subject areas yet."});const x=((r==null?void 0:r.inconsistent)??[]).filter(h=>!u.has(h));return e.jsxs("div",{className:"sa-editor",children:[e.jsx("nav",{className:"sme-nav",children:i.map(h=>e.jsxs("button",{className:"sme-sa"+(h.id===m?" active":""),onClick:()=>c(h.id),title:h.definition??void 0,children:[h.name,e.jsx("span",{className:"sme-sa-count",children:(t[h.id]??h.members).length})]},h.id))}),e.jsxs("div",{className:"sa-main",children:[e.jsxs("div",{className:"sa-head",children:[e.jsx("h2",{children:(r==null?void 0:r.name)??"…"}),(r==null?void 0:r.definition)&&e.jsx("p",{className:"sme-muted",children:r.definition}),e.jsx("input",{className:"sme-search sa-filter",type:"search",placeholder:"Filter both lists…",value:v,onChange:h=>j(h.target.value)})]}),x.length>0&&n&&e.jsxs("div",{className:"sa-nudge",children:[x.length," object",x.length>1?"s are":" is"," homed in this area but not included.",e.jsxs("button",{className:"sme-link",onClick:()=>H(x,!0),children:["Add ",x.length>1?"them all":"it"]})]}),e.jsxs("div",{className:"sa-panes",children:[e.jsx(ee,{title:`Available (${z.length})`,rows:z,picked:b,onToggle:h=>G(b,h,o),homedHere:(r==null?void 0:r.homed_here)??[]}),e.jsxs("div",{className:"sa-controls",children:[e.jsx("button",{className:"sme-secondary",disabled:!n||!b.size,onClick:()=>H([...b].filter(h=>!u.has(h)),!0),title:"Add the selected objects",children:"→"}),e.jsx("button",{className:"sme-secondary",disabled:!n||!z.length,onClick:()=>H(z.map(h=>h.id),!0),title:"Add everything matching the filter",children:"»"}),e.jsx("button",{className:"sme-secondary",disabled:!n||!b.size,onClick:()=>H([...b].filter(h=>u.has(h)),!1),title:"Remove the selected objects",children:"←"}),e.jsx("button",{className:"sme-secondary",disabled:!n||!M.length,onClick:()=>H(M.map(h=>h.id),!1),title:"Remove everything matching the filter",children:"«"})]}),e.jsx(ee,{title:`Included (${M.length})`,rows:M,picked:b,onToggle:h=>G(b,h,o),homedHere:(r==null?void 0:r.homed_here)??[]})]}),e.jsxs("div",{className:"sa-expand",children:[e.jsx("h3",{children:"Add related objects"}),e.jsxs("div",{className:"sa-expand-row",children:[e.jsxs("select",{value:f,onChange:h=>N(h.target.value),children:[e.jsx("option",{value:"ancestors",children:"ancestors — the parents its keys point at"}),e.jsx("option",{value:"descendants",children:"descendants — what points at it"}),e.jsx("option",{value:"both",children:"both"})]}),e.jsxs("label",{children:["levels",e.jsx("input",{type:"number",min:1,max:10,value:_,onChange:h=>B(Math.max(1,Math.min(10,Number(h.target.value))))})]}),e.jsx("button",{className:"sme-secondary",onClick:T,disabled:!n,children:"Preview"})]}),A&&e.jsx("p",{className:"sme-error-line",children:A}),E&&e.jsxs("div",{className:"sa-hops",children:[E.length===0&&e.jsx("p",{className:"sme-muted",children:"nothing new to add"}),E.map(h=>e.jsxs("label",{className:"sa-hop",children:[e.jsx("input",{type:"checkbox",checked:C.has(h.id),onChange:()=>G(C,h.id,R)}),e.jsx("span",{className:"sa-hop-name",children:h.name}),e.jsxs("span",{className:"sa-hop-why",children:["via ",h.via_name," · ",h.direction.replace(/s$/,""),", level ",h.level]})]},h.id)),E.length>0&&e.jsxs("div",{className:"sa-hop-actions",children:[e.jsx("button",{className:"sme-secondary",onClick:()=>S(null),children:"Cancel"}),e.jsxs("button",{className:"sme-primary",onClick:J,disabled:!C.size,children:["Add ",C.size," object",C.size===1?"":"s"]})]})]})]})]})]})}function ee({title:s,rows:n,picked:t,onToggle:i,homedHere:l}){const m=a.useMemo(()=>new Set(l),[l]);return e.jsxs("div",{className:"sa-pane",children:[e.jsx("h3",{children:s}),e.jsxs("ul",{children:[n.map(c=>e.jsxs("li",{className:"sa-row"+(t.has(c.id)?" picked":""),onClick:()=>i(c.id),children:[e.jsx("input",{type:"checkbox",readOnly:!0,checked:t.has(c.id)}),e.jsx("span",{className:"sa-row-name",children:c.name}),m.has(c.id)?e.jsx("span",{className:"sme-badge",children:"home"}):e.jsx("span",{className:"sme-badge borrowed",children:"borrowed"})]},c.id)),!n.length&&e.jsx("li",{className:"sme-empty",children:"nothing here"})]})]})}function xs({objects:s,onCreate:n,onClose:t}){const[i,l]=a.useState(""),[m,c]=a.useState(""),[r]=a.useState(s),[d,v]=a.useState([]),[j,b]=a.useState(new Set),[o,f]=a.useState(""),[N,_]=a.useState("ancestors"),[B,E]=a.useState(1),[S,C]=a.useState(null),[R,A]=a.useState(new Set),[w,$]=a.useState(""),[I,g]=a.useState(null);a.useEffect(()=>{ge().then(x=>{x.subject_areas[0]&&$(x.subject_areas[0].id)}).catch(()=>{})},[]);const O=a.useMemo(()=>new Set(d),[d]),u=o.trim().toLowerCase(),M=x=>!u||x.name.toLowerCase().includes(u),z=a.useMemo(()=>d.map(x=>r.find(h=>h.id===x)).filter(x=>!!x&&M(x)),[d,r,u]),W=a.useMemo(()=>r.filter(x=>!O.has(x.id)&&M(x)),[r,O,u]),H=(x,h)=>{v(k=>h?[...k,...x.filter(D=>!k.includes(D))]:k.filter(D=>!x.includes(D))),b(new Set)},G=(x,h,k)=>{const D=new Set(x);D.has(h)?D.delete(h):D.add(h),k(D)},T=()=>{const x=j.size?[...j]:d;if(!x.length){g("pick an object to expand from first");return}w&&(g(null),ve(w,{seeds:x,direction:N,levels:B}).then(h=>{const k=h.hops.filter(D=>!O.has(D.id));C(k),A(new Set(k.map(D=>D.id)))}).catch(h=>g(String(h))))},J=()=>{i.trim()&&n(i.trim(),m.trim(),d)};return e.jsx("div",{className:"sme-modal-backdrop",onClick:t,children:e.jsxs("div",{className:"sme-modal sa-modal",onClick:x=>x.stopPropagation(),children:[e.jsx("h2",{children:"New subject area"}),e.jsx("p",{className:"sme-hint",children:"A subject area is a filtered view of the model. Name it and choose what it contains — both land as one proposal."}),e.jsxs("div",{className:"sme-field-row",children:[e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Name"}),e.jsx("input",{autoFocus:!0,value:i,placeholder:"e.g. UseCase-ApraStressTesting",onChange:x=>l(x.target.value),onKeyDown:x=>x.key==="Enter"&&d.length===0&&J()})]}),e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Definition (optional)"}),e.jsx("input",{value:m,placeholder:"what this view is for",onChange:x=>c(x.target.value)})]})]}),e.jsx("input",{className:"sme-search sa-filter",type:"search",placeholder:"Filter both lists…",value:o,onChange:x=>f(x.target.value)}),e.jsxs("div",{className:"sa-panes",children:[e.jsx(ee,{title:`Available (${W.length})`,rows:W,picked:j,onToggle:x=>G(j,x,b),homedHere:[]}),e.jsxs("div",{className:"sa-controls",children:[e.jsx("button",{className:"sme-secondary",disabled:!j.size,onClick:()=>H([...j].filter(x=>!O.has(x)),!0),title:"Add the selected objects",children:"→"}),e.jsx("button",{className:"sme-secondary",disabled:!W.length,onClick:()=>H(W.map(x=>x.id),!0),title:"Add everything matching the filter",children:"»"}),e.jsx("button",{className:"sme-secondary",disabled:!j.size,onClick:()=>H([...j].filter(x=>O.has(x)),!1),title:"Remove the selected objects",children:"←"}),e.jsx("button",{className:"sme-secondary",disabled:!z.length,onClick:()=>H(z.map(x=>x.id),!1),title:"Remove everything matching the filter",children:"«"})]}),e.jsx(ee,{title:`Included (${z.length})`,rows:z,picked:j,onToggle:x=>G(j,x,b),homedHere:[]})]}),e.jsxs("div",{className:"sa-expand",children:[e.jsx("h3",{children:"Add related objects"}),e.jsxs("div",{className:"sa-expand-row",children:[e.jsxs("select",{value:N,onChange:x=>_(x.target.value),children:[e.jsx("option",{value:"ancestors",children:"ancestors — the parents its keys point at"}),e.jsx("option",{value:"descendants",children:"descendants — what points at it"}),e.jsx("option",{value:"both",children:"both"})]}),e.jsxs("label",{children:["levels",e.jsx("input",{type:"number",min:1,max:10,value:B,onChange:x=>E(Math.max(1,Math.min(10,Number(x.target.value))))})]}),e.jsx("button",{className:"sme-secondary",onClick:T,disabled:!w,title:w?"Preview related objects to add":"Available once the model has at least one saved subject area to walk the graph from",children:"Preview"})]}),S&&e.jsxs("div",{className:"sa-hops",children:[S.length===0&&e.jsx("p",{className:"sme-muted",children:"nothing new to add"}),S.map(x=>e.jsxs("label",{className:"sa-hop",children:[e.jsx("input",{type:"checkbox",checked:R.has(x.id),onChange:()=>G(R,x.id,A)}),e.jsx("span",{className:"sa-hop-name",children:x.name}),e.jsxs("span",{className:"sa-hop-why",children:["via ",x.via_name," · ",x.direction.replace(/s$/,""),", level ",x.level]})]},x.id)),S.length>0&&e.jsxs("div",{className:"sa-hop-actions",children:[e.jsx("button",{className:"sme-secondary",onClick:()=>C(null),children:"Cancel"}),e.jsxs("button",{className:"sme-primary",disabled:!R.size,onClick:()=>{H([...R],!0),C(null)},children:["Add ",R.size]})]})]})]}),I&&e.jsx("p",{className:"sme-error-line",children:I}),e.jsxs("div",{className:"sme-modal-foot",children:[e.jsx("button",{className:"sme-secondary",onClick:t,children:"Cancel"}),e.jsxs("button",{className:"sme-primary",disabled:!i.trim(),onClick:J,children:["Create",d.length>0&&` with ${d.length} object${d.length===1?"":"s"}`]})]})]})})}const bs=new Set(["set_definition","set_stewardship","set_subject_area","set_pattern","rename_entity","add_attribute","update_attribute","delete_attribute","set_alignment","clear_alignment","set_term_map","clear_term_map","update_synonyms","set_object_definition","set_subject_area_members","create_subject_area","update_subject_area","create_entity","delete_entity","create_relationship","rename_relationship","update_relationship","delete_relationship"]);function gs({doc:s,subjectArea:n,onSubjectArea:t,exec:i,canEdit:l,direct:m=!1,onSelectEntity:c,onImported:r,onImportPreview:d,openImport:v=!1,prefillImport:j="",query:b="",busy:o}){var I;const[f,N]=a.useState(null),[_,B]=a.useState(null),[E,S]=a.useState(!1),[C,R]=a.useState(null),A=a.useRef(null),w=a.useMemo(()=>({canEdit:l,mode:m?"direct":"staged",allow:m?void 0:bs,canArbitrate:m,canCommit:m}),[l,m]),$=a.useCallback(g=>{N(g),g&&(c==null||c(g))},[c]);return e.jsxs("div",{className:"sme-model-view",children:[e.jsxs("nav",{className:"sme-nav",children:[e.jsxs("div",{className:"sme-nav-head",children:[e.jsx("span",{children:"Subject areas"}),l&&e.jsx("button",{className:"sme-nav-add",title:"New subject area",onClick:()=>S(!0),children:"+"})]}),e.jsxs("button",{className:"sme-sa"+(n===""?" active":""),onClick:()=>t(""),children:["Whole model",e.jsx("span",{className:"sme-sa-count",children:((I=s.counts)==null?void 0:I.entities_total)??s.entities.length})]}),s.subject_areas.map(g=>e.jsxs("button",{className:"sme-sa"+(n===g.id?" active":""),onClick:()=>t(g.id),title:g.definition??void 0,children:[g.name,e.jsx("span",{className:"sme-sa-count",children:g.member_count??0})]},g.id))]}),E&&e.jsx(xs,{objects:s.entities.flatMap(g=>g.conceptual?[{id:g.conceptual.id,kind:"conceptual_entity",name:g.conceptual.name,definition:g.conceptual.definition??null,synonyms:[],subject_area:g.conceptual.subject_area??null,stewardship:null,ontology:null,where_used:[]}]:[]),onClose:()=>S(!1),onCreate:(g,O,u)=>{const M=Ne();i("create_subject_area",{name:g,...O?{definition:O}:{},id:M}),u.length&&i("set_subject_area_members",{id:M,members:u}),S(!1),t(M)}}),e.jsxs("div",{className:"erd-wrap",children:[e.jsxs("div",{className:"erd-bar",children:[e.jsxs("span",{className:"erd-count",children:[s.entities.length," entities · ",s.relationships.length," relationships",s.scope&&" · scoped"]}),l&&e.jsx("button",{className:"erd-action",onClick:()=>{var g;return(g=A.current)==null?void 0:g.newEntity()},title:"Add an entity (n)",children:"+ Entity"}),e.jsx("span",{className:"erd-hint",children:"drag between entities to relate them"}),e.jsxs("span",{className:"erd-group",children:[e.jsxs("button",{className:"erd-action ghost",onClick:()=>{var g;return(g=A.current)==null?void 0:g.relayout()},title:"Auto-arrange the diagram",children:[e.jsx("span",{className:"erd-ico","aria-hidden":"true",children:"⟲"}),"Re-layout"]}),e.jsxs("button",{className:"erd-action ghost",onClick:()=>{var g;return(g=A.current)==null?void 0:g.fitView()},title:"Fit the whole model in view",children:[e.jsx("span",{className:"erd-ico","aria-hidden":"true",children:"⛶"}),"Fit"]})]}),e.jsx("span",{className:"erd-sep","aria-hidden":"true"}),e.jsxs("span",{className:"erd-group",children:[e.jsx("button",{className:"erd-action ghost"+(_==="ontology"?" on":""),onClick:()=>B(g=>g==="ontology"?null:"ontology"),children:"Ontology"}),e.jsx("button",{className:"erd-action ghost"+(_==="layers"?" on":""),onClick:()=>B(g=>g==="layers"?null:"layers"),children:"Layers"})]}),e.jsx("span",{className:"erd-sep","aria-hidden":"true"}),e.jsx(Ue,{exec:i,canEdit:l,onImported:r,onPreview:d,openImport:v,prefillImport:j}),o&&e.jsx("span",{className:"erd-busy",children:"updating…"}),!l&&e.jsx("span",{className:"sme-chip",children:"read-only"}),C&&e.jsx("span",{className:"erd-error",children:C})]}),e.jsxs("div",{className:"erd-canvas canvas-wrap",children:[e.jsx(Fe,{children:e.jsx(Te,{doc:s,caps:w,exec:i,selectedId:f,onSelect:$,query:b,onError:R,handleRef:A})}),_&&e.jsxs("aside",{className:"side-panel",children:[e.jsxs("div",{className:"detail-header",children:[e.jsx("h2",{children:_==="ontology"?"Ontology":"Ontology layers"}),e.jsx("button",{className:"icon-btn",onClick:()=>B(null),children:"✕"})]}),_==="ontology"?e.jsx(Ye,{}):e.jsx(Je,{refreshKey:0,onFocusEntity:g=>{var O;B(null),(O=A.current)==null||O.focusEntity(g)}})]})]})]})]})}function vs({user:s,onView:n}){const[t,i]=a.useState(null),[l,m]=a.useState(null);if(a.useEffect(()=>{Qe(s).then(i).catch(r=>m(String(r)))},[s]),l)return e.jsx("p",{className:"sme-splash error",children:l});if(!t)return e.jsx("div",{className:"sme-splash",children:"◮ looking for your proposals…"});if(!t.git)return e.jsx("p",{className:"sme-placeholder",children:"This model isn't in a git repository."});const c=t.proposals.filter(r=>!r.merged).length;return e.jsxs("div",{className:"pr-wrap",children:[e.jsxs("div",{className:"pr-head",children:[e.jsx("h2",{children:"My proposals"}),e.jsxs("span",{className:"meta",children:[c," open · base: ",t.base]})]}),!t.proposals.length&&e.jsx("p",{className:"sme-placeholder",children:"Nothing proposed yet. Edits you submit for review will appear here."}),t.proposals.map(r=>e.jsx(ys,{p:r,gh:t.gh,onView:()=>n(r.branch)},r.branch)),!t.gh&&t.proposals.length>0&&e.jsxs("div",{className:"pr-degrade",children:["Review status isn't available here (",e.jsx("code",{children:"gh"})," is not installed or not signed in). Branch, contents, merge state and conflicts all still come from git — each card links out to the compare view."]})]})}function Ns(s,n){var t,i;return s.merged?{kind:"accepted",text:"✅ Accepted"}:s.pushed?n&&((t=s.pr)==null?void 0:t.state)==="CLOSED"?{kind:"declined",text:"✖ Declined"}:n&&((i=s.pr)==null?void 0:i.reviews)==="CHANGES_REQUESTED"?{kind:"changes",text:"💬 Changes requested"}:{kind:"awaiting",text:"⏳ Awaiting review"}:{kind:"local",text:"📥 Saved locally"}}function ys({p:s,gh:n,onView:t}){const i=Ns(s,n);return e.jsxs("div",{className:"pr-card"+(i.kind==="attention"?" attention":""),children:[e.jsxs("div",{className:"pr-top",children:[e.jsx("span",{className:"pr-title",children:s.title}),e.jsx("span",{className:"pr-chip "+i.kind,children:i.text})]}),e.jsxs("div",{className:"pr-branch",children:[s.branch," · ",s.created,s.behind>0&&` · ${s.behind} behind`]}),e.jsxs("div",{className:"pr-foot",children:[e.jsx("span",{className:"pr-link",children:s.merged?e.jsxs(e.Fragment,{children:["merged",n&&s.pr?` · PR #${s.pr.number}`:""]}):s.pushed?n&&s.pr?e.jsxs("a",{href:s.pr.url,target:"_blank",rel:"noreferrer",children:["PR #",s.pr.number]}):s.compare_url?e.jsx("a",{href:s.compare_url,target:"_blank",rel:"noreferrer",children:"open the compare view →"}):"pushed":"not sent yet — no connection to the shared repo"}),e.jsx("span",{className:"pr-btns",children:e.jsx("button",{className:"sme-secondary",onClick:t,children:"View"})})]})]})}function ws({changes:s,routeAdvice:n,identity:t,user:i,onUser:l,onDrop:m,onClose:c,onProposed:r}){const d=!!(t&&t.source!=="anonymous"),[v,j]=a.useState(i||(localStorage.getItem("mdl.sme.user")??"")),[b,o]=a.useState(s.length===1?`Update ${s[0].label.toLowerCase()}`:"Glossary updates"),[f,N]=a.useState(""),[_,B]=a.useState(!1),E=we(_?f:b),[S,C]=a.useState(""),[R,A]=a.useState(!1),[w,$]=a.useState(null),[I,g]=a.useState(null),O=()=>{!d&&!v.trim()||(d||(localStorage.setItem("mdl.sme.user",v.trim()),l==null||l(v.trim())),A(!0),g(null),Xe({user:d?"":v.trim(),slug:E,title:b,body:S.trim(),changes:s.map(u=>({op:u.op,payload:u.payload}))}).then($).catch(u=>g(u instanceof Ze?u.message:String(u))).finally(()=>A(!1)))};return w!=null&&w.ok?e.jsx("div",{className:"sme-modal-backdrop",onClick:()=>r(w),children:e.jsxs("div",{className:"sme-modal",onClick:u=>u.stopPropagation(),children:[e.jsx("h2",{children:"✓ Sent for review"}),e.jsx("p",{children:w.message}),w.pr_url&&e.jsx("p",{children:e.jsx("a",{href:w.pr_url,target:"_blank",rel:"noreferrer",children:"View pull request →"})}),w.compare_url&&e.jsx("p",{children:e.jsx("a",{href:w.compare_url,target:"_blank",rel:"noreferrer",children:"Open the pull request →"})}),e.jsxs("p",{className:"sme-muted",children:["Your suggestion is on branch ",e.jsx("code",{children:w.branch}),". A steward will review it."]}),e.jsx("div",{className:"sme-modal-foot",children:e.jsx("button",{className:"sme-primary",onClick:()=>r(w),children:"Done"})})]})}):e.jsx("div",{className:"sme-modal-backdrop",onClick:c,children:e.jsxs("div",{className:"sme-modal",onClick:u=>u.stopPropagation(),children:[e.jsxs("div",{className:"sme-card-head",children:[e.jsx("h2",{children:"Submit for review"}),e.jsx("button",{className:"sme-secondary",onClick:c,children:"✕"})]}),e.jsx("h3",{children:"Your changes"}),e.jsx("ul",{className:"sme-diff",children:s.map((u,M)=>e.jsxs("li",{children:[e.jsxs("div",{className:"sme-diff-head",children:[e.jsx("b",{children:u.label}),e.jsx("button",{className:"sme-link danger",onClick:()=>m(M),children:"discard"})]}),e.jsx("div",{className:"sme-diff-before",children:u.before}),e.jsx("div",{className:"sme-diff-after",children:u.after})]},M))}),d?e.jsxs("p",{className:"sme-signed-in",children:["Signed in as ",e.jsx("strong",{children:t.name}),t.email?` (${t.email})`:""," — this proposal is attributed to you."]}):e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Your name (for attribution)"}),e.jsx("input",{value:v,onChange:u=>j(u.target.value),placeholder:"e.g. a.hough"})]}),e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Title"}),e.jsx("input",{value:b,onChange:u=>o(u.target.value)})]}),e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Branch name (edit to add a ticket id, e.g. PROJ-123)"}),e.jsx("input",{value:_?f:E,onChange:u=>{B(!0),N(u.target.value)},placeholder:"clarify-counterparty"})]}),e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Note for the reviewer (optional)"}),e.jsx("textarea",{rows:2,value:S,onChange:u=>C(u.target.value)})]}),e.jsx(ks,{cl:n,user:d?t.name:v,changeSlug:E}),I&&e.jsx("p",{className:"sme-error-line",children:I}),e.jsxs("div",{className:"sme-modal-foot",children:[e.jsx("button",{className:"sme-secondary",onClick:c,children:"Keep editing"}),e.jsx("button",{className:"sme-primary",disabled:R||!d&&!v.trim()||s.length===0,onClick:O,children:R?"Submitting…":"Submit for review"})]})]})})}function ks({cl:s,user:n,changeSlug:t}){if(!(s!=null&&s.primary))return null;const i=s.reviewers_actual??s.reviewers,l=we(n||"you"),m=s.routes.length>1;return e.jsxs(e.Fragment,{children:[m&&e.jsxs("div",{className:"sub-advice",children:[e.jsx("span",{className:"i",children:"ⓘ"})," These changes span routes"," ",e.jsx("strong",{children:s.routes.join(" and ")}),". The whole proposal will be reviewed as route ",s.primary," (",s.primary_name,") — the strictest gate wins, so it needs"," ",i.join(", ")," plus ",e.jsx("code",{children:s.gates[s.gates.length-1]}),". Proposing the meaning-only changes separately would get them reviewed faster."]}),e.jsxs("div",{className:"sub-dest",children:[e.jsxs("div",{className:"row",children:[e.jsx("span",{className:"k",children:"Goes to"}),e.jsxs("code",{children:["sme/",l,"/",t||"…"]})]}),e.jsxs("div",{className:"row",children:[e.jsx("span",{className:"k",children:"Reviewers"}),e.jsx("span",{children:i.join(", ")})]})]})]})}function we(s){return s.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"change"}const ke=[{id:"all",label:"All"},{id:"additions",label:"Additions"},{id:"modifications",label:"Modifications"},{id:"moves",label:"Renames"},{id:"deletions",label:"Deletions"},{id:"conflicts",label:"Conflicts"}];function _e(s,n){switch(n){case"all":return!0;case"additions":return s.change==="added";case"deletions":return s.change==="removed";case"moves":return s.renamed;case"modifications":return s.change==="modified"&&!s.renamed;case"conflicts":return s.severity==="breaking"}}function _s(s,n){return n==="all"?s.objects:s.objects.filter(t=>_e(t,n))}function Ss(s){const n={};for(const{id:t}of ke)n[t]=t==="all"?s.objects.length:s.objects.filter(i=>_e(i,t)).length;return n}function Q(s,n){return`${s}\0${n}`}function Se(s){const n=s.fields.map(t=>Q(s.ulid,t.field));for(const t of s.children)for(const i of t.fields)n.push(Q(s.ulid,`${t.ulid}.${i.field}`));return n.length?n:[Q(s.ulid,"*")]}function Ce(s,n){const t=Se(s),i=t.filter(l=>n.has(l)).length;return i===0?"none":i===t.length?"all":"some"}function Ae(s,n){return Ce(s,n)!=="none"}function Cs(s,n){return s.objects.filter(t=>Ae(t,n)).map(t=>t.ulid)}function As(s,n){const t=new Set;for(const i of s.objects){if(i.object_kind!=="logical_entity"||i.change!=="added"||!Ae(i,n))continue;const l=i.name_after??i.name_before;l&&t.add(l)}return t}function $s(s,n){if(n.size===0)return[];const t=new Set,i=[],l=m=>[m.entity_id,m.from_entity,m.to_entity,m.from,m.to].filter(c=>typeof c=="string");for(const m of s){const c=m.payload;switch(m.op){case"create_entity":{const r=typeof c.name=="string"?c.name:"",d=typeof c.id=="string"?c.id:"";n.has(r)&&(t.add(d),i.push(m));break}case"add_attribute":{const r=typeof c.entity_id=="string"?c.entity_id:"";t.has(r)&&i.push(m);break}case"create_relationship":case"create_key_group":{const r=l(c);r.length>0&&r.every(d=>t.has(d))&&i.push(m);break}default:i.push(m)}}return i}function $e(s){const n=new Set;for(const t of s.objects)for(const i of Se(t))n.add(i);return n}const Es="modulepreload",Rs=function(s){return"/"+s},me={},Ms=function(n,t,i){let l=Promise.resolve();if(t&&t.length>0){document.getElementsByTagName("link");const c=document.querySelector("meta[property=csp-nonce]"),r=(c==null?void 0:c.nonce)||(c==null?void 0:c.getAttribute("nonce"));l=Promise.allSettled(t.map(d=>{if(d=Rs(d),d in me)return;me[d]=!0;const v=d.endsWith(".css"),j=v?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${d}"]${j}`))return;const b=document.createElement("link");if(b.rel=v?"stylesheet":Es,v||(b.as="script"),b.crossOrigin="",b.href=d,r&&b.setAttribute("nonce",r),document.head.appendChild(b),v)return new Promise((o,f)=>{b.addEventListener("load",o),b.addEventListener("error",()=>f(new Error(`Unable to preload CSS for ${d}`)))})}))}function m(c){const r=new Event("vite:preloadError",{cancelable:!0});if(r.payload=c,window.dispatchEvent(r),!r.defaultPrevented)throw c}return l.then(c=>{for(const r of c||[])r.status==="rejected"&&m(r.reason);return n().catch(m)})};function Ds({diff:s,selectable:n,selected:t,onToggle:i,onToggleField:l}){var f;const[m,c]=a.useState("all"),r=a.useMemo(()=>_s(s,m),[s,m]),d=a.useMemo(()=>Ss(s),[s]),[v,j]=a.useState(((f=s.objects[0])==null?void 0:f.ulid)??null),b=a.useMemo(()=>r.find(N=>N.ulid===v)??r[0]??s.objects[0]??null,[r,s,v]),o=!!l;return s.objects.length?e.jsxs("div",{className:"rv-wrap",children:[n!==void 0&&e.jsx("div",{className:"rv-filters",role:"tablist","aria-label":"Filter changes",children:ke.filter(N=>N.id==="all"||d[N.id]>0).map(N=>e.jsxs("button",{role:"tab","aria-selected":m===N.id,className:"rv-filter"+(m===N.id?" active":""),onClick:()=>c(N.id),children:[N.label,e.jsx("span",{className:"rv-filter-count",children:d[N.id]})]},N.id))}),e.jsxs("div",{className:"rv-body",children:[e.jsx("div",{className:"rv-list",children:r.length===0?e.jsx("p",{className:"sme-placeholder",children:"No changes match this filter."}):r.map(N=>e.jsx(Is,{obj:N,active:N.ulid===((b==null?void 0:b.ulid)??""),selectable:n,perField:o,objState:o?Ce(N,t??new Set):void 0,checkedObject:(t==null?void 0:t.has(N.ulid))??!0,onSelect:()=>j(N.ulid),onToggleObject:()=>i==null?void 0:i(N.ulid),onToggleField:l},N.ulid))}),e.jsx("div",{className:"rv-detail",children:b&&e.jsx(Os,{obj:b,selectable:n,perField:o,selected:t,onToggleField:l})})]})]}):e.jsxs("p",{className:"sme-placeholder",children:["No model changes against ",s.base.label,"."]})}function Ps(s){return s.renamed?"renamed":s.severity==="breaking"?"breaking":s.change}function Is({obj:s,active:n,selectable:t,perField:i,objState:l,checkedObject:m,onSelect:c,onToggleObject:r,onToggleField:d}){const v=o=>{o&&i&&(o.indeterminate=l==="some")},j=i?l!=="none":m,b=()=>{if(!i)return r();for(const o of s.fields)d==null||d(s.ulid,o.field);for(const o of s.children)for(const f of o.fields)d==null||d(s.ulid,`${o.ulid}.${f.field}`);!s.fields.length&&!s.children.length&&(d==null||d(s.ulid,"*"))};return e.jsxs("div",{className:"rv-obj"+(n?" active":""),onClick:c,children:[e.jsxs("div",{className:"rv-obj-head",children:[t&&e.jsx("input",{type:"checkbox",ref:v,checked:j,onClick:o=>o.stopPropagation(),onChange:b,"aria-label":`include ${s.name_before??s.name_after}`}),e.jsx("span",{className:"rv-obj-name",children:s.name_before??s.name_after}),e.jsx("span",{className:"rv-obj-kind",children:s.object_kind_label}),e.jsxs("span",{className:"sev "+(s.renamed?"renamed":s.severity),children:[s.severity==="breaking"&&"⚠ ",Ps(s)]})]}),e.jsxs("ul",{className:"rv-obj-fields",children:[s.fields.map((o,f)=>e.jsx("li",{children:o.label},o.field+f)),s.children.flatMap(o=>o.fields.map((f,N)=>e.jsxs("li",{children:[f.label,": ",o.name_before??o.name_after]},o.ulid+N)))]})]})}function Os({obj:s,selectable:n,perField:t,selected:i,onToggleField:l}){const m=s.children.flatMap(r=>r.fields.map(d=>({field:d,on:r.name_before??r.name_after??"",key:`${r.ulid}.${d.field}`}))),c=(r,d)=>{if(!n||!t)return d;const v=Q(s.ulid,r);return e.jsxs("div",{className:"rv-field-pick",children:[e.jsx("input",{type:"checkbox",checked:(i==null?void 0:i.has(v))??!0,onChange:()=>l==null?void 0:l(s.ulid,r),"aria-label":`include change: ${r}`}),e.jsx("div",{className:"rv-field-body",children:d})]})};return e.jsxs(e.Fragment,{children:[e.jsx("h2",{children:s.renamed?`${s.name_before} → ${s.name_after}`:s.name_before??s.name_after}),e.jsxs("div",{className:"rv-detail-kind",children:[s.object_kind_label,s.renamed&&" · renamed",s.path&&e.jsxs("span",{className:"rv-src",children:[" · ",s.path]})]}),s.fields.map((r,d)=>e.jsx("div",{children:c(r.field,e.jsx(ue,{f:r}))},r.field+d)),m.map(({field:r,on:d,key:v},j)=>e.jsx("div",{children:c(v,e.jsx(ue,{f:r,on:d}))},"c"+j)),s.severity==="breaking"&&e.jsxs("div",{className:"rv-note",children:[e.jsx("span",{className:"i",children:"ⓘ"}),e.jsxs("span",{children:["This is a structural change (route B). It will need an architect's review, and CI will run ",e.jsx("code",{children:"mdl drift --check"}),"."]})]})]})}function ue({f:s,on:n}){var i,l,m;const t=n?`${s.label}: ${n}`:s.label;if((i=s.breaks)!=null&&i.length)return e.jsxs("div",{className:"rv-section",children:[e.jsx("h3",{children:t}),e.jsxs("div",{className:"rv-break",children:[e.jsxs("div",{className:"rv-break-head",children:[e.jsx("span",{children:"⚠"}),e.jsxs("span",{children:[n??String(s.before??"")," removed"]}),s.detail&&e.jsx("span",{className:"rv-break-meta",children:s.detail})]}),e.jsxs("div",{className:"rv-break-body",children:["This is realised by ",s.breaks.length," dbt model",s.breaks.length>1?"s":"",". Removing it will break ",s.breaks.length>1?"them":"it","."]}),e.jsx("ul",{className:"rv-usage",children:s.breaks.map(c=>e.jsxs("li",{children:[e.jsxs("span",{className:"m",children:["→ ",c.name]}),e.jsxs("span",{className:"p",children:[c.target," · ",c.materialization]})]},c.name))})]})]});if(s.kind==="definition_changed"){const c=String(s.before??""),r=String(s.after??"");return e.jsxs("div",{className:"rv-section",children:[e.jsx("h3",{children:t}),e.jsxs("div",{className:"rv-ba",children:[e.jsxs("div",{className:"rv-ba-col",children:[e.jsx("div",{className:"rv-ba-label",children:"before"}),e.jsx("div",{className:"rv-ba-text",children:je(c,r,"del")})]}),e.jsxs("div",{className:"rv-ba-col",children:[e.jsx("div",{className:"rv-ba-label",children:"after"}),e.jsx("div",{className:"rv-ba-text",children:je(r,c,"ins")})]})]})]})}if(Array.isArray(s.before)||Array.isArray(s.after)){const c=new Set(((l=s.before)==null?void 0:l.map(String))??[]),r=new Set(((m=s.after)==null?void 0:m.map(String))??[]),d=[...r].filter(j=>!c.has(j)),v=[...c].filter(j=>!r.has(j));return e.jsxs("div",{className:"rv-section",children:[e.jsx("h3",{children:t}),e.jsxs("div",{className:"rv-chips",children:[d.map(j=>e.jsxs("span",{className:"rv-chip-add",children:["+ ",j]},"a"+j)),v.map(j=>e.jsxs("span",{className:"rv-chip-del",children:["− ",j]},"r"+j))]})]})}return e.jsxs("div",{className:"rv-section",children:[e.jsx("h3",{children:t}),e.jsxs("div",{className:"rv-scalar",children:[e.jsx("span",{className:"from",children:pe(s.before)}),e.jsx("span",{className:"arrow",children:"→"}),e.jsx("span",{className:"to",children:pe(s.after)})]})]})}function pe(s){return s==null||s===""?"—":typeof s=="boolean"?s?"yes":"no":typeof s=="object"?JSON.stringify(s):String(s)}function je(s,n,t){const i=s.split(/(\s+)/),l=n.split(/(\s+)/),m=o=>o.toLowerCase().replace(/[.,;:]/g,""),c=i.length,r=l.length,d=Array.from({length:c+1},()=>new Array(r+1).fill(0));for(let o=c-1;o>=0;o--)for(let f=r-1;f>=0;f--)d[o][f]=m(i[o])===m(l[f])?d[o+1][f+1]+1:Math.max(d[o+1][f],d[o][f+1]);const v=new Set;let j=0,b=0;for(;j=d[j][b+1]?j++:b++;return i.map((o,f)=>!o.trim()||v.has(f)?e.jsx("span",{children:o},f):t==="del"?e.jsx("del",{children:o},f):e.jsx("ins",{children:o},f))}const Bs=a.lazy(()=>Ms(()=>import("./ModelDiagram-CRUBpPVn.js"),__vite__mapDeps([0,1,2,3])).then(s=>({default:s.ModelDiagram})));function Ls({stagedDiff:s,stagedRoute:n,user:t,onBack:i,onSubmit:l,excluded:m,onToggleField:c,selectable:r,action:d}){const[v,j]=a.useState(null),[b,o]=a.useState(null),[f,N]=a.useState(null),[_,B]=a.useState(null),[E,S]=a.useState(null),[C,R]=a.useState("changes"),A=a.useCallback(()=>{be(t).then($=>{B($);const I=$.base_branch??"main";s?j(s):es("HEAD").then(g=>g.ok?j(g):S(g.error??"could not read the model")).catch(g=>S(String(g))),n?o(n):ss("HEAD").then(o).catch(()=>{}),ns(I).then(N).catch(()=>{})}).catch($=>S(String($)))},[t,s,n]);if(a.useEffect(A,[A]),E)return e.jsxs("div",{className:"rv-shell",children:[e.jsx(fe,{onBack:i,diff:null}),e.jsx("p",{className:"sme-splash error",children:e.jsx("pre",{children:E})})]});if(!v)return e.jsx("div",{className:"sme-splash",children:"◮ reading your changes…"});const w=new Set([...$e(v)].filter($=>!m.has($)));return e.jsxs("div",{className:"rv-shell",children:[e.jsx(fe,{onBack:i,diff:v,tab:C,onTab:R}),C==="changes"?e.jsx(Ds,{diff:v,selectable:r,selected:w,onToggleField:c}):e.jsx(a.Suspense,{fallback:e.jsx("div",{className:"sme-splash",children:"◮ drawing the model…"}),children:e.jsx(Bs,{severityByUlid:zs(v)})}),e.jsxs("div",{className:"rv-foot",children:[e.jsx(Hs,{cl:b}),e.jsx(Ws,{conf:f,ctx:_}),e.jsxs("div",{className:"rv-actions",children:[e.jsx("button",{className:"sme-secondary",onClick:i,children:d?"Cancel":"Keep editing"}),d?e.jsx("button",{className:"sme-primary",disabled:!v.objects.length||!!d.disabledReason,title:d.disabledReason??"",onClick:()=>d.apply(Cs(v,w)),children:d.label}):e.jsx("button",{className:"sme-primary",disabled:!v.objects.length||(_?!_.can_propose:!1),title:_&&!_.can_propose?"the working tree has uncommitted changes":"",onClick:()=>l(b),children:"Submit for review →"})]})]})]})}function zs(s){const n=new Map;for(const t of s.objects)n.set(t.ulid,t.severity);return n}function fe({onBack:s,diff:n,tab:t,onTab:i}){const l=n==null?void 0:n.counts;return e.jsxs("div",{className:"rv-head",children:[e.jsxs("div",{children:[e.jsx("button",{className:"rv-back",onClick:s,children:"‹ Back to terms"}),e.jsx("h1",{className:"rv-title",children:"Review your changes"}),l&&e.jsxs("div",{className:"rv-sub",children:[l.objects," object",l.objects===1?"":"s"," ·"," ",(l.breaking??0)+(l.additive??0)+(l.cosmetic??0)," changes",(n==null?void 0:n.has_breaking)&&e.jsxs("span",{className:"warn",children:[" · ⚠ ",l.breaking," breaking"]})," · comparing to ",e.jsx("code",{children:n==null?void 0:n.base.label})]})]}),i&&e.jsxs("div",{className:"rv-tabs",children:[e.jsxs("button",{className:"rv-tab"+(t==="changes"?" active":""),onClick:()=>i("changes"),children:["Changes ",(n==null?void 0:n.objects.length)??0]}),e.jsx("button",{className:"rv-tab"+(t==="diagram"?" active":""),onClick:()=>i("diagram"),children:"Diagram"})]})]})}function Hs({cl:s}){if(!(s!=null&&s.primary))return null;const n=s.reviewers_actual??s.reviewers;return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"rv-route",children:[e.jsxs("span",{className:"rv-route-badge",children:["Route ",s.primary," · ",s.primary_name]}),e.jsx("span",{className:"k",children:"Reviewers"}),e.jsx("span",{children:n.join(", ")}),s.reviewers_actual&&e.jsx("span",{className:"rv-src",children:"from .github/CODEOWNERS"})]}),e.jsxs("div",{className:"rv-gates",children:["CI gates"," ",s.gates.map(t=>e.jsx("code",{children:t},t))]})]})}function Ws({conf:s,ctx:n}){return s!=null&&s.ok?s.clean?e.jsxs("div",{className:"rv-conflict ok",children:[e.jsx("span",{children:"✓"}),e.jsxs("span",{children:["Merges cleanly onto ",s.base]}),s.behind>0&&e.jsxs("span",{className:"detail",children:["· ",s.base," is ",s.behind," commit",s.behind===1?"":"s"," ahead"]}),(n==null?void 0:n.dirty)&&e.jsx("span",{className:"detail",children:"· uncommitted changes in the working tree"})]}):e.jsxs("div",{className:"rv-conflict bad",children:[e.jsx("span",{children:"⚠"}),e.jsxs("span",{children:[s.base," has changed and ",s.files.length," file",s.files.length===1?"":"s"," now conflict"]}),e.jsx("span",{className:"detail",children:s.files.map(t=>t.path).join(", ")})]}):null}function qs({term:s,canEdit:n,pendingCount:t,onEdit:i}){var l,m;return e.jsxs("div",{className:"sme-card",children:[e.jsxs("div",{className:"sme-card-head",children:[e.jsxs("div",{children:[e.jsx("h1",{children:s.name}),((l=s.subject_area)==null?void 0:l.name)&&e.jsx("span",{className:"sme-chip",children:s.subject_area.name}),s.kind==="term"&&e.jsx("span",{className:"sme-chip",children:"glossary term"})]}),n&&e.jsx("button",{className:"sme-primary",onClick:i,children:t>0?"Continue editing":"Suggest an edit"})]}),e.jsx("p",{className:"sme-definition",children:s.definition??e.jsx("em",{children:"No definition yet."})}),s.synonyms.length>0&&e.jsxs("section",{children:[e.jsx("h3",{children:"Also called"}),e.jsx("div",{children:s.synonyms.map(c=>e.jsx("span",{className:"sme-chip",children:c},c))})]}),s.stewardship&&(s.stewardship.owner||s.stewardship.steward)&&e.jsxs("section",{children:[e.jsx("h3",{children:"Who owns this"}),s.stewardship.owner&&e.jsxs("div",{className:"sme-kv",children:[e.jsx("span",{className:"k",children:"owner"}),e.jsx("span",{children:s.stewardship.owner})]}),s.stewardship.steward&&e.jsxs("div",{className:"sme-kv",children:[e.jsx("span",{className:"k",children:"steward"}),e.jsx("span",{children:s.stewardship.steward})]})]}),((m=s.ontology)==null?void 0:m.aligns_to)&&e.jsxs("section",{children:[e.jsx("h3",{children:"Standard it maps to"}),e.jsxs("div",{className:"sme-kv",children:[e.jsx("span",{className:"k",children:"aligned to"}),e.jsx("code",{children:s.ontology.aligns_to}),s.ontology.status==="proposed"&&e.jsx("span",{className:"sme-badge proposed",children:"awaiting architect"})]})]}),e.jsxs("section",{children:[e.jsx("h3",{children:"Where it's used"}),s.where_used.length===0?e.jsx("p",{className:"sme-muted",children:s.kind==="term"?"A glossary term — not yet realised by a data model.":"Not yet realised by any data model."}):e.jsx("ul",{className:"sme-usage",children:s.where_used.map(c=>e.jsxs("li",{children:[e.jsx("span",{className:"sme-usage-model",children:c.logical_entity}),c.unmanaged&&e.jsx("span",{className:"sme-badge",children:"engineer-owned"}),c.physical.length>0&&e.jsx("span",{className:"sme-usage-phys",children:c.physical.map(r=>r.name).join(", ")})]},c.logical_id))})]})]})}function Gs({term:s,pending:n,onStage:t,onDone:i,catalogOwned:l=[],catalog:m=null}){var $,I,g,O;const c=u=>l.includes(u),r=u=>n.find(M=>M.label===u),d=(u,M)=>{const z=r(u);return z?z.after:M},[v,j]=a.useState(d("Definition",s.definition??"")),[b,o]=a.useState(s.synonyms),[f,N]=a.useState(""),[_,B]=a.useState((($=s.stewardship)==null?void 0:$.owner)??""),[E,S]=a.useState(((I=s.stewardship)==null?void 0:I.steward)??""),C=()=>{v.trim()!==(s.definition??"").trim()&&t({op:"set_definition",payload:{id:s.id,definition:v.trim()},label:"Definition",before:s.definition??"(none)",after:v.trim()||"(none)"})},R=(u,M)=>{var z,W;t({op:"set_stewardship",payload:{id:s.id,owner:u||null,steward:M||null},label:"Stewardship",before:`owner: ${((z=s.stewardship)==null?void 0:z.owner)??"—"} · steward: ${((W=s.stewardship)==null?void 0:W.steward)??"—"}`,after:`owner: ${u||"—"} · steward: ${M||"—"}`})},A=u=>{o(u),t({op:"update_synonyms",payload:{id:s.id,synonyms:u},label:"Also called",before:s.synonyms.join(", ")||"(none)",after:u.join(", ")||"(none)"})},w=s.kind==="term";return e.jsxs("div",{className:"sme-editor",children:[e.jsxs("div",{className:"sme-card-head",children:[e.jsxs("h1",{children:["Suggest an edit — ",s.name]}),e.jsx("button",{className:"sme-secondary",onClick:i,children:"Back"})]}),e.jsxs("p",{className:"sme-hint",children:["You can refine what this term ",e.jsx("em",{children:"means"}),". Structure (keys, relationships, how it's built) stays with the data team."]}),(c("definition")||c("synonyms")||c("stewardship"))&&m&&e.jsxs("div",{className:"sme-catalog-banner",children:["Definitions, synonyms, and ownership are mastered in ",e.jsx("b",{children:m.name}),". Edit them there — this glossary mirrors them read-only.",m.url&&e.jsxs(e.Fragment,{children:[" ",e.jsxs("a",{href:m.url,target:"_blank",rel:"noreferrer",children:["Open in ",m.name," →"]})]}),e.jsx("div",{className:"sme-catalog-note",children:"You can still propose a standard mapping below."})]}),e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Definition"}),c("definition")?e.jsx("p",{className:"sme-readonly-value",children:s.definition??"—"}):e.jsx("textarea",{rows:4,value:v,onChange:u=>j(u.target.value),onBlur:C,placeholder:"A plain-language business definition…"})]}),e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Also called (synonyms)"}),c("synonyms")?e.jsx("div",{className:"sme-syn-row",children:s.synonyms.length?s.synonyms.map(u=>e.jsx("span",{className:"sme-chip",children:u},u)):e.jsx("span",{className:"sme-muted",children:"none"})}):e.jsxs("div",{className:"sme-syn-row",children:[b.map(u=>e.jsxs("span",{className:"sme-chip removable",onClick:()=>A(b.filter(M=>M!==u)),children:[u," ✕"]},u)),e.jsx("input",{value:f,placeholder:"add + Enter",onChange:u=>N(u.target.value),onKeyDown:u=>{u.key==="Enter"&&f.trim()&&(A([...b,f.trim()]),N(""))}})]})]}),!w&&(c("stewardship")?e.jsxs("div",{className:"sme-field-row",children:[e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Owner"}),e.jsx("p",{className:"sme-readonly-value",children:((g=s.stewardship)==null?void 0:g.owner)??"—"})]}),e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Steward"}),e.jsx("p",{className:"sme-readonly-value",children:((O=s.stewardship)==null?void 0:O.steward)??"—"})]})]}):e.jsxs("div",{className:"sme-field-row",children:[e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Owner"}),e.jsx("input",{value:_,onChange:u=>B(u.target.value),onBlur:()=>R(_,E)})]}),e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Steward"}),e.jsx("input",{value:E,onChange:u=>S(u.target.value),onBlur:()=>R(_,E)})]})]})),e.jsx(Vs,{term:s,onStage:t}),e.jsx("p",{className:"sme-note",children:n.length>0?`${n.length} change(s) staged — use “Submit for review” at the top when you're done.`:"Changes you make are collected until you submit them for review."})]})}const Ks=["skos:exactMatch","skos:closeMatch","skos:broadMatch","skos:narrowMatch"];function Vs({term:s,onStage:n}){var b;const[t,i]=a.useState(!1),[l,m]=a.useState(s.name),[c,r]=a.useState([]),[d,v]=a.useState("skos:closeMatch"),j=o=>{m(o),ts(o).then(f=>r(f.results)).catch(()=>r([]))};return t?e.jsxs("div",{className:"sme-field sme-align",children:[e.jsx("span",{children:"Propose a standard mapping (a suggestion; the architect confirms)"}),e.jsx("input",{value:l,onChange:o=>j(o.target.value),placeholder:"Search standards…",autoFocus:!0}),e.jsx("div",{className:"sme-align-results",children:c.map(o=>e.jsxs("button",{className:"sme-align-card",onClick:()=>{var f;n({op:"set_alignment",payload:{id:s.id,aligns_to:o.prefixed,alignment:d,status:"proposed"},label:"Standard mapping",before:((f=s.ontology)==null?void 0:f.aligns_to)??"(none)",after:`${o.prefixed} (${d}, proposed)`}),i(!1)},children:[e.jsx("strong",{children:o.label})," ",e.jsx("code",{children:o.prefixed}),o.definition&&e.jsx("span",{className:"sme-align-def",children:o.definition})]},o.iri))}),e.jsx("select",{value:d,onChange:o=>v(o.target.value),children:Ks.map(o=>e.jsx("option",{children:o},o))})]}):e.jsxs("div",{className:"sme-field",children:[e.jsx("span",{children:"Standard mapping"}),e.jsxs("div",{children:[(b=s.ontology)!=null&&b.aligns_to?e.jsx("code",{className:"sme-current-align",children:s.ontology.aligns_to}):e.jsx("span",{className:"sme-muted",children:"not mapped to a standard"}),e.jsx("button",{className:"sme-link",onClick:()=>i(!0),children:"Propose a mapping…"})]})]})}function Us(){const[s,n]=a.useState(null),[t,i]=a.useState(!0),[l,m]=a.useState(null),[c,r]=a.useState(""),[d,v]=a.useState(null),[j,b]=a.useState(""),[o,f]=a.useState(""),[N,_]=a.useState(null),[B,E]=a.useState(!1),[S,C]=a.useState([]),[R,A]=a.useState(!1),w=a.useMemo(()=>new URLSearchParams(window.location.search).get("import"),[]),$=!!w,I=w&&w!=="1"?w:null,[g,O]=a.useState("");a.useEffect(()=>{I&&as(I).then(p=>p.ok&&p.content&&O(p.content)).catch(()=>{})},[I]);const[u,M]=a.useState($?"model":window.location.hash==="#proposals"?"proposals":"browse"),[z,W]=a.useState(new Set),[H,G]=a.useState(null),[T,J]=a.useState(()=>localStorage.getItem("mdl.sme.user")??""),[x,h]=a.useState(null),[k,D]=a.useState(null),[q,Ee]=a.useState(!1),[Re,Me]=a.useState(null),De=a.useCallback((p,y)=>{var Y;const L=Z=>{var ce;const F=k==null?void 0:k.entities.find(oe=>{var de;return oe.id===Z||((de=oe.conceptual)==null?void 0:de.id)===Z});return((ce=F==null?void 0:F.conceptual)==null?void 0:ce.name)??(F==null?void 0:F.name)??"object"},P=L(y.id??y.entity_id);switch(p){case"create_entity":return{label:`New entity: ${y.name}`,before:"—",after:String(y.name??"")};case"create_relationship":return{label:`New relationship: ${L(y.from_entity)} → ${L(y.to_entity)}`,before:"—",after:String(y.cardinality??"many_to_one")};case"delete_entity":return{label:`Deleted ${P}`,before:P,after:"—"};case"delete_relationship":return{label:"Relationship removed",before:"",after:"—"};case"update_relationship":return{label:"Relationship changed",before:"",after:[y.cardinality,y.optionality,y.identifying?"identifying":""].filter(Boolean).join(", ")};case"set_definition":return{label:`Definition: ${P}`,before:"",after:String(y.definition??"")};case"add_attribute":return{label:`Attribute added to ${P}`,before:"—",after:String(y.name??"")};case"delete_attribute":return{label:`Attribute removed from ${P}`,before:"",after:"—"};case"update_attribute":return{label:`Attribute changed on ${P}`,before:"",after:JSON.stringify(y)};case"rename_entity":return{label:`Renamed ${P}`,before:P,after:String(y.name??"")};case"set_subject_area":return{label:`Subject area: ${P}`,before:"",after:String(y.subject_area??"none")};case"set_stewardship":return{label:`Stewardship: ${P}`,before:"",after:String(y.steward??"")};case"set_subject_area_members":{const Z=y.__label,F=((Y=y.members)==null?void 0:Y.length)??0;return{label:Z??"Subject area members",before:"",after:`${F} object${F===1?"":"s"}`}}case"set_alignment":return{label:`Alignment: ${P}`,before:"",after:String(y.aligns_to??"")};default:return{label:`${p.replace(/_/g," ")}: ${P}`,before:"",after:""}}},[k]),V=us({subjectArea:j,describe:De}),Pe=a.useCallback(async(p,y)=>{const L=(k==null?void 0:k.fingerprint)??"",P=await rs(p,y,L);return await ie(j||void 0).then(D),P},[k,j]),Ie=a.useMemo(()=>{const p={};for(const y of V.pending)y.op==="set_subject_area_members"&&(p[y.payload.id]=y.payload.members??[]);return p},[V.pending]),U=a.useMemo(()=>[...S,...V.pending],[S,V.pending]),[Oe,se]=a.useState(null),[Be,ne]=a.useState(null);a.useEffect(()=>{if(!U.length){se(null),ne(null);return}const p=new AbortController,y=U.map(L=>({op:L.op,payload:L.payload}));return xe(y,j||void 0,p.signal).then(L=>se(L.diff??null)).catch(L=>{L.name!=="AbortError"&&se(null)}),is(y).then(ne).catch(()=>ne(null)),()=>p.abort()},[U,j]);const Le=a.useMemo(()=>ps(U),[U]).size{M(p),window.location.hash=p==="browse"?"":`#${p}`},[]),te=a.useRef(!0);a.useEffect(()=>{const p=()=>{const y=window.location.hash;if(te.current&&!y&&$){te.current=!1;return}te.current=!1,M(y==="#proposals"?"proposals":y==="#review"?"review":y==="#model"?"model":y==="#areas"?"areas":"browse")};return p(),window.addEventListener("hashchange",p),()=>window.removeEventListener("hashchange",p)},[]);const ae=a.useCallback(()=>{ls({subject_area:j,q:o}).then(n).catch(p=>v(String(p)))},[j,o]);a.useEffect(ae,[ae]),a.useEffect(()=>{ie(j||void 0).then(p=>{i(p.read_only),r(p.project.name),D(p),Ee(!!p.direct),h(p.identity??null),p.identity&&p.identity.source!=="anonymous"&&p.identity.name&&J(p.identity.name)}).catch(()=>{}),cs().then(m).catch(()=>{})},[j]);const re=a.useMemo(()=>(s==null?void 0:s.terms.find(p=>p.id===N))??null,[s,N]),ze=a.useCallback(p=>{const y=p.key??ye(p.op,p.payload);C(L=>[...L.filter(P=>P.key!==y),{...p,key:y}])},[]),He=p=>C(y=>y.filter((L,P)=>P!==p)),We=()=>{C([]),A(!1),E(!1),ae()};if(d)return e.jsxs("div",{className:"sme-splash error",children:[e.jsx("h1",{children:"◮ Glossary"}),e.jsx("pre",{children:d}),e.jsxs("p",{children:["Is ",e.jsx("code",{children:"mdl glossary"})," pointed at a model?"]})]});if(!s)return e.jsx("div",{className:"sme-splash",children:"◮ loading glossary…"});const X=!t,le=(l==null?void 0:l.catalog_owned_fields)??[],qe=le.length>0;return e.jsxs("div",{className:"sme",children:[e.jsxs("header",{className:"sme-top",children:[e.jsxs("div",{className:"sme-brand",children:[e.jsx("span",{className:"sme-logo",children:"◮"}),e.jsx("span",{children:"Glossary"}),e.jsx("span",{className:"sme-project",children:c}),t&&e.jsx("span",{className:"sme-chip",children:"read-only"}),qe&&e.jsxs("span",{className:"sme-chip catalog",title:`Definitions are mastered in ${l==null?void 0:l.catalog_name}`,children:["mirrors ",l==null?void 0:l.catalog_name]})]}),e.jsx("input",{className:"sme-search",type:"search",placeholder:"Search terms & definitions…",value:o,onChange:p=>f(p.target.value)}),e.jsxs("nav",{className:"sme-tabs",children:[e.jsx("button",{className:"sme-tab"+(u==="browse"?" active":""),onClick:()=>K("browse"),children:"Terms"}),e.jsx("button",{className:"sme-tab"+(u==="model"?" active":""),onClick:()=>K("model"),children:"Model"}),e.jsx("button",{className:"sme-tab"+(u==="areas"?" active":""),onClick:()=>K("areas"),children:"Subject areas"}),e.jsx("button",{className:"sme-tab"+(u==="proposals"?" active":""),onClick:()=>K("proposals"),children:"My proposals"})]}),U.length>0&&e.jsxs("button",{className:"sme-tray",onClick:()=>K("review"),children:[U.length," change",U.length>1?"s":""," · Review →"]})]}),u==="browse"&&e.jsx(js,{user:T}),u==="review"?e.jsx(Ls,{stagedDiff:H??Oe,stagedRoute:H?null:Be,user:T,selectable:Le,excluded:z,onToggleField:(p,y)=>W(L=>{const P=new Set(L),Y=Q(p,y);return P.has(Y)?P.delete(Y):P.add(Y),P}),onBack:()=>{G(null),W(new Set),K("browse")},onSubmit:p=>{Me(p),A(!0)},action:H?{id:"apply-import",label:"Apply import →",primary:!0,apply:async()=>{const p=H,y=new Set([...$e(p)].filter(Y=>!z.has(Y))),L=As(p,y),P=$s(H.changes,L);await os(P,!0),G(null),W(new Set),K("browse"),await ie(j||void 0).then(D)}}:void 0}):u==="model"?V.previewDoc??k?e.jsx(gs,{doc:V.previewDoc??k,subjectArea:j,onSubjectArea:b,exec:q?Pe:V.exec,canEdit:X,direct:q,onImported:()=>K("review"),onImportPreview:p=>{W(new Set),G(p),K("review")},openImport:$,prefillImport:g,query:o,busy:V.busy}):e.jsx("div",{className:"sme-splash",children:"◮ loading the model…"}):u==="areas"?e.jsx(fs,{exec:V.exec,canEdit:X,stagedMembers:Ie}):u==="proposals"?e.jsx(vs,{user:T,onView:()=>K("review")}):e.jsxs("div",{className:"sme-body",children:[e.jsxs("nav",{className:"sme-nav",children:[e.jsx("button",{className:"sme-sa"+(j===""?" active":""),onClick:()=>b(""),children:"All subject areas"}),s.subject_areas.map(p=>e.jsx("button",{className:"sme-sa"+(j===p.id?" active":""),onClick:()=>b(p.id),title:p.definition??void 0,children:p.name},p.id))]}),e.jsxs("ul",{className:"sme-list",children:[s.terms.map(p=>{var y;return e.jsxs("li",{className:"sme-list-item"+(p.id===N?" active":""),onClick:()=>{_(p.id),E(!1)},children:[e.jsx("span",{className:"sme-term-name",children:p.name}),p.kind==="term"&&e.jsx("span",{className:"sme-kind",children:"term"}),((y=p.ontology)==null?void 0:y.status)==="proposed"&&e.jsx("span",{className:"sme-badge proposed",title:"alignment awaiting architect",children:"proposed"}),e.jsx("span",{className:"sme-term-def",children:p.definition??"no definition yet"})]},p.id)}),s.terms.length===0&&e.jsx("li",{className:"sme-empty",children:"no terms match"})]}),e.jsx("section",{className:"sme-detail",children:re?B&&X?e.jsx(Gs,{term:re,pending:S,onStage:ze,onDone:()=>E(!1),catalogOwned:le,catalog:l?{name:l.catalog_name,url:l.catalog_url}:null}):e.jsx(qs,{term:re,canEdit:X,pendingCount:S.length,onEdit:()=>E(!0)}):e.jsx("div",{className:"sme-placeholder",children:"Select a term to see its definition."})})]}),R&&e.jsx(ws,{changes:U,routeAdvice:Re,identity:x,user:T,onUser:p=>{J(p),localStorage.setItem("mdl.sme.user",p)},onDrop:He,onClose:()=>A(!1),onProposed:()=>{We(),V.clear(),W(new Set),K("proposals")}})]})}Ge.createRoot(document.getElementById("root")).render(e.jsx(Ke.StrictMode,{children:e.jsx(Us,{})})); diff --git a/packages/server/src/mdl_server/static/assets/sme-rGO675Bx.js b/packages/server/src/mdl_server/static/assets/sme-rGO675Bx.js deleted file mode 100644 index c7137e3..0000000 --- a/packages/server/src/mdl_server/static/assets/sme-rGO675Bx.js +++ /dev/null @@ -1,2 +0,0 @@ -const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/ModelDiagram-oAb1enKe.js","assets/client-DOmNpTln.js","assets/styles-BtrhR1xb.js","assets/styles-DxhL4SV-.css"])))=>i.map(i=>d[i]); -import{r as n,j as e,c as Ae,R as Ee}from"./client-DOmNpTln.js";import{p as pe,c as je,d as xe,e as $e,h as be,I as Re,R as Me,M as De,O as Pe,L as Ie,i as Oe,j as Te,A as Be,k as Le,l as Fe,m as ze,o as qe,s as We,f as le,n as Ge,q as He,r as Ve}from"./styles-BtrhR1xb.js";/* empty css */const Ke="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function ce(s,t){let a="";for(let l=0;l>=5n;return a}function ge(){const s=BigInt(Date.now())&(1n<<48n)-1n,t=new Uint8Array(10);crypto.getRandomValues(t);let a=0n;for(const l of t)a=a<<8n|BigInt(l);return ce(s,10)+ce(a,16)}const Ue={create_entity:["id","conceptual_id"],create_relationship:["id","from_fk_id"],create_subject_area:["id"],create_term:["id"],create_domain:["id"],create_code_set:["id"],create_key_group:["id"],create_category:["id"],add_attribute:["id"]};function Ye(s,t){const a=Ue[s];if(!a)return t;const l={...t};for(const i of a)l[i]||(l[i]=ge());return l}function fe(s,t){if(s.startsWith("create_")||s==="add_attribute")return`${s}:${t.id??t.attribute_id}`;const a=t.id??t.entity_id??"",l=t.attribute_id??"";return l?`${s}:${a}:${l}`:`${s}:${a}`}function Je({subjectArea:s,describe:t}){const[a,l]=n.useState([]),[i,x]=n.useState(null),[c,r]=n.useState(!1),m=n.useRef(null),N=n.useCallback(async(h,g)=>{g=Ye(h,g),h==="set_alignment"&&g.status===void 0&&(g={...g,status:"proposed"});const _=fe(h,g),{label:C,before:T,after:S}=t(h,g);return l(y=>{const A=y.filter(k=>k.key!==_);if(h.startsWith("delete_")){const k=g.id??g.entity_id;if(k&&y.some(o=>o.op.startsWith("create_")&&o.payload.id===k))return A.filter(o=>o.payload.id!==k)}return[...A,{op:h,payload:g,label:C,before:T,after:S,key:_}]}),{ok:!0,fingerprint:"",created_id:g.id??null,diagnostics:[]}},[t]);n.useEffect(()=>{if(!a.length){x(null);return}const h=setTimeout(()=>{var _;(_=m.current)==null||_.abort();const g=new AbortController;m.current=g,r(!0),pe(a.map(C=>({op:C.op,payload:C.payload})),s,g.signal).then(x).catch(C=>{C.name!=="AbortError"&&x(null)}).finally(()=>r(!1))},250);return()=>clearTimeout(h)},[a,s]);const b=n.useCallback(h=>{l(g=>g.filter(_=>_.key!==h))},[]),f=n.useCallback(()=>l([]),[]);return n.useMemo(()=>({pending:a,previewDoc:(i==null?void 0:i.model)??null,previewDiff:(i==null?void 0:i.diff)??null,diagnostics:(i==null?void 0:i.diagnostics)??[],failure:i&&i.failed_index!==null?{index:i.failed_index,error:i.error??"invalid change"}:null,busy:c,exec:N,drop:b,clear:f}),[a,i,c,N,b,f])}function Qe(s){const t=new Map;for(const l of s)for(const i of["id","conceptual_id","from_fk_id"]){const x=l.payload[i];l.op.startsWith("create_")&&typeof x=="string"&&t.set(x,l.key)}if(!t.size)return new Set;const a=new Set;for(const l of s)if(!l.op.startsWith("create_"))for(const i of Object.values(l.payload))typeof i=="string"&&t.has(i)&&(a.add(l.key),a.add(t.get(i)));return a}function Xe({user:s}){const[t,a]=n.useState(null);return n.useEffect(()=>{je(s).then(a).catch(()=>{})},[s]),!(t!=null&&t.ok)||!t.git?null:t.read_only?e.jsxs("div",{className:"git-banner",children:[e.jsx("code",{children:t.branch}),e.jsx("span",{children:"browse only — editing is disabled on this deployment"})]}):t.dirty?e.jsxs("div",{className:"git-banner warn",children:[e.jsx("code",{children:t.branch}),e.jsx("span",{children:"uncommitted changes in the working tree — a proposal will be refused until they are committed or discarded"})]}):t.on_base?e.jsxs("div",{className:"git-banner",children:[e.jsx("code",{children:t.branch}),e.jsx("span",{children:"protected — your edits become a pull request"})]}):e.jsxs("div",{className:"git-banner",children:[e.jsx("code",{children:t.branch}),e.jsx("span",{children:"your proposal branch"}),t.behind?e.jsxs("span",{className:"dim",children:["· ",t.base_branch," is ",t.behind," ahead"]}):null]})}function Ze({exec:s,canEdit:t,stagedMembers:a}){const[l,i]=n.useState([]),[x,c]=n.useState(""),[r,m]=n.useState(null),[N,b]=n.useState(""),[f,h]=n.useState(new Set),[g,_]=n.useState("ancestors"),[C,T]=n.useState(1),[S,y]=n.useState(null),[A,k]=n.useState(new Set),[R,o]=n.useState(null);n.useEffect(()=>{xe().then(d=>{i(d.subject_areas),c(w=>{var M;return w||((M=d.subject_areas[0])==null?void 0:M.id)||""})}).catch(d=>o(String(d)))},[]),n.useEffect(()=>{x&&(y(null),h(new Set),$e(x).then(m).catch(d=>o(String(d))))},[x]);const E=n.useMemo(()=>a[x]??(r==null?void 0:r.members)??[],[a,x,r]),$=n.useMemo(()=>{const d=new Map;for(const w of[...(r==null?void 0:r.included)??[],...(r==null?void 0:r.available)??[]])d.set(w.id,w);return d},[r]),D=N.trim().toLowerCase(),B=d=>!D||d.name.toLowerCase().includes(D),u=n.useMemo(()=>new Set(E),[E]),P=n.useMemo(()=>E.map(d=>$.get(d)).filter(d=>!!d&&B(d)),[E,$,D]),F=n.useMemo(()=>[...$.values()].filter(d=>!u.has(d.id)&&B(d)),[$,u,D]),I=n.useCallback(d=>{if(!r)return;const w=d.filter(q=>!(r.members??[]).includes(q)).length,M=(r.members??[]).filter(q=>!d.includes(q)).length;s("set_subject_area_members",{id:r.id,members:d,__label:`${r.name}: ${d.length} objects (+${w} −${M})`})},[r,s]),z=(d,w)=>{const M=w?[...E,...d.filter(q=>!u.has(q))]:E.filter(q=>!d.includes(q));I(M),h(new Set)},W=(d,w,M)=>{const q=new Set(d);q.has(w)?q.delete(w):q.add(w),M(q)},U=()=>{if(!r)return;const d=f.size?[...f]:E;if(!d.length){o("add an object first, or select one to expand from");return}o(null),be(r.id,{seeds:d,direction:g,levels:C}).then(w=>{y(w.hops),k(new Set(w.added))}).catch(w=>o(String(w)))},K=()=>{z([...A],!0),y(null)};if(R&&!r)return e.jsx("p",{className:"sme-splash error",children:R});if(!l.length)return e.jsx("p",{className:"sme-placeholder",children:"No subject areas yet."});const j=((r==null?void 0:r.inconsistent)??[]).filter(d=>!u.has(d));return e.jsxs("div",{className:"sa-editor",children:[e.jsx("nav",{className:"sme-nav",children:l.map(d=>e.jsxs("button",{className:"sme-sa"+(d.id===x?" active":""),onClick:()=>c(d.id),title:d.definition??void 0,children:[d.name,e.jsx("span",{className:"sme-sa-count",children:(a[d.id]??d.members).length})]},d.id))}),e.jsxs("div",{className:"sa-main",children:[e.jsxs("div",{className:"sa-head",children:[e.jsx("h2",{children:(r==null?void 0:r.name)??"…"}),(r==null?void 0:r.definition)&&e.jsx("p",{className:"sme-muted",children:r.definition}),e.jsx("input",{className:"sme-search sa-filter",type:"search",placeholder:"Filter both lists…",value:N,onChange:d=>b(d.target.value)})]}),j.length>0&&t&&e.jsxs("div",{className:"sa-nudge",children:[j.length," object",j.length>1?"s are":" is"," homed in this area but not included.",e.jsxs("button",{className:"sme-link",onClick:()=>z(j,!0),children:["Add ",j.length>1?"them all":"it"]})]}),e.jsxs("div",{className:"sa-panes",children:[e.jsx(Q,{title:`Available (${F.length})`,rows:F,picked:f,onToggle:d=>W(f,d,h),homedHere:(r==null?void 0:r.homed_here)??[]}),e.jsxs("div",{className:"sa-controls",children:[e.jsx("button",{className:"sme-secondary",disabled:!t||!f.size,onClick:()=>z([...f].filter(d=>!u.has(d)),!0),title:"Add the selected objects",children:"→"}),e.jsx("button",{className:"sme-secondary",disabled:!t||!F.length,onClick:()=>z(F.map(d=>d.id),!0),title:"Add everything matching the filter",children:"»"}),e.jsx("button",{className:"sme-secondary",disabled:!t||!f.size,onClick:()=>z([...f].filter(d=>u.has(d)),!1),title:"Remove the selected objects",children:"←"}),e.jsx("button",{className:"sme-secondary",disabled:!t||!P.length,onClick:()=>z(P.map(d=>d.id),!1),title:"Remove everything matching the filter",children:"«"})]}),e.jsx(Q,{title:`Included (${P.length})`,rows:P,picked:f,onToggle:d=>W(f,d,h),homedHere:(r==null?void 0:r.homed_here)??[]})]}),e.jsxs("div",{className:"sa-expand",children:[e.jsx("h3",{children:"Add related objects"}),e.jsxs("div",{className:"sa-expand-row",children:[e.jsxs("select",{value:g,onChange:d=>_(d.target.value),children:[e.jsx("option",{value:"ancestors",children:"ancestors — the parents its keys point at"}),e.jsx("option",{value:"descendants",children:"descendants — what points at it"}),e.jsx("option",{value:"both",children:"both"})]}),e.jsxs("label",{children:["levels",e.jsx("input",{type:"number",min:1,max:10,value:C,onChange:d=>T(Math.max(1,Math.min(10,Number(d.target.value))))})]}),e.jsx("button",{className:"sme-secondary",onClick:U,disabled:!t,children:"Preview"})]}),R&&e.jsx("p",{className:"sme-error-line",children:R}),S&&e.jsxs("div",{className:"sa-hops",children:[S.length===0&&e.jsx("p",{className:"sme-muted",children:"nothing new to add"}),S.map(d=>e.jsxs("label",{className:"sa-hop",children:[e.jsx("input",{type:"checkbox",checked:A.has(d.id),onChange:()=>W(A,d.id,k)}),e.jsx("span",{className:"sa-hop-name",children:d.name}),e.jsxs("span",{className:"sa-hop-why",children:["via ",d.via_name," · ",d.direction.replace(/s$/,""),", level ",d.level]})]},d.id)),S.length>0&&e.jsxs("div",{className:"sa-hop-actions",children:[e.jsx("button",{className:"sme-secondary",onClick:()=>y(null),children:"Cancel"}),e.jsxs("button",{className:"sme-primary",onClick:K,disabled:!A.size,children:["Add ",A.size," object",A.size===1?"":"s"]})]})]})]})]})]})}function Q({title:s,rows:t,picked:a,onToggle:l,homedHere:i}){const x=n.useMemo(()=>new Set(i),[i]);return e.jsxs("div",{className:"sa-pane",children:[e.jsx("h3",{children:s}),e.jsxs("ul",{children:[t.map(c=>e.jsxs("li",{className:"sa-row"+(a.has(c.id)?" picked":""),onClick:()=>l(c.id),children:[e.jsx("input",{type:"checkbox",readOnly:!0,checked:a.has(c.id)}),e.jsx("span",{className:"sa-row-name",children:c.name}),x.has(c.id)?e.jsx("span",{className:"sme-badge",children:"home"}):e.jsx("span",{className:"sme-badge borrowed",children:"borrowed"})]},c.id)),!t.length&&e.jsx("li",{className:"sme-empty",children:"nothing here"})]})]})}function es({objects:s,onCreate:t,onClose:a}){const[l,i]=n.useState(""),[x,c]=n.useState(""),[r]=n.useState(s),[m,N]=n.useState([]),[b,f]=n.useState(new Set),[h,g]=n.useState(""),[_,C]=n.useState("ancestors"),[T,S]=n.useState(1),[y,A]=n.useState(null),[k,R]=n.useState(new Set),[o,E]=n.useState(""),[$,D]=n.useState(null);n.useEffect(()=>{xe().then(j=>{j.subject_areas[0]&&E(j.subject_areas[0].id)}).catch(()=>{})},[]);const B=n.useMemo(()=>new Set(m),[m]),u=h.trim().toLowerCase(),P=j=>!u||j.name.toLowerCase().includes(u),F=n.useMemo(()=>m.map(j=>r.find(d=>d.id===j)).filter(j=>!!j&&P(j)),[m,r,u]),I=n.useMemo(()=>r.filter(j=>!B.has(j.id)&&P(j)),[r,B,u]),z=(j,d)=>{N(w=>d?[...w,...j.filter(M=>!w.includes(M))]:w.filter(M=>!j.includes(M))),f(new Set)},W=(j,d,w)=>{const M=new Set(j);M.has(d)?M.delete(d):M.add(d),w(M)},U=()=>{const j=b.size?[...b]:m;if(!j.length){D("pick an object to expand from first");return}o&&(D(null),be(o,{seeds:j,direction:_,levels:T}).then(d=>{const w=d.hops.filter(M=>!B.has(M.id));A(w),R(new Set(w.map(M=>M.id)))}).catch(d=>D(String(d))))},K=()=>{l.trim()&&t(l.trim(),x.trim(),m)};return e.jsx("div",{className:"sme-modal-backdrop",onClick:a,children:e.jsxs("div",{className:"sme-modal sa-modal",onClick:j=>j.stopPropagation(),children:[e.jsx("h2",{children:"New subject area"}),e.jsx("p",{className:"sme-hint",children:"A subject area is a filtered view of the model. Name it and choose what it contains — both land as one proposal."}),e.jsxs("div",{className:"sme-field-row",children:[e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Name"}),e.jsx("input",{autoFocus:!0,value:l,placeholder:"e.g. UseCase-ApraStressTesting",onChange:j=>i(j.target.value),onKeyDown:j=>j.key==="Enter"&&m.length===0&&K()})]}),e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Definition (optional)"}),e.jsx("input",{value:x,placeholder:"what this view is for",onChange:j=>c(j.target.value)})]})]}),e.jsx("input",{className:"sme-search sa-filter",type:"search",placeholder:"Filter both lists…",value:h,onChange:j=>g(j.target.value)}),e.jsxs("div",{className:"sa-panes",children:[e.jsx(Q,{title:`Available (${I.length})`,rows:I,picked:b,onToggle:j=>W(b,j,f),homedHere:[]}),e.jsxs("div",{className:"sa-controls",children:[e.jsx("button",{className:"sme-secondary",disabled:!b.size,onClick:()=>z([...b].filter(j=>!B.has(j)),!0),title:"Add the selected objects",children:"→"}),e.jsx("button",{className:"sme-secondary",disabled:!I.length,onClick:()=>z(I.map(j=>j.id),!0),title:"Add everything matching the filter",children:"»"}),e.jsx("button",{className:"sme-secondary",disabled:!b.size,onClick:()=>z([...b].filter(j=>B.has(j)),!1),title:"Remove the selected objects",children:"←"}),e.jsx("button",{className:"sme-secondary",disabled:!F.length,onClick:()=>z(F.map(j=>j.id),!1),title:"Remove everything matching the filter",children:"«"})]}),e.jsx(Q,{title:`Included (${F.length})`,rows:F,picked:b,onToggle:j=>W(b,j,f),homedHere:[]})]}),e.jsxs("div",{className:"sa-expand",children:[e.jsx("h3",{children:"Add related objects"}),e.jsxs("div",{className:"sa-expand-row",children:[e.jsxs("select",{value:_,onChange:j=>C(j.target.value),children:[e.jsx("option",{value:"ancestors",children:"ancestors — the parents its keys point at"}),e.jsx("option",{value:"descendants",children:"descendants — what points at it"}),e.jsx("option",{value:"both",children:"both"})]}),e.jsxs("label",{children:["levels",e.jsx("input",{type:"number",min:1,max:10,value:T,onChange:j=>S(Math.max(1,Math.min(10,Number(j.target.value))))})]}),e.jsx("button",{className:"sme-secondary",onClick:U,disabled:!o,title:o?"Preview related objects to add":"Available once the model has at least one saved subject area to walk the graph from",children:"Preview"})]}),y&&e.jsxs("div",{className:"sa-hops",children:[y.length===0&&e.jsx("p",{className:"sme-muted",children:"nothing new to add"}),y.map(j=>e.jsxs("label",{className:"sa-hop",children:[e.jsx("input",{type:"checkbox",checked:k.has(j.id),onChange:()=>W(k,j.id,R)}),e.jsx("span",{className:"sa-hop-name",children:j.name}),e.jsxs("span",{className:"sa-hop-why",children:["via ",j.via_name," · ",j.direction.replace(/s$/,""),", level ",j.level]})]},j.id)),y.length>0&&e.jsxs("div",{className:"sa-hop-actions",children:[e.jsx("button",{className:"sme-secondary",onClick:()=>A(null),children:"Cancel"}),e.jsxs("button",{className:"sme-primary",disabled:!k.size,onClick:()=>{z([...k],!0),A(null)},children:["Add ",k.size]})]})]})]}),$&&e.jsx("p",{className:"sme-error-line",children:$}),e.jsxs("div",{className:"sme-modal-foot",children:[e.jsx("button",{className:"sme-secondary",onClick:a,children:"Cancel"}),e.jsxs("button",{className:"sme-primary",disabled:!l.trim(),onClick:K,children:["Create",m.length>0&&` with ${m.length} object${m.length===1?"":"s"}`]})]})]})})}const ss=new Set(["set_definition","set_stewardship","set_subject_area","set_pattern","rename_entity","add_attribute","update_attribute","delete_attribute","set_alignment","clear_alignment","set_term_map","clear_term_map","update_synonyms","set_object_definition","set_subject_area_members","create_subject_area","update_subject_area","create_entity","delete_entity","create_relationship","rename_relationship","update_relationship","delete_relationship"]);function ns({doc:s,subjectArea:t,onSubjectArea:a,exec:l,canEdit:i,direct:x=!1,onSelectEntity:c,onImported:r,query:m="",busy:N}){var R;const[b,f]=n.useState(null),[h,g]=n.useState(null),[_,C]=n.useState(!1),[T,S]=n.useState(null),y=n.useRef(null),A=n.useMemo(()=>({canEdit:i,mode:x?"direct":"staged",allow:x?void 0:ss,canArbitrate:x,canCommit:x}),[i,x]),k=n.useCallback(o=>{f(o),o&&(c==null||c(o))},[c]);return e.jsxs("div",{className:"sme-model-view",children:[e.jsxs("nav",{className:"sme-nav",children:[e.jsxs("div",{className:"sme-nav-head",children:[e.jsx("span",{children:"Subject areas"}),i&&e.jsx("button",{className:"sme-nav-add",title:"New subject area",onClick:()=>C(!0),children:"+"})]}),e.jsxs("button",{className:"sme-sa"+(t===""?" active":""),onClick:()=>a(""),children:["Whole model",e.jsx("span",{className:"sme-sa-count",children:((R=s.counts)==null?void 0:R.entities_total)??s.entities.length})]}),s.subject_areas.map(o=>e.jsxs("button",{className:"sme-sa"+(t===o.id?" active":""),onClick:()=>a(o.id),title:o.definition??void 0,children:[o.name,e.jsx("span",{className:"sme-sa-count",children:o.member_count??0})]},o.id))]}),_&&e.jsx(es,{objects:s.entities.flatMap(o=>o.conceptual?[{id:o.conceptual.id,kind:"conceptual_entity",name:o.conceptual.name,definition:o.conceptual.definition??null,synonyms:[],subject_area:o.conceptual.subject_area??null,stewardship:null,ontology:null,where_used:[]}]:[]),onClose:()=>C(!1),onCreate:(o,E,$)=>{const D=ge();l("create_subject_area",{name:o,...E?{definition:E}:{},id:D}),$.length&&l("set_subject_area_members",{id:D,members:$}),C(!1),a(D)}}),e.jsxs("div",{className:"erd-wrap",children:[e.jsxs("div",{className:"erd-bar",children:[e.jsxs("span",{className:"erd-count",children:[s.entities.length," entities · ",s.relationships.length," relationships",s.scope&&" · scoped"]}),i&&e.jsx("button",{className:"erd-action",onClick:()=>{var o;return(o=y.current)==null?void 0:o.newEntity()},title:"Add an entity (n)",children:"+ Entity"}),e.jsx("span",{className:"erd-hint",children:"drag between entities to relate them"}),e.jsxs("span",{className:"erd-group",children:[e.jsxs("button",{className:"erd-action ghost",onClick:()=>{var o;return(o=y.current)==null?void 0:o.relayout()},title:"Auto-arrange the diagram",children:[e.jsx("span",{className:"erd-ico","aria-hidden":"true",children:"⟲"}),"Re-layout"]}),e.jsxs("button",{className:"erd-action ghost",onClick:()=>{var o;return(o=y.current)==null?void 0:o.fitView()},title:"Fit the whole model in view",children:[e.jsx("span",{className:"erd-ico","aria-hidden":"true",children:"⛶"}),"Fit"]})]}),e.jsx("span",{className:"erd-sep","aria-hidden":"true"}),e.jsxs("span",{className:"erd-group",children:[e.jsx("button",{className:"erd-action ghost"+(h==="ontology"?" on":""),onClick:()=>g(o=>o==="ontology"?null:"ontology"),children:"Ontology"}),e.jsx("button",{className:"erd-action ghost"+(h==="layers"?" on":""),onClick:()=>g(o=>o==="layers"?null:"layers"),children:"Layers"})]}),e.jsx("span",{className:"erd-sep","aria-hidden":"true"}),e.jsx(Re,{exec:l,canEdit:i,onImported:r}),N&&e.jsx("span",{className:"erd-busy",children:"updating…"}),!i&&e.jsx("span",{className:"sme-chip",children:"read-only"}),T&&e.jsx("span",{className:"erd-error",children:T})]}),e.jsxs("div",{className:"erd-canvas canvas-wrap",children:[e.jsx(Me,{children:e.jsx(De,{doc:s,caps:A,exec:l,selectedId:b,onSelect:k,query:m,onError:S,handleRef:y})}),h&&e.jsxs("aside",{className:"side-panel",children:[e.jsxs("div",{className:"detail-header",children:[e.jsx("h2",{children:h==="ontology"?"Ontology":"Ontology layers"}),e.jsx("button",{className:"icon-btn",onClick:()=>g(null),children:"✕"})]}),h==="ontology"?e.jsx(Pe,{}):e.jsx(Ie,{refreshKey:0,onFocusEntity:o=>{var E;g(null),(E=y.current)==null||E.focusEntity(o)}})]})]})]})]})}function as({user:s,onView:t}){const[a,l]=n.useState(null),[i,x]=n.useState(null);if(n.useEffect(()=>{Oe(s).then(l).catch(r=>x(String(r)))},[s]),i)return e.jsx("p",{className:"sme-splash error",children:i});if(!a)return e.jsx("div",{className:"sme-splash",children:"◮ looking for your proposals…"});if(!a.git)return e.jsx("p",{className:"sme-placeholder",children:"This model isn't in a git repository."});const c=a.proposals.filter(r=>!r.merged).length;return e.jsxs("div",{className:"pr-wrap",children:[e.jsxs("div",{className:"pr-head",children:[e.jsx("h2",{children:"My proposals"}),e.jsxs("span",{className:"meta",children:[c," open · base: ",a.base]})]}),!a.proposals.length&&e.jsx("p",{className:"sme-placeholder",children:"Nothing proposed yet. Edits you submit for review will appear here."}),a.proposals.map(r=>e.jsx(rs,{p:r,gh:a.gh,onView:()=>t(r.branch)},r.branch)),!a.gh&&a.proposals.length>0&&e.jsxs("div",{className:"pr-degrade",children:["Review status isn't available here (",e.jsx("code",{children:"gh"})," is not installed or not signed in). Branch, contents, merge state and conflicts all still come from git — each card links out to the compare view."]})]})}function ts(s,t){var a,l;return s.merged?{kind:"accepted",text:"✅ Accepted"}:s.pushed?t&&((a=s.pr)==null?void 0:a.state)==="CLOSED"?{kind:"declined",text:"✖ Declined"}:t&&((l=s.pr)==null?void 0:l.reviews)==="CHANGES_REQUESTED"?{kind:"changes",text:"💬 Changes requested"}:{kind:"awaiting",text:"⏳ Awaiting review"}:{kind:"local",text:"📥 Saved locally"}}function rs({p:s,gh:t,onView:a}){const l=ts(s,t);return e.jsxs("div",{className:"pr-card"+(l.kind==="attention"?" attention":""),children:[e.jsxs("div",{className:"pr-top",children:[e.jsx("span",{className:"pr-title",children:s.title}),e.jsx("span",{className:"pr-chip "+l.kind,children:l.text})]}),e.jsxs("div",{className:"pr-branch",children:[s.branch," · ",s.created,s.behind>0&&` · ${s.behind} behind`]}),e.jsxs("div",{className:"pr-foot",children:[e.jsx("span",{className:"pr-link",children:s.merged?e.jsxs(e.Fragment,{children:["merged",t&&s.pr?` · PR #${s.pr.number}`:""]}):s.pushed?t&&s.pr?e.jsxs("a",{href:s.pr.url,target:"_blank",rel:"noreferrer",children:["PR #",s.pr.number]}):s.compare_url?e.jsx("a",{href:s.compare_url,target:"_blank",rel:"noreferrer",children:"open the compare view →"}):"pushed":"not sent yet — no connection to the shared repo"}),e.jsx("span",{className:"pr-btns",children:e.jsx("button",{className:"sme-secondary",onClick:a,children:"View"})})]})]})}function is({changes:s,routeAdvice:t,identity:a,user:l,onUser:i,onDrop:x,onClose:c,onProposed:r}){const m=!!(a&&a.source!=="anonymous"),[N,b]=n.useState(l||(localStorage.getItem("mdl.sme.user")??"")),[f,h]=n.useState(s.length===1?`Update ${s[0].label.toLowerCase()}`:"Glossary updates"),[g,_]=n.useState(""),[C,T]=n.useState(!1),S=ve(C?g:f),[y,A]=n.useState(""),[k,R]=n.useState(!1),[o,E]=n.useState(null),[$,D]=n.useState(null),B=()=>{!m&&!N.trim()||(m||(localStorage.setItem("mdl.sme.user",N.trim()),i==null||i(N.trim())),R(!0),D(null),Te({user:m?"":N.trim(),slug:S,title:f,body:y.trim(),changes:s.map(u=>({op:u.op,payload:u.payload}))}).then(E).catch(u=>D(u instanceof Be?u.message:String(u))).finally(()=>R(!1)))};return o!=null&&o.ok?e.jsx("div",{className:"sme-modal-backdrop",onClick:()=>r(o),children:e.jsxs("div",{className:"sme-modal",onClick:u=>u.stopPropagation(),children:[e.jsx("h2",{children:"✓ Sent for review"}),e.jsx("p",{children:o.message}),o.pr_url&&e.jsx("p",{children:e.jsx("a",{href:o.pr_url,target:"_blank",rel:"noreferrer",children:"View pull request →"})}),o.compare_url&&e.jsx("p",{children:e.jsx("a",{href:o.compare_url,target:"_blank",rel:"noreferrer",children:"Open the pull request →"})}),e.jsxs("p",{className:"sme-muted",children:["Your suggestion is on branch ",e.jsx("code",{children:o.branch}),". A steward will review it."]}),e.jsx("div",{className:"sme-modal-foot",children:e.jsx("button",{className:"sme-primary",onClick:()=>r(o),children:"Done"})})]})}):e.jsx("div",{className:"sme-modal-backdrop",onClick:c,children:e.jsxs("div",{className:"sme-modal",onClick:u=>u.stopPropagation(),children:[e.jsxs("div",{className:"sme-card-head",children:[e.jsx("h2",{children:"Submit for review"}),e.jsx("button",{className:"sme-secondary",onClick:c,children:"✕"})]}),e.jsx("h3",{children:"Your changes"}),e.jsx("ul",{className:"sme-diff",children:s.map((u,P)=>e.jsxs("li",{children:[e.jsxs("div",{className:"sme-diff-head",children:[e.jsx("b",{children:u.label}),e.jsx("button",{className:"sme-link danger",onClick:()=>x(P),children:"discard"})]}),e.jsx("div",{className:"sme-diff-before",children:u.before}),e.jsx("div",{className:"sme-diff-after",children:u.after})]},P))}),m?e.jsxs("p",{className:"sme-signed-in",children:["Signed in as ",e.jsx("strong",{children:a.name}),a.email?` (${a.email})`:""," — this proposal is attributed to you."]}):e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Your name (for attribution)"}),e.jsx("input",{value:N,onChange:u=>b(u.target.value),placeholder:"e.g. a.hough"})]}),e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Title"}),e.jsx("input",{value:f,onChange:u=>h(u.target.value)})]}),e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Branch name (edit to add a ticket id, e.g. PROJ-123)"}),e.jsx("input",{value:C?g:S,onChange:u=>{T(!0),_(u.target.value)},placeholder:"clarify-counterparty"})]}),e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Note for the reviewer (optional)"}),e.jsx("textarea",{rows:2,value:y,onChange:u=>A(u.target.value)})]}),e.jsx(ls,{cl:t,user:m?a.name:N,changeSlug:S}),$&&e.jsx("p",{className:"sme-error-line",children:$}),e.jsxs("div",{className:"sme-modal-foot",children:[e.jsx("button",{className:"sme-secondary",onClick:c,children:"Keep editing"}),e.jsx("button",{className:"sme-primary",disabled:k||!m&&!N.trim()||s.length===0,onClick:B,children:k?"Submitting…":"Submit for review"})]})]})})}function ls({cl:s,user:t,changeSlug:a}){if(!(s!=null&&s.primary))return null;const l=s.reviewers_actual??s.reviewers,i=ve(t||"you"),x=s.routes.length>1;return e.jsxs(e.Fragment,{children:[x&&e.jsxs("div",{className:"sub-advice",children:[e.jsx("span",{className:"i",children:"ⓘ"})," These changes span routes"," ",e.jsx("strong",{children:s.routes.join(" and ")}),". The whole proposal will be reviewed as route ",s.primary," (",s.primary_name,") — the strictest gate wins, so it needs"," ",l.join(", ")," plus ",e.jsx("code",{children:s.gates[s.gates.length-1]}),". Proposing the meaning-only changes separately would get them reviewed faster."]}),e.jsxs("div",{className:"sub-dest",children:[e.jsxs("div",{className:"row",children:[e.jsx("span",{className:"k",children:"Goes to"}),e.jsxs("code",{children:["sme/",i,"/",a||"…"]})]}),e.jsxs("div",{className:"row",children:[e.jsx("span",{className:"k",children:"Reviewers"}),e.jsx("span",{children:l.join(", ")})]})]})]})}function ve(s){return s.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-|-$/g,"")||"change"}const cs="modulepreload",os=function(s){return"/"+s},oe={},ds=function(t,a,l){let i=Promise.resolve();if(a&&a.length>0){document.getElementsByTagName("link");const c=document.querySelector("meta[property=csp-nonce]"),r=(c==null?void 0:c.nonce)||(c==null?void 0:c.getAttribute("nonce"));i=Promise.allSettled(a.map(m=>{if(m=os(m),m in oe)return;oe[m]=!0;const N=m.endsWith(".css"),b=N?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${m}"]${b}`))return;const f=document.createElement("link");if(f.rel=N?"stylesheet":cs,N||(f.as="script"),f.crossOrigin="",f.href=m,r&&f.setAttribute("nonce",r),document.head.appendChild(f),N)return new Promise((h,g)=>{f.addEventListener("load",h),f.addEventListener("error",()=>g(new Error(`Unable to preload CSS for ${m}`)))})}))}function x(c){const r=new Event("vite:preloadError",{cancelable:!0});if(r.payload=c,window.dispatchEvent(r),!r.defaultPrevented)throw c}return i.then(c=>{for(const r of c||[])r.status==="rejected"&&x(r.reason);return t().catch(x)})};function hs({diff:s,selectable:t,selected:a,onToggle:l}){var r;const[i,x]=n.useState(((r=s.objects[0])==null?void 0:r.ulid)??null),c=n.useMemo(()=>s.objects.find(m=>m.ulid===i)??s.objects[0]??null,[s,i]);return s.objects.length?e.jsxs("div",{className:"rv-body",children:[e.jsx("div",{className:"rv-list",children:s.objects.map(m=>e.jsx(us,{obj:m,active:m.ulid===((c==null?void 0:c.ulid)??""),checked:(a==null?void 0:a.has(m.ulid))??!0,selectable:t,onSelect:()=>x(m.ulid),onToggle:()=>l==null?void 0:l(m.ulid)},m.ulid))}),e.jsx("div",{className:"rv-detail",children:c&&e.jsx(ps,{obj:c})})]}):e.jsxs("p",{className:"sme-placeholder",children:["No model changes against ",s.base.label,"."]})}function ms(s){return s.renamed?"renamed":s.severity==="breaking"?"breaking":s.change}function us({obj:s,active:t,checked:a,selectable:l,onSelect:i,onToggle:x}){return e.jsxs("div",{className:"rv-obj"+(t?" active":""),onClick:i,children:[e.jsxs("div",{className:"rv-obj-head",children:[l&&e.jsx("input",{type:"checkbox",checked:a,onClick:c=>c.stopPropagation(),onChange:x,"aria-label":`include ${s.name_before??s.name_after}`}),e.jsx("span",{className:"rv-obj-name",children:s.name_before??s.name_after}),e.jsx("span",{className:"rv-obj-kind",children:s.object_kind_label}),e.jsxs("span",{className:"sev "+(s.renamed?"renamed":s.severity),children:[s.severity==="breaking"&&"⚠ ",ms(s)]})]}),e.jsxs("ul",{className:"rv-obj-fields",children:[s.fields.map((c,r)=>e.jsx("li",{children:c.label},c.field+r)),s.children.flatMap(c=>c.fields.map((r,m)=>e.jsxs("li",{children:[r.label,": ",c.name_before??c.name_after]},c.ulid+m)))]})]})}function ps({obj:s}){const t=s.children.flatMap(a=>a.fields.map(l=>({field:l,on:a.name_before??a.name_after??""})));return e.jsxs(e.Fragment,{children:[e.jsx("h2",{children:s.renamed?`${s.name_before} → ${s.name_after}`:s.name_before??s.name_after}),e.jsxs("div",{className:"rv-detail-kind",children:[s.object_kind_label,s.renamed&&" · renamed",s.path&&e.jsxs("span",{className:"rv-src",children:[" · ",s.path]})]}),s.fields.map((a,l)=>e.jsx(de,{f:a},a.field+l)),t.map(({field:a,on:l},i)=>e.jsx(de,{f:a,on:l},"c"+i)),s.severity==="breaking"&&e.jsxs("div",{className:"rv-note",children:[e.jsx("span",{className:"i",children:"ⓘ"}),e.jsxs("span",{children:["This is a structural change (route B). It will need an architect's review, and CI will run ",e.jsx("code",{children:"mdl drift --check"}),"."]})]})]})}function de({f:s,on:t}){var l,i,x;const a=t?`${s.label}: ${t}`:s.label;if((l=s.breaks)!=null&&l.length)return e.jsxs("div",{className:"rv-section",children:[e.jsx("h3",{children:a}),e.jsxs("div",{className:"rv-break",children:[e.jsxs("div",{className:"rv-break-head",children:[e.jsx("span",{children:"⚠"}),e.jsxs("span",{children:[t??String(s.before??"")," removed"]}),s.detail&&e.jsx("span",{className:"rv-break-meta",children:s.detail})]}),e.jsxs("div",{className:"rv-break-body",children:["This is realised by ",s.breaks.length," dbt model",s.breaks.length>1?"s":"",". Removing it will break ",s.breaks.length>1?"them":"it","."]}),e.jsx("ul",{className:"rv-usage",children:s.breaks.map(c=>e.jsxs("li",{children:[e.jsxs("span",{className:"m",children:["→ ",c.name]}),e.jsxs("span",{className:"p",children:[c.target," · ",c.materialization]})]},c.name))})]})]});if(s.kind==="definition_changed"){const c=String(s.before??""),r=String(s.after??"");return e.jsxs("div",{className:"rv-section",children:[e.jsx("h3",{children:a}),e.jsxs("div",{className:"rv-ba",children:[e.jsxs("div",{className:"rv-ba-col",children:[e.jsx("div",{className:"rv-ba-label",children:"before"}),e.jsx("div",{className:"rv-ba-text",children:me(c,r,"del")})]}),e.jsxs("div",{className:"rv-ba-col",children:[e.jsx("div",{className:"rv-ba-label",children:"after"}),e.jsx("div",{className:"rv-ba-text",children:me(r,c,"ins")})]})]})]})}if(Array.isArray(s.before)||Array.isArray(s.after)){const c=new Set(((i=s.before)==null?void 0:i.map(String))??[]),r=new Set(((x=s.after)==null?void 0:x.map(String))??[]),m=[...r].filter(b=>!c.has(b)),N=[...c].filter(b=>!r.has(b));return e.jsxs("div",{className:"rv-section",children:[e.jsx("h3",{children:a}),e.jsxs("div",{className:"rv-chips",children:[m.map(b=>e.jsxs("span",{className:"rv-chip-add",children:["+ ",b]},"a"+b)),N.map(b=>e.jsxs("span",{className:"rv-chip-del",children:["− ",b]},"r"+b))]})]})}return e.jsxs("div",{className:"rv-section",children:[e.jsx("h3",{children:a}),e.jsxs("div",{className:"rv-scalar",children:[e.jsx("span",{className:"from",children:he(s.before)}),e.jsx("span",{className:"arrow",children:"→"}),e.jsx("span",{className:"to",children:he(s.after)})]})]})}function he(s){return s==null||s===""?"—":typeof s=="boolean"?s?"yes":"no":typeof s=="object"?JSON.stringify(s):String(s)}function me(s,t,a){const l=s.split(/(\s+)/),i=t.split(/(\s+)/),x=h=>h.toLowerCase().replace(/[.,;:]/g,""),c=l.length,r=i.length,m=Array.from({length:c+1},()=>new Array(r+1).fill(0));for(let h=c-1;h>=0;h--)for(let g=r-1;g>=0;g--)m[h][g]=x(l[h])===x(i[g])?m[h+1][g+1]+1:Math.max(m[h+1][g],m[h][g+1]);const N=new Set;let b=0,f=0;for(;b=m[b][f+1]?b++:f++;return l.map((h,g)=>!h.trim()||N.has(g)?e.jsx("span",{children:h},g):a==="del"?e.jsx("del",{children:h},g):e.jsx("ins",{children:h},g))}const js=n.lazy(()=>ds(()=>import("./ModelDiagram-oAb1enKe.js"),__vite__mapDeps([0,1,2,3])).then(s=>({default:s.ModelDiagram})));function xs({stagedDiff:s,stagedRoute:t,user:a,onBack:l,onSubmit:i,excluded:x,onToggleObject:c,selectable:r}){const[m,N]=n.useState(null),[b,f]=n.useState(null),[h,g]=n.useState(null),[_,C]=n.useState(null),[T,S]=n.useState(null),[y,A]=n.useState("changes"),k=n.useCallback(()=>{je(a).then(o=>{C(o);const E=o.base_branch??"main";s?N(s):Le("HEAD").then($=>$.ok?N($):S($.error??"could not read the model")).catch($=>S(String($))),t?f(t):Fe("HEAD").then(f).catch(()=>{}),ze(E).then(g).catch(()=>{})}).catch(o=>S(String(o)))},[a,s,t]);if(n.useEffect(k,[k]),T)return e.jsxs("div",{className:"rv-shell",children:[e.jsx(ue,{onBack:l,diff:null}),e.jsx("p",{className:"sme-splash error",children:e.jsx("pre",{children:T})})]});if(!m)return e.jsx("div",{className:"sme-splash",children:"◮ reading your changes…"});const R=new Set(m.objects.map(o=>o.ulid).filter(o=>!x.has(o)));return e.jsxs("div",{className:"rv-shell",children:[e.jsx(ue,{onBack:l,diff:m,tab:y,onTab:A}),y==="changes"?e.jsx(hs,{diff:m,selectable:r,selected:R,onToggle:c}):e.jsx(n.Suspense,{fallback:e.jsx("div",{className:"sme-splash",children:"◮ drawing the model…"}),children:e.jsx(js,{severityByUlid:bs(m)})}),e.jsxs("div",{className:"rv-foot",children:[e.jsx(gs,{cl:b}),e.jsx(fs,{conf:h,ctx:_}),e.jsxs("div",{className:"rv-actions",children:[e.jsx("button",{className:"sme-secondary",onClick:l,children:"Keep editing"}),e.jsx("button",{className:"sme-primary",disabled:!m.objects.length||(_?!_.can_propose:!1),title:_&&!_.can_propose?"the working tree has uncommitted changes":"",onClick:()=>i(b),children:"Submit for review →"})]})]})]})}function bs(s){const t=new Map;for(const a of s.objects)t.set(a.ulid,a.severity);return t}function ue({onBack:s,diff:t,tab:a,onTab:l}){const i=t==null?void 0:t.counts;return e.jsxs("div",{className:"rv-head",children:[e.jsxs("div",{children:[e.jsx("button",{className:"rv-back",onClick:s,children:"‹ Back to terms"}),e.jsx("h1",{className:"rv-title",children:"Review your changes"}),i&&e.jsxs("div",{className:"rv-sub",children:[i.objects," object",i.objects===1?"":"s"," ·"," ",(i.breaking??0)+(i.additive??0)+(i.cosmetic??0)," changes",(t==null?void 0:t.has_breaking)&&e.jsxs("span",{className:"warn",children:[" · ⚠ ",i.breaking," breaking"]})," · comparing to ",e.jsx("code",{children:t==null?void 0:t.base.label})]})]}),l&&e.jsxs("div",{className:"rv-tabs",children:[e.jsxs("button",{className:"rv-tab"+(a==="changes"?" active":""),onClick:()=>l("changes"),children:["Changes ",(t==null?void 0:t.objects.length)??0]}),e.jsx("button",{className:"rv-tab"+(a==="diagram"?" active":""),onClick:()=>l("diagram"),children:"Diagram"})]})]})}function gs({cl:s}){if(!(s!=null&&s.primary))return null;const t=s.reviewers_actual??s.reviewers;return e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"rv-route",children:[e.jsxs("span",{className:"rv-route-badge",children:["Route ",s.primary," · ",s.primary_name]}),e.jsx("span",{className:"k",children:"Reviewers"}),e.jsx("span",{children:t.join(", ")}),s.reviewers_actual&&e.jsx("span",{className:"rv-src",children:"from .github/CODEOWNERS"})]}),e.jsxs("div",{className:"rv-gates",children:["CI gates"," ",s.gates.map(a=>e.jsx("code",{children:a},a))]})]})}function fs({conf:s,ctx:t}){return s!=null&&s.ok?s.clean?e.jsxs("div",{className:"rv-conflict ok",children:[e.jsx("span",{children:"✓"}),e.jsxs("span",{children:["Merges cleanly onto ",s.base]}),s.behind>0&&e.jsxs("span",{className:"detail",children:["· ",s.base," is ",s.behind," commit",s.behind===1?"":"s"," ahead"]}),(t==null?void 0:t.dirty)&&e.jsx("span",{className:"detail",children:"· uncommitted changes in the working tree"})]}):e.jsxs("div",{className:"rv-conflict bad",children:[e.jsx("span",{children:"⚠"}),e.jsxs("span",{children:[s.base," has changed and ",s.files.length," file",s.files.length===1?"":"s"," now conflict"]}),e.jsx("span",{className:"detail",children:s.files.map(a=>a.path).join(", ")})]}):null}function vs({term:s,canEdit:t,pendingCount:a,onEdit:l}){var i,x;return e.jsxs("div",{className:"sme-card",children:[e.jsxs("div",{className:"sme-card-head",children:[e.jsxs("div",{children:[e.jsx("h1",{children:s.name}),((i=s.subject_area)==null?void 0:i.name)&&e.jsx("span",{className:"sme-chip",children:s.subject_area.name}),s.kind==="term"&&e.jsx("span",{className:"sme-chip",children:"glossary term"})]}),t&&e.jsx("button",{className:"sme-primary",onClick:l,children:a>0?"Continue editing":"Suggest an edit"})]}),e.jsx("p",{className:"sme-definition",children:s.definition??e.jsx("em",{children:"No definition yet."})}),s.synonyms.length>0&&e.jsxs("section",{children:[e.jsx("h3",{children:"Also called"}),e.jsx("div",{children:s.synonyms.map(c=>e.jsx("span",{className:"sme-chip",children:c},c))})]}),s.stewardship&&(s.stewardship.owner||s.stewardship.steward)&&e.jsxs("section",{children:[e.jsx("h3",{children:"Who owns this"}),s.stewardship.owner&&e.jsxs("div",{className:"sme-kv",children:[e.jsx("span",{className:"k",children:"owner"}),e.jsx("span",{children:s.stewardship.owner})]}),s.stewardship.steward&&e.jsxs("div",{className:"sme-kv",children:[e.jsx("span",{className:"k",children:"steward"}),e.jsx("span",{children:s.stewardship.steward})]})]}),((x=s.ontology)==null?void 0:x.aligns_to)&&e.jsxs("section",{children:[e.jsx("h3",{children:"Standard it maps to"}),e.jsxs("div",{className:"sme-kv",children:[e.jsx("span",{className:"k",children:"aligned to"}),e.jsx("code",{children:s.ontology.aligns_to}),s.ontology.status==="proposed"&&e.jsx("span",{className:"sme-badge proposed",children:"awaiting architect"})]})]}),e.jsxs("section",{children:[e.jsx("h3",{children:"Where it's used"}),s.where_used.length===0?e.jsx("p",{className:"sme-muted",children:s.kind==="term"?"A glossary term — not yet realised by a data model.":"Not yet realised by any data model."}):e.jsx("ul",{className:"sme-usage",children:s.where_used.map(c=>e.jsxs("li",{children:[e.jsx("span",{className:"sme-usage-model",children:c.logical_entity}),c.unmanaged&&e.jsx("span",{className:"sme-badge",children:"engineer-owned"}),c.physical.length>0&&e.jsx("span",{className:"sme-usage-phys",children:c.physical.map(r=>r.name).join(", ")})]},c.logical_id))})]})]})}function Ns({term:s,pending:t,onStage:a,onDone:l,catalogOwned:i=[],catalog:x=null}){var E,$,D,B;const c=u=>i.includes(u),r=u=>t.find(P=>P.label===u),m=(u,P)=>{const F=r(u);return F?F.after:P},[N,b]=n.useState(m("Definition",s.definition??"")),[f,h]=n.useState(s.synonyms),[g,_]=n.useState(""),[C,T]=n.useState(((E=s.stewardship)==null?void 0:E.owner)??""),[S,y]=n.useState((($=s.stewardship)==null?void 0:$.steward)??""),A=()=>{N.trim()!==(s.definition??"").trim()&&a({op:"set_definition",payload:{id:s.id,definition:N.trim()},label:"Definition",before:s.definition??"(none)",after:N.trim()||"(none)"})},k=(u,P)=>{var F,I;a({op:"set_stewardship",payload:{id:s.id,owner:u||null,steward:P||null},label:"Stewardship",before:`owner: ${((F=s.stewardship)==null?void 0:F.owner)??"—"} · steward: ${((I=s.stewardship)==null?void 0:I.steward)??"—"}`,after:`owner: ${u||"—"} · steward: ${P||"—"}`})},R=u=>{h(u),a({op:"update_synonyms",payload:{id:s.id,synonyms:u},label:"Also called",before:s.synonyms.join(", ")||"(none)",after:u.join(", ")||"(none)"})},o=s.kind==="term";return e.jsxs("div",{className:"sme-editor",children:[e.jsxs("div",{className:"sme-card-head",children:[e.jsxs("h1",{children:["Suggest an edit — ",s.name]}),e.jsx("button",{className:"sme-secondary",onClick:l,children:"Back"})]}),e.jsxs("p",{className:"sme-hint",children:["You can refine what this term ",e.jsx("em",{children:"means"}),". Structure (keys, relationships, how it's built) stays with the data team."]}),(c("definition")||c("synonyms")||c("stewardship"))&&x&&e.jsxs("div",{className:"sme-catalog-banner",children:["Definitions, synonyms, and ownership are mastered in ",e.jsx("b",{children:x.name}),". Edit them there — this glossary mirrors them read-only.",x.url&&e.jsxs(e.Fragment,{children:[" ",e.jsxs("a",{href:x.url,target:"_blank",rel:"noreferrer",children:["Open in ",x.name," →"]})]}),e.jsx("div",{className:"sme-catalog-note",children:"You can still propose a standard mapping below."})]}),e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Definition"}),c("definition")?e.jsx("p",{className:"sme-readonly-value",children:s.definition??"—"}):e.jsx("textarea",{rows:4,value:N,onChange:u=>b(u.target.value),onBlur:A,placeholder:"A plain-language business definition…"})]}),e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Also called (synonyms)"}),c("synonyms")?e.jsx("div",{className:"sme-syn-row",children:s.synonyms.length?s.synonyms.map(u=>e.jsx("span",{className:"sme-chip",children:u},u)):e.jsx("span",{className:"sme-muted",children:"none"})}):e.jsxs("div",{className:"sme-syn-row",children:[f.map(u=>e.jsxs("span",{className:"sme-chip removable",onClick:()=>R(f.filter(P=>P!==u)),children:[u," ✕"]},u)),e.jsx("input",{value:g,placeholder:"add + Enter",onChange:u=>_(u.target.value),onKeyDown:u=>{u.key==="Enter"&&g.trim()&&(R([...f,g.trim()]),_(""))}})]})]}),!o&&(c("stewardship")?e.jsxs("div",{className:"sme-field-row",children:[e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Owner"}),e.jsx("p",{className:"sme-readonly-value",children:((D=s.stewardship)==null?void 0:D.owner)??"—"})]}),e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Steward"}),e.jsx("p",{className:"sme-readonly-value",children:((B=s.stewardship)==null?void 0:B.steward)??"—"})]})]}):e.jsxs("div",{className:"sme-field-row",children:[e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Owner"}),e.jsx("input",{value:C,onChange:u=>T(u.target.value),onBlur:()=>k(C,S)})]}),e.jsxs("label",{className:"sme-field",children:[e.jsx("span",{children:"Steward"}),e.jsx("input",{value:S,onChange:u=>y(u.target.value),onBlur:()=>k(C,S)})]})]})),e.jsx(ys,{term:s,onStage:a}),e.jsx("p",{className:"sme-note",children:t.length>0?`${t.length} change(s) staged — use “Submit for review” at the top when you're done.`:"Changes you make are collected until you submit them for review."})]})}const ws=["skos:exactMatch","skos:closeMatch","skos:broadMatch","skos:narrowMatch"];function ys({term:s,onStage:t}){var f;const[a,l]=n.useState(!1),[i,x]=n.useState(s.name),[c,r]=n.useState([]),[m,N]=n.useState("skos:closeMatch"),b=h=>{x(h),qe(h).then(g=>r(g.results)).catch(()=>r([]))};return a?e.jsxs("div",{className:"sme-field sme-align",children:[e.jsx("span",{children:"Propose a standard mapping (a suggestion; the architect confirms)"}),e.jsx("input",{value:i,onChange:h=>b(h.target.value),placeholder:"Search standards…",autoFocus:!0}),e.jsx("div",{className:"sme-align-results",children:c.map(h=>e.jsxs("button",{className:"sme-align-card",onClick:()=>{var g;t({op:"set_alignment",payload:{id:s.id,aligns_to:h.prefixed,alignment:m,status:"proposed"},label:"Standard mapping",before:((g=s.ontology)==null?void 0:g.aligns_to)??"(none)",after:`${h.prefixed} (${m}, proposed)`}),l(!1)},children:[e.jsx("strong",{children:h.label})," ",e.jsx("code",{children:h.prefixed}),h.definition&&e.jsx("span",{className:"sme-align-def",children:h.definition})]},h.iri))}),e.jsx("select",{value:m,onChange:h=>N(h.target.value),children:ws.map(h=>e.jsx("option",{children:h},h))})]}):e.jsxs("div",{className:"sme-field",children:[e.jsx("span",{children:"Standard mapping"}),e.jsxs("div",{children:[(f=s.ontology)!=null&&f.aligns_to?e.jsx("code",{className:"sme-current-align",children:s.ontology.aligns_to}):e.jsx("span",{className:"sme-muted",children:"not mapped to a standard"}),e.jsx("button",{className:"sme-link",onClick:()=>l(!0),children:"Propose a mapping…"})]})]})}function _s(){const[s,t]=n.useState(null),[a,l]=n.useState(!0),[i,x]=n.useState(null),[c,r]=n.useState(""),[m,N]=n.useState(null),[b,f]=n.useState(""),[h,g]=n.useState(""),[_,C]=n.useState(null),[T,S]=n.useState(!1),[y,A]=n.useState([]),[k,R]=n.useState(!1),[o,E]=n.useState(window.location.hash==="#proposals"?"proposals":"browse"),[$,D]=n.useState(new Set),[B,u]=n.useState(()=>localStorage.getItem("mdl.sme.user")??""),[P,F]=n.useState(null),[I,z]=n.useState(null),[W,U]=n.useState(!1),[K,j]=n.useState(null),d=n.useCallback((p,v)=>{var ae;const O=J=>{var te;const V=I==null?void 0:I.entities.find(re=>{var ie;return re.id===J||((ie=re.conceptual)==null?void 0:ie.id)===J});return((te=V==null?void 0:V.conceptual)==null?void 0:te.name)??(V==null?void 0:V.name)??"object"},L=O(v.id??v.entity_id);switch(p){case"create_entity":return{label:`New entity: ${v.name}`,before:"—",after:String(v.name??"")};case"create_relationship":return{label:`New relationship: ${O(v.from_entity)} → ${O(v.to_entity)}`,before:"—",after:String(v.cardinality??"many_to_one")};case"delete_entity":return{label:`Deleted ${L}`,before:L,after:"—"};case"delete_relationship":return{label:"Relationship removed",before:"",after:"—"};case"update_relationship":return{label:"Relationship changed",before:"",after:[v.cardinality,v.optionality,v.identifying?"identifying":""].filter(Boolean).join(", ")};case"set_definition":return{label:`Definition: ${L}`,before:"",after:String(v.definition??"")};case"add_attribute":return{label:`Attribute added to ${L}`,before:"—",after:String(v.name??"")};case"delete_attribute":return{label:`Attribute removed from ${L}`,before:"",after:"—"};case"update_attribute":return{label:`Attribute changed on ${L}`,before:"",after:JSON.stringify(v)};case"rename_entity":return{label:`Renamed ${L}`,before:L,after:String(v.name??"")};case"set_subject_area":return{label:`Subject area: ${L}`,before:"",after:String(v.subject_area??"none")};case"set_stewardship":return{label:`Stewardship: ${L}`,before:"",after:String(v.steward??"")};case"set_subject_area_members":{const J=v.__label,V=((ae=v.members)==null?void 0:ae.length)??0;return{label:J??"Subject area members",before:"",after:`${V} object${V===1?"":"s"}`}}case"set_alignment":return{label:`Alignment: ${L}`,before:"",after:String(v.aligns_to??"")};default:return{label:`${p.replace(/_/g," ")}: ${L}`,before:"",after:""}}},[I]),w=Je({subjectArea:b,describe:d}),M=n.useCallback(async(p,v)=>{const O=(I==null?void 0:I.fingerprint)??"",L=await We(p,v,O);return await le(b||void 0).then(z),L},[I,b]),q=n.useMemo(()=>{const p={};for(const v of w.pending)v.op==="set_subject_area_members"&&(p[v.payload.id]=v.payload.members??[]);return p},[w.pending]),G=n.useMemo(()=>[...y,...w.pending],[y,w.pending]),[Ne,X]=n.useState(null),[we,Z]=n.useState(null);n.useEffect(()=>{if(!G.length){X(null),Z(null);return}const p=new AbortController,v=G.map(O=>({op:O.op,payload:O.payload}));return pe(v,b||void 0,p.signal).then(O=>X(O.diff??null)).catch(O=>{O.name!=="AbortError"&&X(null)}),Ge(v).then(Z).catch(()=>Z(null)),()=>p.abort()},[G,b]);const ye=n.useMemo(()=>Qe(G),[G]).size{E(p),window.location.hash=p==="browse"?"":`#${p}`},[]);n.useEffect(()=>{const p=()=>{const v=window.location.hash;E(v==="#proposals"?"proposals":v==="#review"?"review":v==="#model"?"model":v==="#areas"?"areas":"browse")};return p(),window.addEventListener("hashchange",p),()=>window.removeEventListener("hashchange",p)},[]);const ee=n.useCallback(()=>{He({subject_area:b,q:h}).then(t).catch(p=>N(String(p)))},[b,h]);n.useEffect(ee,[ee]),n.useEffect(()=>{le(b||void 0).then(p=>{l(p.read_only),r(p.project.name),z(p),U(!!p.direct),F(p.identity??null),p.identity&&p.identity.source!=="anonymous"&&p.identity.name&&u(p.identity.name)}).catch(()=>{}),Ve().then(x).catch(()=>{})},[b]);const se=n.useMemo(()=>(s==null?void 0:s.terms.find(p=>p.id===_))??null,[s,_]),_e=n.useCallback(p=>{const v=p.key??fe(p.op,p.payload);A(O=>[...O.filter(L=>L.key!==v),{...p,key:v}])},[]),Se=p=>A(v=>v.filter((O,L)=>L!==p)),ke=()=>{A([]),R(!1),S(!1),ee()};if(m)return e.jsxs("div",{className:"sme-splash error",children:[e.jsx("h1",{children:"◮ Glossary"}),e.jsx("pre",{children:m}),e.jsxs("p",{children:["Is ",e.jsx("code",{children:"mdl glossary"})," pointed at a model?"]})]});if(!s)return e.jsx("div",{className:"sme-splash",children:"◮ loading glossary…"});const Y=!a,ne=(i==null?void 0:i.catalog_owned_fields)??[],Ce=ne.length>0;return e.jsxs("div",{className:"sme",children:[e.jsxs("header",{className:"sme-top",children:[e.jsxs("div",{className:"sme-brand",children:[e.jsx("span",{className:"sme-logo",children:"◮"}),e.jsx("span",{children:"Glossary"}),e.jsx("span",{className:"sme-project",children:c}),a&&e.jsx("span",{className:"sme-chip",children:"read-only"}),Ce&&e.jsxs("span",{className:"sme-chip catalog",title:`Definitions are mastered in ${i==null?void 0:i.catalog_name}`,children:["mirrors ",i==null?void 0:i.catalog_name]})]}),e.jsx("input",{className:"sme-search",type:"search",placeholder:"Search terms & definitions…",value:h,onChange:p=>g(p.target.value)}),e.jsxs("nav",{className:"sme-tabs",children:[e.jsx("button",{className:"sme-tab"+(o==="browse"?" active":""),onClick:()=>H("browse"),children:"Terms"}),e.jsx("button",{className:"sme-tab"+(o==="model"?" active":""),onClick:()=>H("model"),children:"Model"}),e.jsx("button",{className:"sme-tab"+(o==="areas"?" active":""),onClick:()=>H("areas"),children:"Subject areas"}),e.jsx("button",{className:"sme-tab"+(o==="proposals"?" active":""),onClick:()=>H("proposals"),children:"My proposals"})]}),G.length>0&&e.jsxs("button",{className:"sme-tray",onClick:()=>H("review"),children:[G.length," change",G.length>1?"s":""," · Review →"]})]}),o==="browse"&&e.jsx(Xe,{user:B}),o==="review"?e.jsx(xs,{stagedDiff:Ne,stagedRoute:we,user:B,selectable:ye,excluded:$,onToggleObject:p=>D(v=>{const O=new Set(v);return O.has(p)?O.delete(p):O.add(p),O}),onBack:()=>H("browse"),onSubmit:p=>{j(p),R(!0)}}):o==="model"?w.previewDoc??I?e.jsx(ns,{doc:w.previewDoc??I,subjectArea:b,onSubjectArea:f,exec:W?M:w.exec,canEdit:Y,direct:W,onImported:()=>H("review"),query:h,busy:w.busy}):e.jsx("div",{className:"sme-splash",children:"◮ loading the model…"}):o==="areas"?e.jsx(Ze,{exec:w.exec,canEdit:Y,stagedMembers:q}):o==="proposals"?e.jsx(as,{user:B,onView:()=>H("review")}):e.jsxs("div",{className:"sme-body",children:[e.jsxs("nav",{className:"sme-nav",children:[e.jsx("button",{className:"sme-sa"+(b===""?" active":""),onClick:()=>f(""),children:"All subject areas"}),s.subject_areas.map(p=>e.jsx("button",{className:"sme-sa"+(b===p.id?" active":""),onClick:()=>f(p.id),title:p.definition??void 0,children:p.name},p.id))]}),e.jsxs("ul",{className:"sme-list",children:[s.terms.map(p=>{var v;return e.jsxs("li",{className:"sme-list-item"+(p.id===_?" active":""),onClick:()=>{C(p.id),S(!1)},children:[e.jsx("span",{className:"sme-term-name",children:p.name}),p.kind==="term"&&e.jsx("span",{className:"sme-kind",children:"term"}),((v=p.ontology)==null?void 0:v.status)==="proposed"&&e.jsx("span",{className:"sme-badge proposed",title:"alignment awaiting architect",children:"proposed"}),e.jsx("span",{className:"sme-term-def",children:p.definition??"no definition yet"})]},p.id)}),s.terms.length===0&&e.jsx("li",{className:"sme-empty",children:"no terms match"})]}),e.jsx("section",{className:"sme-detail",children:se?T&&Y?e.jsx(Ns,{term:se,pending:y,onStage:_e,onDone:()=>S(!1),catalogOwned:ne,catalog:i?{name:i.catalog_name,url:i.catalog_url}:null}):e.jsx(vs,{term:se,canEdit:Y,pendingCount:y.length,onEdit:()=>S(!0)}):e.jsx("div",{className:"sme-placeholder",children:"Select a term to see its definition."})})]}),k&&e.jsx(is,{changes:G,routeAdvice:K,identity:P,user:B,onUser:p=>{u(p),localStorage.setItem("mdl.sme.user",p)},onDrop:Se,onClose:()=>R(!1),onProposed:()=>{ke(),w.clear(),D(new Set),H("proposals")}})]})}Ae.createRoot(document.getElementById("root")).render(e.jsx(Ee.StrictMode,{children:e.jsx(_s,{})})); diff --git a/packages/server/src/mdl_server/static/assets/styles-B90OKxCj.js b/packages/server/src/mdl_server/static/assets/styles-B90OKxCj.js new file mode 100644 index 0000000..6cbaefa --- /dev/null +++ b/packages/server/src/mdl_server/static/assets/styles-B90OKxCj.js @@ -0,0 +1,23 @@ +var tl=Object.defineProperty;var nl=(e,t,n)=>t in e?tl(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var ue=(e,t,n)=>nl(e,typeof t!="symbol"?t+"":t,n);import{r as w,g as fi,R as M,j as h}from"./client-DOmNpTln.js";function ye(e){if(typeof e=="string"||typeof e=="number")return""+e;let t="";if(Array.isArray(e))for(let n=0,r;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?ul:cl;gi.useSyncExternalStore=Et.useSyncExternalStore!==void 0?Et.useSyncExternalStore:dl;pi.exports=gi;var fl=pi.exports;/** + * @license React + * use-sync-external-store-shim/with-selector.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var kn=w,hl=fl;function ml(e,t){return e===t&&(e!==0||1/e===1/t)||e!==e&&t!==t}var pl=typeof Object.is=="function"?Object.is:ml,gl=hl.useSyncExternalStore,yl=kn.useRef,xl=kn.useEffect,wl=kn.useMemo,bl=kn.useDebugValue;mi.useSyncExternalStoreWithSelector=function(e,t,n,r,s){var i=yl(null);if(i.current===null){var o={hasValue:!1,value:null};i.current=o}else o=i.current;i=wl(function(){function l(f){if(!c){if(c=!0,u=f,f=r(f),s!==void 0&&o.hasValue){var x=o.value;if(s(x,f))return d=x}return d=f}if(x=d,pl(u,f))return x;var y=r(f);return s!==void 0&&s(x,y)?(u=f,x):(u=f,d=y)}var c=!1,u,d,m=n===void 0?null:n;return[function(){return l(t())},m===null?void 0:function(){return l(m())}]},[t,n,r,s]);var a=gl(e,i[0],i[1]);return xl(function(){o.hasValue=!0,o.value=a},[a]),bl(a),a};hi.exports=mi;var vl=hi.exports;const _l=fi(vl),El={},Wr=e=>{let t;const n=new Set,r=(u,d)=>{const m=typeof u=="function"?u(t):u;if(!Object.is(m,t)){const f=t;t=d??(typeof m!="object"||m===null)?m:Object.assign({},t,m),n.forEach(x=>x(t,f))}},s=()=>t,l={setState:r,getState:s,getInitialState:()=>c,subscribe:u=>(n.add(u),()=>n.delete(u)),destroy:()=>{(El?"production":void 0)!=="production"&&console.warn("[DEPRECATED] The `destroy` method will be unsupported in a future version. Instead use unsubscribe function returned by subscribe. Everything will be garbage-collected if store is garbage-collected."),n.clear()}},c=t=e(r,s,l);return l},Nl=e=>e?Wr(e):Wr,{useDebugValue:Sl}=M,{useSyncExternalStoreWithSelector:kl}=_l,jl=e=>e;function yi(e,t=jl,n){const r=kl(e.subscribe,e.getState,e.getServerState||e.getInitialState,t,n);return Sl(r),r}const Ur=(e,t)=>{const n=Nl(e),r=(s,i=t)=>yi(n,s,i);return Object.assign(r,n),r},Cl=(e,t)=>e?Ur(e,t):Ur;function ge(e,t){if(Object.is(e,t))return!0;if(typeof e!="object"||e===null||typeof t!="object"||t===null)return!1;if(e instanceof Map&&t instanceof Map){if(e.size!==t.size)return!1;for(const[r,s]of e)if(!Object.is(s,t.get(r)))return!1;return!0}if(e instanceof Set&&t instanceof Set){if(e.size!==t.size)return!1;for(const r of e)if(!t.has(r))return!1;return!0}const n=Object.keys(e);if(n.length!==Object.keys(t).length)return!1;for(const r of n)if(!Object.prototype.hasOwnProperty.call(t,r)||!Object.is(e[r],t[r]))return!1;return!0}var $l={value:()=>{}};function jn(){for(var e=0,t=arguments.length,n={},r;e=0&&(r=n.slice(s+1),n=n.slice(0,s)),n&&!t.hasOwnProperty(n))throw new Error("unknown type: "+n);return{type:n,name:r}})}cn.prototype=jn.prototype={constructor:cn,on:function(e,t){var n=this._,r=Ml(e+"",n),s,i=-1,o=r.length;if(arguments.length<2){for(;++i0)for(var n=new Array(s),r=0,s,i;r=0&&(t=e.slice(0,n))!=="xmlns"&&(e=e.slice(n+1)),qr.hasOwnProperty(t)?{space:qr[t],local:e}:e}function Il(e){return function(){var t=this.ownerDocument,n=this.namespaceURI;return n===nr&&t.documentElement.namespaceURI===nr?t.createElement(e):t.createElementNS(n,e)}}function Rl(e){return function(){return this.ownerDocument.createElementNS(e.space,e.local)}}function xi(e){var t=Cn(e);return(t.local?Rl:Il)(t)}function Tl(){}function wr(e){return e==null?Tl:function(){return this.querySelector(e)}}function Ol(e){typeof e!="function"&&(e=wr(e));for(var t=this._groups,n=t.length,r=new Array(n),s=0;s=$&&($=E+1);!(A=v[$])&&++$=0;)(o=r[s])&&(i&&o.compareDocumentPosition(i)^4&&i.parentNode.insertBefore(o,i),i=o);return this}function oc(e){e||(e=ac);function t(d,m){return d&&m?e(d.__data__,m.__data__):!d-!m}for(var n=this._groups,r=n.length,s=new Array(r),i=0;it?1:e>=t?0:NaN}function lc(){var e=arguments[0];return arguments[0]=this,e.apply(null,arguments),this}function cc(){return Array.from(this)}function uc(){for(var e=this._groups,t=0,n=e.length;t1?this.each((t==null?vc:typeof t=="function"?Ec:_c)(e,t,n??"")):Nt(this.node(),e)}function Nt(e,t){return e.style.getPropertyValue(t)||Ei(e).getComputedStyle(e,null).getPropertyValue(t)}function Sc(e){return function(){delete this[e]}}function kc(e,t){return function(){this[e]=t}}function jc(e,t){return function(){var n=t.apply(this,arguments);n==null?delete this[e]:this[e]=n}}function Cc(e,t){return arguments.length>1?this.each((t==null?Sc:typeof t=="function"?jc:kc)(e,t)):this.node()[e]}function Ni(e){return e.trim().split(/^|\s+/)}function br(e){return e.classList||new Si(e)}function Si(e){this._node=e,this._names=Ni(e.getAttribute("class")||"")}Si.prototype={add:function(e){var t=this._names.indexOf(e);t<0&&(this._names.push(e),this._node.setAttribute("class",this._names.join(" ")))},remove:function(e){var t=this._names.indexOf(e);t>=0&&(this._names.splice(t,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(e){return this._names.indexOf(e)>=0}};function ki(e,t){for(var n=br(e),r=-1,s=t.length;++r=0&&(n=t.slice(r+1),t=t.slice(0,r)),{type:t,name:n}})}function nu(e){return function(){var t=this.__on;if(t){for(var n=0,r=-1,s=t.length,i;n()=>e;function rr(e,{sourceEvent:t,subject:n,target:r,identifier:s,active:i,x:o,y:a,dx:l,dy:c,dispatch:u}){Object.defineProperties(this,{type:{value:e,enumerable:!0,configurable:!0},sourceEvent:{value:t,enumerable:!0,configurable:!0},subject:{value:n,enumerable:!0,configurable:!0},target:{value:r,enumerable:!0,configurable:!0},identifier:{value:s,enumerable:!0,configurable:!0},active:{value:i,enumerable:!0,configurable:!0},x:{value:o,enumerable:!0,configurable:!0},y:{value:a,enumerable:!0,configurable:!0},dx:{value:l,enumerable:!0,configurable:!0},dy:{value:c,enumerable:!0,configurable:!0},_:{value:u}})}rr.prototype.on=function(){var e=this._.on.apply(this._,arguments);return e===this._?this:e};function fu(e){return!e.ctrlKey&&!e.button}function hu(){return this.parentNode}function mu(e,t){return t??{x:e.x,y:e.y}}function pu(){return navigator.maxTouchPoints||"ontouchstart"in this}function gu(){var e=fu,t=hu,n=mu,r=pu,s={},i=jn("start","drag","end"),o=0,a,l,c,u,d=0;function m(b){b.on("mousedown.drag",f).filter(r).on("touchstart.drag",v).on("touchmove.drag",p,du).on("touchend.drag touchcancel.drag",E).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function f(b,A){if(!(u||!e.call(this,b,A))){var j=$(this,t.call(this,b,A),b,A,"mouse");j&&(Ne(b.view).on("mousemove.drag",x,zt).on("mouseup.drag",y,zt),Mi(b.view),Hn(b),c=!1,a=b.clientX,l=b.clientY,j("start",b))}}function x(b){if(wt(b),!c){var A=b.clientX-a,j=b.clientY-l;c=A*A+j*j>d}s.mouse("drag",b)}function y(b){Ne(b.view).on("mousemove.drag mouseup.drag",null),Ai(b.view,c),wt(b),s.mouse("end",b)}function v(b,A){if(e.call(this,b,A)){var j=b.changedTouches,_=t.call(this,b,A),I=j.length,S,D;for(S=0;S>8&15|t>>4&240,t>>4&15|t&240,(t&15)<<4|t&15,1):n===8?Jt(t>>24&255,t>>16&255,t>>8&255,(t&255)/255):n===4?Jt(t>>12&15|t>>8&240,t>>8&15|t>>4&240,t>>4&15|t&240,((t&15)<<4|t&15)/255):null):(t=xu.exec(e))?new ve(t[1],t[2],t[3],1):(t=wu.exec(e))?new ve(t[1]*255/100,t[2]*255/100,t[3]*255/100,1):(t=bu.exec(e))?Jt(t[1],t[2],t[3],t[4]):(t=vu.exec(e))?Jt(t[1]*255/100,t[2]*255/100,t[3]*255/100,t[4]):(t=_u.exec(e))?ns(t[1],t[2]/100,t[3]/100,1):(t=Eu.exec(e))?ns(t[1],t[2]/100,t[3]/100,t[4]):Kr.hasOwnProperty(e)?Jr(Kr[e]):e==="transparent"?new ve(NaN,NaN,NaN,0):null}function Jr(e){return new ve(e>>16&255,e>>8&255,e&255,1)}function Jt(e,t,n,r){return r<=0&&(e=t=n=NaN),new ve(e,t,n,r)}function ku(e){return e instanceof Xt||(e=Vt(e)),e?(e=e.rgb(),new ve(e.r,e.g,e.b,e.opacity)):new ve}function sr(e,t,n,r){return arguments.length===1?ku(e):new ve(e,t,n,r??1)}function ve(e,t,n,r){this.r=+e,this.g=+t,this.b=+n,this.opacity=+r}vr(ve,sr,Ii(Xt,{brighter(e){return e=e==null?mn:Math.pow(mn,e),new ve(this.r*e,this.g*e,this.b*e,this.opacity)},darker(e){return e=e==null?Ht:Math.pow(Ht,e),new ve(this.r*e,this.g*e,this.b*e,this.opacity)},rgb(){return this},clamp(){return new ve(at(this.r),at(this.g),at(this.b),pn(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:es,formatHex:es,formatHex8:ju,formatRgb:ts,toString:ts}));function es(){return`#${it(this.r)}${it(this.g)}${it(this.b)}`}function ju(){return`#${it(this.r)}${it(this.g)}${it(this.b)}${it((isNaN(this.opacity)?1:this.opacity)*255)}`}function ts(){const e=pn(this.opacity);return`${e===1?"rgb(":"rgba("}${at(this.r)}, ${at(this.g)}, ${at(this.b)}${e===1?")":`, ${e})`}`}function pn(e){return isNaN(e)?1:Math.max(0,Math.min(1,e))}function at(e){return Math.max(0,Math.min(255,Math.round(e)||0))}function it(e){return e=at(e),(e<16?"0":"")+e.toString(16)}function ns(e,t,n,r){return r<=0?e=t=n=NaN:n<=0||n>=1?e=t=NaN:t<=0&&(e=NaN),new Me(e,t,n,r)}function Ri(e){if(e instanceof Me)return new Me(e.h,e.s,e.l,e.opacity);if(e instanceof Xt||(e=Vt(e)),!e)return new Me;if(e instanceof Me)return e;e=e.rgb();var t=e.r/255,n=e.g/255,r=e.b/255,s=Math.min(t,n,r),i=Math.max(t,n,r),o=NaN,a=i-s,l=(i+s)/2;return a?(t===i?o=(n-r)/a+(n0&&l<1?0:o,new Me(o,a,l,e.opacity)}function Cu(e,t,n,r){return arguments.length===1?Ri(e):new Me(e,t,n,r??1)}function Me(e,t,n,r){this.h=+e,this.s=+t,this.l=+n,this.opacity=+r}vr(Me,Cu,Ii(Xt,{brighter(e){return e=e==null?mn:Math.pow(mn,e),new Me(this.h,this.s,this.l*e,this.opacity)},darker(e){return e=e==null?Ht:Math.pow(Ht,e),new Me(this.h,this.s,this.l*e,this.opacity)},rgb(){var e=this.h%360+(this.h<0)*360,t=isNaN(e)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*t,s=2*n-r;return new ve(Fn(e>=240?e-240:e+120,s,r),Fn(e,s,r),Fn(e<120?e+240:e-120,s,r),this.opacity)},clamp(){return new Me(rs(this.h),en(this.s),en(this.l),pn(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const e=pn(this.opacity);return`${e===1?"hsl(":"hsla("}${rs(this.h)}, ${en(this.s)*100}%, ${en(this.l)*100}%${e===1?")":`, ${e})`}`}}));function rs(e){return e=(e||0)%360,e<0?e+360:e}function en(e){return Math.max(0,Math.min(1,e||0))}function Fn(e,t,n){return(e<60?t+(n-t)*e/60:e<180?n:e<240?t+(n-t)*(240-e)/60:t)*255}const Ti=e=>()=>e;function $u(e,t){return function(n){return e+n*t}}function Mu(e,t,n){return e=Math.pow(e,n),t=Math.pow(t,n)-e,n=1/n,function(r){return Math.pow(e+r*t,n)}}function Au(e){return(e=+e)==1?Oi:function(t,n){return n-t?Mu(t,n,e):Ti(isNaN(t)?n:t)}}function Oi(e,t){var n=t-e;return n?$u(e,n):Ti(isNaN(e)?t:e)}const ss=function e(t){var n=Au(t);function r(s,i){var o=n((s=sr(s)).r,(i=sr(i)).r),a=n(s.g,i.g),l=n(s.b,i.b),c=Oi(s.opacity,i.opacity);return function(u){return s.r=o(u),s.g=a(u),s.b=l(u),s.opacity=c(u),s+""}}return r.gamma=e,r}(1);function Ue(e,t){return e=+e,t=+t,function(n){return e*(1-n)+t*n}}var ir=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,Vn=new RegExp(ir.source,"g");function Iu(e){return function(){return e}}function Ru(e){return function(t){return e(t)+""}}function Tu(e,t){var n=ir.lastIndex=Vn.lastIndex=0,r,s,i,o=-1,a=[],l=[];for(e=e+"",t=t+"";(r=ir.exec(e))&&(s=Vn.exec(t));)(i=s.index)>n&&(i=t.slice(n,i),a[o]?a[o]+=i:a[++o]=i),(r=r[0])===(s=s[0])?a[o]?a[o]+=s:a[++o]=s:(a[++o]=null,l.push({i:o,x:Ue(r,s)})),n=Vn.lastIndex;return n180?u+=360:u-c>180&&(c+=360),m.push({i:d.push(s(d)+"rotate(",null,r)-2,x:Ue(c,u)})):u&&d.push(s(d)+"rotate("+u+r)}function a(c,u,d,m){c!==u?m.push({i:d.push(s(d)+"skewX(",null,r)-2,x:Ue(c,u)}):u&&d.push(s(d)+"skewX("+u+r)}function l(c,u,d,m,f,x){if(c!==d||u!==m){var y=f.push(s(f)+"scale(",null,",",null,")");x.push({i:y-4,x:Ue(c,d)},{i:y-2,x:Ue(u,m)})}else(d!==1||m!==1)&&f.push(s(f)+"scale("+d+","+m+")")}return function(c,u){var d=[],m=[];return c=e(c),u=e(u),i(c.translateX,c.translateY,u.translateX,u.translateY,d,m),o(c.rotate,u.rotate,d,m),a(c.skewX,u.skewX,d,m),l(c.scaleX,c.scaleY,u.scaleX,u.scaleY,d,m),c=u=null,function(f){for(var x=-1,y=m.length,v;++x=0&&e._call.call(void 0,t),e=e._next;--St}function as(){ct=(yn=Bt.now())+$n,St=Ot=0;try{Gu()}finally{St=0,Wu(),ct=0}}function Yu(){var e=Bt.now(),t=e-yn;t>Pi&&($n-=t,yn=e)}function Wu(){for(var e,t=gn,n,r=1/0;t;)t._call?(r>t._time&&(r=t._time),e=t,t=t._next):(n=t._next,t._next=null,t=e?e._next=n:gn=n);Dt=e,ar(r)}function ar(e){if(!St){Ot&&(Ot=clearTimeout(Ot));var t=e-ct;t>24?(e<1/0&&(Ot=setTimeout(as,e-Bt.now()-$n)),Mt&&(Mt=clearInterval(Mt))):(Mt||(yn=Bt.now(),Mt=setInterval(Yu,Pi)),St=1,zi(as))}}function ls(e,t,n){var r=new xn;return t=t==null?0:+t,r.restart(s=>{r.stop(),e(s+t)},t,n),r}var Uu=jn("start","end","cancel","interrupt"),Xu=[],Fi=0,cs=1,lr=2,un=3,us=4,cr=5,dn=6;function Mn(e,t,n,r,s,i){var o=e.__transition;if(!o)e.__transition={};else if(n in o)return;qu(e,n,{name:t,index:r,group:s,on:Uu,tween:Xu,time:i.time,delay:i.delay,duration:i.duration,ease:i.ease,timer:null,state:Fi})}function Er(e,t){var n=Ae(e,t);if(n.state>Fi)throw new Error("too late; already scheduled");return n}function Oe(e,t){var n=Ae(e,t);if(n.state>un)throw new Error("too late; already running");return n}function Ae(e,t){var n=e.__transition;if(!n||!(n=n[t]))throw new Error("transition not found");return n}function qu(e,t,n){var r=e.__transition,s;r[t]=n,n.timer=Hi(i,0,n.time);function i(c){n.state=cs,n.timer.restart(o,n.delay,n.time),n.delay<=c&&o(c-n.delay)}function o(c){var u,d,m,f;if(n.state!==cs)return l();for(u in r)if(f=r[u],f.name===n.name){if(f.state===un)return ls(o);f.state===us?(f.state=dn,f.timer.stop(),f.on.call("interrupt",e,e.__data__,f.index,f.group),delete r[u]):+ulr&&r.state=0&&(t=t.slice(0,n)),!t||t==="start"})}function Sd(e,t,n){var r,s,i=Nd(t)?Er:Oe;return function(){var o=i(this,e),a=o.on;a!==r&&(s=(r=a).copy()).on(t,n),o.on=s}}function kd(e,t){var n=this._id;return arguments.length<2?Ae(this.node(),n).on.on(e):this.each(Sd(n,e,t))}function jd(e){return function(){var t=this.parentNode;for(var n in this.__transition)if(+n!==e)return;t&&t.removeChild(this)}}function Cd(){return this.on("end.remove",jd(this._id))}function $d(e){var t=this._name,n=this._id;typeof e!="function"&&(e=wr(e));for(var r=this._groups,s=r.length,i=new Array(s),o=0;o()=>e;function ef(e,{sourceEvent:t,target:n,transform:r,dispatch:s}){Object.defineProperties(this,{type:{value:e,enumerable:!0,configurable:!0},sourceEvent:{value:t,enumerable:!0,configurable:!0},target:{value:n,enumerable:!0,configurable:!0},transform:{value:r,enumerable:!0,configurable:!0},_:{value:s}})}function He(e,t,n){this.k=e,this.x=t,this.y=n}He.prototype={constructor:He,scale:function(e){return e===1?this:new He(this.k*e,this.x,this.y)},translate:function(e,t){return e===0&t===0?this:new He(this.k,this.x+this.k*e,this.y+this.k*t)},apply:function(e){return[e[0]*this.k+this.x,e[1]*this.k+this.y]},applyX:function(e){return e*this.k+this.x},applyY:function(e){return e*this.k+this.y},invert:function(e){return[(e[0]-this.x)/this.k,(e[1]-this.y)/this.k]},invertX:function(e){return(e-this.x)/this.k},invertY:function(e){return(e-this.y)/this.k},rescaleX:function(e){return e.copy().domain(e.range().map(this.invertX,this).map(e.invert,e))},rescaleY:function(e){return e.copy().domain(e.range().map(this.invertY,this).map(e.invert,e))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var Fe=new He(1,0,0);He.prototype;function Bn(e){e.stopImmediatePropagation()}function At(e){e.preventDefault(),e.stopImmediatePropagation()}function tf(e){return(!e.ctrlKey||e.type==="wheel")&&!e.button}function nf(){var e=this;return e instanceof SVGElement?(e=e.ownerSVGElement||e,e.hasAttribute("viewBox")?(e=e.viewBox.baseVal,[[e.x,e.y],[e.x+e.width,e.y+e.height]]):[[0,0],[e.width.baseVal.value,e.height.baseVal.value]]):[[0,0],[e.clientWidth,e.clientHeight]]}function ds(){return this.__zoom||Fe}function rf(e){return-e.deltaY*(e.deltaMode===1?.05:e.deltaMode?1:.002)*(e.ctrlKey?10:1)}function sf(){return navigator.maxTouchPoints||"ontouchstart"in this}function of(e,t,n){var r=e.invertX(t[0][0])-n[0][0],s=e.invertX(t[1][0])-n[1][0],i=e.invertY(t[0][1])-n[0][1],o=e.invertY(t[1][1])-n[1][1];return e.translate(s>r?(r+s)/2:Math.min(0,r)||Math.max(0,s),o>i?(i+o)/2:Math.min(0,i)||Math.max(0,o))}function Yi(){var e=tf,t=nf,n=of,r=rf,s=sf,i=[0,1/0],o=[[-1/0,-1/0],[1/0,1/0]],a=250,l=Vu,c=jn("start","zoom","end"),u,d,m,f=500,x=150,y=0,v=10;function p(g){g.property("__zoom",ds).on("wheel.zoom",I,{passive:!1}).on("mousedown.zoom",S).on("dblclick.zoom",D).filter(s).on("touchstart.zoom",P).on("touchmove.zoom",V).on("touchend.zoom touchcancel.zoom",F).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}p.transform=function(g,C,N,R){var H=g.selection?g.selection():g;H.property("__zoom",ds),g!==H?A(g,C,N,R):H.interrupt().each(function(){j(this,arguments).event(R).start().zoom(null,typeof C=="function"?C.apply(this,arguments):C).end()})},p.scaleBy=function(g,C,N,R){p.scaleTo(g,function(){var H=this.__zoom.k,k=typeof C=="function"?C.apply(this,arguments):C;return H*k},N,R)},p.scaleTo=function(g,C,N,R){p.transform(g,function(){var H=t.apply(this,arguments),k=this.__zoom,T=N==null?b(H):typeof N=="function"?N.apply(this,arguments):N,L=k.invert(T),z=typeof C=="function"?C.apply(this,arguments):C;return n($(E(k,z),T,L),H,o)},N,R)},p.translateBy=function(g,C,N,R){p.transform(g,function(){return n(this.__zoom.translate(typeof C=="function"?C.apply(this,arguments):C,typeof N=="function"?N.apply(this,arguments):N),t.apply(this,arguments),o)},null,R)},p.translateTo=function(g,C,N,R,H){p.transform(g,function(){var k=t.apply(this,arguments),T=this.__zoom,L=R==null?b(k):typeof R=="function"?R.apply(this,arguments):R;return n(Fe.translate(L[0],L[1]).scale(T.k).translate(typeof C=="function"?-C.apply(this,arguments):-C,typeof N=="function"?-N.apply(this,arguments):-N),k,o)},R,H)};function E(g,C){return C=Math.max(i[0],Math.min(i[1],C)),C===g.k?g:new He(C,g.x,g.y)}function $(g,C,N){var R=C[0]-N[0]*g.k,H=C[1]-N[1]*g.k;return R===g.x&&H===g.y?g:new He(g.k,R,H)}function b(g){return[(+g[0][0]+ +g[1][0])/2,(+g[0][1]+ +g[1][1])/2]}function A(g,C,N,R){g.on("start.zoom",function(){j(this,arguments).event(R).start()}).on("interrupt.zoom end.zoom",function(){j(this,arguments).event(R).end()}).tween("zoom",function(){var H=this,k=arguments,T=j(H,k).event(R),L=t.apply(H,k),z=N==null?b(L):typeof N=="function"?N.apply(H,k):N,Y=Math.max(L[1][0]-L[0][0],L[1][1]-L[0][1]),G=H.__zoom,K=typeof C=="function"?C.apply(H,k):C,J=l(G.invert(z).concat(Y/G.k),K.invert(z).concat(Y/K.k));return function(ee){if(ee===1)ee=K;else{var ie=J(ee),te=Y/ie[2];ee=new He(te,z[0]-ie[0]*te,z[1]-ie[1]*te)}T.zoom(null,ee)}})}function j(g,C,N){return!N&&g.__zooming||new _(g,C)}function _(g,C){this.that=g,this.args=C,this.active=0,this.sourceEvent=null,this.extent=t.apply(g,C),this.taps=0}_.prototype={event:function(g){return g&&(this.sourceEvent=g),this},start:function(){return++this.active===1&&(this.that.__zooming=this,this.emit("start")),this},zoom:function(g,C){return this.mouse&&g!=="mouse"&&(this.mouse[1]=C.invert(this.mouse[0])),this.touch0&&g!=="touch"&&(this.touch0[1]=C.invert(this.touch0[0])),this.touch1&&g!=="touch"&&(this.touch1[1]=C.invert(this.touch1[0])),this.that.__zoom=C,this.emit("zoom"),this},end:function(){return--this.active===0&&(delete this.that.__zooming,this.emit("end")),this},emit:function(g){var C=Ne(this.that).datum();c.call(g,this.that,new ef(g,{sourceEvent:this.sourceEvent,target:p,transform:this.that.__zoom,dispatch:c}),C)}};function I(g,...C){if(!e.apply(this,arguments))return;var N=j(this,C).event(g),R=this.__zoom,H=Math.max(i[0],Math.min(i[1],R.k*Math.pow(2,r.apply(this,arguments)))),k=$e(g);if(N.wheel)(N.mouse[0][0]!==k[0]||N.mouse[0][1]!==k[1])&&(N.mouse[1]=R.invert(N.mouse[0]=k)),clearTimeout(N.wheel);else{if(R.k===H)return;N.mouse=[k,R.invert(k)],fn(this),N.start()}At(g),N.wheel=setTimeout(T,x),N.zoom("mouse",n($(E(R,H),N.mouse[0],N.mouse[1]),N.extent,o));function T(){N.wheel=null,N.end()}}function S(g,...C){if(m||!e.apply(this,arguments))return;var N=g.currentTarget,R=j(this,C,!0).event(g),H=Ne(g.view).on("mousemove.zoom",z,!0).on("mouseup.zoom",Y,!0),k=$e(g,N),T=g.clientX,L=g.clientY;Mi(g.view),Bn(g),R.mouse=[k,this.__zoom.invert(k)],fn(this),R.start();function z(G){if(At(G),!R.moved){var K=G.clientX-T,J=G.clientY-L;R.moved=K*K+J*J>y}R.event(G).zoom("mouse",n($(R.that.__zoom,R.mouse[0]=$e(G,N),R.mouse[1]),R.extent,o))}function Y(G){H.on("mousemove.zoom mouseup.zoom",null),Ai(G.view,R.moved),At(G),R.event(G).end()}}function D(g,...C){if(e.apply(this,arguments)){var N=this.__zoom,R=$e(g.changedTouches?g.changedTouches[0]:g,this),H=N.invert(R),k=N.k*(g.shiftKey?.5:2),T=n($(E(N,k),R,H),t.apply(this,C),o);At(g),a>0?Ne(this).transition().duration(a).call(A,T,R,g):Ne(this).call(p.transform,T,R,g)}}function P(g,...C){if(e.apply(this,arguments)){var N=g.touches,R=N.length,H=j(this,C,g.changedTouches.length===R).event(g),k,T,L,z;for(Bn(g),T=0;T"[React Flow]: Seems like you have not used zustand provider as an ancestor. Help: https://reactflow.dev/error#001",error002:()=>"It looks like you've created a new nodeTypes or edgeTypes object. If this wasn't on purpose please define the nodeTypes/edgeTypes outside of the component or memoize them.",error003:e=>`Node type "${e}" not found. Using fallback type "default".`,error004:()=>"The React Flow parent container needs a width and a height to render the graph.",error005:()=>"Only child nodes can use a parent extent.",error006:()=>"Can't create edge. An edge needs a source and a target.",error007:e=>`The old edge with id=${e} does not exist.`,error009:e=>`Marker type "${e}" doesn't exist.`,error008:(e,t)=>`Couldn't create edge for ${e?"target":"source"} handle id: "${e?t.targetHandle:t.sourceHandle}", edge id: ${t.id}.`,error010:()=>"Handle: No node id found. Make sure to only use a Handle inside a custom Node.",error011:e=>`Edge type "${e}" not found. Using fallback type "default".`,error012:e=>`Node with id "${e}" does not exist, it may have been removed. This can happen when a node is deleted before the "onNodeClick" handler is called.`},Wi=Be.error001();function ae(e,t){const n=w.useContext(An);if(n===null)throw new Error(Wi);return yi(n,e,t)}const pe=()=>{const e=w.useContext(An);if(e===null)throw new Error(Wi);return w.useMemo(()=>({getState:e.getState,setState:e.setState,subscribe:e.subscribe,destroy:e.destroy}),[e])},lf=e=>e.userSelectionActive?"none":"all";function Sr({position:e,children:t,className:n,style:r,...s}){const i=ae(lf),o=`${e}`.split("-");return M.createElement("div",{className:ye(["react-flow__panel",n,...o]),style:{...r,pointerEvents:i},...s},t)}function cf({proOptions:e,position:t="bottom-right"}){return e!=null&&e.hideAttribution?null:M.createElement(Sr,{position:t,className:"react-flow__attribution","data-message":"Please only hide this attribution when you are subscribed to React Flow Pro: https://reactflow.dev/pro"},M.createElement("a",{href:"https://reactflow.dev",target:"_blank",rel:"noopener noreferrer","aria-label":"React Flow attribution"},"React Flow"))}const uf=({x:e,y:t,label:n,labelStyle:r={},labelShowBg:s=!0,labelBgStyle:i={},labelBgPadding:o=[2,4],labelBgBorderRadius:a=2,children:l,className:c,...u})=>{const d=w.useRef(null),[m,f]=w.useState({x:0,y:0,width:0,height:0}),x=ye(["react-flow__edge-textwrapper",c]);return w.useEffect(()=>{if(d.current){const y=d.current.getBBox();f({x:y.x,y:y.y,width:y.width,height:y.height})}},[n]),typeof n>"u"||!n?null:M.createElement("g",{transform:`translate(${e-m.width/2} ${t-m.height/2})`,className:x,visibility:m.width?"visible":"hidden",...u},s&&M.createElement("rect",{width:m.width+2*o[0],x:-o[0],y:-o[1],height:m.height+2*o[1],className:"react-flow__edge-textbg",style:i,rx:a,ry:a}),M.createElement("text",{className:"react-flow__edge-text",y:m.height/2,dy:"0.3em",ref:d,style:r},n),l)};var df=w.memo(uf);const kr=e=>({width:e.offsetWidth,height:e.offsetHeight}),kt=(e,t=0,n=1)=>Math.min(Math.max(e,t),n),jr=(e={x:0,y:0},t)=>({x:kt(e.x,t[0][0],t[1][0]),y:kt(e.y,t[0][1],t[1][1])}),fs=(e,t,n)=>en?-kt(Math.abs(e-n),1,50)/50:0,Ui=(e,t)=>{const n=fs(e.x,35,t.width-35)*20,r=fs(e.y,35,t.height-35)*20;return[n,r]},Xi=e=>{var t;return((t=e.getRootNode)==null?void 0:t.call(e))||(window==null?void 0:window.document)},qi=(e,t)=>({x:Math.min(e.x,t.x),y:Math.min(e.y,t.y),x2:Math.max(e.x2,t.x2),y2:Math.max(e.y2,t.y2)}),Gt=({x:e,y:t,width:n,height:r})=>({x:e,y:t,x2:e+n,y2:t+r}),Ki=({x:e,y:t,x2:n,y2:r})=>({x:e,y:t,width:n-e,height:r-t}),hs=e=>({...e.positionAbsolute||{x:0,y:0},width:e.width||0,height:e.height||0}),ff=(e,t)=>Ki(qi(Gt(e),Gt(t))),ur=(e,t)=>{const n=Math.max(0,Math.min(e.x+e.width,t.x+t.width)-Math.max(e.x,t.x)),r=Math.max(0,Math.min(e.y+e.height,t.y+t.height)-Math.max(e.y,t.y));return Math.ceil(n*r)},hf=e=>Se(e.width)&&Se(e.height)&&Se(e.x)&&Se(e.y),Se=e=>!isNaN(e)&&isFinite(e),le=Symbol.for("internals"),Zi=["Enter"," ","Escape"],mf=(e,t)=>{},pf=e=>"nativeEvent"in e;function dr(e){var s,i;const t=pf(e)?e.nativeEvent:e,n=((i=(s=t.composedPath)==null?void 0:s.call(t))==null?void 0:i[0])||e.target;return["INPUT","SELECT","TEXTAREA"].includes(n==null?void 0:n.nodeName)||(n==null?void 0:n.hasAttribute("contenteditable"))||!!(n!=null&&n.closest(".nokey"))}const Qi=e=>"clientX"in e,Ze=(e,t)=>{var i,o;const n=Qi(e),r=n?e.clientX:(i=e.touches)==null?void 0:i[0].clientX,s=n?e.clientY:(o=e.touches)==null?void 0:o[0].clientY;return{x:r-((t==null?void 0:t.left)??0),y:s-((t==null?void 0:t.top)??0)}},wn=()=>{var e;return typeof navigator<"u"&&((e=navigator==null?void 0:navigator.userAgent)==null?void 0:e.indexOf("Mac"))>=0},qt=({id:e,path:t,labelX:n,labelY:r,label:s,labelStyle:i,labelShowBg:o,labelBgStyle:a,labelBgPadding:l,labelBgBorderRadius:c,style:u,markerEnd:d,markerStart:m,interactionWidth:f=20})=>M.createElement(M.Fragment,null,M.createElement("path",{id:e,style:u,d:t,fill:"none",className:"react-flow__edge-path",markerEnd:d,markerStart:m}),f&&M.createElement("path",{d:t,fill:"none",strokeOpacity:0,strokeWidth:f,className:"react-flow__edge-interaction"}),s&&Se(n)&&Se(r)?M.createElement(df,{x:n,y:r,label:s,labelStyle:i,labelShowBg:o,labelBgStyle:a,labelBgPadding:l,labelBgBorderRadius:c}):null);qt.displayName="BaseEdge";function It(e,t,n){return n===void 0?n:r=>{const s=t().edges.find(i=>i.id===e);s&&n(r,{...s})}}function Ji({sourceX:e,sourceY:t,targetX:n,targetY:r}){const s=Math.abs(n-e)/2,i=n{const[v,p,E]=to({sourceX:e,sourceY:t,sourcePosition:s,targetX:n,targetY:r,targetPosition:i});return M.createElement(qt,{path:v,labelX:p,labelY:E,label:o,labelStyle:a,labelShowBg:l,labelBgStyle:c,labelBgPadding:u,labelBgBorderRadius:d,style:m,markerEnd:f,markerStart:x,interactionWidth:y})});Cr.displayName="SimpleBezierEdge";const ps={[Z.Left]:{x:-1,y:0},[Z.Right]:{x:1,y:0},[Z.Top]:{x:0,y:-1},[Z.Bottom]:{x:0,y:1}},gf=({source:e,sourcePosition:t=Z.Bottom,target:n})=>t===Z.Left||t===Z.Right?e.xMath.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2));function yf({source:e,sourcePosition:t=Z.Bottom,target:n,targetPosition:r=Z.Top,center:s,offset:i}){const o=ps[t],a=ps[r],l={x:e.x+o.x*i,y:e.y+o.y*i},c={x:n.x+a.x*i,y:n.y+a.y*i},u=gf({source:l,sourcePosition:t,target:c}),d=u.x!==0?"x":"y",m=u[d];let f=[],x,y;const v={x:0,y:0},p={x:0,y:0},[E,$,b,A]=Ji({sourceX:e.x,sourceY:e.y,targetX:n.x,targetY:n.y});if(o[d]*a[d]===-1){x=s.x??E,y=s.y??$;const _=[{x,y:l.y},{x,y:c.y}],I=[{x:l.x,y},{x:c.x,y}];o[d]===m?f=d==="x"?_:I:f=d==="x"?I:_}else{const _=[{x:l.x,y:c.y}],I=[{x:c.x,y:l.y}];if(d==="x"?f=o.x===m?I:_:f=o.y===m?_:I,t===r){const F=Math.abs(e[d]-n[d]);if(F<=i){const g=Math.min(i-1,i-F);o[d]===m?v[d]=(l[d]>e[d]?-1:1)*g:p[d]=(c[d]>n[d]?-1:1)*g}}if(t!==r){const F=d==="x"?"y":"x",g=o[d]===a[F],C=l[F]>c[F],N=l[F]=V?(x=(S.x+D.x)/2,y=f[0].y):(x=f[0].x,y=(S.y+D.y)/2)}return[[e,{x:l.x+v.x,y:l.y+v.y},...f,{x:c.x+p.x,y:c.y+p.y},n],x,y,b,A]}function xf(e,t,n,r){const s=Math.min(gs(e,t)/2,gs(t,n)/2,r),{x:i,y:o}=t;if(e.x===i&&i===n.x||e.y===o&&o===n.y)return`L${i} ${o}`;if(e.y===o){const c=e.x{let $="";return E>0&&E{const[p,E,$]=vn({sourceX:e,sourceY:t,sourcePosition:d,targetX:n,targetY:r,targetPosition:m,borderRadius:y==null?void 0:y.borderRadius,offset:y==null?void 0:y.offset});return M.createElement(qt,{path:p,labelX:E,labelY:$,label:s,labelStyle:i,labelShowBg:o,labelBgStyle:a,labelBgPadding:l,labelBgBorderRadius:c,style:u,markerEnd:f,markerStart:x,interactionWidth:v})});In.displayName="SmoothStepEdge";const $r=w.memo(e=>{var t;return M.createElement(In,{...e,pathOptions:w.useMemo(()=>{var n;return{borderRadius:0,offset:(n=e.pathOptions)==null?void 0:n.offset}},[(t=e.pathOptions)==null?void 0:t.offset])})});$r.displayName="StepEdge";function wf({sourceX:e,sourceY:t,targetX:n,targetY:r}){const[s,i,o,a]=Ji({sourceX:e,sourceY:t,targetX:n,targetY:r});return[`M ${e},${t}L ${n},${r}`,s,i,o,a]}const Mr=w.memo(({sourceX:e,sourceY:t,targetX:n,targetY:r,label:s,labelStyle:i,labelShowBg:o,labelBgStyle:a,labelBgPadding:l,labelBgBorderRadius:c,style:u,markerEnd:d,markerStart:m,interactionWidth:f})=>{const[x,y,v]=wf({sourceX:e,sourceY:t,targetX:n,targetY:r});return M.createElement(qt,{path:x,labelX:y,labelY:v,label:s,labelStyle:i,labelShowBg:o,labelBgStyle:a,labelBgPadding:l,labelBgBorderRadius:c,style:u,markerEnd:d,markerStart:m,interactionWidth:f})});Mr.displayName="StraightEdge";function rn(e,t){return e>=0?.5*e:t*25*Math.sqrt(-e)}function ys({pos:e,x1:t,y1:n,x2:r,y2:s,c:i}){switch(e){case Z.Left:return[t-rn(t-r,i),n];case Z.Right:return[t+rn(r-t,i),n];case Z.Top:return[t,n-rn(n-s,i)];case Z.Bottom:return[t,n+rn(s-n,i)]}}function no({sourceX:e,sourceY:t,sourcePosition:n=Z.Bottom,targetX:r,targetY:s,targetPosition:i=Z.Top,curvature:o=.25}){const[a,l]=ys({pos:n,x1:e,y1:t,x2:r,y2:s,c:o}),[c,u]=ys({pos:i,x1:r,y1:s,x2:e,y2:t,c:o}),[d,m,f,x]=eo({sourceX:e,sourceY:t,targetX:r,targetY:s,sourceControlX:a,sourceControlY:l,targetControlX:c,targetControlY:u});return[`M${e},${t} C${a},${l} ${c},${u} ${r},${s}`,d,m,f,x]}const _n=w.memo(({sourceX:e,sourceY:t,targetX:n,targetY:r,sourcePosition:s=Z.Bottom,targetPosition:i=Z.Top,label:o,labelStyle:a,labelShowBg:l,labelBgStyle:c,labelBgPadding:u,labelBgBorderRadius:d,style:m,markerEnd:f,markerStart:x,pathOptions:y,interactionWidth:v})=>{const[p,E,$]=no({sourceX:e,sourceY:t,sourcePosition:s,targetX:n,targetY:r,targetPosition:i,curvature:y==null?void 0:y.curvature});return M.createElement(qt,{path:p,labelX:E,labelY:$,label:o,labelStyle:a,labelShowBg:l,labelBgStyle:c,labelBgPadding:u,labelBgBorderRadius:d,style:m,markerEnd:f,markerStart:x,interactionWidth:v})});_n.displayName="BezierEdge";const Ar=w.createContext(null),bf=Ar.Provider;Ar.Consumer;const vf=()=>w.useContext(Ar),_f=e=>"id"in e&&"source"in e&&"target"in e,Ef=({source:e,sourceHandle:t,target:n,targetHandle:r})=>`reactflow__edge-${e}${t||""}-${n}${r||""}`,fr=(e,t)=>typeof e>"u"?"":typeof e=="string"?e:`${t?`${t}__`:""}${Object.keys(e).sort().map(r=>`${r}=${e[r]}`).join("&")}`,Nf=(e,t)=>t.some(n=>n.source===e.source&&n.target===e.target&&(n.sourceHandle===e.sourceHandle||!n.sourceHandle&&!e.sourceHandle)&&(n.targetHandle===e.targetHandle||!n.targetHandle&&!e.targetHandle)),Sf=(e,t)=>{if(!e.source||!e.target)return t;let n;return _f(e)?n={...e}:n={...e,id:Ef(e)},Nf(n,t)?t:t.concat(n)},hr=({x:e,y:t},[n,r,s],i,[o,a])=>{const l={x:(e-n)/s,y:(t-r)/s};return i?{x:o*Math.round(l.x/o),y:a*Math.round(l.y/a)}:l},ro=({x:e,y:t},[n,r,s])=>({x:e*s+n,y:t*s+r}),lt=(e,t=[0,0])=>{if(!e)return{x:0,y:0,positionAbsolute:{x:0,y:0}};const n=(e.width??0)*t[0],r=(e.height??0)*t[1],s={x:e.position.x-n,y:e.position.y-r};return{...s,positionAbsolute:e.positionAbsolute?{x:e.positionAbsolute.x-n,y:e.positionAbsolute.y-r}:s}},Kt=(e,t=[0,0])=>{if(e.length===0)return{x:0,y:0,width:0,height:0};const n=e.reduce((r,s)=>{const{x:i,y:o}=lt(s,t).positionAbsolute;return qi(r,Gt({x:i,y:o,width:s.width||0,height:s.height||0}))},{x:1/0,y:1/0,x2:-1/0,y2:-1/0});return Ki(n)},kf=(e,t=[0,0])=>(console.warn("[DEPRECATED] `getRectOfNodes` is deprecated. Instead use `getNodesBounds` https://reactflow.dev/api-reference/utils/get-nodes-bounds."),Kt(e,t)),so=(e,t,[n,r,s]=[0,0,1],i=!1,o=!1,a=[0,0])=>{const l={x:(t.x-n)/s,y:(t.y-r)/s,width:t.width/s,height:t.height/s},c=[];return e.forEach(u=>{const{width:d,height:m,selectable:f=!0,hidden:x=!1}=u;if(o&&!f||x)return!1;const{positionAbsolute:y}=lt(u,a),v={x:y.x,y:y.y,width:d||0,height:m||0},p=ur(l,v),E=typeof d>"u"||typeof m>"u"||d===null||m===null,$=i&&p>0,b=(d||0)*(m||0);(E||$||p>=b||u.dragging)&&c.push(u)}),c},io=(e,t)=>{const n=e.map(r=>r.id);return t.filter(r=>n.includes(r.source)||n.includes(r.target))},oo=(e,t,n,r,s,i=.1)=>{const o=t/(e.width*(1+i)),a=n/(e.height*(1+i)),l=Math.min(o,a),c=kt(l,r,s),u=e.x+e.width/2,d=e.y+e.height/2,m=t/2-u*c,f=n/2-d*c;return{x:m,y:f,zoom:c}},st=(e,t=0)=>e.transition().duration(t);function xs(e,t,n,r){return(t[n]||[]).reduce((s,i)=>{var o,a;return`${e.id}-${i.id}-${n}`!==r&&s.push({id:i.id||null,type:n,nodeId:e.id,x:(((o=e.positionAbsolute)==null?void 0:o.x)??0)+i.x+i.width/2,y:(((a=e.positionAbsolute)==null?void 0:a.y)??0)+i.y+i.height/2}),s},[])}function jf(e,t,n,r,s,i){const{x:o,y:a}=Ze(e),c=t.elementsFromPoint(o,a).find(x=>x.classList.contains("react-flow__handle"));if(c){const x=c.getAttribute("data-nodeid");if(x){const y=Ir(void 0,c),v=c.getAttribute("data-handleid"),p=i({nodeId:x,id:v,type:y});if(p){const E=s.find($=>$.nodeId===x&&$.type===y&&$.id===v);return{handle:{id:v,type:y,nodeId:x,x:(E==null?void 0:E.x)||n.x,y:(E==null?void 0:E.y)||n.y},validHandleResult:p}}}}let u=[],d=1/0;if(s.forEach(x=>{const y=Math.sqrt((x.x-n.x)**2+(x.y-n.y)**2);if(y<=r){const v=i(x);y<=d&&(yx.isValid),f=u.some(({handle:x})=>x.type==="target");return u.find(({handle:x,validHandleResult:y})=>f?x.type==="target":m?y.isValid:!0)||u[0]}const Cf={source:null,target:null,sourceHandle:null,targetHandle:null},ao=()=>({handleDomNode:null,isValid:!1,connection:Cf,endHandle:null});function lo(e,t,n,r,s,i,o){const a=s==="target",l=o.querySelector(`.react-flow__handle[data-id="${e==null?void 0:e.nodeId}-${e==null?void 0:e.id}-${e==null?void 0:e.type}"]`),c={...ao(),handleDomNode:l};if(l){const u=Ir(void 0,l),d=l.getAttribute("data-nodeid"),m=l.getAttribute("data-handleid"),f=l.classList.contains("connectable"),x=l.classList.contains("connectableend"),y={source:a?d:n,sourceHandle:a?m:r,target:a?n:d,targetHandle:a?r:m};c.connection=y,f&&x&&(t===ut.Strict?a&&u==="source"||!a&&u==="target":d!==n||m!==r)&&(c.endHandle={nodeId:d,handleId:m,type:u},c.isValid=i(y))}return c}function $f({nodes:e,nodeId:t,handleId:n,handleType:r}){return e.reduce((s,i)=>{if(i[le]){const{handleBounds:o}=i[le];let a=[],l=[];o&&(a=xs(i,o,"source",`${t}-${n}-${r}`),l=xs(i,o,"target",`${t}-${n}-${r}`)),s.push(...a,...l)}return s},[])}function Ir(e,t){return e||(t!=null&&t.classList.contains("target")?"target":t!=null&&t.classList.contains("source")?"source":null)}function Gn(e){e==null||e.classList.remove("valid","connecting","react-flow__handle-valid","react-flow__handle-connecting")}function Mf(e,t){let n=null;return t?n="valid":e&&!t&&(n="invalid"),n}function co({event:e,handleId:t,nodeId:n,onConnect:r,isTarget:s,getState:i,setState:o,isValidConnection:a,edgeUpdaterType:l,onReconnectEnd:c}){const u=Xi(e.target),{connectionMode:d,domNode:m,autoPanOnConnect:f,connectionRadius:x,onConnectStart:y,panBy:v,getNodes:p,cancelConnection:E}=i();let $=0,b;const{x:A,y:j}=Ze(e),_=u==null?void 0:u.elementFromPoint(A,j),I=Ir(l,_),S=m==null?void 0:m.getBoundingClientRect();if(!S||!I)return;let D,P=Ze(e,S),V=!1,F=null,g=!1,C=null;const N=$f({nodes:p(),nodeId:n,handleId:t,handleType:I}),R=()=>{if(!f)return;const[T,L]=Ui(P,S);v({x:T,y:L}),$=requestAnimationFrame(R)};o({connectionPosition:P,connectionStatus:null,connectionNodeId:n,connectionHandleId:t,connectionHandleType:I,connectionStartHandle:{nodeId:n,handleId:t,type:I},connectionEndHandle:null}),y==null||y(e,{nodeId:n,handleId:t,handleType:I});function H(T){const{transform:L}=i();P=Ze(T,S);const{handle:z,validHandleResult:Y}=jf(T,u,hr(P,L,!1,[1,1]),x,N,G=>lo(G,d,n,t,s?"target":"source",a,u));if(b=z,V||(R(),V=!0),C=Y.handleDomNode,F=Y.connection,g=Y.isValid,o({connectionPosition:b&&g?ro({x:b.x,y:b.y},L):P,connectionStatus:Mf(!!b,g),connectionEndHandle:Y.endHandle}),!b&&!g&&!C)return Gn(D);F.source!==F.target&&C&&(Gn(D),D=C,C.classList.add("connecting","react-flow__handle-connecting"),C.classList.toggle("valid",g),C.classList.toggle("react-flow__handle-valid",g))}function k(T){var L,z;(b||C)&&F&&g&&(r==null||r(F)),(z=(L=i()).onConnectEnd)==null||z.call(L,T),l&&(c==null||c(T)),Gn(D),E(),cancelAnimationFrame($),V=!1,g=!1,F=null,C=null,u.removeEventListener("mousemove",H),u.removeEventListener("mouseup",k),u.removeEventListener("touchmove",H),u.removeEventListener("touchend",k)}u.addEventListener("mousemove",H),u.addEventListener("mouseup",k),u.addEventListener("touchmove",H),u.addEventListener("touchend",k)}const ws=()=>!0,Af=e=>({connectionStartHandle:e.connectionStartHandle,connectOnClick:e.connectOnClick,noPanClassName:e.noPanClassName}),If=(e,t,n)=>r=>{const{connectionStartHandle:s,connectionEndHandle:i,connectionClickStartHandle:o}=r;return{connecting:(s==null?void 0:s.nodeId)===e&&(s==null?void 0:s.handleId)===t&&(s==null?void 0:s.type)===n||(i==null?void 0:i.nodeId)===e&&(i==null?void 0:i.handleId)===t&&(i==null?void 0:i.type)===n,clickConnecting:(o==null?void 0:o.nodeId)===e&&(o==null?void 0:o.handleId)===t&&(o==null?void 0:o.type)===n}},uo=w.forwardRef(({type:e="source",position:t=Z.Top,isValidConnection:n,isConnectable:r=!0,isConnectableStart:s=!0,isConnectableEnd:i=!0,id:o,onConnect:a,children:l,className:c,onMouseDown:u,onTouchStart:d,...m},f)=>{var S,D;const x=o||null,y=e==="target",v=pe(),p=vf(),{connectOnClick:E,noPanClassName:$}=ae(Af,ge),{connecting:b,clickConnecting:A}=ae(If(p,x,e),ge);p||(D=(S=v.getState()).onError)==null||D.call(S,"010",Be.error010());const j=P=>{const{defaultEdgeOptions:V,onConnect:F,hasDefaultEdges:g}=v.getState(),C={...V,...P};if(g){const{edges:N,setEdges:R}=v.getState();R(Sf(C,N))}F==null||F(C),a==null||a(C)},_=P=>{if(!p)return;const V=Qi(P);s&&(V&&P.button===0||!V)&&co({event:P,handleId:x,nodeId:p,onConnect:j,isTarget:y,getState:v.getState,setState:v.setState,isValidConnection:n||v.getState().isValidConnection||ws}),V?u==null||u(P):d==null||d(P)},I=P=>{const{onClickConnectStart:V,onClickConnectEnd:F,connectionClickStartHandle:g,connectionMode:C,isValidConnection:N}=v.getState();if(!p||!g&&!s)return;if(!g){V==null||V(P,{nodeId:p,handleId:x,handleType:e}),v.setState({connectionClickStartHandle:{nodeId:p,type:e,handleId:x}});return}const R=Xi(P.target),H=n||N||ws,{connection:k,isValid:T}=lo({nodeId:p,id:x,type:e},C,g.nodeId,g.handleId||null,g.type,H,R);T&&j(k),F==null||F(P),v.setState({connectionClickStartHandle:null})};return M.createElement("div",{"data-handleid":x,"data-nodeid":p,"data-handlepos":t,"data-id":`${p}-${x}-${e}`,className:ye(["react-flow__handle",`react-flow__handle-${t}`,"nodrag",$,c,{source:!y,target:y,connectable:r,connectablestart:s,connectableend:i,connecting:A,connectionindicator:r&&(s&&!b||i&&b)}]),onMouseDown:_,onTouchStart:_,onClick:E?I:void 0,ref:f,...m},l)});uo.displayName="Handle";var Ke=w.memo(uo);const fo=({data:e,isConnectable:t,targetPosition:n=Z.Top,sourcePosition:r=Z.Bottom})=>M.createElement(M.Fragment,null,M.createElement(Ke,{type:"target",position:n,isConnectable:t}),e==null?void 0:e.label,M.createElement(Ke,{type:"source",position:r,isConnectable:t}));fo.displayName="DefaultNode";var mr=w.memo(fo);const ho=({data:e,isConnectable:t,sourcePosition:n=Z.Bottom})=>M.createElement(M.Fragment,null,e==null?void 0:e.label,M.createElement(Ke,{type:"source",position:n,isConnectable:t}));ho.displayName="InputNode";var mo=w.memo(ho);const po=({data:e,isConnectable:t,targetPosition:n=Z.Top})=>M.createElement(M.Fragment,null,M.createElement(Ke,{type:"target",position:n,isConnectable:t}),e==null?void 0:e.label);po.displayName="OutputNode";var go=w.memo(po);const Rr=()=>null;Rr.displayName="GroupNode";const Rf=e=>({selectedNodes:e.getNodes().filter(t=>t.selected),selectedEdges:e.edges.filter(t=>t.selected).map(t=>({...t}))}),sn=e=>e.id;function Tf(e,t){return ge(e.selectedNodes.map(sn),t.selectedNodes.map(sn))&&ge(e.selectedEdges.map(sn),t.selectedEdges.map(sn))}const yo=w.memo(({onSelectionChange:e})=>{const t=pe(),{selectedNodes:n,selectedEdges:r}=ae(Rf,Tf);return w.useEffect(()=>{const s={nodes:n,edges:r};e==null||e(s),t.getState().onSelectionChange.forEach(i=>i(s))},[n,r,e]),null});yo.displayName="SelectionListener";const Of=e=>!!e.onSelectionChange;function Df({onSelectionChange:e}){const t=ae(Of);return e||t?M.createElement(yo,{onSelectionChange:e}):null}const Lf=e=>({setNodes:e.setNodes,setEdges:e.setEdges,setDefaultNodesAndEdges:e.setDefaultNodesAndEdges,setMinZoom:e.setMinZoom,setMaxZoom:e.setMaxZoom,setTranslateExtent:e.setTranslateExtent,setNodeExtent:e.setNodeExtent,reset:e.reset});function mt(e,t){w.useEffect(()=>{typeof e<"u"&&t(e)},[e])}function ne(e,t,n){w.useEffect(()=>{typeof t<"u"&&n({[e]:t})},[t])}const Pf=({nodes:e,edges:t,defaultNodes:n,defaultEdges:r,onConnect:s,onConnectStart:i,onConnectEnd:o,onClickConnectStart:a,onClickConnectEnd:l,nodesDraggable:c,nodesConnectable:u,nodesFocusable:d,edgesFocusable:m,edgesUpdatable:f,elevateNodesOnSelect:x,minZoom:y,maxZoom:v,nodeExtent:p,onNodesChange:E,onEdgesChange:$,elementsSelectable:b,connectionMode:A,snapGrid:j,snapToGrid:_,translateExtent:I,connectOnClick:S,defaultEdgeOptions:D,fitView:P,fitViewOptions:V,onNodesDelete:F,onEdgesDelete:g,onNodeDrag:C,onNodeDragStart:N,onNodeDragStop:R,onSelectionDrag:H,onSelectionDragStart:k,onSelectionDragStop:T,noPanClassName:L,nodeOrigin:z,rfId:Y,autoPanOnConnect:G,autoPanOnNodeDrag:K,onError:J,connectionRadius:ee,isValidConnection:ie,nodeDragThreshold:te})=>{const{setNodes:re,setEdges:fe,setDefaultNodesAndEdges:B,setMinZoom:q,setMaxZoom:W,setTranslateExtent:Q,setNodeExtent:U,reset:X}=ae(Lf,ge),O=pe();return w.useEffect(()=>{const se=r==null?void 0:r.map(ce=>({...ce,...D}));return B(n,se),()=>{X()}},[]),ne("defaultEdgeOptions",D,O.setState),ne("connectionMode",A,O.setState),ne("onConnect",s,O.setState),ne("onConnectStart",i,O.setState),ne("onConnectEnd",o,O.setState),ne("onClickConnectStart",a,O.setState),ne("onClickConnectEnd",l,O.setState),ne("nodesDraggable",c,O.setState),ne("nodesConnectable",u,O.setState),ne("nodesFocusable",d,O.setState),ne("edgesFocusable",m,O.setState),ne("edgesUpdatable",f,O.setState),ne("elementsSelectable",b,O.setState),ne("elevateNodesOnSelect",x,O.setState),ne("snapToGrid",_,O.setState),ne("snapGrid",j,O.setState),ne("onNodesChange",E,O.setState),ne("onEdgesChange",$,O.setState),ne("connectOnClick",S,O.setState),ne("fitViewOnInit",P,O.setState),ne("fitViewOnInitOptions",V,O.setState),ne("onNodesDelete",F,O.setState),ne("onEdgesDelete",g,O.setState),ne("onNodeDrag",C,O.setState),ne("onNodeDragStart",N,O.setState),ne("onNodeDragStop",R,O.setState),ne("onSelectionDrag",H,O.setState),ne("onSelectionDragStart",k,O.setState),ne("onSelectionDragStop",T,O.setState),ne("noPanClassName",L,O.setState),ne("nodeOrigin",z,O.setState),ne("rfId",Y,O.setState),ne("autoPanOnConnect",G,O.setState),ne("autoPanOnNodeDrag",K,O.setState),ne("onError",J,O.setState),ne("connectionRadius",ee,O.setState),ne("isValidConnection",ie,O.setState),ne("nodeDragThreshold",te,O.setState),mt(e,re),mt(t,fe),mt(y,q),mt(v,W),mt(I,Q),mt(p,U),null},bs={display:"none"},zf={position:"absolute",width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0px, 0px, 0px, 0px)",clipPath:"inset(100%)"},xo="react-flow__node-desc",wo="react-flow__edge-desc",Hf="react-flow__aria-live",Ff=e=>e.ariaLiveMessage;function Vf({rfId:e}){const t=ae(Ff);return M.createElement("div",{id:`${Hf}-${e}`,"aria-live":"assertive","aria-atomic":"true",style:zf},t)}function Bf({rfId:e,disableKeyboardA11y:t}){return M.createElement(M.Fragment,null,M.createElement("div",{id:`${xo}-${e}`,style:bs},"Press enter or space to select a node.",!t&&"You can then use the arrow keys to move the node around."," Press delete to remove it and escape to cancel."," "),M.createElement("div",{id:`${wo}-${e}`,style:bs},"Press enter or space to select an edge. You can then press delete to remove it or escape to cancel."),!t&&M.createElement(Vf,{rfId:e}))}var Wt=(e=null,t={actInsideInputWithModifier:!0})=>{const[n,r]=w.useState(!1),s=w.useRef(!1),i=w.useRef(new Set([])),[o,a]=w.useMemo(()=>{if(e!==null){const c=(Array.isArray(e)?e:[e]).filter(d=>typeof d=="string").map(d=>d.split("+")),u=c.reduce((d,m)=>d.concat(...m),[]);return[c,u]}return[[],[]]},[e]);return w.useEffect(()=>{const l=typeof document<"u"?document:null,c=(t==null?void 0:t.target)||l;if(e!==null){const u=f=>{if(s.current=f.ctrlKey||f.metaKey||f.shiftKey,(!s.current||s.current&&!t.actInsideInputWithModifier)&&dr(f))return!1;const y=_s(f.code,a);i.current.add(f[y]),vs(o,i.current,!1)&&(f.preventDefault(),r(!0))},d=f=>{if((!s.current||s.current&&!t.actInsideInputWithModifier)&&dr(f))return!1;const y=_s(f.code,a);vs(o,i.current,!0)?(r(!1),i.current.clear()):i.current.delete(f[y]),f.key==="Meta"&&i.current.clear(),s.current=!1},m=()=>{i.current.clear(),r(!1)};return c==null||c.addEventListener("keydown",u),c==null||c.addEventListener("keyup",d),window.addEventListener("blur",m),()=>{c==null||c.removeEventListener("keydown",u),c==null||c.removeEventListener("keyup",d),window.removeEventListener("blur",m)}}},[e,r]),n};function vs(e,t,n){return e.filter(r=>n||r.length===t.size).some(r=>r.every(s=>t.has(s)))}function _s(e,t){return t.includes(e)?"code":"key"}function bo(e,t,n,r){var a,l;const s=e.parentNode||e.parentId;if(!s)return n;const i=t.get(s),o=lt(i,r);return bo(i,t,{x:(n.x??0)+o.x,y:(n.y??0)+o.y,z:(((a=i[le])==null?void 0:a.z)??0)>(n.z??0)?((l=i[le])==null?void 0:l.z)??0:n.z??0},r)}function vo(e,t,n){e.forEach(r=>{var i;const s=r.parentNode||r.parentId;if(s&&!e.has(s))throw new Error(`Parent node ${s} not found`);if(s||n!=null&&n[r.id]){const{x:o,y:a,z:l}=bo(r,e,{...r.position,z:((i=r[le])==null?void 0:i.z)??0},t);r.positionAbsolute={x:o,y:a},r[le].z=l,n!=null&&n[r.id]&&(r[le].isParent=!0)}})}function Yn(e,t,n,r){const s=new Map,i={},o=r?1e3:0;return e.forEach(a=>{var f;const l=(Se(a.zIndex)?a.zIndex:0)+(a.selected?o:0),c=t.get(a.id),u={...a,positionAbsolute:{x:a.position.x,y:a.position.y}},d=a.parentNode||a.parentId;d&&(i[d]=!0);const m=(c==null?void 0:c.type)&&(c==null?void 0:c.type)!==a.type;Object.defineProperty(u,le,{enumerable:!1,value:{handleBounds:m||(f=c==null?void 0:c[le])==null?void 0:f.handleBounds,z:l}}),s.set(a.id,u)}),vo(s,n,i),s}function _o(e,t={}){const{getNodes:n,width:r,height:s,minZoom:i,maxZoom:o,d3Zoom:a,d3Selection:l,fitViewOnInitDone:c,fitViewOnInit:u,nodeOrigin:d}=e(),m=t.initial&&!c&&u;if(a&&l&&(m||!t.initial)){const x=n().filter(v=>{var E;const p=t.includeHiddenNodes?v.width&&v.height:!v.hidden;return(E=t.nodes)!=null&&E.length?p&&t.nodes.some($=>$.id===v.id):p}),y=x.every(v=>v.width&&v.height);if(x.length>0&&y){const v=Kt(x,d),{x:p,y:E,zoom:$}=oo(v,r,s,t.minZoom??i,t.maxZoom??o,t.padding??.1),b=Fe.translate(p,E).scale($);return typeof t.duration=="number"&&t.duration>0?a.transform(st(l,t.duration),b):a.transform(l,b),!0}}return!1}function Gf(e,t){return e.forEach(n=>{const r=t.get(n.id);r&&t.set(r.id,{...r,[le]:r[le],selected:n.selected})}),new Map(t)}function Yf(e,t){return t.map(n=>{const r=e.find(s=>s.id===n.id);return r&&(n.selected=r.selected),n})}function on({changedNodes:e,changedEdges:t,get:n,set:r}){const{nodeInternals:s,edges:i,onNodesChange:o,onEdgesChange:a,hasDefaultNodes:l,hasDefaultEdges:c}=n();e!=null&&e.length&&(l&&r({nodeInternals:Gf(e,s)}),o==null||o(e)),t!=null&&t.length&&(c&&r({edges:Yf(t,i)}),a==null||a(t))}const pt=()=>{},Wf={zoomIn:pt,zoomOut:pt,zoomTo:pt,getZoom:()=>1,setViewport:pt,getViewport:()=>({x:0,y:0,zoom:1}),fitView:()=>!1,setCenter:pt,fitBounds:pt,project:e=>e,screenToFlowPosition:e=>e,flowToScreenPosition:e=>e,viewportInitialized:!1},Uf=e=>({d3Zoom:e.d3Zoom,d3Selection:e.d3Selection}),Xf=()=>{const e=pe(),{d3Zoom:t,d3Selection:n}=ae(Uf,ge);return w.useMemo(()=>n&&t?{zoomIn:s=>t.scaleBy(st(n,s==null?void 0:s.duration),1.2),zoomOut:s=>t.scaleBy(st(n,s==null?void 0:s.duration),1/1.2),zoomTo:(s,i)=>t.scaleTo(st(n,i==null?void 0:i.duration),s),getZoom:()=>e.getState().transform[2],setViewport:(s,i)=>{const[o,a,l]=e.getState().transform,c=Fe.translate(s.x??o,s.y??a).scale(s.zoom??l);t.transform(st(n,i==null?void 0:i.duration),c)},getViewport:()=>{const[s,i,o]=e.getState().transform;return{x:s,y:i,zoom:o}},fitView:s=>_o(e.getState,s),setCenter:(s,i,o)=>{const{width:a,height:l,maxZoom:c}=e.getState(),u=typeof(o==null?void 0:o.zoom)<"u"?o.zoom:c,d=a/2-s*u,m=l/2-i*u,f=Fe.translate(d,m).scale(u);t.transform(st(n,o==null?void 0:o.duration),f)},fitBounds:(s,i)=>{const{width:o,height:a,minZoom:l,maxZoom:c}=e.getState(),{x:u,y:d,zoom:m}=oo(s,o,a,l,c,(i==null?void 0:i.padding)??.1),f=Fe.translate(u,d).scale(m);t.transform(st(n,i==null?void 0:i.duration),f)},project:s=>{const{transform:i,snapToGrid:o,snapGrid:a}=e.getState();return console.warn("[DEPRECATED] `project` is deprecated. Instead use `screenToFlowPosition`. There is no need to subtract the react flow bounds anymore! https://reactflow.dev/api-reference/types/react-flow-instance#screen-to-flow-position"),hr(s,i,o,a)},screenToFlowPosition:s=>{const{transform:i,snapToGrid:o,snapGrid:a,domNode:l}=e.getState();if(!l)return s;const{x:c,y:u}=l.getBoundingClientRect(),d={x:s.x-c,y:s.y-u};return hr(d,i,o,a)},flowToScreenPosition:s=>{const{transform:i,domNode:o}=e.getState();if(!o)return s;const{x:a,y:l}=o.getBoundingClientRect(),c=ro(s,i);return{x:c.x+a,y:c.y+l}},viewportInitialized:!0}:Wf,[t,n])};function Rn(){const e=Xf(),t=pe(),n=w.useCallback(()=>t.getState().getNodes().map(y=>({...y})),[]),r=w.useCallback(y=>t.getState().nodeInternals.get(y),[]),s=w.useCallback(()=>{const{edges:y=[]}=t.getState();return y.map(v=>({...v}))},[]),i=w.useCallback(y=>{const{edges:v=[]}=t.getState();return v.find(p=>p.id===y)},[]),o=w.useCallback(y=>{const{getNodes:v,setNodes:p,hasDefaultNodes:E,onNodesChange:$}=t.getState(),b=v(),A=typeof y=="function"?y(b):y;if(E)p(A);else if($){const j=A.length===0?b.map(_=>({type:"remove",id:_.id})):A.map(_=>({item:_,type:"reset"}));$(j)}},[]),a=w.useCallback(y=>{const{edges:v=[],setEdges:p,hasDefaultEdges:E,onEdgesChange:$}=t.getState(),b=typeof y=="function"?y(v):y;if(E)p(b);else if($){const A=b.length===0?v.map(j=>({type:"remove",id:j.id})):b.map(j=>({item:j,type:"reset"}));$(A)}},[]),l=w.useCallback(y=>{const v=Array.isArray(y)?y:[y],{getNodes:p,setNodes:E,hasDefaultNodes:$,onNodesChange:b}=t.getState();if($){const j=[...p(),...v];E(j)}else if(b){const A=v.map(j=>({item:j,type:"add"}));b(A)}},[]),c=w.useCallback(y=>{const v=Array.isArray(y)?y:[y],{edges:p=[],setEdges:E,hasDefaultEdges:$,onEdgesChange:b}=t.getState();if($)E([...p,...v]);else if(b){const A=v.map(j=>({item:j,type:"add"}));b(A)}},[]),u=w.useCallback(()=>{const{getNodes:y,edges:v=[],transform:p}=t.getState(),[E,$,b]=p;return{nodes:y().map(A=>({...A})),edges:v.map(A=>({...A})),viewport:{x:E,y:$,zoom:b}}},[]),d=w.useCallback(({nodes:y,edges:v})=>{const{nodeInternals:p,getNodes:E,edges:$,hasDefaultNodes:b,hasDefaultEdges:A,onNodesDelete:j,onEdgesDelete:_,onNodesChange:I,onEdgesChange:S}=t.getState(),D=(y||[]).map(C=>C.id),P=(v||[]).map(C=>C.id),V=E().reduce((C,N)=>{const R=N.parentNode||N.parentId,H=!D.includes(N.id)&&R&&C.find(T=>T.id===R);return(typeof N.deletable=="boolean"?N.deletable:!0)&&(D.includes(N.id)||H)&&C.push(N),C},[]),F=$.filter(C=>typeof C.deletable=="boolean"?C.deletable:!0),g=F.filter(C=>P.includes(C.id));if(V||g){const C=io(V,F),N=[...g,...C],R=N.reduce((H,k)=>(H.includes(k.id)||H.push(k.id),H),[]);if((A||b)&&(A&&t.setState({edges:$.filter(H=>!R.includes(H.id))}),b&&(V.forEach(H=>{p.delete(H.id)}),t.setState({nodeInternals:new Map(p)}))),R.length>0&&(_==null||_(N),S&&S(R.map(H=>({id:H,type:"remove"})))),V.length>0&&(j==null||j(V),I)){const H=V.map(k=>({id:k.id,type:"remove"}));I(H)}}},[]),m=w.useCallback(y=>{const v=hf(y),p=v?null:t.getState().nodeInternals.get(y.id);return!v&&!p?[null,null,v]:[v?y:hs(p),p,v]},[]),f=w.useCallback((y,v=!0,p)=>{const[E,$,b]=m(y);return E?(p||t.getState().getNodes()).filter(A=>{if(!b&&(A.id===$.id||!A.positionAbsolute))return!1;const j=hs(A),_=ur(j,E);return v&&_>0||_>=E.width*E.height}):[]},[]),x=w.useCallback((y,v,p=!0)=>{const[E]=m(y);if(!E)return!1;const $=ur(E,v);return p&&$>0||$>=E.width*E.height},[]);return w.useMemo(()=>({...e,getNodes:n,getNode:r,getEdges:s,getEdge:i,setNodes:o,setEdges:a,addNodes:l,addEdges:c,toObject:u,deleteElements:d,getIntersectingNodes:f,isNodeIntersecting:x}),[e,n,r,s,i,o,a,l,c,u,d,f,x])}const qf={actInsideInputWithModifier:!1};var Kf=({deleteKeyCode:e,multiSelectionKeyCode:t})=>{const n=pe(),{deleteElements:r}=Rn(),s=Wt(e,qf),i=Wt(t);w.useEffect(()=>{if(s){const{edges:o,getNodes:a}=n.getState(),l=a().filter(u=>u.selected),c=o.filter(u=>u.selected);r({nodes:l,edges:c}),n.setState({nodesSelectionActive:!1})}},[s]),w.useEffect(()=>{n.setState({multiSelectionActive:i})},[i])};function Zf(e){const t=pe();w.useEffect(()=>{let n;const r=()=>{var i,o;if(!e.current)return;const s=kr(e.current);(s.height===0||s.width===0)&&((o=(i=t.getState()).onError)==null||o.call(i,"004",Be.error004())),t.setState({width:s.width||500,height:s.height||500})};return r(),window.addEventListener("resize",r),e.current&&(n=new ResizeObserver(()=>r()),n.observe(e.current)),()=>{window.removeEventListener("resize",r),n&&e.current&&n.unobserve(e.current)}},[])}const Tr={position:"absolute",width:"100%",height:"100%",top:0,left:0},Qf=(e,t)=>e.x!==t.x||e.y!==t.y||e.zoom!==t.k,an=e=>({x:e.x,y:e.y,zoom:e.k}),gt=(e,t)=>e.target.closest(`.${t}`),Es=(e,t)=>t===2&&Array.isArray(e)&&e.includes(2),Ns=e=>{const t=e.ctrlKey&&wn()?10:1;return-e.deltaY*(e.deltaMode===1?.05:e.deltaMode?1:.002)*t},Jf=e=>({d3Zoom:e.d3Zoom,d3Selection:e.d3Selection,d3ZoomHandler:e.d3ZoomHandler,userSelectionActive:e.userSelectionActive}),eh=({onMove:e,onMoveStart:t,onMoveEnd:n,onPaneContextMenu:r,zoomOnScroll:s=!0,zoomOnPinch:i=!0,panOnScroll:o=!1,panOnScrollSpeed:a=.5,panOnScrollMode:l=ot.Free,zoomOnDoubleClick:c=!0,elementsSelectable:u,panOnDrag:d=!0,defaultViewport:m,translateExtent:f,minZoom:x,maxZoom:y,zoomActivationKeyCode:v,preventScrolling:p=!0,children:E,noWheelClassName:$,noPanClassName:b})=>{const A=w.useRef(),j=pe(),_=w.useRef(!1),I=w.useRef(!1),S=w.useRef(null),D=w.useRef({x:0,y:0,zoom:0}),{d3Zoom:P,d3Selection:V,d3ZoomHandler:F,userSelectionActive:g}=ae(Jf,ge),C=Wt(v),N=w.useRef(0),R=w.useRef(!1),H=w.useRef();return Zf(S),w.useEffect(()=>{if(S.current){const k=S.current.getBoundingClientRect(),T=Yi().scaleExtent([x,y]).translateExtent(f),L=Ne(S.current).call(T),z=Fe.translate(m.x,m.y).scale(kt(m.zoom,x,y)),Y=[[0,0],[k.width,k.height]],G=T.constrain()(z,Y,f);T.transform(L,G),T.wheelDelta(Ns),j.setState({d3Zoom:T,d3Selection:L,d3ZoomHandler:L.on("wheel.zoom"),transform:[G.x,G.y,G.k],domNode:S.current.closest(".react-flow")})}},[]),w.useEffect(()=>{V&&P&&(o&&!C&&!g?V.on("wheel.zoom",k=>{if(gt(k,$))return!1;k.preventDefault(),k.stopImmediatePropagation();const T=V.property("__zoom").k||1;if(k.ctrlKey&&i){const ie=$e(k),te=Ns(k),re=T*Math.pow(2,te);P.scaleTo(V,re,ie,k);return}const L=k.deltaMode===1?20:1;let z=l===ot.Vertical?0:k.deltaX*L,Y=l===ot.Horizontal?0:k.deltaY*L;!wn()&&k.shiftKey&&l!==ot.Vertical&&(z=k.deltaY*L,Y=0),P.translateBy(V,-(z/T)*a,-(Y/T)*a,{internal:!0});const G=an(V.property("__zoom")),{onViewportChangeStart:K,onViewportChange:J,onViewportChangeEnd:ee}=j.getState();clearTimeout(H.current),R.current||(R.current=!0,t==null||t(k,G),K==null||K(G)),R.current&&(e==null||e(k,G),J==null||J(G),H.current=setTimeout(()=>{n==null||n(k,G),ee==null||ee(G),R.current=!1},150))},{passive:!1}):typeof F<"u"&&V.on("wheel.zoom",function(k,T){if(!p&&k.type==="wheel"&&!k.ctrlKey||gt(k,$))return null;k.preventDefault(),F.call(this,k,T)},{passive:!1}))},[g,o,l,V,P,F,C,i,p,$,t,e,n]),w.useEffect(()=>{P&&P.on("start",k=>{var z,Y;if(!k.sourceEvent||k.sourceEvent.internal)return null;N.current=(z=k.sourceEvent)==null?void 0:z.button;const{onViewportChangeStart:T}=j.getState(),L=an(k.transform);_.current=!0,D.current=L,((Y=k.sourceEvent)==null?void 0:Y.type)==="mousedown"&&j.setState({paneDragging:!0}),T==null||T(L),t==null||t(k.sourceEvent,L)})},[P,t]),w.useEffect(()=>{P&&(g&&!_.current?P.on("zoom",null):g||P.on("zoom",k=>{var L;const{onViewportChange:T}=j.getState();if(j.setState({transform:[k.transform.x,k.transform.y,k.transform.k]}),I.current=!!(r&&Es(d,N.current??0)),(e||T)&&!((L=k.sourceEvent)!=null&&L.internal)){const z=an(k.transform);T==null||T(z),e==null||e(k.sourceEvent,z)}}))},[g,P,e,d,r]),w.useEffect(()=>{P&&P.on("end",k=>{if(!k.sourceEvent||k.sourceEvent.internal)return null;const{onViewportChangeEnd:T}=j.getState();if(_.current=!1,j.setState({paneDragging:!1}),r&&Es(d,N.current??0)&&!I.current&&r(k.sourceEvent),I.current=!1,(n||T)&&Qf(D.current,k.transform)){const L=an(k.transform);D.current=L,clearTimeout(A.current),A.current=setTimeout(()=>{T==null||T(L),n==null||n(k.sourceEvent,L)},o?150:0)}})},[P,o,d,n,r]),w.useEffect(()=>{P&&P.filter(k=>{const T=C||s,L=i&&k.ctrlKey;if((d===!0||Array.isArray(d)&&d.includes(1))&&k.button===1&&k.type==="mousedown"&&(gt(k,"react-flow__node")||gt(k,"react-flow__edge")))return!0;if(!d&&!T&&!o&&!c&&!i||g||!c&&k.type==="dblclick"||gt(k,$)&&k.type==="wheel"||gt(k,b)&&(k.type!=="wheel"||o&&k.type==="wheel"&&!C)||!i&&k.ctrlKey&&k.type==="wheel"||!T&&!o&&!L&&k.type==="wheel"||!d&&(k.type==="mousedown"||k.type==="touchstart")||Array.isArray(d)&&!d.includes(k.button)&&k.type==="mousedown")return!1;const z=Array.isArray(d)&&d.includes(k.button)||!k.button||k.button<=1;return(!k.ctrlKey||k.type==="wheel")&&z})},[g,P,s,i,o,c,d,u,C]),M.createElement("div",{className:"react-flow__renderer",ref:S,style:Tr},E)},th=e=>({userSelectionActive:e.userSelectionActive,userSelectionRect:e.userSelectionRect});function nh(){const{userSelectionActive:e,userSelectionRect:t}=ae(th,ge);return e&&t?M.createElement("div",{className:"react-flow__selection react-flow__container",style:{width:t.width,height:t.height,transform:`translate(${t.x}px, ${t.y}px)`}}):null}function Ss(e,t){const n=t.parentNode||t.parentId,r=e.find(s=>s.id===n);if(r){const s=t.position.x+t.width-r.width,i=t.position.y+t.height-r.height;if(s>0||i>0||t.position.x<0||t.position.y<0){if(r.style={...r.style},r.style.width=r.style.width??r.width,r.style.height=r.style.height??r.height,s>0&&(r.style.width+=s),i>0&&(r.style.height+=i),t.position.x<0){const o=Math.abs(t.position.x);r.position.x=r.position.x-o,r.style.width+=o,t.position.x=0}if(t.position.y<0){const o=Math.abs(t.position.y);r.position.y=r.position.y-o,r.style.height+=o,t.position.y=0}r.width=r.style.width,r.height=r.style.height}}}function rh(e,t){if(e.some(r=>r.type==="reset"))return e.filter(r=>r.type==="reset").map(r=>r.item);const n=e.filter(r=>r.type==="add").map(r=>r.item);return t.reduce((r,s)=>{const i=e.filter(a=>a.id===s.id);if(i.length===0)return r.push(s),r;const o={...s};for(const a of i)if(a)switch(a.type){case"select":{o.selected=a.selected;break}case"position":{typeof a.position<"u"&&(o.position=a.position),typeof a.positionAbsolute<"u"&&(o.positionAbsolute=a.positionAbsolute),typeof a.dragging<"u"&&(o.dragging=a.dragging),o.expandParent&&Ss(r,o);break}case"dimensions":{typeof a.dimensions<"u"&&(o.width=a.dimensions.width,o.height=a.dimensions.height),typeof a.updateStyle<"u"&&(o.style={...o.style||{},...a.dimensions}),typeof a.resizing=="boolean"&&(o.resizing=a.resizing),o.expandParent&&Ss(r,o);break}case"remove":return r}return r.push(o),r},n)}function sh(e,t){return rh(e,t)}const Xe=(e,t)=>({id:e,type:"select",selected:t});function xt(e,t){return e.reduce((n,r)=>{const s=t.includes(r.id);return!r.selected&&s?(r.selected=!0,n.push(Xe(r.id,!0))):r.selected&&!s&&(r.selected=!1,n.push(Xe(r.id,!1))),n},[])}const Wn=(e,t)=>n=>{n.target===t.current&&(e==null||e(n))},ih=e=>({userSelectionActive:e.userSelectionActive,elementsSelectable:e.elementsSelectable,dragging:e.paneDragging}),Eo=w.memo(({isSelecting:e,selectionMode:t=Yt.Full,panOnDrag:n,onSelectionStart:r,onSelectionEnd:s,onPaneClick:i,onPaneContextMenu:o,onPaneScroll:a,onPaneMouseEnter:l,onPaneMouseMove:c,onPaneMouseLeave:u,children:d})=>{const m=w.useRef(null),f=pe(),x=w.useRef(0),y=w.useRef(0),v=w.useRef(),{userSelectionActive:p,elementsSelectable:E,dragging:$}=ae(ih,ge),b=()=>{f.setState({userSelectionActive:!1,userSelectionRect:null}),x.current=0,y.current=0},A=F=>{i==null||i(F),f.getState().resetSelectedElements(),f.setState({nodesSelectionActive:!1})},j=F=>{if(Array.isArray(n)&&(n!=null&&n.includes(2))){F.preventDefault();return}o==null||o(F)},_=a?F=>a(F):void 0,I=F=>{const{resetSelectedElements:g,domNode:C}=f.getState();if(v.current=C==null?void 0:C.getBoundingClientRect(),!E||!e||F.button!==0||F.target!==m.current||!v.current)return;const{x:N,y:R}=Ze(F,v.current);g(),f.setState({userSelectionRect:{width:0,height:0,startX:N,startY:R,x:N,y:R}}),r==null||r(F)},S=F=>{const{userSelectionRect:g,nodeInternals:C,edges:N,transform:R,onNodesChange:H,onEdgesChange:k,nodeOrigin:T,getNodes:L}=f.getState();if(!e||!v.current||!g)return;f.setState({userSelectionActive:!0,nodesSelectionActive:!1});const z=Ze(F,v.current),Y=g.startX??0,G=g.startY??0,K={...g,x:z.xre.id),te=ee.map(re=>re.id);if(x.current!==te.length){x.current=te.length;const re=xt(J,te);re.length&&(H==null||H(re))}if(y.current!==ie.length){y.current=ie.length;const re=xt(N,ie);re.length&&(k==null||k(re))}f.setState({userSelectionRect:K})},D=F=>{if(F.button!==0)return;const{userSelectionRect:g}=f.getState();!p&&g&&F.target===m.current&&(A==null||A(F)),f.setState({nodesSelectionActive:x.current>0}),b(),s==null||s(F)},P=F=>{p&&(f.setState({nodesSelectionActive:x.current>0}),s==null||s(F)),b()},V=E&&(e||p);return M.createElement("div",{className:ye(["react-flow__pane",{dragging:$,selection:e}]),onClick:V?void 0:Wn(A,m),onContextMenu:Wn(j,m),onWheel:Wn(_,m),onMouseEnter:V?void 0:l,onMouseDown:V?I:void 0,onMouseMove:V?S:c,onMouseUp:V?D:void 0,onMouseLeave:V?P:u,ref:m,style:Tr},d,M.createElement(nh,null))});Eo.displayName="Pane";function No(e,t){const n=e.parentNode||e.parentId;if(!n)return!1;const r=t.get(n);return r?r.selected?!0:No(r,t):!1}function ks(e,t,n){let r=e;do{if(r!=null&&r.matches(t))return!0;if(r===n.current)return!1;r=r.parentElement}while(r);return!1}function oh(e,t,n,r){return Array.from(e.values()).filter(s=>(s.selected||s.id===r)&&(!s.parentNode||s.parentId||!No(s,e))&&(s.draggable||t&&typeof s.draggable>"u")).map(s=>{var i,o;return{id:s.id,position:s.position||{x:0,y:0},positionAbsolute:s.positionAbsolute||{x:0,y:0},distance:{x:n.x-(((i=s.positionAbsolute)==null?void 0:i.x)??0),y:n.y-(((o=s.positionAbsolute)==null?void 0:o.y)??0)},delta:{x:0,y:0},extent:s.extent,parentNode:s.parentNode||s.parentId,parentId:s.parentNode||s.parentId,width:s.width,height:s.height,expandParent:s.expandParent}})}function ah(e,t){return!t||t==="parent"?t:[t[0],[t[1][0]-(e.width||0),t[1][1]-(e.height||0)]]}function So(e,t,n,r,s=[0,0],i){const o=ah(e,e.extent||r);let a=o;const l=e.parentNode||e.parentId;if(e.extent==="parent"&&!e.expandParent)if(l&&e.width&&e.height){const d=n.get(l),{x:m,y:f}=lt(d,s).positionAbsolute;a=d&&Se(m)&&Se(f)&&Se(d.width)&&Se(d.height)?[[m+e.width*s[0],f+e.height*s[1]],[m+d.width-e.width+e.width*s[0],f+d.height-e.height+e.height*s[1]]]:a}else i==null||i("005",Be.error005()),a=o;else if(e.extent&&l&&e.extent!=="parent"){const d=n.get(l),{x:m,y:f}=lt(d,s).positionAbsolute;a=[[e.extent[0][0]+m,e.extent[0][1]+f],[e.extent[1][0]+m,e.extent[1][1]+f]]}let c={x:0,y:0};if(l){const d=n.get(l);c=lt(d,s).positionAbsolute}const u=a&&a!=="parent"?jr(t,a):t;return{position:{x:u.x-c.x,y:u.y-c.y},positionAbsolute:u}}function Un({nodeId:e,dragItems:t,nodeInternals:n}){const r=t.map(s=>({...n.get(s.id),position:s.position,positionAbsolute:s.positionAbsolute}));return[e?r.find(s=>s.id===e):r[0],r]}const js=(e,t,n,r)=>{const s=t.querySelectorAll(e);if(!s||!s.length)return null;const i=Array.from(s),o=t.getBoundingClientRect(),a={x:o.width*r[0],y:o.height*r[1]};return i.map(l=>{const c=l.getBoundingClientRect();return{id:l.getAttribute("data-handleid"),position:l.getAttribute("data-handlepos"),x:(c.left-o.left-a.x)/n,y:(c.top-o.top-a.y)/n,...kr(l)}})};function Rt(e,t,n){return n===void 0?n:r=>{const s=t().nodeInternals.get(e);s&&n(r,{...s})}}function pr({id:e,store:t,unselect:n=!1,nodeRef:r}){const{addSelectedNodes:s,unselectNodesAndEdges:i,multiSelectionActive:o,nodeInternals:a,onError:l}=t.getState(),c=a.get(e);if(!c){l==null||l("012",Be.error012(e));return}t.setState({nodesSelectionActive:!1}),c.selected?(n||c.selected&&o)&&(i({nodes:[c],edges:[]}),requestAnimationFrame(()=>{var u;return(u=r==null?void 0:r.current)==null?void 0:u.blur()})):s([e])}function lh(){const e=pe();return w.useCallback(({sourceEvent:n})=>{const{transform:r,snapGrid:s,snapToGrid:i}=e.getState(),o=n.touches?n.touches[0].clientX:n.clientX,a=n.touches?n.touches[0].clientY:n.clientY,l={x:(o-r[0])/r[2],y:(a-r[1])/r[2]};return{xSnapped:i?s[0]*Math.round(l.x/s[0]):l.x,ySnapped:i?s[1]*Math.round(l.y/s[1]):l.y,...l}},[])}function Xn(e){return(t,n,r)=>e==null?void 0:e(t,r)}function ko({nodeRef:e,disabled:t=!1,noDragClassName:n,handleSelector:r,nodeId:s,isSelectable:i,selectNodesOnDrag:o}){const a=pe(),[l,c]=w.useState(!1),u=w.useRef([]),d=w.useRef({x:null,y:null}),m=w.useRef(0),f=w.useRef(null),x=w.useRef({x:0,y:0}),y=w.useRef(null),v=w.useRef(!1),p=w.useRef(!1),E=w.useRef(!1),$=lh();return w.useEffect(()=>{if(e!=null&&e.current){const b=Ne(e.current),A=({x:I,y:S})=>{const{nodeInternals:D,onNodeDrag:P,onSelectionDrag:V,updateNodePositions:F,nodeExtent:g,snapGrid:C,snapToGrid:N,nodeOrigin:R,onError:H}=a.getState();d.current={x:I,y:S};let k=!1,T={x:0,y:0,x2:0,y2:0};if(u.current.length>1&&g){const z=Kt(u.current,R);T=Gt(z)}if(u.current=u.current.map(z=>{const Y={x:I-z.distance.x,y:S-z.distance.y};N&&(Y.x=C[0]*Math.round(Y.x/C[0]),Y.y=C[1]*Math.round(Y.y/C[1]));const G=[[g[0][0],g[0][1]],[g[1][0],g[1][1]]];u.current.length>1&&g&&!z.extent&&(G[0][0]=z.positionAbsolute.x-T.x+g[0][0],G[1][0]=z.positionAbsolute.x+(z.width??0)-T.x2+g[1][0],G[0][1]=z.positionAbsolute.y-T.y+g[0][1],G[1][1]=z.positionAbsolute.y+(z.height??0)-T.y2+g[1][1]);const K=So(z,Y,D,G,R,H);return k=k||z.position.x!==K.position.x||z.position.y!==K.position.y,z.position=K.position,z.positionAbsolute=K.positionAbsolute,z}),!k)return;F(u.current,!0,!0),c(!0);const L=s?P:Xn(V);if(L&&y.current){const[z,Y]=Un({nodeId:s,dragItems:u.current,nodeInternals:D});L(y.current,z,Y)}},j=()=>{if(!f.current)return;const[I,S]=Ui(x.current,f.current);if(I!==0||S!==0){const{transform:D,panBy:P}=a.getState();d.current.x=(d.current.x??0)-I/D[2],d.current.y=(d.current.y??0)-S/D[2],P({x:I,y:S})&&A(d.current)}m.current=requestAnimationFrame(j)},_=I=>{var R;const{nodeInternals:S,multiSelectionActive:D,nodesDraggable:P,unselectNodesAndEdges:V,onNodeDragStart:F,onSelectionDragStart:g}=a.getState();p.current=!0;const C=s?F:Xn(g);(!o||!i)&&!D&&s&&((R=S.get(s))!=null&&R.selected||V()),s&&i&&o&&pr({id:s,store:a,nodeRef:e});const N=$(I);if(d.current=N,u.current=oh(S,P,N,s),C&&u.current){const[H,k]=Un({nodeId:s,dragItems:u.current,nodeInternals:S});C(I.sourceEvent,H,k)}};if(t)b.on(".drag",null);else{const I=gu().on("start",S=>{const{domNode:D,nodeDragThreshold:P}=a.getState();P===0&&_(S),E.current=!1;const V=$(S);d.current=V,f.current=(D==null?void 0:D.getBoundingClientRect())||null,x.current=Ze(S.sourceEvent,f.current)}).on("drag",S=>{var F,g;const D=$(S),{autoPanOnNodeDrag:P,nodeDragThreshold:V}=a.getState();if(S.sourceEvent.type==="touchmove"&&S.sourceEvent.touches.length>1&&(E.current=!0),!E.current){if(!v.current&&p.current&&P&&(v.current=!0,j()),!p.current){const C=D.xSnapped-(((F=d==null?void 0:d.current)==null?void 0:F.x)??0),N=D.ySnapped-(((g=d==null?void 0:d.current)==null?void 0:g.y)??0);Math.sqrt(C*C+N*N)>V&&_(S)}(d.current.x!==D.xSnapped||d.current.y!==D.ySnapped)&&u.current&&p.current&&(y.current=S.sourceEvent,x.current=Ze(S.sourceEvent,f.current),A(D))}}).on("end",S=>{if(!(!p.current||E.current)&&(c(!1),v.current=!1,p.current=!1,cancelAnimationFrame(m.current),u.current)){const{updateNodePositions:D,nodeInternals:P,onNodeDragStop:V,onSelectionDragStop:F}=a.getState(),g=s?V:Xn(F);if(D(u.current,!1,!1),g){const[C,N]=Un({nodeId:s,dragItems:u.current,nodeInternals:P});g(S.sourceEvent,C,N)}}}).filter(S=>{const D=S.target;return!S.button&&(!n||!ks(D,`.${n}`,e))&&(!r||ks(D,r,e))});return b.call(I),()=>{b.on(".drag",null)}}}},[e,t,n,r,i,a,s,o,$]),l}function jo(){const e=pe();return w.useCallback(n=>{const{nodeInternals:r,nodeExtent:s,updateNodePositions:i,getNodes:o,snapToGrid:a,snapGrid:l,onError:c,nodesDraggable:u}=e.getState(),d=o().filter(E=>E.selected&&(E.draggable||u&&typeof E.draggable>"u")),m=a?l[0]:5,f=a?l[1]:5,x=n.isShiftPressed?4:1,y=n.x*m*x,v=n.y*f*x,p=d.map(E=>{if(E.positionAbsolute){const $={x:E.positionAbsolute.x+y,y:E.positionAbsolute.y+v};a&&($.x=l[0]*Math.round($.x/l[0]),$.y=l[1]*Math.round($.y/l[1]));const{positionAbsolute:b,position:A}=So(E,$,r,s,void 0,c);E.position=A,E.positionAbsolute=b}return E});i(p,!0,!1)},[])}const vt={ArrowUp:{x:0,y:-1},ArrowDown:{x:0,y:1},ArrowLeft:{x:-1,y:0},ArrowRight:{x:1,y:0}};var Tt=e=>{const t=({id:n,type:r,data:s,xPos:i,yPos:o,xPosOrigin:a,yPosOrigin:l,selected:c,onClick:u,onMouseEnter:d,onMouseMove:m,onMouseLeave:f,onContextMenu:x,onDoubleClick:y,style:v,className:p,isDraggable:E,isSelectable:$,isConnectable:b,isFocusable:A,selectNodesOnDrag:j,sourcePosition:_,targetPosition:I,hidden:S,resizeObserver:D,dragHandle:P,zIndex:V,isParent:F,noDragClassName:g,noPanClassName:C,initialized:N,disableKeyboardA11y:R,ariaLabel:H,rfId:k,hasHandleBounds:T})=>{const L=pe(),z=w.useRef(null),Y=w.useRef(null),G=w.useRef(_),K=w.useRef(I),J=w.useRef(r),ee=$||E||u||d||m||f,ie=jo(),te=Rt(n,L.getState,d),re=Rt(n,L.getState,m),fe=Rt(n,L.getState,f),B=Rt(n,L.getState,x),q=Rt(n,L.getState,y),W=X=>{const{nodeDragThreshold:O}=L.getState();if($&&(!j||!E||O>0)&&pr({id:n,store:L,nodeRef:z}),u){const se=L.getState().nodeInternals.get(n);se&&u(X,{...se})}},Q=X=>{if(!dr(X)&&!R)if(Zi.includes(X.key)&&$){const O=X.key==="Escape";pr({id:n,store:L,unselect:O,nodeRef:z})}else E&&c&&Object.prototype.hasOwnProperty.call(vt,X.key)&&(L.setState({ariaLiveMessage:`Moved selected node ${X.key.replace("Arrow","").toLowerCase()}. New position, x: ${~~i}, y: ${~~o}`}),ie({x:vt[X.key].x,y:vt[X.key].y,isShiftPressed:X.shiftKey}))};w.useEffect(()=>()=>{Y.current&&(D==null||D.unobserve(Y.current),Y.current=null)},[]),w.useEffect(()=>{if(z.current&&!S){const X=z.current;(!N||!T||Y.current!==X)&&(Y.current&&(D==null||D.unobserve(Y.current)),D==null||D.observe(X),Y.current=X)}},[S,N,T]),w.useEffect(()=>{const X=J.current!==r,O=G.current!==_,se=K.current!==I;z.current&&(X||O||se)&&(X&&(J.current=r),O&&(G.current=_),se&&(K.current=I),L.getState().updateNodeDimensions([{id:n,nodeElement:z.current,forceUpdate:!0}]))},[n,r,_,I]);const U=ko({nodeRef:z,disabled:S||!E,noDragClassName:g,handleSelector:P,nodeId:n,isSelectable:$,selectNodesOnDrag:j});return S?null:M.createElement("div",{className:ye(["react-flow__node",`react-flow__node-${r}`,{[C]:E},p,{selected:c,selectable:$,parent:F,dragging:U}]),ref:z,style:{zIndex:V,transform:`translate(${a}px,${l}px)`,pointerEvents:ee?"all":"none",visibility:N?"visible":"hidden",...v},"data-id":n,"data-testid":`rf__node-${n}`,onMouseEnter:te,onMouseMove:re,onMouseLeave:fe,onContextMenu:B,onClick:W,onDoubleClick:q,onKeyDown:A?Q:void 0,tabIndex:A?0:void 0,role:A?"button":void 0,"aria-describedby":R?void 0:`${xo}-${k}`,"aria-label":H},M.createElement(bf,{value:n},M.createElement(e,{id:n,data:s,type:r,xPos:i,yPos:o,selected:c,isConnectable:b,sourcePosition:_,targetPosition:I,dragging:U,dragHandle:P,zIndex:V})))};return t.displayName="NodeWrapper",w.memo(t)};const ch=e=>{const t=e.getNodes().filter(n=>n.selected);return{...Kt(t,e.nodeOrigin),transformString:`translate(${e.transform[0]}px,${e.transform[1]}px) scale(${e.transform[2]})`,userSelectionActive:e.userSelectionActive}};function uh({onSelectionContextMenu:e,noPanClassName:t,disableKeyboardA11y:n}){const r=pe(),{width:s,height:i,x:o,y:a,transformString:l,userSelectionActive:c}=ae(ch,ge),u=jo(),d=w.useRef(null);if(w.useEffect(()=>{var x;n||(x=d.current)==null||x.focus({preventScroll:!0})},[n]),ko({nodeRef:d}),c||!s||!i)return null;const m=e?x=>{const y=r.getState().getNodes().filter(v=>v.selected);e(x,y)}:void 0,f=x=>{Object.prototype.hasOwnProperty.call(vt,x.key)&&u({x:vt[x.key].x,y:vt[x.key].y,isShiftPressed:x.shiftKey})};return M.createElement("div",{className:ye(["react-flow__nodesselection","react-flow__container",t]),style:{transform:l}},M.createElement("div",{ref:d,className:"react-flow__nodesselection-rect",onContextMenu:m,tabIndex:n?void 0:-1,onKeyDown:n?void 0:f,style:{width:s,height:i,top:a,left:o}}))}var dh=w.memo(uh);const fh=e=>e.nodesSelectionActive,Co=({children:e,onPaneClick:t,onPaneMouseEnter:n,onPaneMouseMove:r,onPaneMouseLeave:s,onPaneContextMenu:i,onPaneScroll:o,deleteKeyCode:a,onMove:l,onMoveStart:c,onMoveEnd:u,selectionKeyCode:d,selectionOnDrag:m,selectionMode:f,onSelectionStart:x,onSelectionEnd:y,multiSelectionKeyCode:v,panActivationKeyCode:p,zoomActivationKeyCode:E,elementsSelectable:$,zoomOnScroll:b,zoomOnPinch:A,panOnScroll:j,panOnScrollSpeed:_,panOnScrollMode:I,zoomOnDoubleClick:S,panOnDrag:D,defaultViewport:P,translateExtent:V,minZoom:F,maxZoom:g,preventScrolling:C,onSelectionContextMenu:N,noWheelClassName:R,noPanClassName:H,disableKeyboardA11y:k})=>{const T=ae(fh),L=Wt(d),z=Wt(p),Y=z||D,G=z||j,K=L||m&&Y!==!0;return Kf({deleteKeyCode:a,multiSelectionKeyCode:v}),M.createElement(eh,{onMove:l,onMoveStart:c,onMoveEnd:u,onPaneContextMenu:i,elementsSelectable:$,zoomOnScroll:b,zoomOnPinch:A,panOnScroll:G,panOnScrollSpeed:_,panOnScrollMode:I,zoomOnDoubleClick:S,panOnDrag:!L&&Y,defaultViewport:P,translateExtent:V,minZoom:F,maxZoom:g,zoomActivationKeyCode:E,preventScrolling:C,noWheelClassName:R,noPanClassName:H},M.createElement(Eo,{onSelectionStart:x,onSelectionEnd:y,onPaneClick:t,onPaneMouseEnter:n,onPaneMouseMove:r,onPaneMouseLeave:s,onPaneContextMenu:i,onPaneScroll:o,panOnDrag:Y,isSelecting:!!K,selectionMode:f},e,T&&M.createElement(dh,{onSelectionContextMenu:N,noPanClassName:H,disableKeyboardA11y:k})))};Co.displayName="FlowRenderer";var hh=w.memo(Co);function mh(e){return ae(w.useCallback(n=>e?so(n.nodeInternals,{x:0,y:0,width:n.width,height:n.height},n.transform,!0):n.getNodes(),[e]))}function ph(e){const t={input:Tt(e.input||mo),default:Tt(e.default||mr),output:Tt(e.output||go),group:Tt(e.group||Rr)},n={},r=Object.keys(e).filter(s=>!["input","default","output","group"].includes(s)).reduce((s,i)=>(s[i]=Tt(e[i]||mr),s),n);return{...t,...r}}const gh=({x:e,y:t,width:n,height:r,origin:s})=>!n||!r?{x:e,y:t}:s[0]<0||s[1]<0||s[0]>1||s[1]>1?{x:e,y:t}:{x:e-n*s[0],y:t-r*s[1]},yh=e=>({nodesDraggable:e.nodesDraggable,nodesConnectable:e.nodesConnectable,nodesFocusable:e.nodesFocusable,elementsSelectable:e.elementsSelectable,updateNodeDimensions:e.updateNodeDimensions,onError:e.onError}),$o=e=>{const{nodesDraggable:t,nodesConnectable:n,nodesFocusable:r,elementsSelectable:s,updateNodeDimensions:i,onError:o}=ae(yh,ge),a=mh(e.onlyRenderVisibleElements),l=w.useRef(),c=w.useMemo(()=>{if(typeof ResizeObserver>"u")return null;const u=new ResizeObserver(d=>{const m=d.map(f=>({id:f.target.getAttribute("data-id"),nodeElement:f.target,forceUpdate:!0}));i(m)});return l.current=u,u},[]);return w.useEffect(()=>()=>{var u;(u=l==null?void 0:l.current)==null||u.disconnect()},[]),M.createElement("div",{className:"react-flow__nodes",style:Tr},a.map(u=>{var A,j,_;let d=u.type||"default";e.nodeTypes[d]||(o==null||o("003",Be.error003(d)),d="default");const m=e.nodeTypes[d]||e.nodeTypes.default,f=!!(u.draggable||t&&typeof u.draggable>"u"),x=!!(u.selectable||s&&typeof u.selectable>"u"),y=!!(u.connectable||n&&typeof u.connectable>"u"),v=!!(u.focusable||r&&typeof u.focusable>"u"),p=e.nodeExtent?jr(u.positionAbsolute,e.nodeExtent):u.positionAbsolute,E=(p==null?void 0:p.x)??0,$=(p==null?void 0:p.y)??0,b=gh({x:E,y:$,width:u.width??0,height:u.height??0,origin:e.nodeOrigin});return M.createElement(m,{key:u.id,id:u.id,className:u.className,style:u.style,type:d,data:u.data,sourcePosition:u.sourcePosition||Z.Bottom,targetPosition:u.targetPosition||Z.Top,hidden:u.hidden,xPos:E,yPos:$,xPosOrigin:b.x,yPosOrigin:b.y,selectNodesOnDrag:e.selectNodesOnDrag,onClick:e.onNodeClick,onMouseEnter:e.onNodeMouseEnter,onMouseMove:e.onNodeMouseMove,onMouseLeave:e.onNodeMouseLeave,onContextMenu:e.onNodeContextMenu,onDoubleClick:e.onNodeDoubleClick,selected:!!u.selected,isDraggable:f,isSelectable:x,isConnectable:y,isFocusable:v,resizeObserver:c,dragHandle:u.dragHandle,zIndex:((A=u[le])==null?void 0:A.z)??0,isParent:!!((j=u[le])!=null&&j.isParent),noDragClassName:e.noDragClassName,noPanClassName:e.noPanClassName,initialized:!!u.width&&!!u.height,rfId:e.rfId,disableKeyboardA11y:e.disableKeyboardA11y,ariaLabel:u.ariaLabel,hasHandleBounds:!!((_=u[le])!=null&&_.handleBounds)})}))};$o.displayName="NodeRenderer";var xh=w.memo($o);const wh=(e,t,n)=>n===Z.Left?e-t:n===Z.Right?e+t:e,bh=(e,t,n)=>n===Z.Top?e-t:n===Z.Bottom?e+t:e,Cs="react-flow__edgeupdater",$s=({position:e,centerX:t,centerY:n,radius:r=10,onMouseDown:s,onMouseEnter:i,onMouseOut:o,type:a})=>M.createElement("circle",{onMouseDown:s,onMouseEnter:i,onMouseOut:o,className:ye([Cs,`${Cs}-${a}`]),cx:wh(t,r,e),cy:bh(n,r,e),r,stroke:"transparent",fill:"transparent"}),vh=()=>!0;var yt=e=>{const t=({id:n,className:r,type:s,data:i,onClick:o,onEdgeDoubleClick:a,selected:l,animated:c,label:u,labelStyle:d,labelShowBg:m,labelBgStyle:f,labelBgPadding:x,labelBgBorderRadius:y,style:v,source:p,target:E,sourceX:$,sourceY:b,targetX:A,targetY:j,sourcePosition:_,targetPosition:I,elementsSelectable:S,hidden:D,sourceHandleId:P,targetHandleId:V,onContextMenu:F,onMouseEnter:g,onMouseMove:C,onMouseLeave:N,reconnectRadius:R,onReconnect:H,onReconnectStart:k,onReconnectEnd:T,markerEnd:L,markerStart:z,rfId:Y,ariaLabel:G,isFocusable:K,isReconnectable:J,pathOptions:ee,interactionWidth:ie,disableKeyboardA11y:te})=>{const re=w.useRef(null),[fe,B]=w.useState(!1),[q,W]=w.useState(!1),Q=pe(),U=w.useMemo(()=>`url('#${fr(z,Y)}')`,[z,Y]),X=w.useMemo(()=>`url('#${fr(L,Y)}')`,[L,Y]);if(D)return null;const O=xe=>{var Re;const{edges:Ce,addSelectedEdges:Je,unselectNodesAndEdges:et,multiSelectionActive:tt}=Q.getState(),De=Ce.find(Ct=>Ct.id===n);De&&(S&&(Q.setState({nodesSelectionActive:!1}),De.selected&&tt?(et({nodes:[],edges:[De]}),(Re=re.current)==null||Re.blur()):Je([n])),o&&o(xe,De))},se=It(n,Q.getState,a),ce=It(n,Q.getState,F),me=It(n,Q.getState,g),we=It(n,Q.getState,C),be=It(n,Q.getState,N),Ee=(xe,Ce)=>{if(xe.button!==0)return;const{edges:Je,isValidConnection:et}=Q.getState(),tt=Ce?E:p,De=(Ce?V:P)||null,Re=Ce?"target":"source",Ct=et||vh,Dn=Ce,$t=Je.find(nt=>nt.id===n);W(!0),k==null||k(xe,$t,Re);const Ln=nt=>{W(!1),T==null||T(nt,$t,Re)};co({event:xe,handleId:De,nodeId:tt,onConnect:nt=>H==null?void 0:H($t,nt),isTarget:Dn,getState:Q.getState,setState:Q.setState,isValidConnection:Ct,edgeUpdaterType:Re,onReconnectEnd:Ln})},Ye=xe=>Ee(xe,!0),oe=xe=>Ee(xe,!1),Qe=()=>B(!0),ft=()=>B(!1),ht=!S&&!o,jt=xe=>{var Ce;if(!te&&Zi.includes(xe.key)&&S){const{unselectNodesAndEdges:Je,addSelectedEdges:et,edges:tt}=Q.getState();xe.key==="Escape"?((Ce=re.current)==null||Ce.blur(),Je({edges:[tt.find(Re=>Re.id===n)]})):et([n])}};return M.createElement("g",{className:ye(["react-flow__edge",`react-flow__edge-${s}`,r,{selected:l,animated:c,inactive:ht,updating:fe}]),onClick:O,onDoubleClick:se,onContextMenu:ce,onMouseEnter:me,onMouseMove:we,onMouseLeave:be,onKeyDown:K?jt:void 0,tabIndex:K?0:void 0,role:K?"button":"img","data-testid":`rf__edge-${n}`,"aria-label":G===null?void 0:G||`Edge from ${p} to ${E}`,"aria-describedby":K?`${wo}-${Y}`:void 0,ref:re},!q&&M.createElement(e,{id:n,source:p,target:E,selected:l,animated:c,label:u,labelStyle:d,labelShowBg:m,labelBgStyle:f,labelBgPadding:x,labelBgBorderRadius:y,data:i,style:v,sourceX:$,sourceY:b,targetX:A,targetY:j,sourcePosition:_,targetPosition:I,sourceHandleId:P,targetHandleId:V,markerStart:U,markerEnd:X,pathOptions:ee,interactionWidth:ie}),J&&M.createElement(M.Fragment,null,(J==="source"||J===!0)&&M.createElement($s,{position:_,centerX:$,centerY:b,radius:R,onMouseDown:Ye,onMouseEnter:Qe,onMouseOut:ft,type:"source"}),(J==="target"||J===!0)&&M.createElement($s,{position:I,centerX:A,centerY:j,radius:R,onMouseDown:oe,onMouseEnter:Qe,onMouseOut:ft,type:"target"})))};return t.displayName="EdgeWrapper",w.memo(t)};function _h(e){const t={default:yt(e.default||_n),straight:yt(e.bezier||Mr),step:yt(e.step||$r),smoothstep:yt(e.step||In),simplebezier:yt(e.simplebezier||Cr)},n={},r=Object.keys(e).filter(s=>!["default","bezier"].includes(s)).reduce((s,i)=>(s[i]=yt(e[i]||_n),s),n);return{...t,...r}}function Ms(e,t,n=null){const r=((n==null?void 0:n.x)||0)+t.x,s=((n==null?void 0:n.y)||0)+t.y,i=(n==null?void 0:n.width)||t.width,o=(n==null?void 0:n.height)||t.height;switch(e){case Z.Top:return{x:r+i/2,y:s};case Z.Right:return{x:r+i,y:s+o/2};case Z.Bottom:return{x:r+i/2,y:s+o};case Z.Left:return{x:r,y:s+o/2}}}function As(e,t){return e?e.length===1||!t?e[0]:t&&e.find(n=>n.id===t)||null:null}const Eh=(e,t,n,r,s,i)=>{const o=Ms(n,e,t),a=Ms(i,r,s);return{sourceX:o.x,sourceY:o.y,targetX:a.x,targetY:a.y}};function Nh({sourcePos:e,targetPos:t,sourceWidth:n,sourceHeight:r,targetWidth:s,targetHeight:i,width:o,height:a,transform:l}){const c={x:Math.min(e.x,t.x),y:Math.min(e.y,t.y),x2:Math.max(e.x+n,t.x+s),y2:Math.max(e.y+r,t.y+i)};c.x===c.x2&&(c.x2+=1),c.y===c.y2&&(c.y2+=1);const u=Gt({x:(0-l[0])/l[2],y:(0-l[1])/l[2],width:o/l[2],height:a/l[2]}),d=Math.max(0,Math.min(u.x2,c.x2)-Math.max(u.x,c.x)),m=Math.max(0,Math.min(u.y2,c.y2)-Math.max(u.y,c.y));return Math.ceil(d*m)>0}function Is(e){var r,s,i,o,a;const t=((r=e==null?void 0:e[le])==null?void 0:r.handleBounds)||null,n=t&&(e==null?void 0:e.width)&&(e==null?void 0:e.height)&&typeof((s=e==null?void 0:e.positionAbsolute)==null?void 0:s.x)<"u"&&typeof((i=e==null?void 0:e.positionAbsolute)==null?void 0:i.y)<"u";return[{x:((o=e==null?void 0:e.positionAbsolute)==null?void 0:o.x)||0,y:((a=e==null?void 0:e.positionAbsolute)==null?void 0:a.y)||0,width:(e==null?void 0:e.width)||0,height:(e==null?void 0:e.height)||0},t,!!n]}const Sh=[{level:0,isMaxLevel:!0,edges:[]}];function kh(e,t,n=!1){let r=-1;const s=e.reduce((o,a)=>{var u,d;const l=Se(a.zIndex);let c=l?a.zIndex:0;if(n){const m=t.get(a.target),f=t.get(a.source),x=a.selected||(m==null?void 0:m.selected)||(f==null?void 0:f.selected),y=Math.max(((u=f==null?void 0:f[le])==null?void 0:u.z)||0,((d=m==null?void 0:m[le])==null?void 0:d.z)||0,1e3);c=(l?a.zIndex:0)+(x?y:0)}return o[c]?o[c].push(a):o[c]=[a],r=c>r?c:r,o},{}),i=Object.entries(s).map(([o,a])=>{const l=+o;return{edges:a,level:l,isMaxLevel:l===r}});return i.length===0?Sh:i}function jh(e,t,n){const r=ae(w.useCallback(s=>e?s.edges.filter(i=>{const o=t.get(i.source),a=t.get(i.target);return(o==null?void 0:o.width)&&(o==null?void 0:o.height)&&(a==null?void 0:a.width)&&(a==null?void 0:a.height)&&Nh({sourcePos:o.positionAbsolute||{x:0,y:0},targetPos:a.positionAbsolute||{x:0,y:0},sourceWidth:o.width,sourceHeight:o.height,targetWidth:a.width,targetHeight:a.height,width:s.width,height:s.height,transform:s.transform})}):s.edges,[e,t]));return kh(r,t,n)}const Ch=({color:e="none",strokeWidth:t=1})=>M.createElement("polyline",{style:{stroke:e,strokeWidth:t},strokeLinecap:"round",strokeLinejoin:"round",fill:"none",points:"-5,-4 0,0 -5,4"}),$h=({color:e="none",strokeWidth:t=1})=>M.createElement("polyline",{style:{stroke:e,fill:e,strokeWidth:t},strokeLinecap:"round",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4 -5,-4"}),Rs={[bn.Arrow]:Ch,[bn.ArrowClosed]:$h};function Mh(e){const t=pe();return w.useMemo(()=>{var s,i;return Object.prototype.hasOwnProperty.call(Rs,e)?Rs[e]:((i=(s=t.getState()).onError)==null||i.call(s,"009",Be.error009(e)),null)},[e])}const Ah=({id:e,type:t,color:n,width:r=12.5,height:s=12.5,markerUnits:i="strokeWidth",strokeWidth:o,orient:a="auto-start-reverse"})=>{const l=Mh(t);return l?M.createElement("marker",{className:"react-flow__arrowhead",id:e,markerWidth:`${r}`,markerHeight:`${s}`,viewBox:"-10 -10 20 20",markerUnits:i,orient:a,refX:"0",refY:"0"},M.createElement(l,{color:n,strokeWidth:o})):null},Ih=({defaultColor:e,rfId:t})=>n=>{const r=[];return n.edges.reduce((s,i)=>([i.markerStart,i.markerEnd].forEach(o=>{if(o&&typeof o=="object"){const a=fr(o,t);r.includes(a)||(s.push({id:a,color:o.color||e,...o}),r.push(a))}}),s),[]).sort((s,i)=>s.id.localeCompare(i.id))},Mo=({defaultColor:e,rfId:t})=>{const n=ae(w.useCallback(Ih({defaultColor:e,rfId:t}),[e,t]),(r,s)=>!(r.length!==s.length||r.some((i,o)=>i.id!==s[o].id)));return M.createElement("defs",null,n.map(r=>M.createElement(Ah,{id:r.id,key:r.id,type:r.type,color:r.color,width:r.width,height:r.height,markerUnits:r.markerUnits,strokeWidth:r.strokeWidth,orient:r.orient})))};Mo.displayName="MarkerDefinitions";var Rh=w.memo(Mo);const Th=e=>({nodesConnectable:e.nodesConnectable,edgesFocusable:e.edgesFocusable,edgesUpdatable:e.edgesUpdatable,elementsSelectable:e.elementsSelectable,width:e.width,height:e.height,connectionMode:e.connectionMode,nodeInternals:e.nodeInternals,onError:e.onError}),Ao=({defaultMarkerColor:e,onlyRenderVisibleElements:t,elevateEdgesOnSelect:n,rfId:r,edgeTypes:s,noPanClassName:i,onEdgeContextMenu:o,onEdgeMouseEnter:a,onEdgeMouseMove:l,onEdgeMouseLeave:c,onEdgeClick:u,onEdgeDoubleClick:d,onReconnect:m,onReconnectStart:f,onReconnectEnd:x,reconnectRadius:y,children:v,disableKeyboardA11y:p})=>{const{edgesFocusable:E,edgesUpdatable:$,elementsSelectable:b,width:A,height:j,connectionMode:_,nodeInternals:I,onError:S}=ae(Th,ge),D=jh(t,I,n);return A?M.createElement(M.Fragment,null,D.map(({level:P,edges:V,isMaxLevel:F})=>M.createElement("svg",{key:P,style:{zIndex:P},width:A,height:j,className:"react-flow__edges react-flow__container"},F&&M.createElement(Rh,{defaultColor:e,rfId:r}),M.createElement("g",null,V.map(g=>{const[C,N,R]=Is(I.get(g.source)),[H,k,T]=Is(I.get(g.target));if(!R||!T)return null;let L=g.type||"default";s[L]||(S==null||S("011",Be.error011(L)),L="default");const z=s[L]||s.default,Y=_===ut.Strict?k.target:(k.target??[]).concat(k.source??[]),G=As(N.source,g.sourceHandle),K=As(Y,g.targetHandle),J=(G==null?void 0:G.position)||Z.Bottom,ee=(K==null?void 0:K.position)||Z.Top,ie=!!(g.focusable||E&&typeof g.focusable>"u"),te=g.reconnectable||g.updatable,re=typeof m<"u"&&(te||$&&typeof te>"u");if(!G||!K)return S==null||S("008",Be.error008(G,g)),null;const{sourceX:fe,sourceY:B,targetX:q,targetY:W}=Eh(C,G,J,H,K,ee);return M.createElement(z,{key:g.id,id:g.id,className:ye([g.className,i]),type:L,data:g.data,selected:!!g.selected,animated:!!g.animated,hidden:!!g.hidden,label:g.label,labelStyle:g.labelStyle,labelShowBg:g.labelShowBg,labelBgStyle:g.labelBgStyle,labelBgPadding:g.labelBgPadding,labelBgBorderRadius:g.labelBgBorderRadius,style:g.style,source:g.source,target:g.target,sourceHandleId:g.sourceHandle,targetHandleId:g.targetHandle,markerEnd:g.markerEnd,markerStart:g.markerStart,sourceX:fe,sourceY:B,targetX:q,targetY:W,sourcePosition:J,targetPosition:ee,elementsSelectable:b,onContextMenu:o,onMouseEnter:a,onMouseMove:l,onMouseLeave:c,onClick:u,onEdgeDoubleClick:d,onReconnect:m,onReconnectStart:f,onReconnectEnd:x,reconnectRadius:y,rfId:r,ariaLabel:g.ariaLabel,isFocusable:ie,isReconnectable:re,pathOptions:"pathOptions"in g?g.pathOptions:void 0,interactionWidth:g.interactionWidth,disableKeyboardA11y:p})})))),v):null};Ao.displayName="EdgeRenderer";var Oh=w.memo(Ao);const Dh=e=>`translate(${e.transform[0]}px,${e.transform[1]}px) scale(${e.transform[2]})`;function Lh({children:e}){const t=ae(Dh);return M.createElement("div",{className:"react-flow__viewport react-flow__container",style:{transform:t}},e)}function Ph(e){const t=Rn(),n=w.useRef(!1);w.useEffect(()=>{!n.current&&t.viewportInitialized&&e&&(setTimeout(()=>e(t),1),n.current=!0)},[e,t.viewportInitialized])}const zh={[Z.Left]:Z.Right,[Z.Right]:Z.Left,[Z.Top]:Z.Bottom,[Z.Bottom]:Z.Top},Io=({nodeId:e,handleType:t,style:n,type:r=qe.Bezier,CustomComponent:s,connectionStatus:i})=>{var j,_,I;const{fromNode:o,handleId:a,toX:l,toY:c,connectionMode:u}=ae(w.useCallback(S=>({fromNode:S.nodeInternals.get(e),handleId:S.connectionHandleId,toX:(S.connectionPosition.x-S.transform[0])/S.transform[2],toY:(S.connectionPosition.y-S.transform[1])/S.transform[2],connectionMode:S.connectionMode}),[e]),ge),d=(j=o==null?void 0:o[le])==null?void 0:j.handleBounds;let m=d==null?void 0:d[t];if(u===ut.Loose&&(m=m||(d==null?void 0:d[t==="source"?"target":"source"])),!o||!m)return null;const f=a?m.find(S=>S.id===a):m[0],x=f?f.x+f.width/2:(o.width??0)/2,y=f?f.y+f.height/2:o.height??0,v=(((_=o.positionAbsolute)==null?void 0:_.x)??0)+x,p=(((I=o.positionAbsolute)==null?void 0:I.y)??0)+y,E=f==null?void 0:f.position,$=E?zh[E]:null;if(!E||!$)return null;if(s)return M.createElement(s,{connectionLineType:r,connectionLineStyle:n,fromNode:o,fromHandle:f,fromX:v,fromY:p,toX:l,toY:c,fromPosition:E,toPosition:$,connectionStatus:i});let b="";const A={sourceX:v,sourceY:p,sourcePosition:E,targetX:l,targetY:c,targetPosition:$};return r===qe.Bezier?[b]=no(A):r===qe.Step?[b]=vn({...A,borderRadius:0}):r===qe.SmoothStep?[b]=vn(A):r===qe.SimpleBezier?[b]=to(A):b=`M${v},${p} ${l},${c}`,M.createElement("path",{d:b,fill:"none",className:"react-flow__connection-path",style:n})};Io.displayName="ConnectionLine";const Hh=e=>({nodeId:e.connectionNodeId,handleType:e.connectionHandleType,nodesConnectable:e.nodesConnectable,connectionStatus:e.connectionStatus,width:e.width,height:e.height});function Fh({containerStyle:e,style:t,type:n,component:r}){const{nodeId:s,handleType:i,nodesConnectable:o,width:a,height:l,connectionStatus:c}=ae(Hh,ge);return!(s&&i&&a&&o)?null:M.createElement("svg",{style:e,width:a,height:l,className:"react-flow__edges react-flow__connectionline react-flow__container"},M.createElement("g",{className:ye(["react-flow__connection",c])},M.createElement(Io,{nodeId:s,handleType:i,style:t,type:n,CustomComponent:r,connectionStatus:c})))}function Ts(e,t){return w.useRef(null),pe(),w.useMemo(()=>t(e),[e])}const Ro=({nodeTypes:e,edgeTypes:t,onMove:n,onMoveStart:r,onMoveEnd:s,onInit:i,onNodeClick:o,onEdgeClick:a,onNodeDoubleClick:l,onEdgeDoubleClick:c,onNodeMouseEnter:u,onNodeMouseMove:d,onNodeMouseLeave:m,onNodeContextMenu:f,onSelectionContextMenu:x,onSelectionStart:y,onSelectionEnd:v,connectionLineType:p,connectionLineStyle:E,connectionLineComponent:$,connectionLineContainerStyle:b,selectionKeyCode:A,selectionOnDrag:j,selectionMode:_,multiSelectionKeyCode:I,panActivationKeyCode:S,zoomActivationKeyCode:D,deleteKeyCode:P,onlyRenderVisibleElements:V,elementsSelectable:F,selectNodesOnDrag:g,defaultViewport:C,translateExtent:N,minZoom:R,maxZoom:H,preventScrolling:k,defaultMarkerColor:T,zoomOnScroll:L,zoomOnPinch:z,panOnScroll:Y,panOnScrollSpeed:G,panOnScrollMode:K,zoomOnDoubleClick:J,panOnDrag:ee,onPaneClick:ie,onPaneMouseEnter:te,onPaneMouseMove:re,onPaneMouseLeave:fe,onPaneScroll:B,onPaneContextMenu:q,onEdgeContextMenu:W,onEdgeMouseEnter:Q,onEdgeMouseMove:U,onEdgeMouseLeave:X,onReconnect:O,onReconnectStart:se,onReconnectEnd:ce,reconnectRadius:me,noDragClassName:we,noWheelClassName:be,noPanClassName:Ee,elevateEdgesOnSelect:Ye,disableKeyboardA11y:oe,nodeOrigin:Qe,nodeExtent:ft,rfId:ht})=>{const jt=Ts(e,ph),xe=Ts(t,_h);return Ph(i),M.createElement(hh,{onPaneClick:ie,onPaneMouseEnter:te,onPaneMouseMove:re,onPaneMouseLeave:fe,onPaneContextMenu:q,onPaneScroll:B,deleteKeyCode:P,selectionKeyCode:A,selectionOnDrag:j,selectionMode:_,onSelectionStart:y,onSelectionEnd:v,multiSelectionKeyCode:I,panActivationKeyCode:S,zoomActivationKeyCode:D,elementsSelectable:F,onMove:n,onMoveStart:r,onMoveEnd:s,zoomOnScroll:L,zoomOnPinch:z,zoomOnDoubleClick:J,panOnScroll:Y,panOnScrollSpeed:G,panOnScrollMode:K,panOnDrag:ee,defaultViewport:C,translateExtent:N,minZoom:R,maxZoom:H,onSelectionContextMenu:x,preventScrolling:k,noDragClassName:we,noWheelClassName:be,noPanClassName:Ee,disableKeyboardA11y:oe},M.createElement(Lh,null,M.createElement(Oh,{edgeTypes:xe,onEdgeClick:a,onEdgeDoubleClick:c,onlyRenderVisibleElements:V,onEdgeContextMenu:W,onEdgeMouseEnter:Q,onEdgeMouseMove:U,onEdgeMouseLeave:X,onReconnect:O,onReconnectStart:se,onReconnectEnd:ce,reconnectRadius:me,defaultMarkerColor:T,noPanClassName:Ee,elevateEdgesOnSelect:!!Ye,disableKeyboardA11y:oe,rfId:ht},M.createElement(Fh,{style:E,type:p,component:$,containerStyle:b})),M.createElement("div",{className:"react-flow__edgelabel-renderer"}),M.createElement(xh,{nodeTypes:jt,onNodeClick:o,onNodeDoubleClick:l,onNodeMouseEnter:u,onNodeMouseMove:d,onNodeMouseLeave:m,onNodeContextMenu:f,selectNodesOnDrag:g,onlyRenderVisibleElements:V,noPanClassName:Ee,noDragClassName:we,disableKeyboardA11y:oe,nodeOrigin:Qe,nodeExtent:ft,rfId:ht})))};Ro.displayName="GraphView";var Vh=w.memo(Ro);const gr=[[Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY],[Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY]],We={rfId:"1",width:0,height:0,transform:[0,0,1],nodeInternals:new Map,edges:[],onNodesChange:null,onEdgesChange:null,hasDefaultNodes:!1,hasDefaultEdges:!1,d3Zoom:null,d3Selection:null,d3ZoomHandler:void 0,minZoom:.5,maxZoom:2,translateExtent:gr,nodeExtent:gr,nodesSelectionActive:!1,userSelectionActive:!1,userSelectionRect:null,connectionNodeId:null,connectionHandleId:null,connectionHandleType:"source",connectionPosition:{x:0,y:0},connectionStatus:null,connectionMode:ut.Strict,domNode:null,paneDragging:!1,noPanClassName:"nopan",nodeOrigin:[0,0],nodeDragThreshold:0,snapGrid:[15,15],snapToGrid:!1,nodesDraggable:!0,nodesConnectable:!0,nodesFocusable:!0,edgesFocusable:!0,edgesUpdatable:!0,elementsSelectable:!0,elevateNodesOnSelect:!0,fitViewOnInit:!1,fitViewOnInitDone:!1,fitViewOnInitOptions:void 0,onSelectionChange:[],multiSelectionActive:!1,connectionStartHandle:null,connectionEndHandle:null,connectionClickStartHandle:null,connectOnClick:!0,ariaLiveMessage:"",autoPanOnConnect:!0,autoPanOnNodeDrag:!0,connectionRadius:20,onError:mf,isValidConnection:void 0},Bh=()=>Cl((e,t)=>({...We,setNodes:n=>{const{nodeInternals:r,nodeOrigin:s,elevateNodesOnSelect:i}=t();e({nodeInternals:Yn(n,r,s,i)})},getNodes:()=>Array.from(t().nodeInternals.values()),setEdges:n=>{const{defaultEdgeOptions:r={}}=t();e({edges:n.map(s=>({...r,...s}))})},setDefaultNodesAndEdges:(n,r)=>{const s=typeof n<"u",i=typeof r<"u",o=s?Yn(n,new Map,t().nodeOrigin,t().elevateNodesOnSelect):new Map;e({nodeInternals:o,edges:i?r:[],hasDefaultNodes:s,hasDefaultEdges:i})},updateNodeDimensions:n=>{const{onNodesChange:r,nodeInternals:s,fitViewOnInit:i,fitViewOnInitDone:o,fitViewOnInitOptions:a,domNode:l,nodeOrigin:c}=t(),u=l==null?void 0:l.querySelector(".react-flow__viewport");if(!u)return;const d=window.getComputedStyle(u),{m22:m}=new window.DOMMatrixReadOnly(d.transform),f=n.reduce((y,v)=>{const p=s.get(v.id);if(p!=null&&p.hidden)s.set(p.id,{...p,[le]:{...p[le],handleBounds:void 0}});else if(p){const E=kr(v.nodeElement);!!(E.width&&E.height&&(p.width!==E.width||p.height!==E.height||v.forceUpdate))&&(s.set(p.id,{...p,[le]:{...p[le],handleBounds:{source:js(".source",v.nodeElement,m,c),target:js(".target",v.nodeElement,m,c)}},...E}),y.push({id:p.id,type:"dimensions",dimensions:E}))}return y},[]);vo(s,c);const x=o||i&&!o&&_o(t,{initial:!0,...a});e({nodeInternals:new Map(s),fitViewOnInitDone:x}),(f==null?void 0:f.length)>0&&(r==null||r(f))},updateNodePositions:(n,r=!0,s=!1)=>{const{triggerNodeChanges:i}=t(),o=n.map(a=>{const l={id:a.id,type:"position",dragging:s};return r&&(l.positionAbsolute=a.positionAbsolute,l.position=a.position),l});i(o)},triggerNodeChanges:n=>{const{onNodesChange:r,nodeInternals:s,hasDefaultNodes:i,nodeOrigin:o,getNodes:a,elevateNodesOnSelect:l}=t();if(n!=null&&n.length){if(i){const c=sh(n,a()),u=Yn(c,s,o,l);e({nodeInternals:u})}r==null||r(n)}},addSelectedNodes:n=>{const{multiSelectionActive:r,edges:s,getNodes:i}=t();let o,a=null;r?o=n.map(l=>Xe(l,!0)):(o=xt(i(),n),a=xt(s,[])),on({changedNodes:o,changedEdges:a,get:t,set:e})},addSelectedEdges:n=>{const{multiSelectionActive:r,edges:s,getNodes:i}=t();let o,a=null;r?o=n.map(l=>Xe(l,!0)):(o=xt(s,n),a=xt(i(),[])),on({changedNodes:a,changedEdges:o,get:t,set:e})},unselectNodesAndEdges:({nodes:n,edges:r}={})=>{const{edges:s,getNodes:i}=t(),o=n||i(),a=r||s,l=o.map(u=>(u.selected=!1,Xe(u.id,!1))),c=a.map(u=>Xe(u.id,!1));on({changedNodes:l,changedEdges:c,get:t,set:e})},setMinZoom:n=>{const{d3Zoom:r,maxZoom:s}=t();r==null||r.scaleExtent([n,s]),e({minZoom:n})},setMaxZoom:n=>{const{d3Zoom:r,minZoom:s}=t();r==null||r.scaleExtent([s,n]),e({maxZoom:n})},setTranslateExtent:n=>{var r;(r=t().d3Zoom)==null||r.translateExtent(n),e({translateExtent:n})},resetSelectedElements:()=>{const{edges:n,getNodes:r}=t(),i=r().filter(a=>a.selected).map(a=>Xe(a.id,!1)),o=n.filter(a=>a.selected).map(a=>Xe(a.id,!1));on({changedNodes:i,changedEdges:o,get:t,set:e})},setNodeExtent:n=>{const{nodeInternals:r}=t();r.forEach(s=>{s.positionAbsolute=jr(s.position,n)}),e({nodeExtent:n,nodeInternals:new Map(r)})},panBy:n=>{const{transform:r,width:s,height:i,d3Zoom:o,d3Selection:a,translateExtent:l}=t();if(!o||!a||!n.x&&!n.y)return!1;const c=Fe.translate(r[0]+n.x,r[1]+n.y).scale(r[2]),u=[[0,0],[s,i]],d=o==null?void 0:o.constrain()(c,u,l);return o.transform(a,d),r[0]!==d.x||r[1]!==d.y||r[2]!==d.k},cancelConnection:()=>e({connectionNodeId:We.connectionNodeId,connectionHandleId:We.connectionHandleId,connectionHandleType:We.connectionHandleType,connectionStatus:We.connectionStatus,connectionStartHandle:We.connectionStartHandle,connectionEndHandle:We.connectionEndHandle}),reset:()=>e({...We})}),Object.is),To=({children:e})=>{const t=w.useRef(null);return t.current||(t.current=Bh()),M.createElement(af,{value:t.current},e)};To.displayName="ReactFlowProvider";const Oo=({children:e})=>w.useContext(An)?M.createElement(M.Fragment,null,e):M.createElement(To,null,e);Oo.displayName="ReactFlowWrapper";const Gh={input:mo,default:mr,output:go,group:Rr},Yh={default:_n,straight:Mr,step:$r,smoothstep:In,simplebezier:Cr},Wh=[0,0],Uh=[15,15],Xh={x:0,y:0,zoom:1},qh={width:"100%",height:"100%",overflow:"hidden",position:"relative",zIndex:0},Do=w.forwardRef(({nodes:e,edges:t,defaultNodes:n,defaultEdges:r,className:s,nodeTypes:i=Gh,edgeTypes:o=Yh,onNodeClick:a,onEdgeClick:l,onInit:c,onMove:u,onMoveStart:d,onMoveEnd:m,onConnect:f,onConnectStart:x,onConnectEnd:y,onClickConnectStart:v,onClickConnectEnd:p,onNodeMouseEnter:E,onNodeMouseMove:$,onNodeMouseLeave:b,onNodeContextMenu:A,onNodeDoubleClick:j,onNodeDragStart:_,onNodeDrag:I,onNodeDragStop:S,onNodesDelete:D,onEdgesDelete:P,onSelectionChange:V,onSelectionDragStart:F,onSelectionDrag:g,onSelectionDragStop:C,onSelectionContextMenu:N,onSelectionStart:R,onSelectionEnd:H,connectionMode:k=ut.Strict,connectionLineType:T=qe.Bezier,connectionLineStyle:L,connectionLineComponent:z,connectionLineContainerStyle:Y,deleteKeyCode:G="Backspace",selectionKeyCode:K="Shift",selectionOnDrag:J=!1,selectionMode:ee=Yt.Full,panActivationKeyCode:ie="Space",multiSelectionKeyCode:te=wn()?"Meta":"Control",zoomActivationKeyCode:re=wn()?"Meta":"Control",snapToGrid:fe=!1,snapGrid:B=Uh,onlyRenderVisibleElements:q=!1,selectNodesOnDrag:W=!0,nodesDraggable:Q,nodesConnectable:U,nodesFocusable:X,nodeOrigin:O=Wh,edgesFocusable:se,edgesUpdatable:ce,elementsSelectable:me,defaultViewport:we=Xh,minZoom:be=.5,maxZoom:Ee=2,translateExtent:Ye=gr,preventScrolling:oe=!0,nodeExtent:Qe,defaultMarkerColor:ft="#b1b1b7",zoomOnScroll:ht=!0,zoomOnPinch:jt=!0,panOnScroll:xe=!1,panOnScrollSpeed:Ce=.5,panOnScrollMode:Je=ot.Free,zoomOnDoubleClick:et=!0,panOnDrag:tt=!0,onPaneClick:De,onPaneMouseEnter:Re,onPaneMouseMove:Ct,onPaneMouseLeave:Dn,onPaneScroll:$t,onPaneContextMenu:Ln,children:Vr,onEdgeContextMenu:nt,onEdgeDoubleClick:_a,onEdgeMouseEnter:Ea,onEdgeMouseMove:Na,onEdgeMouseLeave:Sa,onEdgeUpdate:ka,onEdgeUpdateStart:ja,onEdgeUpdateEnd:Ca,onReconnect:$a,onReconnectStart:Ma,onReconnectEnd:Aa,reconnectRadius:Ia=10,edgeUpdaterRadius:Ra=10,onNodesChange:Ta,onEdgesChange:Oa,noDragClassName:Da="nodrag",noWheelClassName:La="nowheel",noPanClassName:Br="nopan",fitView:Pa=!1,fitViewOptions:za,connectOnClick:Ha=!0,attributionPosition:Fa,proOptions:Va,defaultEdgeOptions:Ba,elevateNodesOnSelect:Ga=!0,elevateEdgesOnSelect:Ya=!1,disableKeyboardA11y:Gr=!1,autoPanOnConnect:Wa=!0,autoPanOnNodeDrag:Ua=!0,connectionRadius:Xa=20,isValidConnection:qa,onError:Ka,style:Za,id:Yr,nodeDragThreshold:Qa,...Ja},el)=>{const Pn=Yr||"1";return M.createElement("div",{...Ja,style:{...Za,...qh},ref:el,className:ye(["react-flow",s]),"data-testid":"rf__wrapper",id:Yr},M.createElement(Oo,null,M.createElement(Vh,{onInit:c,onMove:u,onMoveStart:d,onMoveEnd:m,onNodeClick:a,onEdgeClick:l,onNodeMouseEnter:E,onNodeMouseMove:$,onNodeMouseLeave:b,onNodeContextMenu:A,onNodeDoubleClick:j,nodeTypes:i,edgeTypes:o,connectionLineType:T,connectionLineStyle:L,connectionLineComponent:z,connectionLineContainerStyle:Y,selectionKeyCode:K,selectionOnDrag:J,selectionMode:ee,deleteKeyCode:G,multiSelectionKeyCode:te,panActivationKeyCode:ie,zoomActivationKeyCode:re,onlyRenderVisibleElements:q,selectNodesOnDrag:W,defaultViewport:we,translateExtent:Ye,minZoom:be,maxZoom:Ee,preventScrolling:oe,zoomOnScroll:ht,zoomOnPinch:jt,zoomOnDoubleClick:et,panOnScroll:xe,panOnScrollSpeed:Ce,panOnScrollMode:Je,panOnDrag:tt,onPaneClick:De,onPaneMouseEnter:Re,onPaneMouseMove:Ct,onPaneMouseLeave:Dn,onPaneScroll:$t,onPaneContextMenu:Ln,onSelectionContextMenu:N,onSelectionStart:R,onSelectionEnd:H,onEdgeContextMenu:nt,onEdgeDoubleClick:_a,onEdgeMouseEnter:Ea,onEdgeMouseMove:Na,onEdgeMouseLeave:Sa,onReconnect:$a??ka,onReconnectStart:Ma??ja,onReconnectEnd:Aa??Ca,reconnectRadius:Ia??Ra,defaultMarkerColor:ft,noDragClassName:Da,noWheelClassName:La,noPanClassName:Br,elevateEdgesOnSelect:Ya,rfId:Pn,disableKeyboardA11y:Gr,nodeOrigin:O,nodeExtent:Qe}),M.createElement(Pf,{nodes:e,edges:t,defaultNodes:n,defaultEdges:r,onConnect:f,onConnectStart:x,onConnectEnd:y,onClickConnectStart:v,onClickConnectEnd:p,nodesDraggable:Q,nodesConnectable:U,nodesFocusable:X,edgesFocusable:se,edgesUpdatable:ce,elementsSelectable:me,elevateNodesOnSelect:Ga,minZoom:be,maxZoom:Ee,nodeExtent:Qe,onNodesChange:Ta,onEdgesChange:Oa,snapToGrid:fe,snapGrid:B,connectionMode:k,translateExtent:Ye,connectOnClick:Ha,defaultEdgeOptions:Ba,fitView:Pa,fitViewOptions:za,onNodesDelete:D,onEdgesDelete:P,onNodeDragStart:_,onNodeDrag:I,onNodeDragStop:S,onSelectionDrag:g,onSelectionDragStart:F,onSelectionDragStop:C,noPanClassName:Br,nodeOrigin:O,rfId:Pn,autoPanOnConnect:Wa,autoPanOnNodeDrag:Ua,onError:Ka,connectionRadius:Xa,isValidConnection:qa,nodeDragThreshold:Qa}),M.createElement(Df,{onSelectionChange:V}),Vr,M.createElement(cf,{proOptions:Va,position:Fa}),M.createElement(Bf,{rfId:Pn,disableKeyboardA11y:Gr})))});Do.displayName="ReactFlow";const Lo=({id:e,x:t,y:n,width:r,height:s,style:i,color:o,strokeColor:a,strokeWidth:l,className:c,borderRadius:u,shapeRendering:d,onClick:m,selected:f})=>{const{background:x,backgroundColor:y}=i||{},v=o||x||y;return M.createElement("rect",{className:ye(["react-flow__minimap-node",{selected:f},c]),x:t,y:n,rx:u,ry:u,width:r,height:s,fill:v,stroke:a,strokeWidth:l,shapeRendering:d,onClick:m?p=>m(p,e):void 0})};Lo.displayName="MiniMapNode";var Kh=w.memo(Lo);const Zh=e=>e.nodeOrigin,Qh=e=>e.getNodes().filter(t=>!t.hidden&&t.width&&t.height),qn=e=>e instanceof Function?e:()=>e;function Jh({nodeStrokeColor:e="transparent",nodeColor:t="#e2e2e2",nodeClassName:n="",nodeBorderRadius:r=5,nodeStrokeWidth:s=2,nodeComponent:i=Kh,onClick:o}){const a=ae(Qh,ge),l=ae(Zh),c=qn(t),u=qn(e),d=qn(n),m=typeof window>"u"||window.chrome?"crispEdges":"geometricPrecision";return M.createElement(M.Fragment,null,a.map(f=>{const{x,y}=lt(f,l).positionAbsolute;return M.createElement(i,{key:f.id,x,y,width:f.width,height:f.height,style:f.style,selected:f.selected,className:d(f),color:c(f),borderRadius:r,strokeColor:u(f),strokeWidth:s,shapeRendering:m,onClick:o,id:f.id})}))}var em=w.memo(Jh);const tm=200,nm=150,rm=e=>{const t=e.getNodes(),n={x:-e.transform[0]/e.transform[2],y:-e.transform[1]/e.transform[2],width:e.width/e.transform[2],height:e.height/e.transform[2]};return{viewBB:n,boundingRect:t.length>0?ff(Kt(t,e.nodeOrigin),n):n,rfId:e.rfId}},sm="react-flow__minimap-desc";function Po({style:e,className:t,nodeStrokeColor:n="transparent",nodeColor:r="#e2e2e2",nodeClassName:s="",nodeBorderRadius:i=5,nodeStrokeWidth:o=2,nodeComponent:a,maskColor:l="rgb(240, 240, 240, 0.6)",maskStrokeColor:c="none",maskStrokeWidth:u=1,position:d="bottom-right",onClick:m,onNodeClick:f,pannable:x=!1,zoomable:y=!1,ariaLabel:v="React Flow mini map",inversePan:p=!1,zoomStep:E=10,offsetScale:$=5}){const b=pe(),A=w.useRef(null),{boundingRect:j,viewBB:_,rfId:I}=ae(rm,ge),S=(e==null?void 0:e.width)??tm,D=(e==null?void 0:e.height)??nm,P=j.width/S,V=j.height/D,F=Math.max(P,V),g=F*S,C=F*D,N=$*F,R=j.x-(g-j.width)/2-N,H=j.y-(C-j.height)/2-N,k=g+N*2,T=C+N*2,L=`${sm}-${I}`,z=w.useRef(0);z.current=F,w.useEffect(()=>{if(A.current){const K=Ne(A.current),J=te=>{const{transform:re,d3Selection:fe,d3Zoom:B}=b.getState();if(te.sourceEvent.type!=="wheel"||!fe||!B)return;const q=-te.sourceEvent.deltaY*(te.sourceEvent.deltaMode===1?.05:te.sourceEvent.deltaMode?1:.002)*E,W=re[2]*Math.pow(2,q);B.scaleTo(fe,W)},ee=te=>{const{transform:re,d3Selection:fe,d3Zoom:B,translateExtent:q,width:W,height:Q}=b.getState();if(te.sourceEvent.type!=="mousemove"||!fe||!B)return;const U=z.current*Math.max(1,re[2])*(p?-1:1),X={x:re[0]-te.sourceEvent.movementX*U,y:re[1]-te.sourceEvent.movementY*U},O=[[0,0],[W,Q]],se=Fe.translate(X.x,X.y).scale(re[2]),ce=B.constrain()(se,O,q);B.transform(fe,ce)},ie=Yi().on("zoom",x?ee:null).on("zoom.wheel",y?J:null);return K.call(ie),()=>{K.on("zoom",null)}}},[x,y,p,E]);const Y=m?K=>{const J=$e(K);m(K,{x:J[0],y:J[1]})}:void 0,G=f?(K,J)=>{const ee=b.getState().nodeInternals.get(J);f(K,ee)}:void 0;return M.createElement(Sr,{position:d,style:e,className:ye(["react-flow__minimap",t]),"data-testid":"rf__minimap"},M.createElement("svg",{width:S,height:D,viewBox:`${R} ${H} ${k} ${T}`,role:"img","aria-labelledby":L,ref:A,onClick:Y},v&&M.createElement("title",{id:L},v),M.createElement(em,{onClick:G,nodeColor:r,nodeStrokeColor:n,nodeBorderRadius:i,nodeClassName:s,nodeStrokeWidth:o,nodeComponent:a}),M.createElement("path",{className:"react-flow__minimap-mask",d:`M${R-N},${H-N}h${k+N*2}v${T+N*2}h${-k-N*2}z + M${_.x},${_.y}h${_.width}v${_.height}h${-_.width}z`,fill:l,fillRule:"evenodd",stroke:c,strokeWidth:u,pointerEvents:"none"})))}Po.displayName="MiniMap";var im=w.memo(Po);function om(){return M.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32"},M.createElement("path",{d:"M32 18.133H18.133V32h-4.266V18.133H0v-4.266h13.867V0h4.266v13.867H32z"}))}function am(){return M.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 5"},M.createElement("path",{d:"M0 0h32v4.2H0z"}))}function lm(){return M.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 30"},M.createElement("path",{d:"M3.692 4.63c0-.53.4-.938.939-.938h5.215V0H4.708C2.13 0 0 2.054 0 4.63v5.216h3.692V4.631zM27.354 0h-5.2v3.692h5.17c.53 0 .984.4.984.939v5.215H32V4.631A4.624 4.624 0 0027.354 0zm.954 24.83c0 .532-.4.94-.939.94h-5.215v3.768h5.215c2.577 0 4.631-2.13 4.631-4.707v-5.139h-3.692v5.139zm-23.677.94c-.531 0-.939-.4-.939-.94v-5.138H0v5.139c0 2.577 2.13 4.707 4.708 4.707h5.138V25.77H4.631z"}))}function cm(){return M.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32"},M.createElement("path",{d:"M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0 8 0 4.571 3.429 4.571 7.619v3.048H3.048A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047zm4.724-13.866H7.467V7.619c0-2.59 2.133-4.724 4.723-4.724 2.591 0 4.724 2.133 4.724 4.724v3.048z"}))}function um(){return M.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32"},M.createElement("path",{d:"M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0c-4.114 1.828-1.37 2.133.305 2.438 1.676.305 4.42 2.59 4.42 5.181v3.048H3.047A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047z"}))}const Lt=({children:e,className:t,...n})=>M.createElement("button",{type:"button",className:ye(["react-flow__controls-button",t]),...n},e);Lt.displayName="ControlButton";const dm=e=>({isInteractive:e.nodesDraggable||e.nodesConnectable||e.elementsSelectable,minZoomReached:e.transform[2]<=e.minZoom,maxZoomReached:e.transform[2]>=e.maxZoom}),zo=({style:e,showZoom:t=!0,showFitView:n=!0,showInteractive:r=!0,fitViewOptions:s,onZoomIn:i,onZoomOut:o,onFitView:a,onInteractiveChange:l,className:c,children:u,position:d="bottom-left"})=>{const m=pe(),[f,x]=w.useState(!1),{isInteractive:y,minZoomReached:v,maxZoomReached:p}=ae(dm,ge),{zoomIn:E,zoomOut:$,fitView:b}=Rn();if(w.useEffect(()=>{x(!0)},[]),!f)return null;const A=()=>{E(),i==null||i()},j=()=>{$(),o==null||o()},_=()=>{b(s),a==null||a()},I=()=>{m.setState({nodesDraggable:!y,nodesConnectable:!y,elementsSelectable:!y}),l==null||l(!y)};return M.createElement(Sr,{className:ye(["react-flow__controls",c]),position:d,style:e,"data-testid":"rf__controls"},t&&M.createElement(M.Fragment,null,M.createElement(Lt,{onClick:A,className:"react-flow__controls-zoomin",title:"zoom in","aria-label":"zoom in",disabled:p},M.createElement(om,null)),M.createElement(Lt,{onClick:j,className:"react-flow__controls-zoomout",title:"zoom out","aria-label":"zoom out",disabled:v},M.createElement(am,null))),n&&M.createElement(Lt,{className:"react-flow__controls-fitview",onClick:_,title:"fit view","aria-label":"fit view"},M.createElement(lm,null)),r&&M.createElement(Lt,{className:"react-flow__controls-interactive",onClick:I,title:"toggle interactivity","aria-label":"toggle interactivity"},y?M.createElement(um,null):M.createElement(cm,null)),u)};zo.displayName="Controls";var fm=w.memo(zo),ke;(function(e){e.Lines="lines",e.Dots="dots",e.Cross="cross"})(ke||(ke={}));function hm({color:e,dimensions:t,lineWidth:n}){return M.createElement("path",{stroke:e,strokeWidth:n,d:`M${t[0]/2} 0 V${t[1]} M0 ${t[1]/2} H${t[0]}`})}function mm({color:e,radius:t}){return M.createElement("circle",{cx:t,cy:t,r:t,fill:e})}const pm={[ke.Dots]:"#91919a",[ke.Lines]:"#eee",[ke.Cross]:"#e2e2e2"},gm={[ke.Dots]:1,[ke.Lines]:1,[ke.Cross]:6},ym=e=>({transform:e.transform,patternId:`pattern-${e.rfId}`});function Ho({id:e,variant:t=ke.Dots,gap:n=20,size:r,lineWidth:s=1,offset:i=2,color:o,style:a,className:l}){const c=w.useRef(null),{transform:u,patternId:d}=ae(ym,ge),m=o||pm[t],f=r||gm[t],x=t===ke.Dots,y=t===ke.Cross,v=Array.isArray(n)?n:[n,n],p=[v[0]*u[2]||1,v[1]*u[2]||1],E=f*u[2],$=y?[E,E]:p,b=x?[E/i,E/i]:[$[0]/i,$[1]/i];return M.createElement("svg",{className:ye(["react-flow__background",l]),style:{...a,position:"absolute",width:"100%",height:"100%",top:0,left:0},ref:c,"data-testid":"rf__background"},M.createElement("pattern",{id:d+e,x:u[0]%p[0],y:u[1]%p[1],width:p[0],height:p[1],patternUnits:"userSpaceOnUse",patternTransform:`translate(-${b[0]},-${b[1]})`},x?M.createElement(mm,{color:m,radius:E/i}):M.createElement(hm,{dimensions:$,color:m,lineWidth:s})),M.createElement("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:`url(#${d+e})`}))}Ho.displayName="Background";var xm=w.memo(Ho);const Or=(()=>{const e=window.location.pathname.match(/^(\/view\/[^/]+)(?:\/|$)/);return e?e[1]:""})();function Fo(e){return Or+e}async function de(e){const t=await fetch(Fo(e));if(!t.ok)throw new Error(`${e}: ${t.status} ${await t.text()}`);return await t.json()}async function Ge(e,t){const n=await fetch(Fo(e),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),r=await n.json();if(!n.ok)throw new Vo(r.error??`${e}: ${n.status}`,n.status);return r}class Vo extends Error{constructor(n,r){super(n);ue(this,"status");this.status=r}}const xx=e=>de(e?`/api/model?subject_area=${encodeURIComponent(e)}`:"/api/model"),wx=()=>de("/api/diagnostics"),Bo=(e,t)=>de(`/api/ontology/search?q=${encodeURIComponent(e)}`+(t?`&within=${encodeURIComponent(t)}`:"")),Go=()=>de("/api/ontology/ontologies"),wm=e=>de(`/api/ontology/term?ref=${encodeURIComponent(e)}`),bm=()=>de("/api/ontology/stack"),vm=()=>de("/api/ontology/coverage"),_m=(e,t,n)=>Ge("/api/command",{op:e,payload:t,fingerprint:n??""}),Em=()=>de("/api/git/status"),Nm=()=>de("/api/git/diff"),Sm=e=>Ge("/api/git/commit",{message:e}),km=()=>Ge("/api/git/discard",{}),jm=()=>de("/api/decisions"),Os=(e,t)=>Ge(`/api/decisions/${e}/verdict`,{verdict:t}),bx=(e={})=>{const t=new URLSearchParams;return e.subject_area&&t.set("subject_area",e.subject_area),e.q&&t.set("q",e.q),de(`/api/glossary/terms?${t.toString()}`)},vx=()=>de("/api/glossary/config"),_x=e=>Ge("/api/git/propose",e),Ex=(e="HEAD")=>de(`/api/git/diff/model?base=${encodeURIComponent(e)}`),Nx=(e="HEAD")=>de(`/api/git/classify?base=${encodeURIComponent(e)}`),Sx=e=>Ge("/api/git/classify",{changes:e}),kx=e=>de(`/api/git/conflicts?base=${encodeURIComponent(e)}`),jx=(e="")=>de(`/api/git/context?user=${encodeURIComponent(e)}`),Cx=(e="")=>de(`/api/git/proposals?user=${encodeURIComponent(e)}`),Cm=()=>de("/api/export"),$m=(e,t)=>{const n=t?`?dialect=${encodeURIComponent(t)}`:"";return`${Or}/api/export/${encodeURIComponent(e)}${n}`},Mm=(e,t,n)=>Ge("/api/import",{format:e,content:t,dialect:n}),Am=(e,t)=>Ge("/api/import/preview",{format:e,content:t}),$x=e=>de(`/api/import/stash/${encodeURIComponent(e)}`),Mx=async(e,t=!1)=>{for(const n of e)try{await _m(n.op,n.payload)}catch(r){if(t&&r instanceof Error&&/already exists/i.test(r.message))continue;throw r}},Ax=(e,t,n)=>fetch(`${Or}/api/preview`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({changes:e,subject_area:t??""}),signal:n}).then(async r=>{if(!r.ok)throw new Vo(await r.text(),r.status);return await r.json()}),Ix=()=>de("/api/glossary/subject-areas"),Rx=e=>de(`/api/glossary/subject-area/${e}`),Tx=(e,t)=>Ge(`/api/glossary/subject-area/${e}/expand`,t),Im={business_key:"🔑",surrogate_key:"#",measure:"Σ",attribute:""};function Rm(e){return e??""}const Dr="__entity_source",Lr="__entity_target",Tm=w.memo(function({data:t,selected:n}){var j;const{entity:r,color:s,dimmed:i,highlighted:o,showTypes:a,collapseDetail:l,expanded:c,onToggleExpand:u,endpointAttrs:d,highlightAttrs:m,dimAttrs:f,onHoverAttr:x}=t,y=_=>_.role==="business_key"?0:d!=null&&d.has(_.id)?1:2,v=[...r.attributes].map((_,I)=>({a:_,i:I})).sort((_,I)=>y(_.a)-y(I.a)||_.i-I.i).map(_=>_.a),p=v.filter(_=>_.role==="business_key");let E=v.filter(_=>_.role!=="business_key");const $=!!l&&!c;let b=0;if($){const _=E.filter(I=>d==null?void 0:d.has(I.id));b=E.length-_.length,E=_}const A=(_,I)=>{const S="attr-row"+(m!=null&&m.has(_.id)?" rel-hit":"")+(f!=null&&f.has(_.id)?" rel-dim":"")+(d!=null&&d.has(_.id)?" endpoint":"");return h.jsxs("div",{className:S,onMouseEnter:x?()=>x(_.id):void 0,onMouseLeave:x?()=>x(null):void 0,children:[h.jsx(Ke,{id:_.id,type:"target",position:Z.Left,className:"port attr-port"}),h.jsx(Ke,{id:_.id,type:"source",position:Z.Right,className:"port attr-port"}),h.jsx("span",{className:"attr-icon",children:Im[_.role]}),h.jsx("span",{className:"attr-name"+(I?" pk":""),children:_.name}),a&&h.jsx("span",{className:"attr-type",children:Rm(_.domain)}),!_.nullable&&h.jsx("span",{className:"attr-notnull",title:"not null",children:"●"})]},_.id)};return h.jsxs("div",{className:"entity-node"+(n?" selected":"")+(i?" dimmed":"")+(o?" highlighted":""),style:{borderTopColor:s},children:[h.jsx(Ke,{id:Lr,type:"target",position:Z.Left,className:"port"}),h.jsx(Ke,{id:Dr,type:"source",position:Z.Right,className:"port"}),h.jsxs("div",{className:"entity-header",children:[h.jsx("span",{className:"entity-name",title:((j=r.conceptual)==null?void 0:j.definition)??void 0,children:r.name}),h.jsxs("span",{className:"entity-badges",children:[r.pattern&&h.jsx("span",{className:"badge pattern",children:r.pattern}),(()=>{var S;const _=(((S=r.conceptual)==null?void 0:S.ontology_refs)??[]).filter(D=>D.uri);if(_.length===0)return null;const I=_.map(D=>D.uri).join(` +`);return h.jsxs("span",{className:"badge ontology",title:I,children:["⚙",_.length>1?` ${_.length}`:""]})})()]})]}),p.length>0&&h.jsx("div",{className:"attr-section keys",children:p.map(_=>A(_,!0))}),h.jsxs("div",{className:"attr-section",children:[E.map(_=>A(_,!1)),r.attributes.length===0&&h.jsx("div",{className:"attr-row empty",children:"no attributes"}),b>0&&h.jsx("div",{className:"attr-row more",title:"Show all columns",onClick:u?()=>u(r.id):void 0,children:`+${b} more`}),c&&!!l&&h.jsx("div",{className:"attr-row more",title:"Collapse to keys",onClick:u?()=>u(r.id):void 0,children:"− collapse"})]})]})}),Om=["string","integer","bigint","decimal","boolean","date","timestamp"];function Dm({entity:e,doc:t,caps:n,exec:r,onClose:s,onFocusEntity:i,onAlign:o,onEditMapping:a}){var m,f,x,y,v,p,E,$,b,A,j,_,I;const l=!n.canEdit,c=e.conceptual,u=t.relationships.filter(S=>S.from.entity===e.id||S.to.entity===e.id),d=S=>{var D;return((D=t.entities.find(P=>P.id===S))==null?void 0:D.name)??S};return h.jsxs("aside",{className:"detail-panel",children:[h.jsxs("div",{className:"detail-header",children:[h.jsxs("div",{style:{flex:1},children:[h.jsx(Pe,{value:e.name,className:"entity-title-input",readOnly:l,onCommit:S=>r("rename_entity",{id:e.id,name:S})}),(e.physical_name||!l)&&h.jsxs("div",{className:"physical-name-row",title:"Physical table name (erwin Physical_Name)",children:[h.jsx("span",{className:"physical-label",children:"physical"}),h.jsx(Pe,{value:e.physical_name??"",className:"physical-name-input",placeholder:l?"—":"physical table name…",readOnly:l,onCommit:S=>r("rename_entity",{id:e.id,physical_name:S})})]}),h.jsxs("div",{children:[h.jsx(Pm,{entity:e,doc:t,readOnly:l,exec:r}),h.jsx(Hm,{entity:e,readOnly:l,exec:r}),e.category&&h.jsx("span",{className:"cat-badge "+e.category.role,title:e.category.role==="supertype"?`Supertype of category "${e.category.category}"`:`Subtype in "${e.category.category}" (${e.category.materialization})`,children:e.category.role==="supertype"?"◆ supertype":"◇ subtype"})]})]}),h.jsx("button",{className:"icon-btn",onClick:s,title:"Close",children:"✕"})]}),h.jsxs("section",{children:[h.jsx("h3",{children:"Definition"}),h.jsx(Pe,{value:((m=c==null?void 0:c.definition)==null?void 0:m.trim())??"",multiline:!0,placeholder:l?"—":"add a business definition…",className:"definition-input",readOnly:l,onCommit:S=>r("set_definition",{id:e.id,definition:S})})]}),h.jsxs("section",{children:[h.jsxs("h3",{children:["Ontology",!l&&h.jsxs("span",{className:"h3-actions",children:[h.jsx("button",{className:"mini-btn",onClick:()=>o(e),children:(((f=c==null?void 0:c.ontology_refs)==null?void 0:f.length)??0)>0?"Add / re-align…":"Align…"}),(((x=c==null?void 0:c.ontology_refs)==null?void 0:x.length)??0)>0&&h.jsx("button",{className:"mini-btn danger",onClick:()=>r("clear_alignment",{id:e.id}),title:"Clear every alignment on this object",children:"Clear all"})]})]}),(c==null?void 0:c.ontology_layer)&&h.jsxs("div",{className:"kv",children:[h.jsx("span",{className:"k",children:"layer"}),h.jsx("span",{className:`chip layer-${c.ontology_layer}`,children:c.ontology_layer}),c.no_industry_equivalent&&h.jsx("span",{className:"chip",title:"reviewed: no industry equivalent",children:"no industry equivalent"})]}),h.jsx(Lm,{entityId:e.id,refs:(c==null?void 0:c.ontology_refs)??[],caps:n,exec:r})]}),h.jsxs("section",{children:[h.jsxs("h3",{children:["Knowledge Graph mapping",!l&&h.jsxs("span",{className:"h3-actions",children:[h.jsx("button",{className:"mini-btn",onClick:()=>a(e),children:(y=e.term_map)!=null&&y.subject_template||(v=e.term_map)!=null&&v.class_iri?"Edit mapping…":"Map…"}),(((p=e.term_map)==null?void 0:p.subject_template)||((E=e.term_map)==null?void 0:E.class_iri))&&h.jsx("button",{className:"mini-btn danger",onClick:()=>r("clear_term_map",{id:e.id}),children:"Clear"})]})]}),($=e.term_map)!=null&&$.subject_template||(b=e.term_map)!=null&&b.class_iri?h.jsxs(h.Fragment,{children:[((A=e.term_map)==null?void 0:A.class_iri)&&h.jsxs("div",{className:"kv",children:[h.jsx("span",{className:"k",children:"class IRI"}),h.jsx("code",{className:"v",children:e.term_map.class_iri})]}),((j=e.term_map)==null?void 0:j.subject_template)&&h.jsxs("div",{className:"kv",children:[h.jsx("span",{className:"k",children:"subject"}),h.jsx("code",{className:"v",children:e.term_map.subject_template})]})]}):h.jsxs("p",{className:"empty-hint",children:["uses the default R2RML term-map (base IRI",t.project.kg_base_iri?` ${t.project.kg_base_iri}`:""," + primary key)"]})]}),h.jsxs("section",{children:[h.jsx("h3",{children:"Stewardship"}),h.jsxs("div",{className:"kv",children:[h.jsx("span",{className:"k",children:"owner"}),h.jsx(Pe,{value:((_=c==null?void 0:c.stewardship)==null?void 0:_.owner)??"",placeholder:"—",readOnly:l,onCommit:S=>{var D;return r("set_stewardship",{id:e.id,owner:S,steward:((D=c==null?void 0:c.stewardship)==null?void 0:D.steward)??null})}})]}),h.jsxs("div",{className:"kv",children:[h.jsx("span",{className:"k",children:"steward"}),h.jsx(Pe,{value:((I=c==null?void 0:c.stewardship)==null?void 0:I.steward)??"",placeholder:"—",readOnly:l,onCommit:S=>{var D;return r("set_stewardship",{id:e.id,owner:((D=c==null?void 0:c.stewardship)==null?void 0:D.owner)??null,steward:S})}})]})]}),h.jsxs("section",{children:[h.jsxs("h3",{children:["Attributes (",e.attributes.length,")"]}),h.jsx("table",{className:"attr-table",children:h.jsx("tbody",{children:e.attributes.map(S=>h.jsx(Vm,{a:S,entity:e,doc:t,readOnly:l,exec:r},S.id))})}),!l&&h.jsx(Bm,{entity:e,exec:r})]}),e.key_groups&&e.key_groups.length>0&&h.jsxs("section",{children:[h.jsxs("h3",{children:["Keys (",e.key_groups.length,")"]}),e.key_groups.map(S=>{const D=S.members.map(P=>{var V;return((V=e.attributes.find(F=>F.id===P))==null?void 0:V.name)??"?"}).join(", ");return h.jsxs("div",{className:"key-row",children:[h.jsx("span",{className:"key-badge "+S.type,children:S.type.toUpperCase()}),h.jsx("span",{className:"key-name",children:S.name}),h.jsx("span",{className:"key-cols",children:D})]},S.id)})]}),e.udp&&Object.keys(e.udp).length>0&&h.jsxs("section",{children:[h.jsx("h3",{children:"Properties (UDP)"}),h.jsx("table",{className:"attr-table",children:h.jsx("tbody",{children:Object.entries(e.udp).map(([S,D])=>h.jsxs("tr",{className:"udp-row",children:[h.jsx("td",{className:"udp-key",children:S}),h.jsx("td",{className:"udp-val",children:String(D)})]},S))})})]}),u.length>0&&h.jsxs("section",{children:[h.jsxs("h3",{children:["Relationships (",u.length,")"]}),u.map(S=>{const D=S.from.entity===e.id?S.to.entity:S.from.entity;return h.jsxs("div",{className:"rel-row",children:[h.jsxs("div",{className:"rel-main",children:[h.jsxs("button",{className:"rel-link",onClick:()=>i(D),children:[h.jsx("span",{className:"rel-card",children:Gm(S,e.id)}),d(D)]}),(S.verb_phrase||S.inverse_verb_phrase||!l)&&h.jsxs("div",{className:"verb-phrases",title:"erwin verb phrases (parent → child, and inverse)",children:[h.jsx(Pe,{value:S.verb_phrase??"",className:"verb-input",placeholder:l?"":"verb phrase…",readOnly:l,onCommit:P=>r("update_relationship",{id:S.id,verb_phrase:P})}),h.jsx("span",{className:"verb-sep",children:"/"}),h.jsx(Pe,{value:S.inverse_verb_phrase??"",className:"verb-input",placeholder:l?"":"inverse…",readOnly:l,onCommit:P=>r("update_relationship",{id:S.id,inverse_verb_phrase:P})})]})]}),!l&&h.jsx("button",{className:"mini-btn danger",title:`delete ${S.name}`,onClick:()=>r("delete_relationship",{id:S.id}),children:"✕"})]},S.id)})]}),h.jsxs("section",{children:[h.jsx("h3",{children:"Identity"}),h.jsx("code",{className:"ulid",title:"Immutable ULID — click to copy",onClick:()=>{var S;return(S=navigator.clipboard)==null?void 0:S.writeText(e.id)},children:e.id}),!l&&h.jsx("div",{style:{marginTop:12},children:h.jsx("button",{className:"mini-btn danger",onClick:()=>{confirm(`Delete entity '${e.name}' (and its relationships)?`)&&r("delete_entity",{id:e.id,cascade:!0}).then(s)},children:"Delete entity…"})})]})]})}function Lm({entityId:e,refs:t,caps:n,exec:r}){const s=!n.canEdit,i=t.filter(o=>o.uri);return i.length===0?h.jsx("p",{className:"empty-hint",children:"not aligned to any ontology term"}):h.jsx("div",{className:"ref-list",children:i.map((o,a)=>{const l=o.status==="proposed";return h.jsxs("div",{className:"ref-card"+(l?" proposed":""),children:[h.jsxs("div",{className:"ref-head",children:[h.jsx("code",{className:"ref-uri",title:o.uri??void 0,children:o.uri}),h.jsx("span",{className:"ref-status "+(l?"proposed":"accepted"),children:l?"proposed":"accepted"})]}),h.jsxs("div",{className:"ref-meta",children:[o.predicate&&h.jsx("span",{className:"ref-pill",children:o.predicate}),o.layer&&h.jsx("span",{className:`chip layer-${o.layer}`,children:o.layer}),o.resolved_via&&h.jsxs("span",{className:"ref-via",title:"resolver that found this term",children:["via ",o.resolved_via]}),typeof o.confidence=="number"&&h.jsxs("span",{className:"ref-via",children:["conf ",Math.round(o.confidence*100),"%"]})]}),!s&&h.jsxs("div",{className:"ref-actions",children:[l&&n.canArbitrate&&h.jsx("button",{className:"mini-btn",onClick:()=>r("promote_alignment",{id:e,uri:o.uri}),title:"Accept this proposed alignment (architect action)",children:"Promote"}),h.jsx("button",{className:"mini-btn danger",onClick:()=>r("clear_alignment",{id:e,uri:o.uri}),title:"Remove this alignment",children:"Remove"})]})]},`${o.uri}-${a}`)})})}function Pe({value:e,onCommit:t,readOnly:n,multiline:r=!1,placeholder:s="",className:i=""}){const[o,a]=w.useState(e);w.useEffect(()=>a(e),[e]);const l=()=>{o.trim()!==e.trim()&&t(o.trim())};return n?h.jsx("span",{className:i,children:e||s}):r?h.jsx("textarea",{className:`edit-input ${i}`,value:o,placeholder:s,rows:3,onChange:c=>a(c.target.value),onBlur:l}):h.jsx("input",{className:`edit-input ${i}`,value:o,placeholder:s,onChange:c=>a(c.target.value),onBlur:l,onKeyDown:c=>c.key==="Enter"&&c.target.blur()})}function Pm({entity:e,doc:t,readOnly:n,exec:r}){var i,o,a;const s=((o=(i=e.conceptual)==null?void 0:i.subject_area)==null?void 0:o.id)??"";return n?(a=e.conceptual)!=null&&a.subject_area?h.jsx("span",{className:"chip",children:e.conceptual.subject_area.name}):null:h.jsxs("select",{className:"chip-select",value:s,onChange:l=>r("set_subject_area",{id:e.id,subject_area:l.target.value||null}),children:[h.jsx("option",{value:"",children:"no subject area"}),t.subject_areas.map(l=>h.jsx("option",{value:l.id,children:l.name},l.id))]})}const zm=["","scd2","hub","link","satellite","bridge"];function Hm({entity:e,readOnly:t,exec:n}){return t?e.pattern?h.jsx("span",{className:"chip pattern",children:e.pattern}):null:h.jsx("select",{className:"chip-select",value:e.pattern??"",onChange:r=>n("set_pattern",{id:e.id,pattern:r.target.value||null}),children:zm.map(r=>h.jsx("option",{value:r,children:r||"no pattern"},r))})}const Fm=["attribute","business_key","measure","surrogate_key"];function Vm({a:e,entity:t,doc:n,readOnly:r,exec:s}){if(r)return h.jsxs("tr",{children:[h.jsxs("td",{className:e.role==="business_key"?"pk":"",children:[e.name,e.physical_name&&e.physical_name!==e.name&&h.jsx("span",{className:"physical-col",title:"Physical column name",children:e.physical_name}),e.enum_values&&e.enum_values.length>0&&h.jsx("span",{className:"enum-badge",title:`Allowed: ${e.enum_values.join(", ")}`,children:"enum"})]}),h.jsx("td",{className:"type",children:e.domain??""}),h.jsx("td",{className:"null",children:e.nullable?"":"NN"})]});const i=o=>s("update_attribute",{entity_id:t.id,attribute_id:e.id,...o});return h.jsxs("tr",{children:[h.jsxs("td",{className:e.role==="business_key"?"pk":"",children:[h.jsx(Pe,{value:e.name,readOnly:!1,onCommit:o=>i({name:o})}),(e.physical_name||!1)&&h.jsx(Pe,{value:e.physical_name??"",className:"physical-col-input",placeholder:"physical…",readOnly:!1,onCommit:o=>i({physical_name:o})}),e.enum_values&&e.enum_values.length>0&&h.jsx("span",{className:"enum-badge",title:`Allowed: ${e.enum_values.join(", ")}`,children:"enum"})]}),h.jsx("td",{className:"type",children:h.jsx("select",{className:"cell-select",value:e.domain??"string",onChange:o=>i({domain:o.target.value}),children:[...new Set([...Om,...n.domains??[],e.domain??"string"])].sort().map(o=>h.jsx("option",{value:o,children:o},o))})}),h.jsx("td",{children:h.jsx("select",{className:"cell-select",value:e.role,onChange:o=>i({role:o.target.value}),title:"role",children:Fm.map(o=>h.jsx("option",{value:o,children:o==="business_key"?"🔑 key":o==="measure"?"Σ measure":o},o))})}),h.jsx("td",{className:"null",children:h.jsx("input",{type:"checkbox",checked:!e.nullable,title:"not null",onChange:o=>i({nullable:!o.target.checked})})}),h.jsx("td",{children:h.jsx("button",{className:"mini-btn danger",title:"delete attribute",onClick:()=>s("delete_attribute",{entity_id:t.id,attribute_id:e.id}),children:"✕"})})]})}function Bm({entity:e,exec:t}){const[n,r]=w.useState(""),s=()=>{n.trim()&&t("add_attribute",{entity_id:e.id,name:n,domain:"string"}).then(()=>r(""))};return h.jsxs("div",{className:"add-attr",children:[h.jsx("input",{className:"edit-input",placeholder:"+ add attribute…",value:n,onChange:i=>r(i.target.value),onKeyDown:i=>i.key==="Enter"&&s()}),n&&h.jsx("button",{className:"mini-btn",onClick:s,children:"Add"})]})}function Gm(e,t){const n=e.from.entity===t;switch(e.cardinality){case"many_to_one":return n?"N:1 →":"1:N ←";case"one_to_many":return n?"1:N →":"N:1 ←";case"one_to_one":return"1:1";default:return"N:M"}}var Ym="\0",rt="\0",Ds="";let Wm=class{constructor(t){ue(this,"_isDirected",!0);ue(this,"_isMultigraph",!1);ue(this,"_isCompound",!1);ue(this,"_label");ue(this,"_defaultNodeLabelFn",()=>{});ue(this,"_defaultEdgeLabelFn",()=>{});ue(this,"_nodes",{});ue(this,"_in",{});ue(this,"_preds",{});ue(this,"_out",{});ue(this,"_sucs",{});ue(this,"_edgeObjs",{});ue(this,"_edgeLabels",{});ue(this,"_nodeCount",0);ue(this,"_edgeCount",0);ue(this,"_parent");ue(this,"_children");t&&(this._isDirected=Object.hasOwn(t,"directed")?t.directed:!0,this._isMultigraph=Object.hasOwn(t,"multigraph")?t.multigraph:!1,this._isCompound=Object.hasOwn(t,"compound")?t.compound:!1),this._isCompound&&(this._parent={},this._children={},this._children[rt]={})}isDirected(){return this._isDirected}isMultigraph(){return this._isMultigraph}isCompound(){return this._isCompound}setGraph(t){return this._label=t,this}graph(){return this._label}setDefaultNodeLabel(t){return this._defaultNodeLabelFn=t,typeof t!="function"&&(this._defaultNodeLabelFn=()=>t),this}nodeCount(){return this._nodeCount}nodes(){return Object.keys(this._nodes)}sources(){var t=this;return this.nodes().filter(n=>Object.keys(t._in[n]).length===0)}sinks(){var t=this;return this.nodes().filter(n=>Object.keys(t._out[n]).length===0)}setNodes(t,n){var r=arguments,s=this;return t.forEach(function(i){r.length>1?s.setNode(i,n):s.setNode(i)}),this}setNode(t,n){return Object.hasOwn(this._nodes,t)?(arguments.length>1&&(this._nodes[t]=n),this):(this._nodes[t]=arguments.length>1?n:this._defaultNodeLabelFn(t),this._isCompound&&(this._parent[t]=rt,this._children[t]={},this._children[rt][t]=!0),this._in[t]={},this._preds[t]={},this._out[t]={},this._sucs[t]={},++this._nodeCount,this)}node(t){return this._nodes[t]}hasNode(t){return Object.hasOwn(this._nodes,t)}removeNode(t){var n=this;if(Object.hasOwn(this._nodes,t)){var r=s=>n.removeEdge(n._edgeObjs[s]);delete this._nodes[t],this._isCompound&&(this._removeFromParentsChildList(t),delete this._parent[t],this.children(t).forEach(function(s){n.setParent(s)}),delete this._children[t]),Object.keys(this._in[t]).forEach(r),delete this._in[t],delete this._preds[t],Object.keys(this._out[t]).forEach(r),delete this._out[t],delete this._sucs[t],--this._nodeCount}return this}setParent(t,n){if(!this._isCompound)throw new Error("Cannot set parent in a non-compound graph");if(n===void 0)n=rt;else{n+="";for(var r=n;r!==void 0;r=this.parent(r))if(r===t)throw new Error("Setting "+n+" as parent of "+t+" would create a cycle");this.setNode(n)}return this.setNode(t),this._removeFromParentsChildList(t),this._parent[t]=n,this._children[n][t]=!0,this}_removeFromParentsChildList(t){delete this._children[this._parent[t]][t]}parent(t){if(this._isCompound){var n=this._parent[t];if(n!==rt)return n}}children(t=rt){if(this._isCompound){var n=this._children[t];if(n)return Object.keys(n)}else{if(t===rt)return this.nodes();if(this.hasNode(t))return[]}}predecessors(t){var n=this._preds[t];if(n)return Object.keys(n)}successors(t){var n=this._sucs[t];if(n)return Object.keys(n)}neighbors(t){var n=this.predecessors(t);if(n){const s=new Set(n);for(var r of this.successors(t))s.add(r);return Array.from(s.values())}}isLeaf(t){var n;return this.isDirected()?n=this.successors(t):n=this.neighbors(t),n.length===0}filterNodes(t){var n=new this.constructor({directed:this._isDirected,multigraph:this._isMultigraph,compound:this._isCompound});n.setGraph(this.graph());var r=this;Object.entries(this._nodes).forEach(function([o,a]){t(o)&&n.setNode(o,a)}),Object.values(this._edgeObjs).forEach(function(o){n.hasNode(o.v)&&n.hasNode(o.w)&&n.setEdge(o,r.edge(o))});var s={};function i(o){var a=r.parent(o);return a===void 0||n.hasNode(a)?(s[o]=a,a):a in s?s[a]:i(a)}return this._isCompound&&n.nodes().forEach(o=>n.setParent(o,i(o))),n}setDefaultEdgeLabel(t){return this._defaultEdgeLabelFn=t,typeof t!="function"&&(this._defaultEdgeLabelFn=()=>t),this}edgeCount(){return this._edgeCount}edges(){return Object.values(this._edgeObjs)}setPath(t,n){var r=this,s=arguments;return t.reduce(function(i,o){return s.length>1?r.setEdge(i,o,n):r.setEdge(i,o),o}),this}setEdge(){var t,n,r,s,i=!1,o=arguments[0];typeof o=="object"&&o!==null&&"v"in o?(t=o.v,n=o.w,r=o.name,arguments.length===2&&(s=arguments[1],i=!0)):(t=o,n=arguments[1],r=arguments[3],arguments.length>2&&(s=arguments[2],i=!0)),t=""+t,n=""+n,r!==void 0&&(r=""+r);var a=Pt(this._isDirected,t,n,r);if(Object.hasOwn(this._edgeLabels,a))return i&&(this._edgeLabels[a]=s),this;if(r!==void 0&&!this._isMultigraph)throw new Error("Cannot set a named edge when isMultigraph = false");this.setNode(t),this.setNode(n),this._edgeLabels[a]=i?s:this._defaultEdgeLabelFn(t,n,r);var l=Um(this._isDirected,t,n,r);return t=l.v,n=l.w,Object.freeze(l),this._edgeObjs[a]=l,Ls(this._preds[n],t),Ls(this._sucs[t],n),this._in[n][a]=l,this._out[t][a]=l,this._edgeCount++,this}edge(t,n,r){var s=arguments.length===1?Kn(this._isDirected,arguments[0]):Pt(this._isDirected,t,n,r);return this._edgeLabels[s]}edgeAsObj(){const t=this.edge(...arguments);return typeof t!="object"?{label:t}:t}hasEdge(t,n,r){var s=arguments.length===1?Kn(this._isDirected,arguments[0]):Pt(this._isDirected,t,n,r);return Object.hasOwn(this._edgeLabels,s)}removeEdge(t,n,r){var s=arguments.length===1?Kn(this._isDirected,arguments[0]):Pt(this._isDirected,t,n,r),i=this._edgeObjs[s];return i&&(t=i.v,n=i.w,delete this._edgeLabels[s],delete this._edgeObjs[s],Ps(this._preds[n],t),Ps(this._sucs[t],n),delete this._in[n][s],delete this._out[t][s],this._edgeCount--),this}inEdges(t,n){var r=this._in[t];if(r){var s=Object.values(r);return n?s.filter(i=>i.v===n):s}}outEdges(t,n){var r=this._out[t];if(r){var s=Object.values(r);return n?s.filter(i=>i.w===n):s}}nodeEdges(t,n){var r=this.inEdges(t,n);if(r)return r.concat(this.outEdges(t,n))}};function Ls(e,t){e[t]?e[t]++:e[t]=1}function Ps(e,t){--e[t]||delete e[t]}function Pt(e,t,n,r){var s=""+t,i=""+n;if(!e&&s>i){var o=s;s=i,i=o}return s+Ds+i+Ds+(r===void 0?Ym:r)}function Um(e,t,n,r){var s=""+t,i=""+n;if(!e&&s>i){var o=s;s=i,i=o}var a={v:s,w:i};return r&&(a.name=r),a}function Kn(e,t){return Pt(e,t.v,t.w,t.name)}var Pr=Wm,Xm="2.2.4",qm={Graph:Pr,version:Xm},Km=Pr,Zm={write:Qm,read:tp};function Qm(e){var t={options:{directed:e.isDirected(),multigraph:e.isMultigraph(),compound:e.isCompound()},nodes:Jm(e),edges:ep(e)};return e.graph()!==void 0&&(t.value=structuredClone(e.graph())),t}function Jm(e){return e.nodes().map(function(t){var n=e.node(t),r=e.parent(t),s={v:t};return n!==void 0&&(s.value=n),r!==void 0&&(s.parent=r),s})}function ep(e){return e.edges().map(function(t){var n=e.edge(t),r={v:t.v,w:t.w};return t.name!==void 0&&(r.name=t.name),n!==void 0&&(r.value=n),r})}function tp(e){var t=new Km(e.options).setGraph(e.value);return e.nodes.forEach(function(n){t.setNode(n.v,n.value),n.parent&&t.setParent(n.v,n.parent)}),e.edges.forEach(function(n){t.setEdge({v:n.v,w:n.w,name:n.name},n.value)}),t}var np=rp;function rp(e){var t={},n=[],r;function s(i){Object.hasOwn(t,i)||(t[i]=!0,r.push(i),e.successors(i).forEach(s),e.predecessors(i).forEach(s))}return e.nodes().forEach(function(i){r=[],s(i),r.length&&n.push(r)}),n}let sp=class{constructor(){ue(this,"_arr",[]);ue(this,"_keyIndices",{})}size(){return this._arr.length}keys(){return this._arr.map(function(t){return t.key})}has(t){return Object.hasOwn(this._keyIndices,t)}priority(t){var n=this._keyIndices[t];if(n!==void 0)return this._arr[n].priority}min(){if(this.size()===0)throw new Error("Queue underflow");return this._arr[0].key}add(t,n){var r=this._keyIndices;if(t=String(t),!Object.hasOwn(r,t)){var s=this._arr,i=s.length;return r[t]=i,s.push({key:t,priority:n}),this._decrease(i),!0}return!1}removeMin(){this._swap(0,this._arr.length-1);var t=this._arr.pop();return delete this._keyIndices[t.key],this._heapify(0),t.key}decrease(t,n){var r=this._keyIndices[t];if(n>this._arr[r].priority)throw new Error("New priority is greater than current priority. Key: "+t+" Old: "+this._arr[r].priority+" New: "+n);this._arr[r].priority=n,this._decrease(r)}_heapify(t){var n=this._arr,r=2*t,s=r+1,i=t;r>1,!(n[s].priority1;function ap(e,t,n,r){return lp(e,String(t),n||op,r||function(s){return e.outEdges(s)})}function lp(e,t,n,r){var s={},i=new ip,o,a,l=function(c){var u=c.v!==o?c.v:c.w,d=s[u],m=n(c),f=a.distance+m;if(m<0)throw new Error("dijkstra does not allow negative edge weights. Bad edge: "+c+" Weight: "+m);f0&&(o=i.removeMin(),a=s[o],a.distance!==Number.POSITIVE_INFINITY);)r(o).forEach(l);return s}var cp=Wo,up=dp;function dp(e,t,n){return e.nodes().reduce(function(r,s){return r[s]=cp(e,s,t,n),r},{})}var Uo=fp;function fp(e){var t=0,n=[],r={},s=[];function i(o){var a=r[o]={onStack:!0,lowlink:t,index:t++};if(n.push(o),e.successors(o).forEach(function(u){Object.hasOwn(r,u)?r[u].onStack&&(a.lowlink=Math.min(a.lowlink,r[u].index)):(i(u),a.lowlink=Math.min(a.lowlink,r[u].lowlink))}),a.lowlink===a.index){var l=[],c;do c=n.pop(),r[c].onStack=!1,l.push(c);while(o!==c);s.push(l)}}return e.nodes().forEach(function(o){Object.hasOwn(r,o)||i(o)}),s}var hp=Uo,mp=pp;function pp(e){return hp(e).filter(function(t){return t.length>1||t.length===1&&e.hasEdge(t[0],t[0])})}var gp=xp,yp=()=>1;function xp(e,t,n){return wp(e,t||yp,n||function(r){return e.outEdges(r)})}function wp(e,t,n){var r={},s=e.nodes();return s.forEach(function(i){r[i]={},r[i][i]={distance:0},s.forEach(function(o){i!==o&&(r[i][o]={distance:Number.POSITIVE_INFINITY})}),n(i).forEach(function(o){var a=o.v===i?o.w:o.v,l=t(o);r[i][a]={distance:l,predecessor:i}})}),s.forEach(function(i){var o=r[i];s.forEach(function(a){var l=r[a];s.forEach(function(c){var u=l[i],d=o[c],m=l[c],f=u.distance+d.distance;fe.successors(a):a=>e.neighbors(a),s=n==="post"?Ep:Np,i=[],o={};return t.forEach(a=>{if(!e.hasNode(a))throw new Error("Graph does not have node: "+a);s(a,r,o,i)}),i}function Ep(e,t,n,r){for(var s=[[e,!1]];s.length>0;){var i=s.pop();i[1]?r.push(i[0]):Object.hasOwn(n,i[0])||(n[i[0]]=!0,s.push([i[0],!0]),Zo(t(i[0]),o=>s.push([o,!1])))}}function Np(e,t,n,r){for(var s=[e];s.length>0;){var i=s.pop();Object.hasOwn(n,i)||(n[i]=!0,r.push(i),Zo(t(i),o=>s.push(o)))}}function Zo(e,t){for(var n=e.length;n--;)t(e[n],n,e);return e}var Sp=Ko,kp=jp;function jp(e,t){return Sp(e,t,"post")}var Cp=Ko,$p=Mp;function Mp(e,t){return Cp(e,t,"pre")}var Ap=Pr,Ip=Yo,Rp=Tp;function Tp(e,t){var n=new Ap,r={},s=new Ip,i;function o(l){var c=l.v===i?l.w:l.v,u=s.priority(c);if(u!==void 0){var d=t(l);d0;){if(i=s.removeMin(),Object.hasOwn(r,i))n.setEdge(i,r[i]);else{if(a)throw new Error("Input graph is not connected: "+e);a=!0}e.nodeEdges(i).forEach(o)}return n}var Op={components:np,dijkstra:Wo,dijkstraAll:up,findCycles:mp,floydWarshall:gp,isAcyclic:bp,postorder:kp,preorder:$p,prim:Rp,tarjan:Uo,topsort:qo},Hs=qm,Ie={Graph:Hs.Graph,json:Zm,alg:Op,version:Hs.version};let Dp=class{constructor(){let t={};t._next=t._prev=t,this._sentinel=t}dequeue(){let t=this._sentinel,n=t._prev;if(n!==t)return Fs(n),n}enqueue(t){let n=this._sentinel;t._prev&&t._next&&Fs(t),t._next=n._next,n._next._prev=t,n._next=t,t._prev=n}toString(){let t=[],n=this._sentinel,r=n._prev;for(;r!==n;)t.push(JSON.stringify(r,Lp)),r=r._prev;return"["+t.join(", ")+"]"}};function Fs(e){e._prev._next=e._next,e._next._prev=e._prev,delete e._next,delete e._prev}function Lp(e,t){if(e!=="_next"&&e!=="_prev")return t}var Pp=Dp;let zp=Ie.Graph,Hp=Pp;var Fp=Bp;let Vp=()=>1;function Bp(e,t){if(e.nodeCount()<=1)return[];let n=Yp(e,t||Vp);return Gp(n.graph,n.buckets,n.zeroIdx).flatMap(s=>e.outEdges(s.v,s.w))}function Gp(e,t,n){let r=[],s=t[t.length-1],i=t[0],o;for(;e.nodeCount();){for(;o=i.dequeue();)Zn(e,t,n,o);for(;o=s.dequeue();)Zn(e,t,n,o);if(e.nodeCount()){for(let a=t.length-2;a>0;--a)if(o=t[a].dequeue(),o){r=r.concat(Zn(e,t,n,o,!0));break}}}return r}function Zn(e,t,n,r,s){let i=s?[]:void 0;return e.inEdges(r.v).forEach(o=>{let a=e.edge(o),l=e.node(o.v);s&&i.push({v:o.v,w:o.w}),l.out-=a,xr(t,n,l)}),e.outEdges(r.v).forEach(o=>{let a=e.edge(o),l=o.w,c=e.node(l);c.in-=a,xr(t,n,c)}),e.removeNode(r.v),i}function Yp(e,t){let n=new zp,r=0,s=0;e.nodes().forEach(a=>{n.setNode(a,{v:a,in:0,out:0})}),e.edges().forEach(a=>{let l=n.edge(a.v,a.w)||0,c=t(a),u=l+c;n.setEdge(a.v,a.w,u),s=Math.max(s,n.node(a.v).out+=c),r=Math.max(r,n.node(a.w).in+=c)});let i=Wp(s+r+3).map(()=>new Hp),o=r+1;return n.nodes().forEach(a=>{xr(i,o,n.node(a))}),{graph:n,buckets:i,zeroIdx:o}}function xr(e,t,n){n.out?n.in?e[n.out-n.in+t].enqueue(n):e[e.length-1].enqueue(n):e[0].enqueue(n)}function Wp(e){const t=[];for(let n=0;nt.setNode(n,e.node(n))),e.edges().forEach(n=>{let r=t.edge(n.v,n.w)||{weight:0,minlen:1},s=e.edge(n);t.setEdge(n.v,n.w,{weight:r.weight+s.weight,minlen:Math.max(r.minlen,s.minlen)})}),t}function Xp(e){let t=new Qo({multigraph:e.isMultigraph()}).setGraph(e.graph());return e.nodes().forEach(n=>{e.children(n).length||t.setNode(n,e.node(n))}),e.edges().forEach(n=>{t.setEdge(n,e.edge(n))}),t}function qp(e){let t=e.nodes().map(n=>{let r={};return e.outEdges(n).forEach(s=>{r[s.w]=(r[s.w]||0)+e.edge(s).weight}),r});return zr(e.nodes(),t)}function Kp(e){let t=e.nodes().map(n=>{let r={};return e.inEdges(n).forEach(s=>{r[s.v]=(r[s.v]||0)+e.edge(s).weight}),r});return zr(e.nodes(),t)}function Zp(e,t){let n=e.x,r=e.y,s=t.x-n,i=t.y-r,o=e.width/2,a=e.height/2;if(!s&&!i)throw new Error("Not possible to find intersection inside of the rectangle");let l,c;return Math.abs(i)*o>Math.abs(s)*a?(i<0&&(a=-a),l=a*s/i,c=a):(s<0&&(o=-o),l=o,c=o*i/s),{x:n+l,y:r+c}}function Qp(e){let t=ra(ta(e)+1).map(()=>[]);return e.nodes().forEach(n=>{let r=e.node(n),s=r.rank;s!==void 0&&(t[s][r.order]=n)}),t}function Jp(e){let t=e.nodes().map(r=>{let s=e.node(r).rank;return s===void 0?Number.MAX_VALUE:s}),n=Tn(Math.min,t);e.nodes().forEach(r=>{let s=e.node(r);Object.hasOwn(s,"rank")&&(s.rank-=n)})}function eg(e){let t=e.nodes().map(o=>e.node(o).rank),n=Tn(Math.min,t),r=[];e.nodes().forEach(o=>{let a=e.node(o).rank-n;r[a]||(r[a]=[]),r[a].push(o)});let s=0,i=e.graph().nodeRankFactor;Array.from(r).forEach((o,a)=>{o===void 0&&a%i!==0?--s:o!==void 0&&s&&o.forEach(l=>e.node(l).rank+=s)})}function tg(e,t,n,r){let s={width:0,height:0};return arguments.length>=4&&(s.rank=n,s.order=r),Jo(e,"border",s,t)}function ng(e,t=ea){const n=[];for(let r=0;rea){const n=ng(t);return e.apply(null,n.map(r=>e.apply(null,r)))}else return e.apply(null,t)}function ta(e){const n=e.nodes().map(r=>{let s=e.node(r).rank;return s===void 0?Number.MIN_VALUE:s});return Tn(Math.max,n)}function rg(e,t){let n={lhs:[],rhs:[]};return e.forEach(r=>{t(r)?n.lhs.push(r):n.rhs.push(r)}),n}function sg(e,t){let n=Date.now();try{return t()}finally{console.log(e+" time: "+(Date.now()-n)+"ms")}}function ig(e,t){return t()}let og=0;function na(e){var t=++og;return e+(""+t)}function ra(e,t,n=1){t==null&&(t=e,e=0);let r=i=>itr[t]),Object.entries(e).reduce((r,[s,i])=>(r[s]=n(i,s),r),{})}function zr(e,t){return e.reduce((n,r,s)=>(n[r]=t[s],n),{})}let cg=Fp,ug=he.uniqueId;var dg={run:fg,undo:mg};function fg(e){(e.graph().acyclicer==="greedy"?cg(e,n(e)):hg(e)).forEach(r=>{let s=e.edge(r);e.removeEdge(r),s.forwardName=r.name,s.reversed=!0,e.setEdge(r.w,r.v,s,ug("rev"))});function n(r){return s=>r.edge(s).weight}}function hg(e){let t=[],n={},r={};function s(i){Object.hasOwn(r,i)||(r[i]=!0,n[i]=!0,e.outEdges(i).forEach(o=>{Object.hasOwn(n,o.w)?t.push(o):s(o.w)}),delete n[i])}return e.nodes().forEach(s),t}function mg(e){e.edges().forEach(t=>{let n=e.edge(t);if(n.reversed){e.removeEdge(t);let r=n.forwardName;delete n.reversed,delete n.forwardName,e.setEdge(t.w,t.v,n,r)}})}let pg=he;var gg={run:yg,undo:wg};function yg(e){e.graph().dummyChains=[],e.edges().forEach(t=>xg(e,t))}function xg(e,t){let n=t.v,r=e.node(n).rank,s=t.w,i=e.node(s).rank,o=t.name,a=e.edge(t),l=a.labelRank;if(i===r+1)return;e.removeEdge(t);let c,u,d;for(d=0,++r;r{let n=e.node(t),r=n.edgeLabel,s;for(e.setEdge(n.edgeObj,r);n.dummy;)s=e.successors(t)[0],e.removeNode(t),r.points.push({x:n.x,y:n.y}),n.dummy==="edge-label"&&(r.x=n.x,r.y=n.y,r.width=n.width,r.height=n.height),t=s,n=e.node(t)})}const{applyWithChunking:bg}=he;var On={longestPath:vg,slack:_g};function vg(e){var t={};function n(r){var s=e.node(r);if(Object.hasOwn(t,r))return s.rank;t[r]=!0;let i=e.outEdges(r).map(a=>a==null?Number.POSITIVE_INFINITY:n(a.w)-e.edge(a).minlen);var o=bg(Math.min,i);return o===Number.POSITIVE_INFINITY&&(o=0),s.rank=o}e.sources().forEach(n)}function _g(e,t){return e.node(t.w).rank-e.node(t.v).rank-e.edge(t).minlen}var Eg=Ie.Graph,En=On.slack,sa=Ng;function Ng(e){var t=new Eg({directed:!1}),n=e.nodes()[0],r=e.nodeCount();t.setNode(n,{});for(var s,i;Sg(t,e){var i=s.v,o=r===i?s.w:i;!e.hasNode(o)&&!En(t,s)&&(e.setNode(o,{}),e.setEdge(r,o,{}),n(o))})}return e.nodes().forEach(n),e.nodeCount()}function kg(e,t){return t.edges().reduce((r,s)=>{let i=Number.POSITIVE_INFINITY;return e.hasNode(s.v)!==e.hasNode(s.w)&&(i=En(t,s)),it.node(r).rank+=n)}var Cg=sa,Vs=On.slack,$g=On.longestPath,Mg=Ie.alg.preorder,Ag=Ie.alg.postorder,Ig=he.simplify,Rg=dt;dt.initLowLimValues=Fr;dt.initCutValues=Hr;dt.calcCutValue=ia;dt.leaveEdge=aa;dt.enterEdge=la;dt.exchangeEdges=ca;function dt(e){e=Ig(e),$g(e);var t=Cg(e);Fr(t),Hr(t,e);for(var n,r;n=aa(t);)r=la(t,e,n),ca(t,e,n,r)}function Hr(e,t){var n=Ag(e,e.nodes());n=n.slice(0,n.length-1),n.forEach(r=>Tg(e,t,r))}function Tg(e,t,n){var r=e.node(n),s=r.parent;e.edge(n,s).cutvalue=ia(e,t,n)}function ia(e,t,n){var r=e.node(n),s=r.parent,i=!0,o=t.edge(n,s),a=0;return o||(i=!1,o=t.edge(s,n)),a=o.weight,t.nodeEdges(n).forEach(l=>{var c=l.v===n,u=c?l.w:l.v;if(u!==s){var d=c===i,m=t.edge(l).weight;if(a+=d?m:-m,Dg(e,n,u)){var f=e.edge(n,u).cutvalue;a+=d?-f:f}}}),a}function Fr(e,t){arguments.length<2&&(t=e.nodes()[0]),oa(e,{},1,t)}function oa(e,t,n,r,s){var i=n,o=e.node(r);return t[r]=!0,e.neighbors(r).forEach(a=>{Object.hasOwn(t,a)||(n=oa(e,t,n,a,r))}),o.low=i,o.lim=n++,s?o.parent=s:delete o.parent,n}function aa(e){return e.edges().find(t=>e.edge(t).cutvalue<0)}function la(e,t,n){var r=n.v,s=n.w;t.hasEdge(r,s)||(r=n.w,s=n.v);var i=e.node(r),o=e.node(s),a=i,l=!1;i.lim>o.lim&&(a=o,l=!0);var c=t.edges().filter(u=>l===Bs(e,e.node(u.v),a)&&l!==Bs(e,e.node(u.w),a));return c.reduce((u,d)=>Vs(t,d)!t.node(s).parent),r=Mg(e,n);r=r.slice(1),r.forEach(s=>{var i=e.node(s).parent,o=t.edge(s,i),a=!1;o||(o=t.edge(i,s),a=!0),t.node(s).rank=t.node(i).rank+(a?o.minlen:-o.minlen)})}function Dg(e,t,n){return e.hasEdge(t,n)}function Bs(e,t,n){return n.low<=t.lim&&t.lim<=n.lim}var Lg=On,ua=Lg.longestPath,Pg=sa,zg=Rg,Hg=Fg;function Fg(e){var t=e.graph().ranker;if(t instanceof Function)return t(e);switch(e.graph().ranker){case"network-simplex":Gs(e);break;case"tight-tree":Bg(e);break;case"longest-path":Vg(e);break;case"none":break;default:Gs(e)}}var Vg=ua;function Bg(e){ua(e),Pg(e)}function Gs(e){zg(e)}var Gg=Yg;function Yg(e){let t=Ug(e);e.graph().dummyChains.forEach(n=>{let r=e.node(n),s=r.edgeObj,i=Wg(e,t,s.v,s.w),o=i.path,a=i.lca,l=0,c=o[l],u=!0;for(;n!==s.w;){if(r=e.node(n),u){for(;(c=o[l])!==a&&e.node(c).maxRanko||a>t[l].lim));for(c=l,l=r;(l=e.parent(l))!==c;)i.push(l);return{path:s.concat(i.reverse()),lca:c}}function Ug(e){let t={},n=0;function r(s){let i=n;e.children(s).forEach(r),t[s]={low:i,lim:n++}}return e.children().forEach(r),t}let Nn=he;var Xg={run:qg,cleanup:Qg};function qg(e){let t=Nn.addDummyNode(e,"root",{},"_root"),n=Kg(e),r=Object.values(n),s=Nn.applyWithChunking(Math.max,r)-1,i=2*s+1;e.graph().nestingRoot=t,e.edges().forEach(a=>e.edge(a).minlen*=i);let o=Zg(e)+1;e.children().forEach(a=>da(e,t,i,o,s,n,a)),e.graph().nodeRankFactor=i}function da(e,t,n,r,s,i,o){let a=e.children(o);if(!a.length){o!==t&&e.setEdge(t,o,{weight:0,minlen:n});return}let l=Nn.addBorderNode(e,"_bt"),c=Nn.addBorderNode(e,"_bb"),u=e.node(o);e.setParent(l,o),u.borderTop=l,e.setParent(c,o),u.borderBottom=c,a.forEach(d=>{da(e,t,n,r,s,i,d);let m=e.node(d),f=m.borderTop?m.borderTop:d,x=m.borderBottom?m.borderBottom:d,y=m.borderTop?r:2*r,v=f!==x?1:s-i[o]+1;e.setEdge(l,f,{weight:y,minlen:v,nestingEdge:!0}),e.setEdge(x,c,{weight:y,minlen:v,nestingEdge:!0})}),e.parent(o)||e.setEdge(t,l,{weight:0,minlen:s+i[o]})}function Kg(e){var t={};function n(r,s){var i=e.children(r);i&&i.length&&i.forEach(o=>n(o,s+1)),t[r]=s}return e.children().forEach(r=>n(r,1)),t}function Zg(e){return e.edges().reduce((t,n)=>t+e.edge(n).weight,0)}function Qg(e){var t=e.graph();e.removeNode(t.nestingRoot),delete t.nestingRoot,e.edges().forEach(n=>{var r=e.edge(n);r.nestingEdge&&e.removeEdge(n)})}let Jg=he;var e0=t0;function t0(e){function t(n){let r=e.children(n),s=e.node(n);if(r.length&&r.forEach(t),Object.hasOwn(s,"minRank")){s.borderLeft=[],s.borderRight=[];for(let i=s.minRank,o=s.maxRank+1;iWs(e.node(t))),e.edges().forEach(t=>Ws(e.edge(t)))}function Ws(e){let t=e.width;e.width=e.height,e.height=t}function i0(e){e.nodes().forEach(t=>Qn(e.node(t))),e.edges().forEach(t=>{let n=e.edge(t);n.points.forEach(Qn),Object.hasOwn(n,"y")&&Qn(n)})}function Qn(e){e.y=-e.y}function o0(e){e.nodes().forEach(t=>Jn(e.node(t))),e.edges().forEach(t=>{let n=e.edge(t);n.points.forEach(Jn),Object.hasOwn(n,"x")&&Jn(n)})}function Jn(e){let t=e.x;e.x=e.y,e.y=t}let Us=he;var a0=l0;function l0(e){let t={},n=e.nodes().filter(l=>!e.children(l).length),r=n.map(l=>e.node(l).rank),s=Us.applyWithChunking(Math.max,r),i=Us.range(s+1).map(()=>[]);function o(l){if(t[l])return;t[l]=!0;let c=e.node(l);i[c.rank].push(l),e.successors(l).forEach(o)}return n.sort((l,c)=>e.node(l).rank-e.node(c).rank).forEach(o),i}let c0=he.zipObject;var u0=d0;function d0(e,t){let n=0;for(let r=1;ru)),s=t.flatMap(c=>e.outEdges(c).map(u=>({pos:r[u.w],weight:e.edge(u).weight})).sort((u,d)=>u.pos-d.pos)),i=1;for(;i{let u=c.pos+i;a[u]+=c.weight;let d=0;for(;u>0;)u%2&&(d+=a[u+1]),u=u-1>>1,a[u]+=c.weight;l+=c.weight*d}),l}var h0=m0;function m0(e,t=[]){return t.map(n=>{let r=e.inEdges(n);if(r.length){let s=r.reduce((i,o)=>{let a=e.edge(o),l=e.node(o.v);return{sum:i.sum+a.weight*l.order,weight:i.weight+a.weight}},{sum:0,weight:0});return{v:n,barycenter:s.sum/s.weight,weight:s.weight}}else return{v:n}})}let p0=he;var g0=y0;function y0(e,t){let n={};e.forEach((s,i)=>{let o=n[s.v]={indegree:0,in:[],out:[],vs:[s.v],i};s.barycenter!==void 0&&(o.barycenter=s.barycenter,o.weight=s.weight)}),t.edges().forEach(s=>{let i=n[s.v],o=n[s.w];i!==void 0&&o!==void 0&&(o.indegree++,i.out.push(n[s.w]))});let r=Object.values(n).filter(s=>!s.indegree);return x0(r)}function x0(e){let t=[];function n(s){return i=>{i.merged||(i.barycenter===void 0||s.barycenter===void 0||i.barycenter>=s.barycenter)&&w0(s,i)}}function r(s){return i=>{i.in.push(s),--i.indegree===0&&e.push(i)}}for(;e.length;){let s=e.pop();t.push(s),s.in.reverse().forEach(n(s)),s.out.forEach(r(s))}return t.filter(s=>!s.merged).map(s=>p0.pick(s,["vs","i","barycenter","weight"]))}function w0(e,t){let n=0,r=0;e.weight&&(n+=e.barycenter*e.weight,r+=e.weight),t.weight&&(n+=t.barycenter*t.weight,r+=t.weight),e.vs=t.vs.concat(e.vs),e.barycenter=n/r,e.weight=r,e.i=Math.min(t.i,e.i),t.merged=!0}let b0=he;var v0=_0;function _0(e,t){let n=b0.partition(e,u=>Object.hasOwn(u,"barycenter")),r=n.lhs,s=n.rhs.sort((u,d)=>d.i-u.i),i=[],o=0,a=0,l=0;r.sort(E0(!!t)),l=Xs(i,s,l),r.forEach(u=>{l+=u.vs.length,i.push(u.vs),o+=u.barycenter*u.weight,a+=u.weight,l=Xs(i,s,l)});let c={vs:i.flat(!0)};return a&&(c.barycenter=o/a,c.weight=a),c}function Xs(e,t,n){let r;for(;t.length&&(r=t[t.length-1]).i<=n;)t.pop(),e.push(r.vs),n++;return n}function E0(e){return(t,n)=>t.barycentern.barycenter?1:e?n.i-t.i:t.i-n.i}let N0=h0,S0=g0,k0=v0;var j0=ha;function ha(e,t,n,r){let s=e.children(t),i=e.node(t),o=i?i.borderLeft:void 0,a=i?i.borderRight:void 0,l={};o&&(s=s.filter(m=>m!==o&&m!==a));let c=N0(e,s);c.forEach(m=>{if(e.children(m.v).length){let f=ha(e,m.v,n,r);l[m.v]=f,Object.hasOwn(f,"barycenter")&&$0(m,f)}});let u=S0(c,n);C0(u,l);let d=k0(u,r);if(o&&(d.vs=[o,d.vs,a].flat(!0),e.predecessors(o).length)){let m=e.node(e.predecessors(o)[0]),f=e.node(e.predecessors(a)[0]);Object.hasOwn(d,"barycenter")||(d.barycenter=0,d.weight=0),d.barycenter=(d.barycenter*d.weight+m.order+f.order)/(d.weight+2),d.weight+=2}return d}function C0(e,t){e.forEach(n=>{n.vs=n.vs.flatMap(r=>t[r]?t[r].vs:r)})}function $0(e,t){e.barycenter!==void 0?(e.barycenter=(e.barycenter*e.weight+t.barycenter*t.weight)/(e.weight+t.weight),e.weight+=t.weight):(e.barycenter=t.barycenter,e.weight=t.weight)}let M0=Ie.Graph,A0=he;var I0=R0;function R0(e,t,n,r){r||(r=e.nodes());let s=T0(e),i=new M0({compound:!0}).setGraph({root:s}).setDefaultNodeLabel(o=>e.node(o));return r.forEach(o=>{let a=e.node(o),l=e.parent(o);(a.rank===t||a.minRank<=t&&t<=a.maxRank)&&(i.setNode(o),i.setParent(o,l||s),e[n](o).forEach(c=>{let u=c.v===o?c.w:c.v,d=i.edge(u,o),m=d!==void 0?d.weight:0;i.setEdge(u,o,{weight:e.edge(c).weight+m})}),Object.hasOwn(a,"minRank")&&i.setNode(o,{borderLeft:a.borderLeft[t],borderRight:a.borderRight[t]}))}),i}function T0(e){for(var t;e.hasNode(t=A0.uniqueId("_root")););return t}var O0=D0;function D0(e,t,n){let r={},s;n.forEach(i=>{let o=e.parent(i),a,l;for(;o;){if(a=e.parent(o),a?(l=r[a],r[a]=o):(l=s,s=o),l&&l!==o){t.setEdge(l,o);return}o=a}})}let L0=a0,P0=u0,z0=j0,H0=I0,F0=O0,V0=Ie.Graph,ln=he;var B0=ma;function ma(e,t){if(t&&typeof t.customOrder=="function"){t.customOrder(e,ma);return}let n=ln.maxRank(e),r=qs(e,ln.range(1,n+1),"inEdges"),s=qs(e,ln.range(n-1,-1,-1),"outEdges"),i=L0(e);if(Ks(e,i),t&&t.disableOptimalOrderHeuristic)return;let o=Number.POSITIVE_INFINITY,a;for(let l=0,c=0;c<4;++l,++c){G0(l%2?r:s,l%4>=2),i=ln.buildLayerMatrix(e);let u=P0(e,i);u{r.has(i)||r.set(i,[]),r.get(i).push(o)};for(const i of e.nodes()){const o=e.node(i);if(typeof o.rank=="number"&&s(o.rank,i),typeof o.minRank=="number"&&typeof o.maxRank=="number")for(let a=o.minRank;a<=o.maxRank;a++)a!==o.rank&&s(a,i)}return t.map(function(i){return H0(e,i,n,r.get(i)||[])})}function G0(e,t){let n=new V0;e.forEach(function(r){let s=r.graph().root,i=z0(r,s,n,t);i.vs.forEach((o,a)=>r.node(o).order=a),F0(r,n,i.vs)})}function Ks(e,t){Object.values(t).forEach(n=>n.forEach((r,s)=>e.node(r).order=s))}let Y0=Ie.Graph,ze=he;var W0={positionX:ry};function U0(e,t){let n={};function r(s,i){let o=0,a=0,l=s.length,c=i[i.length-1];return i.forEach((u,d)=>{let m=q0(e,u),f=m?e.node(m).order:l;(m||u===c)&&(i.slice(a,d+1).forEach(x=>{e.predecessors(x).forEach(y=>{let v=e.node(y),p=v.order;(p{u=i[d],e.node(u).dummy&&e.predecessors(u).forEach(m=>{let f=e.node(m);f.dummy&&(f.orderc)&&pa(n,m,u)})})}function s(i,o){let a=-1,l,c=0;return o.forEach((u,d)=>{if(e.node(u).dummy==="border"){let m=e.predecessors(u);m.length&&(l=e.node(m[0]).order,r(o,c,d,a,l),c=d,a=l)}r(o,c,o.length,l,i.length)}),o}return t.length&&t.reduce(s),n}function q0(e,t){if(e.node(t).dummy)return e.predecessors(t).find(n=>e.node(n).dummy)}function pa(e,t,n){if(t>n){let s=t;t=n,n=s}let r=e[t];r||(e[t]=r={}),r[n]=!0}function K0(e,t,n){if(t>n){let r=t;t=n,n=r}return!!e[t]&&Object.hasOwn(e[t],n)}function Z0(e,t,n,r){let s={},i={},o={};return t.forEach(a=>{a.forEach((l,c)=>{s[l]=l,i[l]=l,o[l]=c})}),t.forEach(a=>{let l=-1;a.forEach(c=>{let u=r(c);if(u.length){u=u.sort((m,f)=>o[m]-o[f]);let d=(u.length-1)/2;for(let m=Math.floor(d),f=Math.ceil(d);m<=f;++m){let x=u[m];i[c]===c&&lMath.max(m,i[f.v]+o.edge(f)),0)}function u(d){let m=o.outEdges(d).reduce((x,y)=>Math.min(x,i[y.w]-o.edge(y)),Number.POSITIVE_INFINITY),f=e.node(d);m!==Number.POSITIVE_INFINITY&&f.borderType!==a&&(i[d]=Math.max(i[d],m))}return l(c,o.predecessors.bind(o)),l(u,o.successors.bind(o)),Object.keys(r).forEach(d=>i[d]=i[n[d]]),i}function J0(e,t,n,r){let s=new Y0,i=e.graph(),o=sy(i.nodesep,i.edgesep,r);return t.forEach(a=>{let l;a.forEach(c=>{let u=n[c];if(s.setNode(u),l){var d=n[l],m=s.edge(d,u);s.setEdge(d,u,Math.max(o(e,c,l),m||0))}l=c})}),s}function ey(e,t){return Object.values(t).reduce((n,r)=>{let s=Number.NEGATIVE_INFINITY,i=Number.POSITIVE_INFINITY;Object.entries(r).forEach(([a,l])=>{let c=iy(e,a)/2;s=Math.max(l+c,s),i=Math.min(l-c,i)});const o=s-i;return o{["l","r"].forEach(o=>{let a=i+o,l=e[a];if(l===t)return;let c=Object.values(l),u=r-ze.applyWithChunking(Math.min,c);o!=="l"&&(u=s-ze.applyWithChunking(Math.max,c)),u&&(e[a]=ze.mapValues(l,d=>d+u))})})}function ny(e,t){return ze.mapValues(e.ul,(n,r)=>{if(t)return e[t.toLowerCase()][r];{let s=Object.values(e).map(i=>i[r]).sort((i,o)=>i-o);return(s[1]+s[2])/2}})}function ry(e){let t=ze.buildLayerMatrix(e),n=Object.assign(U0(e,t),X0(e,t)),r={},s;["u","d"].forEach(o=>{s=o==="u"?t:Object.values(t).reverse(),["l","r"].forEach(a=>{a==="r"&&(s=s.map(d=>Object.values(d).reverse()));let l=(o==="u"?e.predecessors:e.successors).bind(e),c=Z0(e,s,n,l),u=Q0(e,s,c.root,c.align,a==="r");a==="r"&&(u=ze.mapValues(u,d=>-d)),r[o+a]=u})});let i=ey(e,r);return ty(r,i),ny(r,e.graph().align)}function sy(e,t,n){return(r,s,i)=>{let o=r.node(s),a=r.node(i),l=0,c;if(l+=o.width/2,Object.hasOwn(o,"labelpos"))switch(o.labelpos.toLowerCase()){case"l":c=-o.width/2;break;case"r":c=o.width/2;break}if(c&&(l+=n?c:-c),c=0,l+=(o.dummy?t:e)/2,l+=(a.dummy?t:e)/2,l+=a.width/2,Object.hasOwn(a,"labelpos"))switch(a.labelpos.toLowerCase()){case"l":c=a.width/2;break;case"r":c=-a.width/2;break}return c&&(l+=n?c:-c),c=0,l}}function iy(e,t){return e.node(t).width}let ga=he,oy=W0.positionX;var ay=ly;function ly(e){e=ga.asNonCompoundGraph(e),cy(e),Object.entries(oy(e)).forEach(([t,n])=>e.node(t).x=n)}function cy(e){let t=ga.buildLayerMatrix(e),n=e.graph().ranksep,r=0;t.forEach(s=>{const i=s.reduce((o,a)=>{const l=e.node(a).height;return o>l?o:l},0);s.forEach(o=>e.node(o).y=r+i/2),r+=i+n})}let Zs=dg,Qs=gg,uy=Hg,dy=he.normalizeRanks,fy=Gg,hy=he.removeEmptyRanks,Js=Xg,my=e0,ei=n0,py=B0,gy=ay,je=he,yy=Ie.Graph;var xy=wy;function wy(e,t){let n=t&&t.debugTiming?je.time:je.notime;n("layout",()=>{let r=n(" buildLayoutGraph",()=>$y(e));n(" runLayout",()=>by(r,n,t)),n(" updateInputGraph",()=>vy(e,r))})}function by(e,t,n){t(" makeSpaceForEdgeLabels",()=>My(e)),t(" removeSelfEdges",()=>zy(e)),t(" acyclic",()=>Zs.run(e)),t(" nestingGraph.run",()=>Js.run(e)),t(" rank",()=>uy(je.asNonCompoundGraph(e))),t(" injectEdgeLabelProxies",()=>Ay(e)),t(" removeEmptyRanks",()=>hy(e)),t(" nestingGraph.cleanup",()=>Js.cleanup(e)),t(" normalizeRanks",()=>dy(e)),t(" assignRankMinMax",()=>Iy(e)),t(" removeEdgeLabelProxies",()=>Ry(e)),t(" normalize.run",()=>Qs.run(e)),t(" parentDummyChains",()=>fy(e)),t(" addBorderSegments",()=>my(e)),t(" order",()=>py(e,n)),t(" insertSelfEdges",()=>Hy(e)),t(" adjustCoordinateSystem",()=>ei.adjust(e)),t(" position",()=>gy(e)),t(" positionSelfEdges",()=>Fy(e)),t(" removeBorderNodes",()=>Py(e)),t(" normalize.undo",()=>Qs.undo(e)),t(" fixupEdgeLabelCoords",()=>Dy(e)),t(" undoCoordinateSystem",()=>ei.undo(e)),t(" translateGraph",()=>Ty(e)),t(" assignNodeIntersects",()=>Oy(e)),t(" reversePoints",()=>Ly(e)),t(" acyclic.undo",()=>Zs.undo(e))}function vy(e,t){e.nodes().forEach(n=>{let r=e.node(n),s=t.node(n);r&&(r.x=s.x,r.y=s.y,r.rank=s.rank,t.children(n).length&&(r.width=s.width,r.height=s.height))}),e.edges().forEach(n=>{let r=e.edge(n),s=t.edge(n);r.points=s.points,Object.hasOwn(s,"x")&&(r.x=s.x,r.y=s.y)}),e.graph().width=t.graph().width,e.graph().height=t.graph().height}let _y=["nodesep","edgesep","ranksep","marginx","marginy"],Ey={ranksep:50,edgesep:20,nodesep:50,rankdir:"tb"},Ny=["acyclicer","ranker","rankdir","align"],Sy=["width","height","rank"],ti={width:0,height:0},ky=["minlen","weight","width","height","labeloffset"],jy={minlen:1,weight:1,width:0,height:0,labeloffset:10,labelpos:"r"},Cy=["labelpos"];function $y(e){let t=new yy({multigraph:!0,compound:!0}),n=tr(e.graph());return t.setGraph(Object.assign({},Ey,er(n,_y),je.pick(n,Ny))),e.nodes().forEach(r=>{let s=tr(e.node(r));const i=er(s,Sy);Object.keys(ti).forEach(o=>{i[o]===void 0&&(i[o]=ti[o])}),t.setNode(r,i),t.setParent(r,e.parent(r))}),e.edges().forEach(r=>{let s=tr(e.edge(r));t.setEdge(r,Object.assign({},jy,er(s,ky),je.pick(s,Cy)))}),t}function My(e){let t=e.graph();t.ranksep/=2,e.edges().forEach(n=>{let r=e.edge(n);r.minlen*=2,r.labelpos.toLowerCase()!=="c"&&(t.rankdir==="TB"||t.rankdir==="BT"?r.width+=r.labeloffset:r.height+=r.labeloffset)})}function Ay(e){e.edges().forEach(t=>{let n=e.edge(t);if(n.width&&n.height){let r=e.node(t.v),i={rank:(e.node(t.w).rank-r.rank)/2+r.rank,e:t};je.addDummyNode(e,"edge-proxy",i,"_ep")}})}function Iy(e){let t=0;e.nodes().forEach(n=>{let r=e.node(n);r.borderTop&&(r.minRank=e.node(r.borderTop).rank,r.maxRank=e.node(r.borderBottom).rank,t=Math.max(t,r.maxRank))}),e.graph().maxRank=t}function Ry(e){e.nodes().forEach(t=>{let n=e.node(t);n.dummy==="edge-proxy"&&(e.edge(n.e).labelRank=n.rank,e.removeNode(t))})}function Ty(e){let t=Number.POSITIVE_INFINITY,n=0,r=Number.POSITIVE_INFINITY,s=0,i=e.graph(),o=i.marginx||0,a=i.marginy||0;function l(c){let u=c.x,d=c.y,m=c.width,f=c.height;t=Math.min(t,u-m/2),n=Math.max(n,u+m/2),r=Math.min(r,d-f/2),s=Math.max(s,d+f/2)}e.nodes().forEach(c=>l(e.node(c))),e.edges().forEach(c=>{let u=e.edge(c);Object.hasOwn(u,"x")&&l(u)}),t-=o,r-=a,e.nodes().forEach(c=>{let u=e.node(c);u.x-=t,u.y-=r}),e.edges().forEach(c=>{let u=e.edge(c);u.points.forEach(d=>{d.x-=t,d.y-=r}),Object.hasOwn(u,"x")&&(u.x-=t),Object.hasOwn(u,"y")&&(u.y-=r)}),i.width=n-t+o,i.height=s-r+a}function Oy(e){e.edges().forEach(t=>{let n=e.edge(t),r=e.node(t.v),s=e.node(t.w),i,o;n.points?(i=n.points[0],o=n.points[n.points.length-1]):(n.points=[],i=s,o=r),n.points.unshift(je.intersectRect(r,i)),n.points.push(je.intersectRect(s,o))})}function Dy(e){e.edges().forEach(t=>{let n=e.edge(t);if(Object.hasOwn(n,"x"))switch((n.labelpos==="l"||n.labelpos==="r")&&(n.width-=n.labeloffset),n.labelpos){case"l":n.x-=n.width/2+n.labeloffset;break;case"r":n.x+=n.width/2+n.labeloffset;break}})}function Ly(e){e.edges().forEach(t=>{let n=e.edge(t);n.reversed&&n.points.reverse()})}function Py(e){e.nodes().forEach(t=>{if(e.children(t).length){let n=e.node(t),r=e.node(n.borderTop),s=e.node(n.borderBottom),i=e.node(n.borderLeft[n.borderLeft.length-1]),o=e.node(n.borderRight[n.borderRight.length-1]);n.width=Math.abs(o.x-i.x),n.height=Math.abs(s.y-r.y),n.x=i.x+n.width/2,n.y=r.y+n.height/2}}),e.nodes().forEach(t=>{e.node(t).dummy==="border"&&e.removeNode(t)})}function zy(e){e.edges().forEach(t=>{if(t.v===t.w){var n=e.node(t.v);n.selfEdges||(n.selfEdges=[]),n.selfEdges.push({e:t,label:e.edge(t)}),e.removeEdge(t)}})}function Hy(e){var t=je.buildLayerMatrix(e);t.forEach(n=>{var r=0;n.forEach((s,i)=>{var o=e.node(s);o.order=i+r,(o.selfEdges||[]).forEach(a=>{je.addDummyNode(e,"selfedge",{width:a.label.width,height:a.label.height,rank:o.rank,order:i+ ++r,e:a.e,label:a.label},"_se")}),delete o.selfEdges})})}function Fy(e){e.nodes().forEach(t=>{var n=e.node(t);if(n.dummy==="selfedge"){var r=e.node(n.e.v),s=r.x+r.width/2,i=r.y,o=n.x-s,a=r.height/2;e.setEdge(n.e,n.label),e.removeNode(t),n.label.points=[{x:s+2*o/3,y:i-a},{x:s+5*o/6,y:i-a},{x:s+o,y:i},{x:s+5*o/6,y:i+a},{x:s+2*o/3,y:i+a}],n.label.x=n.x,n.label.y=n.y}})}function er(e,t){return je.mapValues(je.pick(e,t),Number)}function tr(e){var t={};return e&&Object.entries(e).forEach(([n,r])=>{typeof n=="string"&&(n=n.toLowerCase()),t[n]=r}),t}let Vy=he,By=Ie.Graph;var Gy={debugOrdering:Yy};function Yy(e){let t=Vy.buildLayerMatrix(e),n=new By({compound:!0,multigraph:!0}).setGraph({});return e.nodes().forEach(r=>{n.setNode(r,{label:r}),n.setParent(r,"layer"+e.node(r).rank)}),e.edges().forEach(r=>n.setEdge(r.v,r.w,{},r.name)),t.forEach((r,s)=>{let i="layer"+s;n.setNode(i,{rank:"same"}),r.reduce((o,a)=>(n.setEdge(o,a,{style:"invis"}),a))}),n}var Wy="1.1.8",Uy={graphlib:Ie,layout:xy,debug:Gy,util:{time:he.time,notime:he.notime},version:Wy};const ni=fi(Uy),_t=264,Xy=44,qy=26,Ky=14;function Sn(e){const t=Math.max(e.attributes.length,1);return Xy+t*qy+Ky}const Zy=40;function ri(e,t,n,r="auto",s,i="LR"){const o=Qy(n,s);return r==="grid"?ai(e,n,o):r==="clustered"?oi(e,t,n,o,i):r==="hierarchical"||e.length<=Zy?si(e,t,n,i):new Set(e.map(l=>o(l.id)).filter(Boolean)).size>1?oi(e,t,n,o,i):ai(e,n,o)}function Qy(e,t){return n=>{var r,s,i;if(t){const o=t.get(n);if(o)return o.name}return((i=(s=(r=e.get(n))==null?void 0:r.conceptual)==null?void 0:s.subject_area)==null?void 0:i.name)??""}}function ya(e,t,n,r=!1,s="LR"){const i=new ni.graphlib.Graph;i.setGraph({rankdir:s,nodesep:r?45:70,ranksep:r?110:150,edgesep:r?20:30,marginx:24,marginy:24,ranker:"network-simplex"}),i.setDefaultEdgeLabel(()=>({}));const o=new Set(e.map(u=>u.id));for(const u of e){const d=n.get(u.id);i.setNode(u.id,{width:_t,height:d?Sn(d):120})}for(const u of t)o.has(u.source)&&o.has(u.target)&&i.setEdge(u.source,u.target,{minlen:1,weight:2});ni.layout(i);let a=0,l=0;return{nodes:e.map(u=>{const d=i.node(u.id),m=n.get(u.id),f=m?Sn(m):120,x=d.x-_t/2,y=d.y-f/2;return a=Math.max(a,x+_t),l=Math.max(l,y+f),{...u,position:{x,y}}}),width:a,height:l}}function si(e,t,n,r="LR"){return ya(e,t,n,!1,r).nodes}function Jy(e,t){const n=a=>{const l=t.get(a);return l?Sn(l):120},r=Math.max(1,Math.round(Math.sqrt(e.length))),s=[];let i=0,o=0;for(let a=0;a{const d=u*(_t+xa);s.push({...c,position:{x:d,y:i}}),o=Math.max(o,d+_t)}),i+=Math.max(...l.map(c=>n(c.id)))+wa}return{nodes:s,width:o,height:i}}const ii=120;function oi(e,t,n,r,s="LR"){const i=new Map;for(const m of e){const f=r(m.id);(i.get(f)??i.set(f,[]).get(f)).push(m)}const a=[...i.keys()].sort((m,f)=>m===""?1:f===""?-1:m.localeCompare(f)).map(m=>{const f=i.get(m),x=new Set(f.map(E=>E.id));let y=0;for(const E of t)x.has(E.source)&&x.has(E.target)&&y++;const p=f.length<=8&&y>=f.length-1?ya(f,t,n,!0,s):Jy(f,n);return{name:m,...p}}),l=Math.max(1,Math.ceil(Math.sqrt(a.length*1.6))),c=[];let u=0;for(let m=0;m[m.id,m.position]));return e.map(m=>({...m,position:d.get(m.id)??m.position}))}const xa=40,wa=40;function ai(e,t,n){const r=c=>{const u=t.get(c);return u?Sn(u):120},s=[...e].sort((c,u)=>{var y,v;const d=n(c.id),m=n(u.id);if(d!==m)return d.localeCompare(m);const f=((y=t.get(c.id))==null?void 0:y.name)??c.id,x=((v=t.get(u.id))==null?void 0:v.name)??u.id;return f.localeCompare(x)}),i=Math.max(1,Math.round(Math.sqrt(s.length))),o=Array.from({length:i},(c,u)=>u*(_t+xa)),a=new Map;let l=0;for(let c=0;ca.set(m.id,{x:o[f],y:l}));const d=Math.max(...u.map(m=>r(m.id)));l+=d+wa}return e.map(c=>({...c,position:a.get(c.id)??c.position}))}function Zt({title:e,onClose:t,children:n,wide:r}){return h.jsx("div",{className:"modal-backdrop",onClick:t,children:h.jsxs("div",{className:"modal"+(r?" wide":""),onClick:s=>s.stopPropagation(),children:[h.jsxs("div",{className:"modal-header",children:[h.jsx("h2",{children:e}),h.jsx("button",{className:"icon-btn",onClick:t,children:"✕"})]}),n]})})}const ex=["skos:exactMatch","skos:closeMatch","skos:broadMatch","skos:narrowMatch","skos:relatedMatch"],ba=["industry","core","domain","specialised"];function tx({entity:e,exec:t,onClose:n}){var b,A;const[r,s]=w.useState(((b=e.conceptual)==null?void 0:b.name)??e.name),[i,o]=w.useState([]),[a,l]=w.useState(null),[c,u]=w.useState(null),[d,m]=w.useState("skos:exactMatch"),[f,x]=w.useState(((A=e.conceptual)==null?void 0:A.ontology_layer)??"core"),[y,v]=w.useState([]),[p,E]=w.useState("");w.useEffect(()=>{Go().then(j=>v(j.ontologies)).catch(()=>{})},[]),w.useEffect(()=>{const j=setTimeout(()=>{if(!r.trim())return o([]);Bo(r,p||void 0).then(_=>{o(_.results),l(_.loaded_terms)}).catch(()=>o([]))},200);return()=>clearTimeout(j)},[r,p]);const $=()=>{c&&t("set_alignment",{id:e.id,aligns_to:c.prefixed,alignment:d,layer:f,resolved_via:c.source}).then(n)};return h.jsxs(Zt,{title:`Align '${e.name}' to ontology`,onClose:n,wide:!0,children:[y.length>0&&h.jsxs("div",{className:"src-picker",children:[h.jsx("button",{className:"src-chip"+(p===""?" active":""),onClick:()=>E(""),children:"all sources"}),y.map(j=>h.jsx("button",{className:"src-chip"+(p===j.id?" active":""),title:j.count!=null?`${j.count} terms`:"live resolver",onClick:()=>E(j.id),children:j.name},j.id))]}),h.jsx("input",{autoFocus:!0,className:"edit-input modal-search",placeholder:p?`Search within ${p}…`:"Search vocabulary terms…",value:r,onChange:j=>s(j.target.value)}),a===0&&y.length===0&&h.jsx("p",{className:"empty-hint",children:"No vocabulary loaded. Declare one in mdl-project.yaml's ontology_stack (or run `mdl ontology vendor fibo`)."}),h.jsxs("div",{className:"term-results",children:[i.map(j=>h.jsxs("button",{className:"term-card"+((c==null?void 0:c.iri)===j.iri?" picked":""),onClick:()=>u(j),children:[h.jsxs("div",{className:"term-head",children:[h.jsx("span",{className:"term-label",children:j.label}),h.jsxs("span",{className:"term-source",children:[j.source_kind==="glossary-term"&&h.jsx("span",{className:"kind-badge",children:"glossary"}),j.source]})]}),h.jsx("code",{className:"term-iri",children:j.prefixed}),j.definition&&h.jsx("p",{className:"term-def",children:j.definition})]},j.iri)),r&&i.length===0&&a!==0&&h.jsxs("p",{className:"empty-hint",children:["no matches for “",r,"”"]})]}),h.jsxs("div",{className:"modal-footer",children:[h.jsxs("label",{children:["predicate",h.jsx("select",{value:d,onChange:j=>m(j.target.value),children:ex.map(j=>h.jsx("option",{children:j},j))})]}),h.jsxs("label",{children:["layer",h.jsx("select",{value:f,onChange:j=>x(j.target.value),children:ba.map(j=>h.jsx("option",{children:j},j))})]}),h.jsxs("button",{className:"primary-btn",disabled:!c,onClick:$,children:["Align",c?` to ${c.label}`:""]})]})]})}function nx({entity:e,doc:t,exec:n,onClose:r}){var b,A,j;const[s,i]=w.useState(((b=e.term_map)==null?void 0:b.subject_template)??""),[o,a]=w.useState(((A=e.term_map)==null?void 0:A.class_iri)??""),l=new Set(e.attributes.map(_=>_.name)),u=Array.from(s.matchAll(/\{([^}]+)\}/g)).map(_=>_[1]).filter(_=>!l.has(_)),d=_=>!_||_.startsWith("http://")||_.startsWith("https://")||/^[^\s:]+:[^\s:]+/.test(_),m=u.length===0&&d(o),f=()=>{n("set_term_map",{id:e.id,subject_template:s.trim()||null,class_iri:o.trim()||null}).then(r)},x=(t.project.name||"").replace(/[^0-9a-zA-Z]+/g,"-").replace(/^-+|-+$/g,"").toLowerCase()||"modelith-model",y=t.project.kg_base_iri||`urn:${x}:`,v=(j=(e.key_groups??[]).find(_=>_.type==="pk"))==null?void 0:j.members.map(_=>{var I;return(I=e.attributes.find(S=>S.id===_))==null?void 0:I.name}).filter(Boolean),p=v&&v.length?`${y}${e.id}/${v.map(_=>`{${_}}`).join("_")}`:"(blank-node: entity has no primary key)",E=o.trim()||`${y}${e.id}`,$=s.trim()||p;return h.jsxs(Zt,{title:`Knowledge Graph mapping — ${e.name}`,onClose:r,wide:!0,children:[h.jsx("p",{className:"empty-hint",style:{marginBottom:14},children:"Override the R2RML term-map for this entity. Leave a field blank to use the default (project base IRI + primary key)."}),h.jsxs("div",{className:"form-row",children:[h.jsx("label",{htmlFor:"tm-class",children:"Class IRI"}),h.jsx("input",{id:"tm-class",className:"edit-input",value:o,placeholder:"https://acme.com/Customer or fibo-fnd:Party",onChange:_=>a(_.target.value)}),d(o)?h.jsxs("code",{className:"form-preview",children:["rr:class ",E]}):h.jsx("span",{className:"form-error",children:"not a valid IRI or prefix:local CURIE"})]}),h.jsxs("div",{className:"form-row",children:[h.jsx("label",{htmlFor:"tm-subject",children:"Subject template"}),h.jsx("input",{id:"tm-subject",className:"edit-input",value:s,placeholder:"https://acme.com/id/customer/{customer_id}",onChange:_=>i(_.target.value)}),u.length>0?h.jsxs("span",{className:"form-error",children:["unknown column",u.length>1?"s":"",": ",u.join(", ")]}):h.jsxs("code",{className:"form-preview",children:["rr:template ",$]}),h.jsxs("span",{className:"form-hint",children:["Wrap a column in ","{ }"," to fill it from each row, e.g."," ","{"+((v==null?void 0:v[0])??"id")+"}",". Columns:"," ",e.attributes.map(_=>_.name).join(", ")]})]}),h.jsxs("div",{className:"modal-footer",children:[h.jsx("button",{className:"mini-btn",onClick:r,children:"Cancel"}),h.jsx("button",{className:"primary-btn",disabled:!m,onClick:f,children:"Save mapping"})]})]})}function rx({doc:e,exec:t,onClose:n,onCreated:r}){const[s,i]=w.useState(""),[o,a]=w.useState(""),[l,c]=w.useState(""),[u,d]=w.useState(""),m=()=>{s.trim()&&t("create_entity",{name:s,definition:o||null,subject_area:l||null,layer:u||null}).then(f=>{const x=f==null?void 0:f.created_id;n(),x&&r(x)})};return h.jsxs(Zt,{title:"New entity",onClose:n,children:[h.jsxs("label",{className:"form-row",children:["name",h.jsx("input",{autoFocus:!0,className:"edit-input",placeholder:"e.g. custody_account",value:s,onChange:f=>i(f.target.value),onKeyDown:f=>f.key==="Enter"&&m()})]}),h.jsxs("label",{className:"form-row",children:["definition",h.jsx("textarea",{className:"edit-input",rows:2,placeholder:"business definition…",value:o,onChange:f=>a(f.target.value)})]}),h.jsxs("label",{className:"form-row",children:["subject area",h.jsxs("select",{value:l,onChange:f=>c(f.target.value),children:[h.jsx("option",{value:"",children:"none"}),e.subject_areas.map(f=>h.jsx("option",{value:f.id,children:f.name},f.id))]})]}),h.jsxs("label",{className:"form-row",children:["ontology layer",h.jsxs("select",{value:u,onChange:f=>d(f.target.value),children:[h.jsx("option",{value:"",children:"none"}),ba.map(f=>h.jsx("option",{children:f},f))]})]}),h.jsx("div",{className:"modal-footer",children:h.jsx("button",{className:"primary-btn",disabled:!s.trim(),onClick:m,children:"Create"})})]})}const va=["many_to_one","one_to_many","one_to_one","many_to_many"];function sx({doc:e,fromId:t,toId:n,initialFromAttr:r,initialToAttr:s,exec:i,onClose:o}){const a=e.entities.find(b=>b.id===t),l=e.entities.find(b=>b.id===n),c=w.useMemo(()=>l==null?void 0:l.attributes.find(b=>b.role==="business_key"),[l]),[u,d]=w.useState(r??""),[m,f]=w.useState(s??(c==null?void 0:c.id)??""),[x,y]=w.useState("many_to_one"),[v,p]=w.useState("mandatory");if(!a||!l)return null;const E=u==="__new__",$=()=>i("create_relationship",{from_entity:a.id,to_entity:l.id,from_attribute:E?null:u||null,to_attribute:m||null,create_from_fk:E,cardinality:x,optionality:v}).then(o);return h.jsxs(Zt,{title:`${a.name} → ${l.name}`,onClose:o,children:[h.jsxs("label",{className:"form-row",children:["cardinality (",a.name," : ",l.name,")",h.jsx("select",{value:x,onChange:b=>y(b.target.value),children:va.map(b=>h.jsx("option",{children:b},b))})]}),h.jsxs("label",{className:"form-row",children:["foreign key on ",a.name,h.jsxs("select",{value:u,onChange:b=>d(b.target.value),children:[h.jsx("option",{value:"",children:"(none)"}),h.jsxs("option",{value:"__new__",children:["➕ create column",c?` "${c.name}"`:""]}),a.attributes.map(b=>h.jsx("option",{value:b.id,children:b.name},b.id))]})]}),h.jsxs("label",{className:"form-row",children:["references on ",l.name,h.jsxs("select",{value:m,onChange:b=>f(b.target.value),children:[h.jsx("option",{value:"",children:"(none)"}),l.attributes.map(b=>h.jsxs("option",{value:b.id,children:[b.name,b.role==="business_key"?" 🔑":""]},b.id))]})]}),h.jsxs("label",{className:"form-row",children:["optionality",h.jsxs("select",{value:v,onChange:b=>p(b.target.value),children:[h.jsx("option",{children:"mandatory"}),h.jsx("option",{children:"optional"})]})]}),h.jsx("div",{className:"modal-footer",children:h.jsx("button",{className:"primary-btn",onClick:$,children:"Create relationship"})})]})}function ix({rel:e,doc:t,exec:n,onClose:r}){const s=p=>{var E;return((E=t.entities.find($=>$.id===p))==null?void 0:E.name)??"?"},[i,o]=w.useState(e.name),[a,l]=w.useState(e.cardinality),[c,u]=w.useState(e.optionality),[d,m]=w.useState(e.identifying),[f,x]=w.useState(!1),y=async()=>{i.trim()&&i.trim()!==e.name&&await n("rename_relationship",{id:e.id,name:i.trim()}),(a!==e.cardinality||c!==e.optionality||d!==e.identifying)&&await n("update_relationship",{id:e.id,cardinality:a,optionality:c,identifying:d}),r()},v=()=>n("delete_relationship",{id:e.id}).then(r);return h.jsxs(Zt,{title:`${s(e.from.entity)} → ${s(e.to.entity)}`,onClose:r,children:[h.jsxs("label",{className:"form-row",children:["relationship name",h.jsx("input",{value:i,onChange:p=>o(p.target.value),autoFocus:!0})]}),h.jsxs("label",{className:"form-row",children:["cardinality",h.jsx("select",{value:a,onChange:p=>l(p.target.value),children:va.map(p=>h.jsx("option",{children:p},p))})]}),h.jsxs("label",{className:"form-row",children:["optionality",h.jsxs("select",{value:c,onChange:p=>u(p.target.value),children:[h.jsx("option",{value:"mandatory",children:"mandatory"}),h.jsx("option",{value:"optional",children:"optional"})]})]}),h.jsxs("label",{className:"form-row",children:["identifying",h.jsxs("select",{value:d?"yes":"no",onChange:p=>m(p.target.value==="yes"),children:[h.jsx("option",{value:"no",children:"no — parent key is a plain reference"}),h.jsx("option",{value:"yes",children:"yes — parent key is part of the child's identity"})]})]}),h.jsxs("div",{className:"modal-footer",style:{justifyContent:"space-between"},children:[f?h.jsx("button",{className:"danger-btn",onClick:v,children:"Confirm delete"}):h.jsx("button",{className:"mini-btn danger",onClick:()=>x(!0),children:"Delete relationship"}),h.jsx("button",{className:"primary-btn",onClick:y,children:"Save"})]})]})}const ox=w.memo(function({id:t,sourceX:n,sourceY:r,targetX:s,targetY:i,sourcePosition:o,targetPosition:a,data:l,selected:c}){const[u]=vn({sourceX:n,sourceY:r,sourcePosition:o,targetX:s,targetY:i,targetPosition:a,borderRadius:10}),d=l==null?void 0:l.relationship,m=(l==null?void 0:l.dimmed)??!1,f=(d==null?void 0:d.cardinality)??"many_to_one",x=(d==null?void 0:d.optionality)==="optional",y=(d==null?void 0:d.identifying)??!1,v=f==="many_to_one"||f==="many_to_many",p=f==="one_to_many"||f==="many_to_many",E="rel-edge"+(c?" selected":"")+(m?" dimmed":""),$=((l==null?void 0:l.memberCount)??0)>1,b=l==null?void 0:l.onHoverEdge;return h.jsxs("g",{className:E,children:[h.jsx("path",{id:t,className:"rel-path",d:u,fill:"none",strokeDasharray:y?void 0:"6 4"}),h.jsx("path",{d:u,fill:"none",strokeWidth:14,stroke:"transparent",onMouseEnter:b?()=>b(d.id):void 0,onMouseLeave:b?()=>b(null):void 0}),h.jsx(li,{x:n,y:r,side:o,many:v,optional:x}),h.jsx(li,{x:s,y:i,side:a,many:p,optional:!1}),(c||$)&&d&&h.jsxs("text",{className:"rel-label",x:(n+s)/2,y:(r+i)/2-8,children:[c?d.verb_phrase||d.name:"",$?`${c?" ":""}(${l.memberCount})`:""]})]})});function li({x:e,y:t,side:n,many:r,optional:s}){const i=n===Z.Left?-1:1,o=7,a=12,l=[];return r?l.push(h.jsx("path",{className:"rel-glyph",d:`M ${e+i*a} ${t} L ${e} ${t-o} M ${e+i*a} ${t} L ${e} ${t} M ${e+i*a} ${t} L ${e} ${t+o}`,fill:"none"},"foot")):l.push(h.jsx("line",{className:"rel-glyph",x1:e+i*(a-3),y1:t-o,x2:e+i*(a-3),y2:t+o},"one")),s?l.push(h.jsx("circle",{className:"rel-glyph ring",cx:e+i*(a+6),cy:t,r:4},"opt")):l.push(h.jsx("line",{className:"rel-glyph",x1:e+i*(a+5),y1:t-o,x2:e+i*(a+5),y2:t+o},"mand")),h.jsx(h.Fragment,{children:l})}const ax={entity:Tm},lx={relationship:ox},ci=["#e0a63a","#e8825a","#d98ba8","#c4a3e0","#7fb0d8","#7fc9a0","#e6c14a"],ui="#8a7d6a";function cx(e,t){const n=(i,o)=>{var a;return!!o&&!!((a=t.get(i))!=null&&a.attributes.some(l=>l.id===o))},r=e.from.attributes[0],s=e.to.attributes[0];return{sourceHandle:n(e.from.entity,r)?r:Dr,targetHandle:n(e.to.entity,s)?s:Lr}}function Px({doc:e,caps:t,exec:n,selectedId:r,onSelect:s,query:i="",showTypes:o=!0,collapseDetail:a=!1,expandedEntities:l,onToggleExpand:c,activeAreas:u,onError:d,handleRef:m}){const{fitView:f,fitBounds:x,getNodes:y}=Rn(),[v,p]=w.useState([]),[E,$]=w.useState([]),b=w.useRef(!1),[A,j]=w.useState(null),[_,I]=w.useState(null),[S,D]=w.useState(!1),[P,V]=w.useState(null),[F,g]=w.useState(null),[C,N]=w.useState(null),[R,H]=w.useState(null),k=!t.canEdit,T=w.useMemo(()=>{const B=new Map;return e.subject_areas.forEach((q,W)=>B.set(q.id,ci[W%ci.length])),B},[e]),L=w.useMemo(()=>{const B=new Map;return e.entities.forEach(q=>B.set(q.id,q)),B},[e]),z=w.useMemo(()=>{const B=new Map,q=new Map;return e.subject_areas.forEach(W=>{(W.members??[]).forEach(Q=>q.set(Q,{id:W.id,name:W.name}))}),e.entities.forEach(W=>{var O,se;const Q=(O=W.conceptual)!=null&&O.id?q.get(W.conceptual.id):void 0,U=(se=W.conceptual)==null?void 0:se.subject_area,X=Q??(U?{id:U.id,name:U.name??U.id}:void 0);X&&B.set(W.id,X)}),B},[e]),Y=w.useCallback(B=>{var W;if(!u||u.size===0)return!1;const q=(W=z.get(B))==null?void 0:W.id;return!(q&&u.has(q))},[u,z]),G=w.useMemo(()=>{const B=new Map,q=(W,Q)=>{if(!Q.length)return;const U=B.get(W)??new Set;Q.forEach(X=>U.add(X)),B.set(W,U)};for(const W of e.relationships)q(W.from.entity,W.from.attributes),q(W.to.entity,W.to.attributes);return B},[e]);w.useEffect(()=>{var X;const B=i.trim().toLowerCase(),q=new Set;if(B)for(const O of e.entities)(O.name.toLowerCase()+" "+(((X=O.conceptual)==null?void 0:X.name.toLowerCase())??"")+" "+O.attributes.map(ce=>ce.name.toLowerCase()).join(" ")).includes(B)&&q.add(O.id);const W=new Set;if(r){W.add(r);for(const O of e.relationships)O.from.entity===r&&W.add(O.to.entity),O.to.entity===r&&W.add(O.from.entity)}const Q=e.entities.map(O=>{const se=B!==""&&!q.has(O.id),ce=r!==null&&!W.has(O.id);return{id:O.id,type:"entity",position:{x:0,y:0},hidden:Y(O.id),data:{entity:O,color:(()=>{const me=z.get(O.id);return me?T.get(me.id)??ui:ui})(),dimmed:se||ce,highlighted:B!==""&&q.has(O.id),showTypes:o,collapseDetail:a,expanded:(l==null?void 0:l.has(O.id))??!1,onToggleExpand:c,endpointAttrs:G.get(O.id),highlightAttrs:void 0,onHoverAttr:N}}}),U=e.relationships.filter(O=>L.has(O.from.entity)&&L.has(O.to.entity)).map(O=>{const{sourceHandle:se,targetHandle:ce}=cx(O,L),me=r!==null&&O.from.entity!==r&&O.to.entity!==r;return{id:O.id,source:O.from.entity,target:O.to.entity,sourceHandle:se,targetHandle:ce,type:"relationship",data:{relationship:O,dimmed:me,memberCount:Math.max(O.from.attributes.length,O.to.attributes.length),onHoverEdge:H}}});p(O=>{const se=new Map(O.map(oe=>[oe.id,oe.position])),ce=Q.every(oe=>se.has(oe.id)),me=((u==null?void 0:u.size)??0)>0;if(b.current&&ce&&O.length>=Q.length&&!me)return Q.map(oe=>({...oe,position:se.get(oe.id)??oe.position}));const we=me?Q.filter(oe=>!oe.hidden):Q,be=ri(we,U,L,"auto",z),Ee=new Map(be.map(oe=>[oe.id,oe.position])),Ye=Q.map(oe=>Ee.has(oe.id)?{...oe,position:Ee.get(oe.id)}:se.has(oe.id)&&b.current?{...oe,position:se.get(oe.id)}:oe);return b.current=!0,requestAnimationFrame(()=>f({padding:.15,duration:300})),Ye}),$(U)},[e,i,r,o,a,l,c,T,L,z,Y,u,G,f]);const K=w.useMemo(()=>{const B=new Set,q=new Set,W=new Map,Q=(U,X)=>{if(!X.length)return;const O=W.get(U)??new Set;X.forEach(se=>O.add(se)),W.set(U,O)};if(C)for(const U of e.relationships)(U.from.attributes.includes(C)||U.to.attributes.includes(C))&&(B.add(U.id),q.add(U.from.entity),q.add(U.to.entity),Q(U.from.entity,U.from.attributes),Q(U.to.entity,U.to.attributes));if(R){const U=e.relationships.find(X=>X.id===R);U&&(Q(U.from.entity,U.from.attributes),Q(U.to.entity,U.to.attributes))}return{active:C!==null,relsForAttr:B,entsForAttr:q,hitAttrsByEntity:W}},[e,C,R]);w.useEffect(()=>{var Q;const B=i.trim().toLowerCase(),q=new Set;if(B)for(const U of e.entities)(U.name.toLowerCase()+" "+(((Q=U.conceptual)==null?void 0:Q.name.toLowerCase())??"")+" "+U.attributes.map(O=>O.name.toLowerCase()).join(" ")).includes(B)&&q.add(U.id);const W=new Set;if(r){W.add(r);for(const U of e.relationships)U.from.entity===r&&W.add(U.to.entity),U.to.entity===r&&W.add(U.from.entity)}p(U=>U.map(X=>{const O=B!==""&&!q.has(X.id),se=r!==null&&!W.has(X.id),ce=K.active&&!K.entsForAttr.has(X.id),me=O||se||ce,we=B!==""&&q.has(X.id)||K.active&&K.entsForAttr.has(X.id),be=K.hitAttrsByEntity.get(X.id);return X.data.dimmed===me&&X.data.highlighted===we&&X.data.highlightAttrs===be?X:{...X,data:{...X.data,dimmed:me,highlighted:we,highlightAttrs:be}}})),$(U=>U.map(X=>{var we,be;const O=(we=X.data)==null?void 0:we.relationship,se=r!==null&&O!==void 0&&O.from.entity!==r&&O.to.entity!==r,ce=K.active&&!K.relsForAttr.has(X.id),me=se||ce;return((be=X.data)==null?void 0:be.dimmed)===me?X:{...X,data:{...X.data,dimmed:me}}}))},[K,i,r,e]),w.useEffect(()=>{var Q;const B=i.trim().toLowerCase();if(!B)return;const q=new Set;for(const U of e.entities)(U.name.toLowerCase()+" "+(((Q=U.conceptual)==null?void 0:Q.name.toLowerCase())??"")+" "+U.attributes.map(O=>O.name.toLowerCase()).join(" ")).includes(B)&&q.add(U.id);if(!q.size)return;const W=requestAnimationFrame(()=>{const U=y().filter(O=>q.has(O.id));if(!U.length)return;const X=kf(U);x(X,{padding:.35,duration:400})});return()=>cancelAnimationFrame(W)},[i,e,y,x]);const J=w.useCallback((B="auto",q="LR")=>{p(W=>ri(W,E,L,B,z,q)),requestAnimationFrame(()=>f({padding:.15,duration:300}))},[E,L,z,f]),ee=w.useCallback(B=>{s(B),p(q=>(q.find(Q=>Q.id===B)&&requestAnimationFrame(()=>f({nodes:[{id:B}],padding:.4,duration:400})),q))},[f,s]);w.useImperativeHandle(m,()=>({relayout:J,fitView:()=>f({padding:.15,duration:300}),focusEntity:ee,newEntity:()=>D(!0)}),[J,f,ee]);const ie=w.useCallback(B=>{if(k||!B.source||!B.target||B.source===B.target)return;const q=B.sourceHandle&&B.sourceHandle!==Dr?B.sourceHandle:void 0,W=B.targetHandle&&B.targetHandle!==Lr?B.targetHandle:void 0;V({from:B.source,to:B.target,fromAttr:q,toAttr:W})},[k]),te=w.useCallback(async(B,q)=>{try{return await n(B,q)}catch(W){throw d==null||d(W instanceof Error?W.message:String(W)),W}},[n,d]),re=r?L.get(r)??null:null,fe=e.relationships.find(B=>B.id===F)??null;return h.jsxs(h.Fragment,{children:[h.jsxs(Do,{nodes:v,edges:E,nodeTypes:ax,edgeTypes:lx,onNodeClick:(B,q)=>s(q.id),onEdgeClick:(B,q)=>!k&&g(q.id),onPaneClick:()=>{s(null),g(null)},onNodeDragStop:(B,q)=>p(W=>W.map(Q=>Q.id===q.id?{...Q,position:q.position}:Q)),onConnect:ie,nodesConnectable:!k,minZoom:.05,onlyRenderVisibleElements:!0,proOptions:{hideAttribution:!0},fitView:!0,children:[h.jsx(xm,{variant:ke.Dots,gap:22,size:1.5,color:"#33291f"}),h.jsx(im,{pannable:!0,zoomable:!0,nodeColor:B=>{var q;return((q=B.data)==null?void 0:q.color)??"#5a4f42"},maskColor:"rgba(20, 17, 15, 0.75)"}),h.jsx(fm,{showInteractive:!1})]}),re&&h.jsx(Dm,{entity:re,doc:e,caps:t,exec:te,onClose:()=>s(null),onFocusEntity:ee,onAlign:j,onEditMapping:I}),A&&h.jsx(tx,{entity:A,exec:te,onClose:()=>j(null)}),_&&h.jsx(nx,{entity:_,doc:e,exec:te,onClose:()=>I(null)}),S&&h.jsx(rx,{doc:e,exec:te,onClose:()=>D(!1),onCreated:ee}),P&&h.jsx(sx,{doc:e,fromId:P.from,toId:P.to,initialFromAttr:P.fromAttr,initialToAttr:P.toAttr,exec:te,onClose:()=>V(null)}),fe&&h.jsx(ix,{rel:fe,doc:e,exec:te,onClose:()=>g(null)})]})}function zx({tab:e,onClose:t,readOnly:n,refreshKey:r,onModelChanged:s,onFocusEntity:i}){return h.jsxs("aside",{className:"side-panel",children:[h.jsxs("div",{className:"detail-header",children:[h.jsxs("h2",{children:[e==="ontology"&&"Ontology",e==="layers"&&"Ontology layers",e==="changes"&&"Uncommitted changes",e==="decisions"&&"Decision ledger"]}),h.jsx("button",{className:"icon-btn",onClick:t,children:"✕"})]}),e==="ontology"&&h.jsx(ux,{}),e==="layers"&&h.jsx(fx,{refreshKey:r,onFocusEntity:i}),e==="changes"&&h.jsx(hx,{readOnly:n,refreshKey:r,onModelChanged:s}),e==="decisions"&&h.jsx(mx,{readOnly:n})]})}function ux(){const[e,t]=w.useState(""),[n,r]=w.useState([]),[s,i]=w.useState({loaded:0,vocabs:[]}),[o,a]=w.useState(null),[l,c]=w.useState([]),[u,d]=w.useState("");w.useEffect(()=>{Go().then(f=>c(f.ontologies)).catch(()=>{})},[]),w.useEffect(()=>{const f=setTimeout(()=>{Bo(e||"a",u||void 0).then(x=>{r(e?x.results:[]),i({loaded:x.loaded_terms,vocabs:x.vocabularies})}).catch(()=>{})},200);return()=>clearTimeout(f)},[e,u]);const m=w.useCallback(f=>{wm(f).then(a).catch(()=>{})},[]);return o?h.jsxs("div",{className:"panel-body",children:[h.jsx("button",{className:"mini-btn",onClick:()=>a(null),children:"← back"}),h.jsx("h3",{style:{marginTop:12},children:o.label}),h.jsx("code",{className:"term-iri",children:o.prefixed}),o.definition&&h.jsx("p",{className:"term-def",children:o.definition}),h.jsxs("div",{className:"kv",children:[h.jsx("span",{className:"k",children:"source"}),h.jsx("span",{className:"v",children:o.source})]}),o.broader.length>0&&h.jsxs(h.Fragment,{children:[h.jsx("h4",{children:"broader"}),o.broader.map(f=>h.jsxs("button",{className:"rel-link",onClick:()=>m(f.iri),children:["↑ ",f.label]},f.iri))]}),o.narrower.length>0&&h.jsxs(h.Fragment,{children:[h.jsx("h4",{children:"narrower"}),o.narrower.map(f=>h.jsxs("button",{className:"rel-link",onClick:()=>m(f.iri),children:["↓ ",f.label]},f.iri))]})]}):h.jsxs("div",{className:"panel-body",children:[l.length>0&&h.jsxs("div",{className:"src-picker",children:[h.jsx("button",{className:"src-chip"+(u===""?" active":""),onClick:()=>d(""),children:"all sources"}),l.map(f=>h.jsxs("button",{className:"src-chip"+(u===f.id?" active":""),title:(f.description??"")+(f.count!=null?` · ${f.count} terms`:" · live"),onClick:()=>d(f.id),children:[f.name,f.layer&&h.jsx("span",{className:`src-layer layer-${f.layer}`,children:f.layer})]},f.id))]}),h.jsx("input",{className:"edit-input",placeholder:u?`Search within ${u}…`:"Search vocabulary terms…",value:e,onChange:f=>t(f.target.value)}),h.jsx("p",{className:"meta-line",children:l.length>0?`${l.length} source${l.length>1?"s":""}: ${s.vocabs.join(", ")}`+(s.loaded>0?` · ${s.loaded} local terms indexed`:""):"no vocabulary loaded — declare ontology_stack in mdl-project.yaml or run `mdl ontology vendor fibo`"}),h.jsx("div",{className:"term-results",children:n.map(f=>h.jsxs("button",{className:"term-card",onClick:()=>m(f.prefixed),children:[h.jsxs("div",{className:"term-head",children:[h.jsx("span",{className:"term-label",children:f.label}),h.jsxs("span",{className:"term-source",children:[f.source_kind==="glossary-term"&&h.jsx("span",{className:"kind-badge",title:"glossary term",children:"glossary"}),f.source]})]}),h.jsx("code",{className:"term-iri",children:f.prefixed}),f.definition&&h.jsx("p",{className:"term-def",children:f.definition})]},f.iri))})]})}const dx=["industry","core","domain","specialised"];function fx({refreshKey:e,onFocusEntity:t}){const[n,r]=w.useState(null),[s,i]=w.useState(null);if(w.useEffect(()=>{bm().then(r).catch(()=>{}),vm().then(i).catch(()=>{})},[e]),!n)return h.jsx("div",{className:"panel-body",children:"loading…"});const o=new Set((s==null?void 0:s.core_uncovered)??[]);return h.jsxs("div",{className:"panel-body",children:[s&&h.jsxs("div",{className:"coverage-banner"+(s.coverage_pct<100?" warn":""),children:["industry alignment coverage: ",h.jsxs("b",{children:[s.coverage_pct,"%"]})," (",s.core_with_industry,"+",s.core_exempt,"/",s.total_core," core terms)"]}),h.jsxs("div",{className:"layer-band external",children:[h.jsx("h4",{children:"industry (external vocabularies)"}),n.external_terms.length===0&&h.jsx("p",{className:"empty-hint",children:"no aligned terms yet"}),n.external_terms.map(a=>h.jsxs("div",{className:"stack-term external",title:a.definition??void 0,children:[a.label,h.jsx("span",{className:"term-source",children:a.source})]},a.iri))]}),dx.slice(1).map(a=>h.jsxs("div",{className:"layer-band",children:[h.jsx("h4",{children:a}),(n.layers[a]??[]).length===0&&h.jsx("p",{className:"empty-hint",children:"—"}),(n.layers[a]??[]).map(l=>{var c;return h.jsxs("button",{className:"stack-term"+(o.has(l.name)?" uncovered":""),title:l.definition??void 0,onClick:()=>t(l.id),children:[l.name,(l.aligned_refs??(l.aligned_to?[l.aligned_to]:[])).map((u,d)=>h.jsxs("span",{className:"align-arrow"+(u.resolved?"":" unresolved")+(u.status==="proposed"?" proposed":""),title:u.ref+(u.resolved_via?` (via ${u.resolved_via})`:""),children:["↑ ",u.label,u.status==="proposed"?" ·prop":""]},`${u.ref}-${d}`)),!l.aligned_to&&(((c=l.aligned_refs)==null?void 0:c.length)??0)===0&&!l.no_industry_equivalent&&h.jsx("span",{className:"align-arrow missing",children:"unaligned"})]},l.id)})]},a))]})}function hx({readOnly:e,refreshKey:t,onModelChanged:n}){const[r,s]=w.useState(null),[i,o]=w.useState(""),[a,l]=w.useState(""),[c,u]=w.useState(!1),d=w.useCallback(()=>{Em().then(s).catch(()=>s(null)),Nm().then(m=>o([m.diff,...m.untracked].filter(Boolean).join(` + +`))).catch(()=>o(""))},[]);return w.useEffect(d,[d,t]),r!=null&&r.git?r.clean?h.jsx("div",{className:"panel-body ok",children:"✓ working tree clean"}):h.jsxs("div",{className:"panel-body",children:[h.jsx("ul",{className:"dirty-list",children:r.dirty.map(m=>h.jsxs("li",{children:[h.jsx("code",{className:"dirty-state",children:m.state})," ",m.path]},m.path))}),h.jsx("pre",{className:"diff-view",children:i.split(` +`).map((m,f)=>h.jsx("span",{className:m.startsWith("+")&&!m.startsWith("+++")?"diff-add":m.startsWith("-")&&!m.startsWith("---")?"diff-del":m.startsWith("@@")?"diff-hunk":"",children:m+` +`},f))}),!e&&h.jsxs(h.Fragment,{children:[h.jsx("input",{className:"edit-input",placeholder:"commit message…",value:a,onChange:m=>l(m.target.value)}),h.jsxs("div",{className:"modal-footer",children:[h.jsx("button",{className:"mini-btn danger",disabled:c,onClick:()=>{confirm("Discard ALL uncommitted model changes?")&&(u(!0),km().then(()=>{u(!1),d(),n()}))},children:"Discard all"}),h.jsx("button",{className:"primary-btn",disabled:c||!a.trim(),onClick:()=>{u(!0),Sm(a).then(()=>{u(!1),l(""),d()})},children:"Commit"})]})]})]}):h.jsx("div",{className:"panel-body",children:"model directory is not in a git repo"})}function mx({readOnly:e}){const[t,n]=w.useState([]),r=w.useCallback(()=>{jm().then(i=>n(i.decisions)).catch(()=>n([]))},[]);if(w.useEffect(r,[r]),t.length===0)return h.jsx("div",{className:"panel-body",children:"no recorded decisions (run `mdl reverse` to propose)"});const s={accepted:"✓",rejected:"✗",proposed:"?"};return h.jsx("div",{className:"panel-body",children:t.map(i=>h.jsxs("div",{className:"decision "+i.verdict,children:[h.jsxs("div",{className:"decision-head",children:[h.jsx("span",{className:"decision-mark",children:s[i.verdict]}),h.jsx("span",{className:"chip",children:i.confidence}),h.jsx("span",{className:"chip",children:i.signal})]}),h.jsx("p",{className:"decision-subject",children:i.subject}),!e&&i.verdict==="proposed"&&h.jsxs("div",{className:"decision-actions",children:[h.jsx("button",{className:"mini-btn",onClick:()=>Os(i.signal_key,"accepted").then(r),children:"Accept"}),h.jsx("button",{className:"mini-btn danger",onClick:()=>Os(i.signal_key,"rejected").then(r),children:"Reject"})]})]},i.signal_key))})}function Hx({exec:e,canEdit:t,onImported:n,submitLabel:r="Import & review",buttonClass:s="erd-action ghost",applyBatch:i,openImport:o=!1,prefillImport:a="",onPreview:l}){const[c,u]=w.useState(o&&t?"import":null),[d,m]=w.useState([]),[f,x]=w.useState("postgres"),y=w.useRef(null);w.useEffect(()=>{Cm().then(p=>m(p.formats)).catch(()=>m([]))},[]),w.useEffect(()=>{if(!c)return;const p=E=>{y.current&&!y.current.contains(E.target)&&u(null)};return document.addEventListener("mousedown",p),()=>document.removeEventListener("mousedown",p)},[c]);const v=d.find(p=>p.id==="sql");return h.jsxs("div",{className:"ie-wrap",ref:y,children:[h.jsxs("button",{className:s+(c==="export"?" on":""),onClick:()=>u(c==="export"?null:"export"),children:[h.jsx("span",{className:"erd-ico","aria-hidden":"true",children:"↧"}),"Export ",h.jsx("span",{className:"erd-caret",children:"▾"})]}),t&&h.jsxs("button",{className:s+(c==="import"?" on":""),onClick:()=>u(c==="import"?null:"import"),children:[h.jsx("span",{className:"erd-ico","aria-hidden":"true",children:"↥"}),"Import ",h.jsx("span",{className:"erd-caret",children:"▾"})]}),c==="export"&&h.jsxs("div",{className:"ie-menu",role:"menu",children:[(v==null?void 0:v.dialects)&&h.jsxs("label",{className:"ie-dialect",children:[h.jsx("span",{children:"SQL dialect"}),h.jsx("select",{value:f,onChange:p=>x(p.target.value),children:v.dialects.map(p=>h.jsx("option",{value:p,children:p},p))})]}),d.map(p=>h.jsx("a",{className:"ie-item",href:$m(p.id,p.id==="sql"?f:void 0),download:!0,onClick:()=>u(null),children:p.label},p.id))]}),c==="import"&&h.jsx(px,{exec:e,submitLabel:r,buttonClass:s,applyBatch:i,onClose:()=>u(null),onImported:p=>{u(null),n==null||n(p)},onPreview:l,prefillImport:a})]})}const di=[{id:"sql",label:"SQL DDL",hint:"CREATE TABLE … PRIMARY KEY / FOREIGN KEY"},{id:"mermaid",label:"Mermaid erDiagram",hint:"structural: entities, attributes, relationships"},{id:"json-schema",label:"JSON Schema",hint:"each object definition becomes an entity"},{id:"erwin",label:"erwin XML",hint:"entities, keys, relationships, subject areas, subtypes"}];function px({exec:e,submitLabel:t,buttonClass:n,applyBatch:r,onClose:s,onImported:i,onPreview:o,prefillImport:a}){var j;const[l,c]=w.useState(o?"erwin":"sql"),[u,d]=w.useState("postgres"),[m,f]=w.useState(a??""),[x,y]=w.useState(!1),[v,p]=w.useState(null),[E,$]=w.useState([]);w.useEffect(()=>{a&&f(a)},[a]);const b=_=>{_&&_.text().then(f).catch(()=>p("could not read that file"))},A=async()=>{y(!0),p(null),$([]);try{if(o&&l==="erwin"){const I=await Am(l,m);if(!I.changes.length){p(I.warnings[0]??"nothing to import from that document"),y(!1);return}s(),o(I),y(!1);return}const _=await Mm(l,m,l==="sql"?u:void 0);if(!_.changes.length){p(_.warnings[0]??"nothing to import from that document"),y(!1);return}if(r)await r(_.changes);else for(const I of _.changes)await e(I.op,I.payload);$(_.warnings),i(_.tables)}catch(_){p(_ instanceof Error?_.message:String(_))}finally{y(!1)}};return h.jsxs("div",{className:"ie-menu ie-import",role:"dialog",children:[h.jsx("div",{className:"ie-tabs",children:di.map(_=>h.jsx("button",{className:"ie-tab"+(l===_.id?" active":""),onClick:()=>c(_.id),children:_.label},_.id))}),h.jsx("p",{className:"ie-hint",children:(j=di.find(_=>_.id===l))==null?void 0:j.hint}),l==="sql"&&h.jsxs("label",{className:"ie-dialect",children:[h.jsx("span",{children:"dialect"}),h.jsx("select",{value:u,onChange:_=>d(_.target.value),children:["postgres","snowflake","mysql","duckdb"].map(_=>h.jsx("option",{children:_},_))})]}),h.jsx("textarea",{className:"ie-textarea",placeholder:`Paste ${l} here, or choose a file…`,value:m,onChange:_=>f(_.target.value),rows:8}),h.jsx("input",{type:"file",className:"ie-file",accept:".sql,.mmd,.md,.json,.xml,.txt",onChange:_=>{var I;return b(((I=_.target.files)==null?void 0:I[0])??null)}}),l==="mermaid"&&h.jsx("p",{className:"ie-warn",children:"Mermaid is a diagram format: types and keys are approximate and relationships are inferred from the lines."}),E.map((_,I)=>h.jsx("p",{className:"ie-warn",children:_},I)),v&&h.jsx("p",{className:"ie-error",children:v}),h.jsxs("div",{className:"ie-foot",children:[h.jsx("button",{className:n,onClick:s,children:"Cancel"}),h.jsx("button",{className:n,disabled:x||!m.trim(),onClick:A,children:x?"Importing…":t})]})]})}export{Vo as A,xm as B,fm as C,Tm as E,Hx as I,fx as L,Px as M,ux as O,ci as P,To as R,zx as S,wx as a,Mx as b,jx as c,Ix as d,Rx as e,xx as f,Em as g,Tx as h,Cx as i,_x as j,Ex as k,Nx as l,kx as m,$x as n,Bo as o,Ax as p,Sx as q,bx as r,_m as s,vx as t,ri as u,Do as v,ox as w,im as x}; diff --git a/packages/server/src/mdl_server/static/assets/styles-BtrhR1xb.js b/packages/server/src/mdl_server/static/assets/styles-BtrhR1xb.js deleted file mode 100644 index f158962..0000000 --- a/packages/server/src/mdl_server/static/assets/styles-BtrhR1xb.js +++ /dev/null @@ -1,23 +0,0 @@ -var tl=Object.defineProperty;var nl=(e,t,n)=>t in e?tl(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var ue=(e,t,n)=>nl(e,typeof t!="symbol"?t+"":t,n);import{r as w,g as fi,R as A,j as h}from"./client-DOmNpTln.js";function ye(e){if(typeof e=="string"||typeof e=="number")return""+e;let t="";if(Array.isArray(e))for(let n=0,r;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?ul:cl;gi.useSyncExternalStore=Et.useSyncExternalStore!==void 0?Et.useSyncExternalStore:dl;pi.exports=gi;var fl=pi.exports;/** - * @license React - * use-sync-external-store-shim/with-selector.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var kn=w,hl=fl;function ml(e,t){return e===t&&(e!==0||1/e===1/t)||e!==e&&t!==t}var pl=typeof Object.is=="function"?Object.is:ml,gl=hl.useSyncExternalStore,yl=kn.useRef,xl=kn.useEffect,wl=kn.useMemo,bl=kn.useDebugValue;mi.useSyncExternalStoreWithSelector=function(e,t,n,r,s){var i=yl(null);if(i.current===null){var o={hasValue:!1,value:null};i.current=o}else o=i.current;i=wl(function(){function l(f){if(!c){if(c=!0,u=f,f=r(f),s!==void 0&&o.hasValue){var y=o.value;if(s(y,f))return d=y}return d=f}if(y=d,pl(u,f))return y;var p=r(f);return s!==void 0&&s(y,p)?(u=f,y):(u=f,d=p)}var c=!1,u,d,m=n===void 0?null:n;return[function(){return l(t())},m===null?void 0:function(){return l(m())}]},[t,n,r,s]);var a=gl(e,i[0],i[1]);return xl(function(){o.hasValue=!0,o.value=a},[a]),bl(a),a};hi.exports=mi;var vl=hi.exports;const _l=fi(vl),El={},Wr=e=>{let t;const n=new Set,r=(u,d)=>{const m=typeof u=="function"?u(t):u;if(!Object.is(m,t)){const f=t;t=d??(typeof m!="object"||m===null)?m:Object.assign({},t,m),n.forEach(y=>y(t,f))}},s=()=>t,l={setState:r,getState:s,getInitialState:()=>c,subscribe:u=>(n.add(u),()=>n.delete(u)),destroy:()=>{(El?"production":void 0)!=="production"&&console.warn("[DEPRECATED] The `destroy` method will be unsupported in a future version. Instead use unsubscribe function returned by subscribe. Everything will be garbage-collected if store is garbage-collected."),n.clear()}},c=t=e(r,s,l);return l},Nl=e=>e?Wr(e):Wr,{useDebugValue:Sl}=A,{useSyncExternalStoreWithSelector:kl}=_l,jl=e=>e;function yi(e,t=jl,n){const r=kl(e.subscribe,e.getState,e.getServerState||e.getInitialState,t,n);return Sl(r),r}const Ur=(e,t)=>{const n=Nl(e),r=(s,i=t)=>yi(n,s,i);return Object.assign(r,n),r},Cl=(e,t)=>e?Ur(e,t):Ur;function ge(e,t){if(Object.is(e,t))return!0;if(typeof e!="object"||e===null||typeof t!="object"||t===null)return!1;if(e instanceof Map&&t instanceof Map){if(e.size!==t.size)return!1;for(const[r,s]of e)if(!Object.is(s,t.get(r)))return!1;return!0}if(e instanceof Set&&t instanceof Set){if(e.size!==t.size)return!1;for(const r of e)if(!t.has(r))return!1;return!0}const n=Object.keys(e);if(n.length!==Object.keys(t).length)return!1;for(const r of n)if(!Object.prototype.hasOwnProperty.call(t,r)||!Object.is(e[r],t[r]))return!1;return!0}var $l={value:()=>{}};function jn(){for(var e=0,t=arguments.length,n={},r;e=0&&(r=n.slice(s+1),n=n.slice(0,s)),n&&!t.hasOwnProperty(n))throw new Error("unknown type: "+n);return{type:n,name:r}})}cn.prototype=jn.prototype={constructor:cn,on:function(e,t){var n=this._,r=Ml(e+"",n),s,i=-1,o=r.length;if(arguments.length<2){for(;++i0)for(var n=new Array(s),r=0,s,i;r=0&&(t=e.slice(0,n))!=="xmlns"&&(e=e.slice(n+1)),qr.hasOwnProperty(t)?{space:qr[t],local:e}:e}function Il(e){return function(){var t=this.ownerDocument,n=this.namespaceURI;return n===nr&&t.documentElement.namespaceURI===nr?t.createElement(e):t.createElementNS(n,e)}}function Rl(e){return function(){return this.ownerDocument.createElementNS(e.space,e.local)}}function xi(e){var t=Cn(e);return(t.local?Rl:Il)(t)}function Tl(){}function wr(e){return e==null?Tl:function(){return this.querySelector(e)}}function Ol(e){typeof e!="function"&&(e=wr(e));for(var t=this._groups,n=t.length,r=new Array(n),s=0;s=M&&(M=_+1);!(j=v[M])&&++M=0;)(o=r[s])&&(i&&o.compareDocumentPosition(i)^4&&i.parentNode.insertBefore(o,i),i=o);return this}function oc(e){e||(e=ac);function t(d,m){return d&&m?e(d.__data__,m.__data__):!d-!m}for(var n=this._groups,r=n.length,s=new Array(r),i=0;it?1:e>=t?0:NaN}function lc(){var e=arguments[0];return arguments[0]=this,e.apply(null,arguments),this}function cc(){return Array.from(this)}function uc(){for(var e=this._groups,t=0,n=e.length;t1?this.each((t==null?vc:typeof t=="function"?Ec:_c)(e,t,n??"")):Nt(this.node(),e)}function Nt(e,t){return e.style.getPropertyValue(t)||Ei(e).getComputedStyle(e,null).getPropertyValue(t)}function Sc(e){return function(){delete this[e]}}function kc(e,t){return function(){this[e]=t}}function jc(e,t){return function(){var n=t.apply(this,arguments);n==null?delete this[e]:this[e]=n}}function Cc(e,t){return arguments.length>1?this.each((t==null?Sc:typeof t=="function"?jc:kc)(e,t)):this.node()[e]}function Ni(e){return e.trim().split(/^|\s+/)}function br(e){return e.classList||new Si(e)}function Si(e){this._node=e,this._names=Ni(e.getAttribute("class")||"")}Si.prototype={add:function(e){var t=this._names.indexOf(e);t<0&&(this._names.push(e),this._node.setAttribute("class",this._names.join(" ")))},remove:function(e){var t=this._names.indexOf(e);t>=0&&(this._names.splice(t,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(e){return this._names.indexOf(e)>=0}};function ki(e,t){for(var n=br(e),r=-1,s=t.length;++r=0&&(n=t.slice(r+1),t=t.slice(0,r)),{type:t,name:n}})}function nu(e){return function(){var t=this.__on;if(t){for(var n=0,r=-1,s=t.length,i;n()=>e;function rr(e,{sourceEvent:t,subject:n,target:r,identifier:s,active:i,x:o,y:a,dx:l,dy:c,dispatch:u}){Object.defineProperties(this,{type:{value:e,enumerable:!0,configurable:!0},sourceEvent:{value:t,enumerable:!0,configurable:!0},subject:{value:n,enumerable:!0,configurable:!0},target:{value:r,enumerable:!0,configurable:!0},identifier:{value:s,enumerable:!0,configurable:!0},active:{value:i,enumerable:!0,configurable:!0},x:{value:o,enumerable:!0,configurable:!0},y:{value:a,enumerable:!0,configurable:!0},dx:{value:l,enumerable:!0,configurable:!0},dy:{value:c,enumerable:!0,configurable:!0},_:{value:u}})}rr.prototype.on=function(){var e=this._.on.apply(this._,arguments);return e===this._?this:e};function fu(e){return!e.ctrlKey&&!e.button}function hu(){return this.parentNode}function mu(e,t){return t??{x:e.x,y:e.y}}function pu(){return navigator.maxTouchPoints||"ontouchstart"in this}function gu(){var e=fu,t=hu,n=mu,r=pu,s={},i=jn("start","drag","end"),o=0,a,l,c,u,d=0;function m(b){b.on("mousedown.drag",f).filter(r).on("touchstart.drag",v).on("touchmove.drag",x,du).on("touchend.drag touchcancel.drag",_).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function f(b,j){if(!(u||!e.call(this,b,j))){var C=M(this,t.call(this,b,j),b,j,"mouse");C&&(Ne(b.view).on("mousemove.drag",y,zt).on("mouseup.drag",p,zt),Mi(b.view),Hn(b),c=!1,a=b.clientX,l=b.clientY,C("start",b))}}function y(b){if(wt(b),!c){var j=b.clientX-a,C=b.clientY-l;c=j*j+C*C>d}s.mouse("drag",b)}function p(b){Ne(b.view).on("mousemove.drag mouseup.drag",null),Ai(b.view,c),wt(b),s.mouse("end",b)}function v(b,j){if(e.call(this,b,j)){var C=b.changedTouches,E=t.call(this,b,j),L=C.length,S,O;for(S=0;S>8&15|t>>4&240,t>>4&15|t&240,(t&15)<<4|t&15,1):n===8?Jt(t>>24&255,t>>16&255,t>>8&255,(t&255)/255):n===4?Jt(t>>12&15|t>>8&240,t>>8&15|t>>4&240,t>>4&15|t&240,((t&15)<<4|t&15)/255):null):(t=xu.exec(e))?new ve(t[1],t[2],t[3],1):(t=wu.exec(e))?new ve(t[1]*255/100,t[2]*255/100,t[3]*255/100,1):(t=bu.exec(e))?Jt(t[1],t[2],t[3],t[4]):(t=vu.exec(e))?Jt(t[1]*255/100,t[2]*255/100,t[3]*255/100,t[4]):(t=_u.exec(e))?ns(t[1],t[2]/100,t[3]/100,1):(t=Eu.exec(e))?ns(t[1],t[2]/100,t[3]/100,t[4]):Kr.hasOwnProperty(e)?Jr(Kr[e]):e==="transparent"?new ve(NaN,NaN,NaN,0):null}function Jr(e){return new ve(e>>16&255,e>>8&255,e&255,1)}function Jt(e,t,n,r){return r<=0&&(e=t=n=NaN),new ve(e,t,n,r)}function ku(e){return e instanceof Xt||(e=Vt(e)),e?(e=e.rgb(),new ve(e.r,e.g,e.b,e.opacity)):new ve}function sr(e,t,n,r){return arguments.length===1?ku(e):new ve(e,t,n,r??1)}function ve(e,t,n,r){this.r=+e,this.g=+t,this.b=+n,this.opacity=+r}vr(ve,sr,Ii(Xt,{brighter(e){return e=e==null?mn:Math.pow(mn,e),new ve(this.r*e,this.g*e,this.b*e,this.opacity)},darker(e){return e=e==null?Ht:Math.pow(Ht,e),new ve(this.r*e,this.g*e,this.b*e,this.opacity)},rgb(){return this},clamp(){return new ve(at(this.r),at(this.g),at(this.b),pn(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:es,formatHex:es,formatHex8:ju,formatRgb:ts,toString:ts}));function es(){return`#${it(this.r)}${it(this.g)}${it(this.b)}`}function ju(){return`#${it(this.r)}${it(this.g)}${it(this.b)}${it((isNaN(this.opacity)?1:this.opacity)*255)}`}function ts(){const e=pn(this.opacity);return`${e===1?"rgb(":"rgba("}${at(this.r)}, ${at(this.g)}, ${at(this.b)}${e===1?")":`, ${e})`}`}function pn(e){return isNaN(e)?1:Math.max(0,Math.min(1,e))}function at(e){return Math.max(0,Math.min(255,Math.round(e)||0))}function it(e){return e=at(e),(e<16?"0":"")+e.toString(16)}function ns(e,t,n,r){return r<=0?e=t=n=NaN:n<=0||n>=1?e=t=NaN:t<=0&&(e=NaN),new Me(e,t,n,r)}function Ri(e){if(e instanceof Me)return new Me(e.h,e.s,e.l,e.opacity);if(e instanceof Xt||(e=Vt(e)),!e)return new Me;if(e instanceof Me)return e;e=e.rgb();var t=e.r/255,n=e.g/255,r=e.b/255,s=Math.min(t,n,r),i=Math.max(t,n,r),o=NaN,a=i-s,l=(i+s)/2;return a?(t===i?o=(n-r)/a+(n0&&l<1?0:o,new Me(o,a,l,e.opacity)}function Cu(e,t,n,r){return arguments.length===1?Ri(e):new Me(e,t,n,r??1)}function Me(e,t,n,r){this.h=+e,this.s=+t,this.l=+n,this.opacity=+r}vr(Me,Cu,Ii(Xt,{brighter(e){return e=e==null?mn:Math.pow(mn,e),new Me(this.h,this.s,this.l*e,this.opacity)},darker(e){return e=e==null?Ht:Math.pow(Ht,e),new Me(this.h,this.s,this.l*e,this.opacity)},rgb(){var e=this.h%360+(this.h<0)*360,t=isNaN(e)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*t,s=2*n-r;return new ve(Fn(e>=240?e-240:e+120,s,r),Fn(e,s,r),Fn(e<120?e+240:e-120,s,r),this.opacity)},clamp(){return new Me(rs(this.h),en(this.s),en(this.l),pn(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const e=pn(this.opacity);return`${e===1?"hsl(":"hsla("}${rs(this.h)}, ${en(this.s)*100}%, ${en(this.l)*100}%${e===1?")":`, ${e})`}`}}));function rs(e){return e=(e||0)%360,e<0?e+360:e}function en(e){return Math.max(0,Math.min(1,e||0))}function Fn(e,t,n){return(e<60?t+(n-t)*e/60:e<180?n:e<240?t+(n-t)*(240-e)/60:t)*255}const Ti=e=>()=>e;function $u(e,t){return function(n){return e+n*t}}function Mu(e,t,n){return e=Math.pow(e,n),t=Math.pow(t,n)-e,n=1/n,function(r){return Math.pow(e+r*t,n)}}function Au(e){return(e=+e)==1?Oi:function(t,n){return n-t?Mu(t,n,e):Ti(isNaN(t)?n:t)}}function Oi(e,t){var n=t-e;return n?$u(e,n):Ti(isNaN(e)?t:e)}const ss=function e(t){var n=Au(t);function r(s,i){var o=n((s=sr(s)).r,(i=sr(i)).r),a=n(s.g,i.g),l=n(s.b,i.b),c=Oi(s.opacity,i.opacity);return function(u){return s.r=o(u),s.g=a(u),s.b=l(u),s.opacity=c(u),s+""}}return r.gamma=e,r}(1);function We(e,t){return e=+e,t=+t,function(n){return e*(1-n)+t*n}}var ir=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,Vn=new RegExp(ir.source,"g");function Iu(e){return function(){return e}}function Ru(e){return function(t){return e(t)+""}}function Tu(e,t){var n=ir.lastIndex=Vn.lastIndex=0,r,s,i,o=-1,a=[],l=[];for(e=e+"",t=t+"";(r=ir.exec(e))&&(s=Vn.exec(t));)(i=s.index)>n&&(i=t.slice(n,i),a[o]?a[o]+=i:a[++o]=i),(r=r[0])===(s=s[0])?a[o]?a[o]+=s:a[++o]=s:(a[++o]=null,l.push({i:o,x:We(r,s)})),n=Vn.lastIndex;return n180?u+=360:u-c>180&&(c+=360),m.push({i:d.push(s(d)+"rotate(",null,r)-2,x:We(c,u)})):u&&d.push(s(d)+"rotate("+u+r)}function a(c,u,d,m){c!==u?m.push({i:d.push(s(d)+"skewX(",null,r)-2,x:We(c,u)}):u&&d.push(s(d)+"skewX("+u+r)}function l(c,u,d,m,f,y){if(c!==d||u!==m){var p=f.push(s(f)+"scale(",null,",",null,")");y.push({i:p-4,x:We(c,d)},{i:p-2,x:We(u,m)})}else(d!==1||m!==1)&&f.push(s(f)+"scale("+d+","+m+")")}return function(c,u){var d=[],m=[];return c=e(c),u=e(u),i(c.translateX,c.translateY,u.translateX,u.translateY,d,m),o(c.rotate,u.rotate,d,m),a(c.skewX,u.skewX,d,m),l(c.scaleX,c.scaleY,u.scaleX,u.scaleY,d,m),c=u=null,function(f){for(var y=-1,p=m.length,v;++y=0&&e._call.call(void 0,t),e=e._next;--St}function as(){ct=(yn=Bt.now())+$n,St=Ot=0;try{Gu()}finally{St=0,Wu(),ct=0}}function Yu(){var e=Bt.now(),t=e-yn;t>Pi&&($n-=t,yn=e)}function Wu(){for(var e,t=gn,n,r=1/0;t;)t._call?(r>t._time&&(r=t._time),e=t,t=t._next):(n=t._next,t._next=null,t=e?e._next=n:gn=n);Dt=e,ar(r)}function ar(e){if(!St){Ot&&(Ot=clearTimeout(Ot));var t=e-ct;t>24?(e<1/0&&(Ot=setTimeout(as,e-Bt.now()-$n)),Mt&&(Mt=clearInterval(Mt))):(Mt||(yn=Bt.now(),Mt=setInterval(Yu,Pi)),St=1,zi(as))}}function ls(e,t,n){var r=new xn;return t=t==null?0:+t,r.restart(s=>{r.stop(),e(s+t)},t,n),r}var Uu=jn("start","end","cancel","interrupt"),Xu=[],Fi=0,cs=1,lr=2,un=3,us=4,cr=5,dn=6;function Mn(e,t,n,r,s,i){var o=e.__transition;if(!o)e.__transition={};else if(n in o)return;qu(e,n,{name:t,index:r,group:s,on:Uu,tween:Xu,time:i.time,delay:i.delay,duration:i.duration,ease:i.ease,timer:null,state:Fi})}function Er(e,t){var n=Ae(e,t);if(n.state>Fi)throw new Error("too late; already scheduled");return n}function Oe(e,t){var n=Ae(e,t);if(n.state>un)throw new Error("too late; already running");return n}function Ae(e,t){var n=e.__transition;if(!n||!(n=n[t]))throw new Error("transition not found");return n}function qu(e,t,n){var r=e.__transition,s;r[t]=n,n.timer=Hi(i,0,n.time);function i(c){n.state=cs,n.timer.restart(o,n.delay,n.time),n.delay<=c&&o(c-n.delay)}function o(c){var u,d,m,f;if(n.state!==cs)return l();for(u in r)if(f=r[u],f.name===n.name){if(f.state===un)return ls(o);f.state===us?(f.state=dn,f.timer.stop(),f.on.call("interrupt",e,e.__data__,f.index,f.group),delete r[u]):+ulr&&r.state=0&&(t=t.slice(0,n)),!t||t==="start"})}function Sd(e,t,n){var r,s,i=Nd(t)?Er:Oe;return function(){var o=i(this,e),a=o.on;a!==r&&(s=(r=a).copy()).on(t,n),o.on=s}}function kd(e,t){var n=this._id;return arguments.length<2?Ae(this.node(),n).on.on(e):this.each(Sd(n,e,t))}function jd(e){return function(){var t=this.parentNode;for(var n in this.__transition)if(+n!==e)return;t&&t.removeChild(this)}}function Cd(){return this.on("end.remove",jd(this._id))}function $d(e){var t=this._name,n=this._id;typeof e!="function"&&(e=wr(e));for(var r=this._groups,s=r.length,i=new Array(s),o=0;o()=>e;function ef(e,{sourceEvent:t,target:n,transform:r,dispatch:s}){Object.defineProperties(this,{type:{value:e,enumerable:!0,configurable:!0},sourceEvent:{value:t,enumerable:!0,configurable:!0},target:{value:n,enumerable:!0,configurable:!0},transform:{value:r,enumerable:!0,configurable:!0},_:{value:s}})}function He(e,t,n){this.k=e,this.x=t,this.y=n}He.prototype={constructor:He,scale:function(e){return e===1?this:new He(this.k*e,this.x,this.y)},translate:function(e,t){return e===0&t===0?this:new He(this.k,this.x+this.k*e,this.y+this.k*t)},apply:function(e){return[e[0]*this.k+this.x,e[1]*this.k+this.y]},applyX:function(e){return e*this.k+this.x},applyY:function(e){return e*this.k+this.y},invert:function(e){return[(e[0]-this.x)/this.k,(e[1]-this.y)/this.k]},invertX:function(e){return(e-this.x)/this.k},invertY:function(e){return(e-this.y)/this.k},rescaleX:function(e){return e.copy().domain(e.range().map(this.invertX,this).map(e.invert,e))},rescaleY:function(e){return e.copy().domain(e.range().map(this.invertY,this).map(e.invert,e))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var Fe=new He(1,0,0);He.prototype;function Bn(e){e.stopImmediatePropagation()}function At(e){e.preventDefault(),e.stopImmediatePropagation()}function tf(e){return(!e.ctrlKey||e.type==="wheel")&&!e.button}function nf(){var e=this;return e instanceof SVGElement?(e=e.ownerSVGElement||e,e.hasAttribute("viewBox")?(e=e.viewBox.baseVal,[[e.x,e.y],[e.x+e.width,e.y+e.height]]):[[0,0],[e.width.baseVal.value,e.height.baseVal.value]]):[[0,0],[e.clientWidth,e.clientHeight]]}function ds(){return this.__zoom||Fe}function rf(e){return-e.deltaY*(e.deltaMode===1?.05:e.deltaMode?1:.002)*(e.ctrlKey?10:1)}function sf(){return navigator.maxTouchPoints||"ontouchstart"in this}function of(e,t,n){var r=e.invertX(t[0][0])-n[0][0],s=e.invertX(t[1][0])-n[1][0],i=e.invertY(t[0][1])-n[0][1],o=e.invertY(t[1][1])-n[1][1];return e.translate(s>r?(r+s)/2:Math.min(0,r)||Math.max(0,s),o>i?(i+o)/2:Math.min(0,i)||Math.max(0,o))}function Yi(){var e=tf,t=nf,n=of,r=rf,s=sf,i=[0,1/0],o=[[-1/0,-1/0],[1/0,1/0]],a=250,l=Vu,c=jn("start","zoom","end"),u,d,m,f=500,y=150,p=0,v=10;function x(g){g.property("__zoom",ds).on("wheel.zoom",L,{passive:!1}).on("mousedown.zoom",S).on("dblclick.zoom",O).filter(s).on("touchstart.zoom",P).on("touchmove.zoom",V).on("touchend.zoom touchcancel.zoom",F).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}x.transform=function(g,$,N,I){var H=g.selection?g.selection():g;H.property("__zoom",ds),g!==H?j(g,$,N,I):H.interrupt().each(function(){C(this,arguments).event(I).start().zoom(null,typeof $=="function"?$.apply(this,arguments):$).end()})},x.scaleBy=function(g,$,N,I){x.scaleTo(g,function(){var H=this.__zoom.k,k=typeof $=="function"?$.apply(this,arguments):$;return H*k},N,I)},x.scaleTo=function(g,$,N,I){x.transform(g,function(){var H=t.apply(this,arguments),k=this.__zoom,R=N==null?b(H):typeof N=="function"?N.apply(this,arguments):N,D=k.invert(R),z=typeof $=="function"?$.apply(this,arguments):$;return n(M(_(k,z),R,D),H,o)},N,I)},x.translateBy=function(g,$,N,I){x.transform(g,function(){return n(this.__zoom.translate(typeof $=="function"?$.apply(this,arguments):$,typeof N=="function"?N.apply(this,arguments):N),t.apply(this,arguments),o)},null,I)},x.translateTo=function(g,$,N,I,H){x.transform(g,function(){var k=t.apply(this,arguments),R=this.__zoom,D=I==null?b(k):typeof I=="function"?I.apply(this,arguments):I;return n(Fe.translate(D[0],D[1]).scale(R.k).translate(typeof $=="function"?-$.apply(this,arguments):-$,typeof N=="function"?-N.apply(this,arguments):-N),k,o)},I,H)};function _(g,$){return $=Math.max(i[0],Math.min(i[1],$)),$===g.k?g:new He($,g.x,g.y)}function M(g,$,N){var I=$[0]-N[0]*g.k,H=$[1]-N[1]*g.k;return I===g.x&&H===g.y?g:new He(g.k,I,H)}function b(g){return[(+g[0][0]+ +g[1][0])/2,(+g[0][1]+ +g[1][1])/2]}function j(g,$,N,I){g.on("start.zoom",function(){C(this,arguments).event(I).start()}).on("interrupt.zoom end.zoom",function(){C(this,arguments).event(I).end()}).tween("zoom",function(){var H=this,k=arguments,R=C(H,k).event(I),D=t.apply(H,k),z=N==null?b(D):typeof N=="function"?N.apply(H,k):N,Y=Math.max(D[1][0]-D[0][0],D[1][1]-D[0][1]),G=H.__zoom,K=typeof $=="function"?$.apply(H,k):$,J=l(G.invert(z).concat(Y/G.k),K.invert(z).concat(Y/K.k));return function(ee){if(ee===1)ee=K;else{var ie=J(ee),te=Y/ie[2];ee=new He(te,z[0]-ie[0]*te,z[1]-ie[1]*te)}R.zoom(null,ee)}})}function C(g,$,N){return!N&&g.__zooming||new E(g,$)}function E(g,$){this.that=g,this.args=$,this.active=0,this.sourceEvent=null,this.extent=t.apply(g,$),this.taps=0}E.prototype={event:function(g){return g&&(this.sourceEvent=g),this},start:function(){return++this.active===1&&(this.that.__zooming=this,this.emit("start")),this},zoom:function(g,$){return this.mouse&&g!=="mouse"&&(this.mouse[1]=$.invert(this.mouse[0])),this.touch0&&g!=="touch"&&(this.touch0[1]=$.invert(this.touch0[0])),this.touch1&&g!=="touch"&&(this.touch1[1]=$.invert(this.touch1[0])),this.that.__zoom=$,this.emit("zoom"),this},end:function(){return--this.active===0&&(delete this.that.__zooming,this.emit("end")),this},emit:function(g){var $=Ne(this.that).datum();c.call(g,this.that,new ef(g,{sourceEvent:this.sourceEvent,target:x,transform:this.that.__zoom,dispatch:c}),$)}};function L(g,...$){if(!e.apply(this,arguments))return;var N=C(this,$).event(g),I=this.__zoom,H=Math.max(i[0],Math.min(i[1],I.k*Math.pow(2,r.apply(this,arguments)))),k=$e(g);if(N.wheel)(N.mouse[0][0]!==k[0]||N.mouse[0][1]!==k[1])&&(N.mouse[1]=I.invert(N.mouse[0]=k)),clearTimeout(N.wheel);else{if(I.k===H)return;N.mouse=[k,I.invert(k)],fn(this),N.start()}At(g),N.wheel=setTimeout(R,y),N.zoom("mouse",n(M(_(I,H),N.mouse[0],N.mouse[1]),N.extent,o));function R(){N.wheel=null,N.end()}}function S(g,...$){if(m||!e.apply(this,arguments))return;var N=g.currentTarget,I=C(this,$,!0).event(g),H=Ne(g.view).on("mousemove.zoom",z,!0).on("mouseup.zoom",Y,!0),k=$e(g,N),R=g.clientX,D=g.clientY;Mi(g.view),Bn(g),I.mouse=[k,this.__zoom.invert(k)],fn(this),I.start();function z(G){if(At(G),!I.moved){var K=G.clientX-R,J=G.clientY-D;I.moved=K*K+J*J>p}I.event(G).zoom("mouse",n(M(I.that.__zoom,I.mouse[0]=$e(G,N),I.mouse[1]),I.extent,o))}function Y(G){H.on("mousemove.zoom mouseup.zoom",null),Ai(G.view,I.moved),At(G),I.event(G).end()}}function O(g,...$){if(e.apply(this,arguments)){var N=this.__zoom,I=$e(g.changedTouches?g.changedTouches[0]:g,this),H=N.invert(I),k=N.k*(g.shiftKey?.5:2),R=n(M(_(N,k),I,H),t.apply(this,$),o);At(g),a>0?Ne(this).transition().duration(a).call(j,R,I,g):Ne(this).call(x.transform,R,I,g)}}function P(g,...$){if(e.apply(this,arguments)){var N=g.touches,I=N.length,H=C(this,$,g.changedTouches.length===I).event(g),k,R,D,z;for(Bn(g),R=0;R"[React Flow]: Seems like you have not used zustand provider as an ancestor. Help: https://reactflow.dev/error#001",error002:()=>"It looks like you've created a new nodeTypes or edgeTypes object. If this wasn't on purpose please define the nodeTypes/edgeTypes outside of the component or memoize them.",error003:e=>`Node type "${e}" not found. Using fallback type "default".`,error004:()=>"The React Flow parent container needs a width and a height to render the graph.",error005:()=>"Only child nodes can use a parent extent.",error006:()=>"Can't create edge. An edge needs a source and a target.",error007:e=>`The old edge with id=${e} does not exist.`,error009:e=>`Marker type "${e}" doesn't exist.`,error008:(e,t)=>`Couldn't create edge for ${e?"target":"source"} handle id: "${e?t.targetHandle:t.sourceHandle}", edge id: ${t.id}.`,error010:()=>"Handle: No node id found. Make sure to only use a Handle inside a custom Node.",error011:e=>`Edge type "${e}" not found. Using fallback type "default".`,error012:e=>`Node with id "${e}" does not exist, it may have been removed. This can happen when a node is deleted before the "onNodeClick" handler is called.`},Wi=Be.error001();function ae(e,t){const n=w.useContext(An);if(n===null)throw new Error(Wi);return yi(n,e,t)}const pe=()=>{const e=w.useContext(An);if(e===null)throw new Error(Wi);return w.useMemo(()=>({getState:e.getState,setState:e.setState,subscribe:e.subscribe,destroy:e.destroy}),[e])},lf=e=>e.userSelectionActive?"none":"all";function Sr({position:e,children:t,className:n,style:r,...s}){const i=ae(lf),o=`${e}`.split("-");return A.createElement("div",{className:ye(["react-flow__panel",n,...o]),style:{...r,pointerEvents:i},...s},t)}function cf({proOptions:e,position:t="bottom-right"}){return e!=null&&e.hideAttribution?null:A.createElement(Sr,{position:t,className:"react-flow__attribution","data-message":"Please only hide this attribution when you are subscribed to React Flow Pro: https://reactflow.dev/pro"},A.createElement("a",{href:"https://reactflow.dev",target:"_blank",rel:"noopener noreferrer","aria-label":"React Flow attribution"},"React Flow"))}const uf=({x:e,y:t,label:n,labelStyle:r={},labelShowBg:s=!0,labelBgStyle:i={},labelBgPadding:o=[2,4],labelBgBorderRadius:a=2,children:l,className:c,...u})=>{const d=w.useRef(null),[m,f]=w.useState({x:0,y:0,width:0,height:0}),y=ye(["react-flow__edge-textwrapper",c]);return w.useEffect(()=>{if(d.current){const p=d.current.getBBox();f({x:p.x,y:p.y,width:p.width,height:p.height})}},[n]),typeof n>"u"||!n?null:A.createElement("g",{transform:`translate(${e-m.width/2} ${t-m.height/2})`,className:y,visibility:m.width?"visible":"hidden",...u},s&&A.createElement("rect",{width:m.width+2*o[0],x:-o[0],y:-o[1],height:m.height+2*o[1],className:"react-flow__edge-textbg",style:i,rx:a,ry:a}),A.createElement("text",{className:"react-flow__edge-text",y:m.height/2,dy:"0.3em",ref:d,style:r},n),l)};var df=w.memo(uf);const kr=e=>({width:e.offsetWidth,height:e.offsetHeight}),kt=(e,t=0,n=1)=>Math.min(Math.max(e,t),n),jr=(e={x:0,y:0},t)=>({x:kt(e.x,t[0][0],t[1][0]),y:kt(e.y,t[0][1],t[1][1])}),fs=(e,t,n)=>en?-kt(Math.abs(e-n),1,50)/50:0,Ui=(e,t)=>{const n=fs(e.x,35,t.width-35)*20,r=fs(e.y,35,t.height-35)*20;return[n,r]},Xi=e=>{var t;return((t=e.getRootNode)==null?void 0:t.call(e))||(window==null?void 0:window.document)},qi=(e,t)=>({x:Math.min(e.x,t.x),y:Math.min(e.y,t.y),x2:Math.max(e.x2,t.x2),y2:Math.max(e.y2,t.y2)}),Gt=({x:e,y:t,width:n,height:r})=>({x:e,y:t,x2:e+n,y2:t+r}),Ki=({x:e,y:t,x2:n,y2:r})=>({x:e,y:t,width:n-e,height:r-t}),hs=e=>({...e.positionAbsolute||{x:0,y:0},width:e.width||0,height:e.height||0}),ff=(e,t)=>Ki(qi(Gt(e),Gt(t))),ur=(e,t)=>{const n=Math.max(0,Math.min(e.x+e.width,t.x+t.width)-Math.max(e.x,t.x)),r=Math.max(0,Math.min(e.y+e.height,t.y+t.height)-Math.max(e.y,t.y));return Math.ceil(n*r)},hf=e=>Se(e.width)&&Se(e.height)&&Se(e.x)&&Se(e.y),Se=e=>!isNaN(e)&&isFinite(e),le=Symbol.for("internals"),Zi=["Enter"," ","Escape"],mf=(e,t)=>{},pf=e=>"nativeEvent"in e;function dr(e){var s,i;const t=pf(e)?e.nativeEvent:e,n=((i=(s=t.composedPath)==null?void 0:s.call(t))==null?void 0:i[0])||e.target;return["INPUT","SELECT","TEXTAREA"].includes(n==null?void 0:n.nodeName)||(n==null?void 0:n.hasAttribute("contenteditable"))||!!(n!=null&&n.closest(".nokey"))}const Qi=e=>"clientX"in e,Ke=(e,t)=>{var i,o;const n=Qi(e),r=n?e.clientX:(i=e.touches)==null?void 0:i[0].clientX,s=n?e.clientY:(o=e.touches)==null?void 0:o[0].clientY;return{x:r-((t==null?void 0:t.left)??0),y:s-((t==null?void 0:t.top)??0)}},wn=()=>{var e;return typeof navigator<"u"&&((e=navigator==null?void 0:navigator.userAgent)==null?void 0:e.indexOf("Mac"))>=0},qt=({id:e,path:t,labelX:n,labelY:r,label:s,labelStyle:i,labelShowBg:o,labelBgStyle:a,labelBgPadding:l,labelBgBorderRadius:c,style:u,markerEnd:d,markerStart:m,interactionWidth:f=20})=>A.createElement(A.Fragment,null,A.createElement("path",{id:e,style:u,d:t,fill:"none",className:"react-flow__edge-path",markerEnd:d,markerStart:m}),f&&A.createElement("path",{d:t,fill:"none",strokeOpacity:0,strokeWidth:f,className:"react-flow__edge-interaction"}),s&&Se(n)&&Se(r)?A.createElement(df,{x:n,y:r,label:s,labelStyle:i,labelShowBg:o,labelBgStyle:a,labelBgPadding:l,labelBgBorderRadius:c}):null);qt.displayName="BaseEdge";function It(e,t,n){return n===void 0?n:r=>{const s=t().edges.find(i=>i.id===e);s&&n(r,{...s})}}function Ji({sourceX:e,sourceY:t,targetX:n,targetY:r}){const s=Math.abs(n-e)/2,i=n{const[v,x,_]=to({sourceX:e,sourceY:t,sourcePosition:s,targetX:n,targetY:r,targetPosition:i});return A.createElement(qt,{path:v,labelX:x,labelY:_,label:o,labelStyle:a,labelShowBg:l,labelBgStyle:c,labelBgPadding:u,labelBgBorderRadius:d,style:m,markerEnd:f,markerStart:y,interactionWidth:p})});Cr.displayName="SimpleBezierEdge";const ps={[Z.Left]:{x:-1,y:0},[Z.Right]:{x:1,y:0},[Z.Top]:{x:0,y:-1},[Z.Bottom]:{x:0,y:1}},gf=({source:e,sourcePosition:t=Z.Bottom,target:n})=>t===Z.Left||t===Z.Right?e.xMath.sqrt(Math.pow(t.x-e.x,2)+Math.pow(t.y-e.y,2));function yf({source:e,sourcePosition:t=Z.Bottom,target:n,targetPosition:r=Z.Top,center:s,offset:i}){const o=ps[t],a=ps[r],l={x:e.x+o.x*i,y:e.y+o.y*i},c={x:n.x+a.x*i,y:n.y+a.y*i},u=gf({source:l,sourcePosition:t,target:c}),d=u.x!==0?"x":"y",m=u[d];let f=[],y,p;const v={x:0,y:0},x={x:0,y:0},[_,M,b,j]=Ji({sourceX:e.x,sourceY:e.y,targetX:n.x,targetY:n.y});if(o[d]*a[d]===-1){y=s.x??_,p=s.y??M;const E=[{x:y,y:l.y},{x:y,y:c.y}],L=[{x:l.x,y:p},{x:c.x,y:p}];o[d]===m?f=d==="x"?E:L:f=d==="x"?L:E}else{const E=[{x:l.x,y:c.y}],L=[{x:c.x,y:l.y}];if(d==="x"?f=o.x===m?L:E:f=o.y===m?E:L,t===r){const F=Math.abs(e[d]-n[d]);if(F<=i){const g=Math.min(i-1,i-F);o[d]===m?v[d]=(l[d]>e[d]?-1:1)*g:x[d]=(c[d]>n[d]?-1:1)*g}}if(t!==r){const F=d==="x"?"y":"x",g=o[d]===a[F],$=l[F]>c[F],N=l[F]=V?(y=(S.x+O.x)/2,p=f[0].y):(y=f[0].x,p=(S.y+O.y)/2)}return[[e,{x:l.x+v.x,y:l.y+v.y},...f,{x:c.x+x.x,y:c.y+x.y},n],y,p,b,j]}function xf(e,t,n,r){const s=Math.min(gs(e,t)/2,gs(t,n)/2,r),{x:i,y:o}=t;if(e.x===i&&i===n.x||e.y===o&&o===n.y)return`L${i} ${o}`;if(e.y===o){const c=e.x{let M="";return _>0&&_{const[x,_,M]=vn({sourceX:e,sourceY:t,sourcePosition:d,targetX:n,targetY:r,targetPosition:m,borderRadius:p==null?void 0:p.borderRadius,offset:p==null?void 0:p.offset});return A.createElement(qt,{path:x,labelX:_,labelY:M,label:s,labelStyle:i,labelShowBg:o,labelBgStyle:a,labelBgPadding:l,labelBgBorderRadius:c,style:u,markerEnd:f,markerStart:y,interactionWidth:v})});In.displayName="SmoothStepEdge";const $r=w.memo(e=>{var t;return A.createElement(In,{...e,pathOptions:w.useMemo(()=>{var n;return{borderRadius:0,offset:(n=e.pathOptions)==null?void 0:n.offset}},[(t=e.pathOptions)==null?void 0:t.offset])})});$r.displayName="StepEdge";function wf({sourceX:e,sourceY:t,targetX:n,targetY:r}){const[s,i,o,a]=Ji({sourceX:e,sourceY:t,targetX:n,targetY:r});return[`M ${e},${t}L ${n},${r}`,s,i,o,a]}const Mr=w.memo(({sourceX:e,sourceY:t,targetX:n,targetY:r,label:s,labelStyle:i,labelShowBg:o,labelBgStyle:a,labelBgPadding:l,labelBgBorderRadius:c,style:u,markerEnd:d,markerStart:m,interactionWidth:f})=>{const[y,p,v]=wf({sourceX:e,sourceY:t,targetX:n,targetY:r});return A.createElement(qt,{path:y,labelX:p,labelY:v,label:s,labelStyle:i,labelShowBg:o,labelBgStyle:a,labelBgPadding:l,labelBgBorderRadius:c,style:u,markerEnd:d,markerStart:m,interactionWidth:f})});Mr.displayName="StraightEdge";function rn(e,t){return e>=0?.5*e:t*25*Math.sqrt(-e)}function ys({pos:e,x1:t,y1:n,x2:r,y2:s,c:i}){switch(e){case Z.Left:return[t-rn(t-r,i),n];case Z.Right:return[t+rn(r-t,i),n];case Z.Top:return[t,n-rn(n-s,i)];case Z.Bottom:return[t,n+rn(s-n,i)]}}function no({sourceX:e,sourceY:t,sourcePosition:n=Z.Bottom,targetX:r,targetY:s,targetPosition:i=Z.Top,curvature:o=.25}){const[a,l]=ys({pos:n,x1:e,y1:t,x2:r,y2:s,c:o}),[c,u]=ys({pos:i,x1:r,y1:s,x2:e,y2:t,c:o}),[d,m,f,y]=eo({sourceX:e,sourceY:t,targetX:r,targetY:s,sourceControlX:a,sourceControlY:l,targetControlX:c,targetControlY:u});return[`M${e},${t} C${a},${l} ${c},${u} ${r},${s}`,d,m,f,y]}const _n=w.memo(({sourceX:e,sourceY:t,targetX:n,targetY:r,sourcePosition:s=Z.Bottom,targetPosition:i=Z.Top,label:o,labelStyle:a,labelShowBg:l,labelBgStyle:c,labelBgPadding:u,labelBgBorderRadius:d,style:m,markerEnd:f,markerStart:y,pathOptions:p,interactionWidth:v})=>{const[x,_,M]=no({sourceX:e,sourceY:t,sourcePosition:s,targetX:n,targetY:r,targetPosition:i,curvature:p==null?void 0:p.curvature});return A.createElement(qt,{path:x,labelX:_,labelY:M,label:o,labelStyle:a,labelShowBg:l,labelBgStyle:c,labelBgPadding:u,labelBgBorderRadius:d,style:m,markerEnd:f,markerStart:y,interactionWidth:v})});_n.displayName="BezierEdge";const Ar=w.createContext(null),bf=Ar.Provider;Ar.Consumer;const vf=()=>w.useContext(Ar),_f=e=>"id"in e&&"source"in e&&"target"in e,Ef=({source:e,sourceHandle:t,target:n,targetHandle:r})=>`reactflow__edge-${e}${t||""}-${n}${r||""}`,fr=(e,t)=>typeof e>"u"?"":typeof e=="string"?e:`${t?`${t}__`:""}${Object.keys(e).sort().map(r=>`${r}=${e[r]}`).join("&")}`,Nf=(e,t)=>t.some(n=>n.source===e.source&&n.target===e.target&&(n.sourceHandle===e.sourceHandle||!n.sourceHandle&&!e.sourceHandle)&&(n.targetHandle===e.targetHandle||!n.targetHandle&&!e.targetHandle)),Sf=(e,t)=>{if(!e.source||!e.target)return t;let n;return _f(e)?n={...e}:n={...e,id:Ef(e)},Nf(n,t)?t:t.concat(n)},hr=({x:e,y:t},[n,r,s],i,[o,a])=>{const l={x:(e-n)/s,y:(t-r)/s};return i?{x:o*Math.round(l.x/o),y:a*Math.round(l.y/a)}:l},ro=({x:e,y:t},[n,r,s])=>({x:e*s+n,y:t*s+r}),lt=(e,t=[0,0])=>{if(!e)return{x:0,y:0,positionAbsolute:{x:0,y:0}};const n=(e.width??0)*t[0],r=(e.height??0)*t[1],s={x:e.position.x-n,y:e.position.y-r};return{...s,positionAbsolute:e.positionAbsolute?{x:e.positionAbsolute.x-n,y:e.positionAbsolute.y-r}:s}},Kt=(e,t=[0,0])=>{if(e.length===0)return{x:0,y:0,width:0,height:0};const n=e.reduce((r,s)=>{const{x:i,y:o}=lt(s,t).positionAbsolute;return qi(r,Gt({x:i,y:o,width:s.width||0,height:s.height||0}))},{x:1/0,y:1/0,x2:-1/0,y2:-1/0});return Ki(n)},kf=(e,t=[0,0])=>(console.warn("[DEPRECATED] `getRectOfNodes` is deprecated. Instead use `getNodesBounds` https://reactflow.dev/api-reference/utils/get-nodes-bounds."),Kt(e,t)),so=(e,t,[n,r,s]=[0,0,1],i=!1,o=!1,a=[0,0])=>{const l={x:(t.x-n)/s,y:(t.y-r)/s,width:t.width/s,height:t.height/s},c=[];return e.forEach(u=>{const{width:d,height:m,selectable:f=!0,hidden:y=!1}=u;if(o&&!f||y)return!1;const{positionAbsolute:p}=lt(u,a),v={x:p.x,y:p.y,width:d||0,height:m||0},x=ur(l,v),_=typeof d>"u"||typeof m>"u"||d===null||m===null,M=i&&x>0,b=(d||0)*(m||0);(_||M||x>=b||u.dragging)&&c.push(u)}),c},io=(e,t)=>{const n=e.map(r=>r.id);return t.filter(r=>n.includes(r.source)||n.includes(r.target))},oo=(e,t,n,r,s,i=.1)=>{const o=t/(e.width*(1+i)),a=n/(e.height*(1+i)),l=Math.min(o,a),c=kt(l,r,s),u=e.x+e.width/2,d=e.y+e.height/2,m=t/2-u*c,f=n/2-d*c;return{x:m,y:f,zoom:c}},st=(e,t=0)=>e.transition().duration(t);function xs(e,t,n,r){return(t[n]||[]).reduce((s,i)=>{var o,a;return`${e.id}-${i.id}-${n}`!==r&&s.push({id:i.id||null,type:n,nodeId:e.id,x:(((o=e.positionAbsolute)==null?void 0:o.x)??0)+i.x+i.width/2,y:(((a=e.positionAbsolute)==null?void 0:a.y)??0)+i.y+i.height/2}),s},[])}function jf(e,t,n,r,s,i){const{x:o,y:a}=Ke(e),c=t.elementsFromPoint(o,a).find(y=>y.classList.contains("react-flow__handle"));if(c){const y=c.getAttribute("data-nodeid");if(y){const p=Ir(void 0,c),v=c.getAttribute("data-handleid"),x=i({nodeId:y,id:v,type:p});if(x){const _=s.find(M=>M.nodeId===y&&M.type===p&&M.id===v);return{handle:{id:v,type:p,nodeId:y,x:(_==null?void 0:_.x)||n.x,y:(_==null?void 0:_.y)||n.y},validHandleResult:x}}}}let u=[],d=1/0;if(s.forEach(y=>{const p=Math.sqrt((y.x-n.x)**2+(y.y-n.y)**2);if(p<=r){const v=i(y);p<=d&&(py.isValid),f=u.some(({handle:y})=>y.type==="target");return u.find(({handle:y,validHandleResult:p})=>f?y.type==="target":m?p.isValid:!0)||u[0]}const Cf={source:null,target:null,sourceHandle:null,targetHandle:null},ao=()=>({handleDomNode:null,isValid:!1,connection:Cf,endHandle:null});function lo(e,t,n,r,s,i,o){const a=s==="target",l=o.querySelector(`.react-flow__handle[data-id="${e==null?void 0:e.nodeId}-${e==null?void 0:e.id}-${e==null?void 0:e.type}"]`),c={...ao(),handleDomNode:l};if(l){const u=Ir(void 0,l),d=l.getAttribute("data-nodeid"),m=l.getAttribute("data-handleid"),f=l.classList.contains("connectable"),y=l.classList.contains("connectableend"),p={source:a?d:n,sourceHandle:a?m:r,target:a?n:d,targetHandle:a?r:m};c.connection=p,f&&y&&(t===ut.Strict?a&&u==="source"||!a&&u==="target":d!==n||m!==r)&&(c.endHandle={nodeId:d,handleId:m,type:u},c.isValid=i(p))}return c}function $f({nodes:e,nodeId:t,handleId:n,handleType:r}){return e.reduce((s,i)=>{if(i[le]){const{handleBounds:o}=i[le];let a=[],l=[];o&&(a=xs(i,o,"source",`${t}-${n}-${r}`),l=xs(i,o,"target",`${t}-${n}-${r}`)),s.push(...a,...l)}return s},[])}function Ir(e,t){return e||(t!=null&&t.classList.contains("target")?"target":t!=null&&t.classList.contains("source")?"source":null)}function Gn(e){e==null||e.classList.remove("valid","connecting","react-flow__handle-valid","react-flow__handle-connecting")}function Mf(e,t){let n=null;return t?n="valid":e&&!t&&(n="invalid"),n}function co({event:e,handleId:t,nodeId:n,onConnect:r,isTarget:s,getState:i,setState:o,isValidConnection:a,edgeUpdaterType:l,onReconnectEnd:c}){const u=Xi(e.target),{connectionMode:d,domNode:m,autoPanOnConnect:f,connectionRadius:y,onConnectStart:p,panBy:v,getNodes:x,cancelConnection:_}=i();let M=0,b;const{x:j,y:C}=Ke(e),E=u==null?void 0:u.elementFromPoint(j,C),L=Ir(l,E),S=m==null?void 0:m.getBoundingClientRect();if(!S||!L)return;let O,P=Ke(e,S),V=!1,F=null,g=!1,$=null;const N=$f({nodes:x(),nodeId:n,handleId:t,handleType:L}),I=()=>{if(!f)return;const[R,D]=Ui(P,S);v({x:R,y:D}),M=requestAnimationFrame(I)};o({connectionPosition:P,connectionStatus:null,connectionNodeId:n,connectionHandleId:t,connectionHandleType:L,connectionStartHandle:{nodeId:n,handleId:t,type:L},connectionEndHandle:null}),p==null||p(e,{nodeId:n,handleId:t,handleType:L});function H(R){const{transform:D}=i();P=Ke(R,S);const{handle:z,validHandleResult:Y}=jf(R,u,hr(P,D,!1,[1,1]),y,N,G=>lo(G,d,n,t,s?"target":"source",a,u));if(b=z,V||(I(),V=!0),$=Y.handleDomNode,F=Y.connection,g=Y.isValid,o({connectionPosition:b&&g?ro({x:b.x,y:b.y},D):P,connectionStatus:Mf(!!b,g),connectionEndHandle:Y.endHandle}),!b&&!g&&!$)return Gn(O);F.source!==F.target&&$&&(Gn(O),O=$,$.classList.add("connecting","react-flow__handle-connecting"),$.classList.toggle("valid",g),$.classList.toggle("react-flow__handle-valid",g))}function k(R){var D,z;(b||$)&&F&&g&&(r==null||r(F)),(z=(D=i()).onConnectEnd)==null||z.call(D,R),l&&(c==null||c(R)),Gn(O),_(),cancelAnimationFrame(M),V=!1,g=!1,F=null,$=null,u.removeEventListener("mousemove",H),u.removeEventListener("mouseup",k),u.removeEventListener("touchmove",H),u.removeEventListener("touchend",k)}u.addEventListener("mousemove",H),u.addEventListener("mouseup",k),u.addEventListener("touchmove",H),u.addEventListener("touchend",k)}const ws=()=>!0,Af=e=>({connectionStartHandle:e.connectionStartHandle,connectOnClick:e.connectOnClick,noPanClassName:e.noPanClassName}),If=(e,t,n)=>r=>{const{connectionStartHandle:s,connectionEndHandle:i,connectionClickStartHandle:o}=r;return{connecting:(s==null?void 0:s.nodeId)===e&&(s==null?void 0:s.handleId)===t&&(s==null?void 0:s.type)===n||(i==null?void 0:i.nodeId)===e&&(i==null?void 0:i.handleId)===t&&(i==null?void 0:i.type)===n,clickConnecting:(o==null?void 0:o.nodeId)===e&&(o==null?void 0:o.handleId)===t&&(o==null?void 0:o.type)===n}},uo=w.forwardRef(({type:e="source",position:t=Z.Top,isValidConnection:n,isConnectable:r=!0,isConnectableStart:s=!0,isConnectableEnd:i=!0,id:o,onConnect:a,children:l,className:c,onMouseDown:u,onTouchStart:d,...m},f)=>{var S,O;const y=o||null,p=e==="target",v=pe(),x=vf(),{connectOnClick:_,noPanClassName:M}=ae(Af,ge),{connecting:b,clickConnecting:j}=ae(If(x,y,e),ge);x||(O=(S=v.getState()).onError)==null||O.call(S,"010",Be.error010());const C=P=>{const{defaultEdgeOptions:V,onConnect:F,hasDefaultEdges:g}=v.getState(),$={...V,...P};if(g){const{edges:N,setEdges:I}=v.getState();I(Sf($,N))}F==null||F($),a==null||a($)},E=P=>{if(!x)return;const V=Qi(P);s&&(V&&P.button===0||!V)&&co({event:P,handleId:y,nodeId:x,onConnect:C,isTarget:p,getState:v.getState,setState:v.setState,isValidConnection:n||v.getState().isValidConnection||ws}),V?u==null||u(P):d==null||d(P)},L=P=>{const{onClickConnectStart:V,onClickConnectEnd:F,connectionClickStartHandle:g,connectionMode:$,isValidConnection:N}=v.getState();if(!x||!g&&!s)return;if(!g){V==null||V(P,{nodeId:x,handleId:y,handleType:e}),v.setState({connectionClickStartHandle:{nodeId:x,type:e,handleId:y}});return}const I=Xi(P.target),H=n||N||ws,{connection:k,isValid:R}=lo({nodeId:x,id:y,type:e},$,g.nodeId,g.handleId||null,g.type,H,I);R&&C(k),F==null||F(P),v.setState({connectionClickStartHandle:null})};return A.createElement("div",{"data-handleid":y,"data-nodeid":x,"data-handlepos":t,"data-id":`${x}-${y}-${e}`,className:ye(["react-flow__handle",`react-flow__handle-${t}`,"nodrag",M,c,{source:!p,target:p,connectable:r,connectablestart:s,connectableend:i,connecting:j,connectionindicator:r&&(s&&!b||i&&b)}]),onMouseDown:E,onTouchStart:E,onClick:_?L:void 0,ref:f,...m},l)});uo.displayName="Handle";var qe=w.memo(uo);const fo=({data:e,isConnectable:t,targetPosition:n=Z.Top,sourcePosition:r=Z.Bottom})=>A.createElement(A.Fragment,null,A.createElement(qe,{type:"target",position:n,isConnectable:t}),e==null?void 0:e.label,A.createElement(qe,{type:"source",position:r,isConnectable:t}));fo.displayName="DefaultNode";var mr=w.memo(fo);const ho=({data:e,isConnectable:t,sourcePosition:n=Z.Bottom})=>A.createElement(A.Fragment,null,e==null?void 0:e.label,A.createElement(qe,{type:"source",position:n,isConnectable:t}));ho.displayName="InputNode";var mo=w.memo(ho);const po=({data:e,isConnectable:t,targetPosition:n=Z.Top})=>A.createElement(A.Fragment,null,A.createElement(qe,{type:"target",position:n,isConnectable:t}),e==null?void 0:e.label);po.displayName="OutputNode";var go=w.memo(po);const Rr=()=>null;Rr.displayName="GroupNode";const Rf=e=>({selectedNodes:e.getNodes().filter(t=>t.selected),selectedEdges:e.edges.filter(t=>t.selected).map(t=>({...t}))}),sn=e=>e.id;function Tf(e,t){return ge(e.selectedNodes.map(sn),t.selectedNodes.map(sn))&&ge(e.selectedEdges.map(sn),t.selectedEdges.map(sn))}const yo=w.memo(({onSelectionChange:e})=>{const t=pe(),{selectedNodes:n,selectedEdges:r}=ae(Rf,Tf);return w.useEffect(()=>{const s={nodes:n,edges:r};e==null||e(s),t.getState().onSelectionChange.forEach(i=>i(s))},[n,r,e]),null});yo.displayName="SelectionListener";const Of=e=>!!e.onSelectionChange;function Df({onSelectionChange:e}){const t=ae(Of);return e||t?A.createElement(yo,{onSelectionChange:e}):null}const Lf=e=>({setNodes:e.setNodes,setEdges:e.setEdges,setDefaultNodesAndEdges:e.setDefaultNodesAndEdges,setMinZoom:e.setMinZoom,setMaxZoom:e.setMaxZoom,setTranslateExtent:e.setTranslateExtent,setNodeExtent:e.setNodeExtent,reset:e.reset});function mt(e,t){w.useEffect(()=>{typeof e<"u"&&t(e)},[e])}function ne(e,t,n){w.useEffect(()=>{typeof t<"u"&&n({[e]:t})},[t])}const Pf=({nodes:e,edges:t,defaultNodes:n,defaultEdges:r,onConnect:s,onConnectStart:i,onConnectEnd:o,onClickConnectStart:a,onClickConnectEnd:l,nodesDraggable:c,nodesConnectable:u,nodesFocusable:d,edgesFocusable:m,edgesUpdatable:f,elevateNodesOnSelect:y,minZoom:p,maxZoom:v,nodeExtent:x,onNodesChange:_,onEdgesChange:M,elementsSelectable:b,connectionMode:j,snapGrid:C,snapToGrid:E,translateExtent:L,connectOnClick:S,defaultEdgeOptions:O,fitView:P,fitViewOptions:V,onNodesDelete:F,onEdgesDelete:g,onNodeDrag:$,onNodeDragStart:N,onNodeDragStop:I,onSelectionDrag:H,onSelectionDragStart:k,onSelectionDragStop:R,noPanClassName:D,nodeOrigin:z,rfId:Y,autoPanOnConnect:G,autoPanOnNodeDrag:K,onError:J,connectionRadius:ee,isValidConnection:ie,nodeDragThreshold:te})=>{const{setNodes:re,setEdges:de,setDefaultNodesAndEdges:B,setMinZoom:q,setMaxZoom:W,setTranslateExtent:Q,setNodeExtent:U,reset:X}=ae(Lf,ge),T=pe();return w.useEffect(()=>{const se=r==null?void 0:r.map(ce=>({...ce,...O}));return B(n,se),()=>{X()}},[]),ne("defaultEdgeOptions",O,T.setState),ne("connectionMode",j,T.setState),ne("onConnect",s,T.setState),ne("onConnectStart",i,T.setState),ne("onConnectEnd",o,T.setState),ne("onClickConnectStart",a,T.setState),ne("onClickConnectEnd",l,T.setState),ne("nodesDraggable",c,T.setState),ne("nodesConnectable",u,T.setState),ne("nodesFocusable",d,T.setState),ne("edgesFocusable",m,T.setState),ne("edgesUpdatable",f,T.setState),ne("elementsSelectable",b,T.setState),ne("elevateNodesOnSelect",y,T.setState),ne("snapToGrid",E,T.setState),ne("snapGrid",C,T.setState),ne("onNodesChange",_,T.setState),ne("onEdgesChange",M,T.setState),ne("connectOnClick",S,T.setState),ne("fitViewOnInit",P,T.setState),ne("fitViewOnInitOptions",V,T.setState),ne("onNodesDelete",F,T.setState),ne("onEdgesDelete",g,T.setState),ne("onNodeDrag",$,T.setState),ne("onNodeDragStart",N,T.setState),ne("onNodeDragStop",I,T.setState),ne("onSelectionDrag",H,T.setState),ne("onSelectionDragStart",k,T.setState),ne("onSelectionDragStop",R,T.setState),ne("noPanClassName",D,T.setState),ne("nodeOrigin",z,T.setState),ne("rfId",Y,T.setState),ne("autoPanOnConnect",G,T.setState),ne("autoPanOnNodeDrag",K,T.setState),ne("onError",J,T.setState),ne("connectionRadius",ee,T.setState),ne("isValidConnection",ie,T.setState),ne("nodeDragThreshold",te,T.setState),mt(e,re),mt(t,de),mt(p,q),mt(v,W),mt(L,Q),mt(x,U),null},bs={display:"none"},zf={position:"absolute",width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0px, 0px, 0px, 0px)",clipPath:"inset(100%)"},xo="react-flow__node-desc",wo="react-flow__edge-desc",Hf="react-flow__aria-live",Ff=e=>e.ariaLiveMessage;function Vf({rfId:e}){const t=ae(Ff);return A.createElement("div",{id:`${Hf}-${e}`,"aria-live":"assertive","aria-atomic":"true",style:zf},t)}function Bf({rfId:e,disableKeyboardA11y:t}){return A.createElement(A.Fragment,null,A.createElement("div",{id:`${xo}-${e}`,style:bs},"Press enter or space to select a node.",!t&&"You can then use the arrow keys to move the node around."," Press delete to remove it and escape to cancel."," "),A.createElement("div",{id:`${wo}-${e}`,style:bs},"Press enter or space to select an edge. You can then press delete to remove it or escape to cancel."),!t&&A.createElement(Vf,{rfId:e}))}var Wt=(e=null,t={actInsideInputWithModifier:!0})=>{const[n,r]=w.useState(!1),s=w.useRef(!1),i=w.useRef(new Set([])),[o,a]=w.useMemo(()=>{if(e!==null){const c=(Array.isArray(e)?e:[e]).filter(d=>typeof d=="string").map(d=>d.split("+")),u=c.reduce((d,m)=>d.concat(...m),[]);return[c,u]}return[[],[]]},[e]);return w.useEffect(()=>{const l=typeof document<"u"?document:null,c=(t==null?void 0:t.target)||l;if(e!==null){const u=f=>{if(s.current=f.ctrlKey||f.metaKey||f.shiftKey,(!s.current||s.current&&!t.actInsideInputWithModifier)&&dr(f))return!1;const p=_s(f.code,a);i.current.add(f[p]),vs(o,i.current,!1)&&(f.preventDefault(),r(!0))},d=f=>{if((!s.current||s.current&&!t.actInsideInputWithModifier)&&dr(f))return!1;const p=_s(f.code,a);vs(o,i.current,!0)?(r(!1),i.current.clear()):i.current.delete(f[p]),f.key==="Meta"&&i.current.clear(),s.current=!1},m=()=>{i.current.clear(),r(!1)};return c==null||c.addEventListener("keydown",u),c==null||c.addEventListener("keyup",d),window.addEventListener("blur",m),()=>{c==null||c.removeEventListener("keydown",u),c==null||c.removeEventListener("keyup",d),window.removeEventListener("blur",m)}}},[e,r]),n};function vs(e,t,n){return e.filter(r=>n||r.length===t.size).some(r=>r.every(s=>t.has(s)))}function _s(e,t){return t.includes(e)?"code":"key"}function bo(e,t,n,r){var a,l;const s=e.parentNode||e.parentId;if(!s)return n;const i=t.get(s),o=lt(i,r);return bo(i,t,{x:(n.x??0)+o.x,y:(n.y??0)+o.y,z:(((a=i[le])==null?void 0:a.z)??0)>(n.z??0)?((l=i[le])==null?void 0:l.z)??0:n.z??0},r)}function vo(e,t,n){e.forEach(r=>{var i;const s=r.parentNode||r.parentId;if(s&&!e.has(s))throw new Error(`Parent node ${s} not found`);if(s||n!=null&&n[r.id]){const{x:o,y:a,z:l}=bo(r,e,{...r.position,z:((i=r[le])==null?void 0:i.z)??0},t);r.positionAbsolute={x:o,y:a},r[le].z=l,n!=null&&n[r.id]&&(r[le].isParent=!0)}})}function Yn(e,t,n,r){const s=new Map,i={},o=r?1e3:0;return e.forEach(a=>{var f;const l=(Se(a.zIndex)?a.zIndex:0)+(a.selected?o:0),c=t.get(a.id),u={...a,positionAbsolute:{x:a.position.x,y:a.position.y}},d=a.parentNode||a.parentId;d&&(i[d]=!0);const m=(c==null?void 0:c.type)&&(c==null?void 0:c.type)!==a.type;Object.defineProperty(u,le,{enumerable:!1,value:{handleBounds:m||(f=c==null?void 0:c[le])==null?void 0:f.handleBounds,z:l}}),s.set(a.id,u)}),vo(s,n,i),s}function _o(e,t={}){const{getNodes:n,width:r,height:s,minZoom:i,maxZoom:o,d3Zoom:a,d3Selection:l,fitViewOnInitDone:c,fitViewOnInit:u,nodeOrigin:d}=e(),m=t.initial&&!c&&u;if(a&&l&&(m||!t.initial)){const y=n().filter(v=>{var _;const x=t.includeHiddenNodes?v.width&&v.height:!v.hidden;return(_=t.nodes)!=null&&_.length?x&&t.nodes.some(M=>M.id===v.id):x}),p=y.every(v=>v.width&&v.height);if(y.length>0&&p){const v=Kt(y,d),{x,y:_,zoom:M}=oo(v,r,s,t.minZoom??i,t.maxZoom??o,t.padding??.1),b=Fe.translate(x,_).scale(M);return typeof t.duration=="number"&&t.duration>0?a.transform(st(l,t.duration),b):a.transform(l,b),!0}}return!1}function Gf(e,t){return e.forEach(n=>{const r=t.get(n.id);r&&t.set(r.id,{...r,[le]:r[le],selected:n.selected})}),new Map(t)}function Yf(e,t){return t.map(n=>{const r=e.find(s=>s.id===n.id);return r&&(n.selected=r.selected),n})}function on({changedNodes:e,changedEdges:t,get:n,set:r}){const{nodeInternals:s,edges:i,onNodesChange:o,onEdgesChange:a,hasDefaultNodes:l,hasDefaultEdges:c}=n();e!=null&&e.length&&(l&&r({nodeInternals:Gf(e,s)}),o==null||o(e)),t!=null&&t.length&&(c&&r({edges:Yf(t,i)}),a==null||a(t))}const pt=()=>{},Wf={zoomIn:pt,zoomOut:pt,zoomTo:pt,getZoom:()=>1,setViewport:pt,getViewport:()=>({x:0,y:0,zoom:1}),fitView:()=>!1,setCenter:pt,fitBounds:pt,project:e=>e,screenToFlowPosition:e=>e,flowToScreenPosition:e=>e,viewportInitialized:!1},Uf=e=>({d3Zoom:e.d3Zoom,d3Selection:e.d3Selection}),Xf=()=>{const e=pe(),{d3Zoom:t,d3Selection:n}=ae(Uf,ge);return w.useMemo(()=>n&&t?{zoomIn:s=>t.scaleBy(st(n,s==null?void 0:s.duration),1.2),zoomOut:s=>t.scaleBy(st(n,s==null?void 0:s.duration),1/1.2),zoomTo:(s,i)=>t.scaleTo(st(n,i==null?void 0:i.duration),s),getZoom:()=>e.getState().transform[2],setViewport:(s,i)=>{const[o,a,l]=e.getState().transform,c=Fe.translate(s.x??o,s.y??a).scale(s.zoom??l);t.transform(st(n,i==null?void 0:i.duration),c)},getViewport:()=>{const[s,i,o]=e.getState().transform;return{x:s,y:i,zoom:o}},fitView:s=>_o(e.getState,s),setCenter:(s,i,o)=>{const{width:a,height:l,maxZoom:c}=e.getState(),u=typeof(o==null?void 0:o.zoom)<"u"?o.zoom:c,d=a/2-s*u,m=l/2-i*u,f=Fe.translate(d,m).scale(u);t.transform(st(n,o==null?void 0:o.duration),f)},fitBounds:(s,i)=>{const{width:o,height:a,minZoom:l,maxZoom:c}=e.getState(),{x:u,y:d,zoom:m}=oo(s,o,a,l,c,(i==null?void 0:i.padding)??.1),f=Fe.translate(u,d).scale(m);t.transform(st(n,i==null?void 0:i.duration),f)},project:s=>{const{transform:i,snapToGrid:o,snapGrid:a}=e.getState();return console.warn("[DEPRECATED] `project` is deprecated. Instead use `screenToFlowPosition`. There is no need to subtract the react flow bounds anymore! https://reactflow.dev/api-reference/types/react-flow-instance#screen-to-flow-position"),hr(s,i,o,a)},screenToFlowPosition:s=>{const{transform:i,snapToGrid:o,snapGrid:a,domNode:l}=e.getState();if(!l)return s;const{x:c,y:u}=l.getBoundingClientRect(),d={x:s.x-c,y:s.y-u};return hr(d,i,o,a)},flowToScreenPosition:s=>{const{transform:i,domNode:o}=e.getState();if(!o)return s;const{x:a,y:l}=o.getBoundingClientRect(),c=ro(s,i);return{x:c.x+a,y:c.y+l}},viewportInitialized:!0}:Wf,[t,n])};function Rn(){const e=Xf(),t=pe(),n=w.useCallback(()=>t.getState().getNodes().map(p=>({...p})),[]),r=w.useCallback(p=>t.getState().nodeInternals.get(p),[]),s=w.useCallback(()=>{const{edges:p=[]}=t.getState();return p.map(v=>({...v}))},[]),i=w.useCallback(p=>{const{edges:v=[]}=t.getState();return v.find(x=>x.id===p)},[]),o=w.useCallback(p=>{const{getNodes:v,setNodes:x,hasDefaultNodes:_,onNodesChange:M}=t.getState(),b=v(),j=typeof p=="function"?p(b):p;if(_)x(j);else if(M){const C=j.length===0?b.map(E=>({type:"remove",id:E.id})):j.map(E=>({item:E,type:"reset"}));M(C)}},[]),a=w.useCallback(p=>{const{edges:v=[],setEdges:x,hasDefaultEdges:_,onEdgesChange:M}=t.getState(),b=typeof p=="function"?p(v):p;if(_)x(b);else if(M){const j=b.length===0?v.map(C=>({type:"remove",id:C.id})):b.map(C=>({item:C,type:"reset"}));M(j)}},[]),l=w.useCallback(p=>{const v=Array.isArray(p)?p:[p],{getNodes:x,setNodes:_,hasDefaultNodes:M,onNodesChange:b}=t.getState();if(M){const C=[...x(),...v];_(C)}else if(b){const j=v.map(C=>({item:C,type:"add"}));b(j)}},[]),c=w.useCallback(p=>{const v=Array.isArray(p)?p:[p],{edges:x=[],setEdges:_,hasDefaultEdges:M,onEdgesChange:b}=t.getState();if(M)_([...x,...v]);else if(b){const j=v.map(C=>({item:C,type:"add"}));b(j)}},[]),u=w.useCallback(()=>{const{getNodes:p,edges:v=[],transform:x}=t.getState(),[_,M,b]=x;return{nodes:p().map(j=>({...j})),edges:v.map(j=>({...j})),viewport:{x:_,y:M,zoom:b}}},[]),d=w.useCallback(({nodes:p,edges:v})=>{const{nodeInternals:x,getNodes:_,edges:M,hasDefaultNodes:b,hasDefaultEdges:j,onNodesDelete:C,onEdgesDelete:E,onNodesChange:L,onEdgesChange:S}=t.getState(),O=(p||[]).map($=>$.id),P=(v||[]).map($=>$.id),V=_().reduce(($,N)=>{const I=N.parentNode||N.parentId,H=!O.includes(N.id)&&I&&$.find(R=>R.id===I);return(typeof N.deletable=="boolean"?N.deletable:!0)&&(O.includes(N.id)||H)&&$.push(N),$},[]),F=M.filter($=>typeof $.deletable=="boolean"?$.deletable:!0),g=F.filter($=>P.includes($.id));if(V||g){const $=io(V,F),N=[...g,...$],I=N.reduce((H,k)=>(H.includes(k.id)||H.push(k.id),H),[]);if((j||b)&&(j&&t.setState({edges:M.filter(H=>!I.includes(H.id))}),b&&(V.forEach(H=>{x.delete(H.id)}),t.setState({nodeInternals:new Map(x)}))),I.length>0&&(E==null||E(N),S&&S(I.map(H=>({id:H,type:"remove"})))),V.length>0&&(C==null||C(V),L)){const H=V.map(k=>({id:k.id,type:"remove"}));L(H)}}},[]),m=w.useCallback(p=>{const v=hf(p),x=v?null:t.getState().nodeInternals.get(p.id);return!v&&!x?[null,null,v]:[v?p:hs(x),x,v]},[]),f=w.useCallback((p,v=!0,x)=>{const[_,M,b]=m(p);return _?(x||t.getState().getNodes()).filter(j=>{if(!b&&(j.id===M.id||!j.positionAbsolute))return!1;const C=hs(j),E=ur(C,_);return v&&E>0||E>=_.width*_.height}):[]},[]),y=w.useCallback((p,v,x=!0)=>{const[_]=m(p);if(!_)return!1;const M=ur(_,v);return x&&M>0||M>=_.width*_.height},[]);return w.useMemo(()=>({...e,getNodes:n,getNode:r,getEdges:s,getEdge:i,setNodes:o,setEdges:a,addNodes:l,addEdges:c,toObject:u,deleteElements:d,getIntersectingNodes:f,isNodeIntersecting:y}),[e,n,r,s,i,o,a,l,c,u,d,f,y])}const qf={actInsideInputWithModifier:!1};var Kf=({deleteKeyCode:e,multiSelectionKeyCode:t})=>{const n=pe(),{deleteElements:r}=Rn(),s=Wt(e,qf),i=Wt(t);w.useEffect(()=>{if(s){const{edges:o,getNodes:a}=n.getState(),l=a().filter(u=>u.selected),c=o.filter(u=>u.selected);r({nodes:l,edges:c}),n.setState({nodesSelectionActive:!1})}},[s]),w.useEffect(()=>{n.setState({multiSelectionActive:i})},[i])};function Zf(e){const t=pe();w.useEffect(()=>{let n;const r=()=>{var i,o;if(!e.current)return;const s=kr(e.current);(s.height===0||s.width===0)&&((o=(i=t.getState()).onError)==null||o.call(i,"004",Be.error004())),t.setState({width:s.width||500,height:s.height||500})};return r(),window.addEventListener("resize",r),e.current&&(n=new ResizeObserver(()=>r()),n.observe(e.current)),()=>{window.removeEventListener("resize",r),n&&e.current&&n.unobserve(e.current)}},[])}const Tr={position:"absolute",width:"100%",height:"100%",top:0,left:0},Qf=(e,t)=>e.x!==t.x||e.y!==t.y||e.zoom!==t.k,an=e=>({x:e.x,y:e.y,zoom:e.k}),gt=(e,t)=>e.target.closest(`.${t}`),Es=(e,t)=>t===2&&Array.isArray(e)&&e.includes(2),Ns=e=>{const t=e.ctrlKey&&wn()?10:1;return-e.deltaY*(e.deltaMode===1?.05:e.deltaMode?1:.002)*t},Jf=e=>({d3Zoom:e.d3Zoom,d3Selection:e.d3Selection,d3ZoomHandler:e.d3ZoomHandler,userSelectionActive:e.userSelectionActive}),eh=({onMove:e,onMoveStart:t,onMoveEnd:n,onPaneContextMenu:r,zoomOnScroll:s=!0,zoomOnPinch:i=!0,panOnScroll:o=!1,panOnScrollSpeed:a=.5,panOnScrollMode:l=ot.Free,zoomOnDoubleClick:c=!0,elementsSelectable:u,panOnDrag:d=!0,defaultViewport:m,translateExtent:f,minZoom:y,maxZoom:p,zoomActivationKeyCode:v,preventScrolling:x=!0,children:_,noWheelClassName:M,noPanClassName:b})=>{const j=w.useRef(),C=pe(),E=w.useRef(!1),L=w.useRef(!1),S=w.useRef(null),O=w.useRef({x:0,y:0,zoom:0}),{d3Zoom:P,d3Selection:V,d3ZoomHandler:F,userSelectionActive:g}=ae(Jf,ge),$=Wt(v),N=w.useRef(0),I=w.useRef(!1),H=w.useRef();return Zf(S),w.useEffect(()=>{if(S.current){const k=S.current.getBoundingClientRect(),R=Yi().scaleExtent([y,p]).translateExtent(f),D=Ne(S.current).call(R),z=Fe.translate(m.x,m.y).scale(kt(m.zoom,y,p)),Y=[[0,0],[k.width,k.height]],G=R.constrain()(z,Y,f);R.transform(D,G),R.wheelDelta(Ns),C.setState({d3Zoom:R,d3Selection:D,d3ZoomHandler:D.on("wheel.zoom"),transform:[G.x,G.y,G.k],domNode:S.current.closest(".react-flow")})}},[]),w.useEffect(()=>{V&&P&&(o&&!$&&!g?V.on("wheel.zoom",k=>{if(gt(k,M))return!1;k.preventDefault(),k.stopImmediatePropagation();const R=V.property("__zoom").k||1;if(k.ctrlKey&&i){const ie=$e(k),te=Ns(k),re=R*Math.pow(2,te);P.scaleTo(V,re,ie,k);return}const D=k.deltaMode===1?20:1;let z=l===ot.Vertical?0:k.deltaX*D,Y=l===ot.Horizontal?0:k.deltaY*D;!wn()&&k.shiftKey&&l!==ot.Vertical&&(z=k.deltaY*D,Y=0),P.translateBy(V,-(z/R)*a,-(Y/R)*a,{internal:!0});const G=an(V.property("__zoom")),{onViewportChangeStart:K,onViewportChange:J,onViewportChangeEnd:ee}=C.getState();clearTimeout(H.current),I.current||(I.current=!0,t==null||t(k,G),K==null||K(G)),I.current&&(e==null||e(k,G),J==null||J(G),H.current=setTimeout(()=>{n==null||n(k,G),ee==null||ee(G),I.current=!1},150))},{passive:!1}):typeof F<"u"&&V.on("wheel.zoom",function(k,R){if(!x&&k.type==="wheel"&&!k.ctrlKey||gt(k,M))return null;k.preventDefault(),F.call(this,k,R)},{passive:!1}))},[g,o,l,V,P,F,$,i,x,M,t,e,n]),w.useEffect(()=>{P&&P.on("start",k=>{var z,Y;if(!k.sourceEvent||k.sourceEvent.internal)return null;N.current=(z=k.sourceEvent)==null?void 0:z.button;const{onViewportChangeStart:R}=C.getState(),D=an(k.transform);E.current=!0,O.current=D,((Y=k.sourceEvent)==null?void 0:Y.type)==="mousedown"&&C.setState({paneDragging:!0}),R==null||R(D),t==null||t(k.sourceEvent,D)})},[P,t]),w.useEffect(()=>{P&&(g&&!E.current?P.on("zoom",null):g||P.on("zoom",k=>{var D;const{onViewportChange:R}=C.getState();if(C.setState({transform:[k.transform.x,k.transform.y,k.transform.k]}),L.current=!!(r&&Es(d,N.current??0)),(e||R)&&!((D=k.sourceEvent)!=null&&D.internal)){const z=an(k.transform);R==null||R(z),e==null||e(k.sourceEvent,z)}}))},[g,P,e,d,r]),w.useEffect(()=>{P&&P.on("end",k=>{if(!k.sourceEvent||k.sourceEvent.internal)return null;const{onViewportChangeEnd:R}=C.getState();if(E.current=!1,C.setState({paneDragging:!1}),r&&Es(d,N.current??0)&&!L.current&&r(k.sourceEvent),L.current=!1,(n||R)&&Qf(O.current,k.transform)){const D=an(k.transform);O.current=D,clearTimeout(j.current),j.current=setTimeout(()=>{R==null||R(D),n==null||n(k.sourceEvent,D)},o?150:0)}})},[P,o,d,n,r]),w.useEffect(()=>{P&&P.filter(k=>{const R=$||s,D=i&&k.ctrlKey;if((d===!0||Array.isArray(d)&&d.includes(1))&&k.button===1&&k.type==="mousedown"&&(gt(k,"react-flow__node")||gt(k,"react-flow__edge")))return!0;if(!d&&!R&&!o&&!c&&!i||g||!c&&k.type==="dblclick"||gt(k,M)&&k.type==="wheel"||gt(k,b)&&(k.type!=="wheel"||o&&k.type==="wheel"&&!$)||!i&&k.ctrlKey&&k.type==="wheel"||!R&&!o&&!D&&k.type==="wheel"||!d&&(k.type==="mousedown"||k.type==="touchstart")||Array.isArray(d)&&!d.includes(k.button)&&k.type==="mousedown")return!1;const z=Array.isArray(d)&&d.includes(k.button)||!k.button||k.button<=1;return(!k.ctrlKey||k.type==="wheel")&&z})},[g,P,s,i,o,c,d,u,$]),A.createElement("div",{className:"react-flow__renderer",ref:S,style:Tr},_)},th=e=>({userSelectionActive:e.userSelectionActive,userSelectionRect:e.userSelectionRect});function nh(){const{userSelectionActive:e,userSelectionRect:t}=ae(th,ge);return e&&t?A.createElement("div",{className:"react-flow__selection react-flow__container",style:{width:t.width,height:t.height,transform:`translate(${t.x}px, ${t.y}px)`}}):null}function Ss(e,t){const n=t.parentNode||t.parentId,r=e.find(s=>s.id===n);if(r){const s=t.position.x+t.width-r.width,i=t.position.y+t.height-r.height;if(s>0||i>0||t.position.x<0||t.position.y<0){if(r.style={...r.style},r.style.width=r.style.width??r.width,r.style.height=r.style.height??r.height,s>0&&(r.style.width+=s),i>0&&(r.style.height+=i),t.position.x<0){const o=Math.abs(t.position.x);r.position.x=r.position.x-o,r.style.width+=o,t.position.x=0}if(t.position.y<0){const o=Math.abs(t.position.y);r.position.y=r.position.y-o,r.style.height+=o,t.position.y=0}r.width=r.style.width,r.height=r.style.height}}}function rh(e,t){if(e.some(r=>r.type==="reset"))return e.filter(r=>r.type==="reset").map(r=>r.item);const n=e.filter(r=>r.type==="add").map(r=>r.item);return t.reduce((r,s)=>{const i=e.filter(a=>a.id===s.id);if(i.length===0)return r.push(s),r;const o={...s};for(const a of i)if(a)switch(a.type){case"select":{o.selected=a.selected;break}case"position":{typeof a.position<"u"&&(o.position=a.position),typeof a.positionAbsolute<"u"&&(o.positionAbsolute=a.positionAbsolute),typeof a.dragging<"u"&&(o.dragging=a.dragging),o.expandParent&&Ss(r,o);break}case"dimensions":{typeof a.dimensions<"u"&&(o.width=a.dimensions.width,o.height=a.dimensions.height),typeof a.updateStyle<"u"&&(o.style={...o.style||{},...a.dimensions}),typeof a.resizing=="boolean"&&(o.resizing=a.resizing),o.expandParent&&Ss(r,o);break}case"remove":return r}return r.push(o),r},n)}function sh(e,t){return rh(e,t)}const Ue=(e,t)=>({id:e,type:"select",selected:t});function xt(e,t){return e.reduce((n,r)=>{const s=t.includes(r.id);return!r.selected&&s?(r.selected=!0,n.push(Ue(r.id,!0))):r.selected&&!s&&(r.selected=!1,n.push(Ue(r.id,!1))),n},[])}const Wn=(e,t)=>n=>{n.target===t.current&&(e==null||e(n))},ih=e=>({userSelectionActive:e.userSelectionActive,elementsSelectable:e.elementsSelectable,dragging:e.paneDragging}),Eo=w.memo(({isSelecting:e,selectionMode:t=Yt.Full,panOnDrag:n,onSelectionStart:r,onSelectionEnd:s,onPaneClick:i,onPaneContextMenu:o,onPaneScroll:a,onPaneMouseEnter:l,onPaneMouseMove:c,onPaneMouseLeave:u,children:d})=>{const m=w.useRef(null),f=pe(),y=w.useRef(0),p=w.useRef(0),v=w.useRef(),{userSelectionActive:x,elementsSelectable:_,dragging:M}=ae(ih,ge),b=()=>{f.setState({userSelectionActive:!1,userSelectionRect:null}),y.current=0,p.current=0},j=F=>{i==null||i(F),f.getState().resetSelectedElements(),f.setState({nodesSelectionActive:!1})},C=F=>{if(Array.isArray(n)&&(n!=null&&n.includes(2))){F.preventDefault();return}o==null||o(F)},E=a?F=>a(F):void 0,L=F=>{const{resetSelectedElements:g,domNode:$}=f.getState();if(v.current=$==null?void 0:$.getBoundingClientRect(),!_||!e||F.button!==0||F.target!==m.current||!v.current)return;const{x:N,y:I}=Ke(F,v.current);g(),f.setState({userSelectionRect:{width:0,height:0,startX:N,startY:I,x:N,y:I}}),r==null||r(F)},S=F=>{const{userSelectionRect:g,nodeInternals:$,edges:N,transform:I,onNodesChange:H,onEdgesChange:k,nodeOrigin:R,getNodes:D}=f.getState();if(!e||!v.current||!g)return;f.setState({userSelectionActive:!0,nodesSelectionActive:!1});const z=Ke(F,v.current),Y=g.startX??0,G=g.startY??0,K={...g,x:z.xre.id),te=ee.map(re=>re.id);if(y.current!==te.length){y.current=te.length;const re=xt(J,te);re.length&&(H==null||H(re))}if(p.current!==ie.length){p.current=ie.length;const re=xt(N,ie);re.length&&(k==null||k(re))}f.setState({userSelectionRect:K})},O=F=>{if(F.button!==0)return;const{userSelectionRect:g}=f.getState();!x&&g&&F.target===m.current&&(j==null||j(F)),f.setState({nodesSelectionActive:y.current>0}),b(),s==null||s(F)},P=F=>{x&&(f.setState({nodesSelectionActive:y.current>0}),s==null||s(F)),b()},V=_&&(e||x);return A.createElement("div",{className:ye(["react-flow__pane",{dragging:M,selection:e}]),onClick:V?void 0:Wn(j,m),onContextMenu:Wn(C,m),onWheel:Wn(E,m),onMouseEnter:V?void 0:l,onMouseDown:V?L:void 0,onMouseMove:V?S:c,onMouseUp:V?O:void 0,onMouseLeave:V?P:u,ref:m,style:Tr},d,A.createElement(nh,null))});Eo.displayName="Pane";function No(e,t){const n=e.parentNode||e.parentId;if(!n)return!1;const r=t.get(n);return r?r.selected?!0:No(r,t):!1}function ks(e,t,n){let r=e;do{if(r!=null&&r.matches(t))return!0;if(r===n.current)return!1;r=r.parentElement}while(r);return!1}function oh(e,t,n,r){return Array.from(e.values()).filter(s=>(s.selected||s.id===r)&&(!s.parentNode||s.parentId||!No(s,e))&&(s.draggable||t&&typeof s.draggable>"u")).map(s=>{var i,o;return{id:s.id,position:s.position||{x:0,y:0},positionAbsolute:s.positionAbsolute||{x:0,y:0},distance:{x:n.x-(((i=s.positionAbsolute)==null?void 0:i.x)??0),y:n.y-(((o=s.positionAbsolute)==null?void 0:o.y)??0)},delta:{x:0,y:0},extent:s.extent,parentNode:s.parentNode||s.parentId,parentId:s.parentNode||s.parentId,width:s.width,height:s.height,expandParent:s.expandParent}})}function ah(e,t){return!t||t==="parent"?t:[t[0],[t[1][0]-(e.width||0),t[1][1]-(e.height||0)]]}function So(e,t,n,r,s=[0,0],i){const o=ah(e,e.extent||r);let a=o;const l=e.parentNode||e.parentId;if(e.extent==="parent"&&!e.expandParent)if(l&&e.width&&e.height){const d=n.get(l),{x:m,y:f}=lt(d,s).positionAbsolute;a=d&&Se(m)&&Se(f)&&Se(d.width)&&Se(d.height)?[[m+e.width*s[0],f+e.height*s[1]],[m+d.width-e.width+e.width*s[0],f+d.height-e.height+e.height*s[1]]]:a}else i==null||i("005",Be.error005()),a=o;else if(e.extent&&l&&e.extent!=="parent"){const d=n.get(l),{x:m,y:f}=lt(d,s).positionAbsolute;a=[[e.extent[0][0]+m,e.extent[0][1]+f],[e.extent[1][0]+m,e.extent[1][1]+f]]}let c={x:0,y:0};if(l){const d=n.get(l);c=lt(d,s).positionAbsolute}const u=a&&a!=="parent"?jr(t,a):t;return{position:{x:u.x-c.x,y:u.y-c.y},positionAbsolute:u}}function Un({nodeId:e,dragItems:t,nodeInternals:n}){const r=t.map(s=>({...n.get(s.id),position:s.position,positionAbsolute:s.positionAbsolute}));return[e?r.find(s=>s.id===e):r[0],r]}const js=(e,t,n,r)=>{const s=t.querySelectorAll(e);if(!s||!s.length)return null;const i=Array.from(s),o=t.getBoundingClientRect(),a={x:o.width*r[0],y:o.height*r[1]};return i.map(l=>{const c=l.getBoundingClientRect();return{id:l.getAttribute("data-handleid"),position:l.getAttribute("data-handlepos"),x:(c.left-o.left-a.x)/n,y:(c.top-o.top-a.y)/n,...kr(l)}})};function Rt(e,t,n){return n===void 0?n:r=>{const s=t().nodeInternals.get(e);s&&n(r,{...s})}}function pr({id:e,store:t,unselect:n=!1,nodeRef:r}){const{addSelectedNodes:s,unselectNodesAndEdges:i,multiSelectionActive:o,nodeInternals:a,onError:l}=t.getState(),c=a.get(e);if(!c){l==null||l("012",Be.error012(e));return}t.setState({nodesSelectionActive:!1}),c.selected?(n||c.selected&&o)&&(i({nodes:[c],edges:[]}),requestAnimationFrame(()=>{var u;return(u=r==null?void 0:r.current)==null?void 0:u.blur()})):s([e])}function lh(){const e=pe();return w.useCallback(({sourceEvent:n})=>{const{transform:r,snapGrid:s,snapToGrid:i}=e.getState(),o=n.touches?n.touches[0].clientX:n.clientX,a=n.touches?n.touches[0].clientY:n.clientY,l={x:(o-r[0])/r[2],y:(a-r[1])/r[2]};return{xSnapped:i?s[0]*Math.round(l.x/s[0]):l.x,ySnapped:i?s[1]*Math.round(l.y/s[1]):l.y,...l}},[])}function Xn(e){return(t,n,r)=>e==null?void 0:e(t,r)}function ko({nodeRef:e,disabled:t=!1,noDragClassName:n,handleSelector:r,nodeId:s,isSelectable:i,selectNodesOnDrag:o}){const a=pe(),[l,c]=w.useState(!1),u=w.useRef([]),d=w.useRef({x:null,y:null}),m=w.useRef(0),f=w.useRef(null),y=w.useRef({x:0,y:0}),p=w.useRef(null),v=w.useRef(!1),x=w.useRef(!1),_=w.useRef(!1),M=lh();return w.useEffect(()=>{if(e!=null&&e.current){const b=Ne(e.current),j=({x:L,y:S})=>{const{nodeInternals:O,onNodeDrag:P,onSelectionDrag:V,updateNodePositions:F,nodeExtent:g,snapGrid:$,snapToGrid:N,nodeOrigin:I,onError:H}=a.getState();d.current={x:L,y:S};let k=!1,R={x:0,y:0,x2:0,y2:0};if(u.current.length>1&&g){const z=Kt(u.current,I);R=Gt(z)}if(u.current=u.current.map(z=>{const Y={x:L-z.distance.x,y:S-z.distance.y};N&&(Y.x=$[0]*Math.round(Y.x/$[0]),Y.y=$[1]*Math.round(Y.y/$[1]));const G=[[g[0][0],g[0][1]],[g[1][0],g[1][1]]];u.current.length>1&&g&&!z.extent&&(G[0][0]=z.positionAbsolute.x-R.x+g[0][0],G[1][0]=z.positionAbsolute.x+(z.width??0)-R.x2+g[1][0],G[0][1]=z.positionAbsolute.y-R.y+g[0][1],G[1][1]=z.positionAbsolute.y+(z.height??0)-R.y2+g[1][1]);const K=So(z,Y,O,G,I,H);return k=k||z.position.x!==K.position.x||z.position.y!==K.position.y,z.position=K.position,z.positionAbsolute=K.positionAbsolute,z}),!k)return;F(u.current,!0,!0),c(!0);const D=s?P:Xn(V);if(D&&p.current){const[z,Y]=Un({nodeId:s,dragItems:u.current,nodeInternals:O});D(p.current,z,Y)}},C=()=>{if(!f.current)return;const[L,S]=Ui(y.current,f.current);if(L!==0||S!==0){const{transform:O,panBy:P}=a.getState();d.current.x=(d.current.x??0)-L/O[2],d.current.y=(d.current.y??0)-S/O[2],P({x:L,y:S})&&j(d.current)}m.current=requestAnimationFrame(C)},E=L=>{var I;const{nodeInternals:S,multiSelectionActive:O,nodesDraggable:P,unselectNodesAndEdges:V,onNodeDragStart:F,onSelectionDragStart:g}=a.getState();x.current=!0;const $=s?F:Xn(g);(!o||!i)&&!O&&s&&((I=S.get(s))!=null&&I.selected||V()),s&&i&&o&&pr({id:s,store:a,nodeRef:e});const N=M(L);if(d.current=N,u.current=oh(S,P,N,s),$&&u.current){const[H,k]=Un({nodeId:s,dragItems:u.current,nodeInternals:S});$(L.sourceEvent,H,k)}};if(t)b.on(".drag",null);else{const L=gu().on("start",S=>{const{domNode:O,nodeDragThreshold:P}=a.getState();P===0&&E(S),_.current=!1;const V=M(S);d.current=V,f.current=(O==null?void 0:O.getBoundingClientRect())||null,y.current=Ke(S.sourceEvent,f.current)}).on("drag",S=>{var F,g;const O=M(S),{autoPanOnNodeDrag:P,nodeDragThreshold:V}=a.getState();if(S.sourceEvent.type==="touchmove"&&S.sourceEvent.touches.length>1&&(_.current=!0),!_.current){if(!v.current&&x.current&&P&&(v.current=!0,C()),!x.current){const $=O.xSnapped-(((F=d==null?void 0:d.current)==null?void 0:F.x)??0),N=O.ySnapped-(((g=d==null?void 0:d.current)==null?void 0:g.y)??0);Math.sqrt($*$+N*N)>V&&E(S)}(d.current.x!==O.xSnapped||d.current.y!==O.ySnapped)&&u.current&&x.current&&(p.current=S.sourceEvent,y.current=Ke(S.sourceEvent,f.current),j(O))}}).on("end",S=>{if(!(!x.current||_.current)&&(c(!1),v.current=!1,x.current=!1,cancelAnimationFrame(m.current),u.current)){const{updateNodePositions:O,nodeInternals:P,onNodeDragStop:V,onSelectionDragStop:F}=a.getState(),g=s?V:Xn(F);if(O(u.current,!1,!1),g){const[$,N]=Un({nodeId:s,dragItems:u.current,nodeInternals:P});g(S.sourceEvent,$,N)}}}).filter(S=>{const O=S.target;return!S.button&&(!n||!ks(O,`.${n}`,e))&&(!r||ks(O,r,e))});return b.call(L),()=>{b.on(".drag",null)}}}},[e,t,n,r,i,a,s,o,M]),l}function jo(){const e=pe();return w.useCallback(n=>{const{nodeInternals:r,nodeExtent:s,updateNodePositions:i,getNodes:o,snapToGrid:a,snapGrid:l,onError:c,nodesDraggable:u}=e.getState(),d=o().filter(_=>_.selected&&(_.draggable||u&&typeof _.draggable>"u")),m=a?l[0]:5,f=a?l[1]:5,y=n.isShiftPressed?4:1,p=n.x*m*y,v=n.y*f*y,x=d.map(_=>{if(_.positionAbsolute){const M={x:_.positionAbsolute.x+p,y:_.positionAbsolute.y+v};a&&(M.x=l[0]*Math.round(M.x/l[0]),M.y=l[1]*Math.round(M.y/l[1]));const{positionAbsolute:b,position:j}=So(_,M,r,s,void 0,c);_.position=j,_.positionAbsolute=b}return _});i(x,!0,!1)},[])}const vt={ArrowUp:{x:0,y:-1},ArrowDown:{x:0,y:1},ArrowLeft:{x:-1,y:0},ArrowRight:{x:1,y:0}};var Tt=e=>{const t=({id:n,type:r,data:s,xPos:i,yPos:o,xPosOrigin:a,yPosOrigin:l,selected:c,onClick:u,onMouseEnter:d,onMouseMove:m,onMouseLeave:f,onContextMenu:y,onDoubleClick:p,style:v,className:x,isDraggable:_,isSelectable:M,isConnectable:b,isFocusable:j,selectNodesOnDrag:C,sourcePosition:E,targetPosition:L,hidden:S,resizeObserver:O,dragHandle:P,zIndex:V,isParent:F,noDragClassName:g,noPanClassName:$,initialized:N,disableKeyboardA11y:I,ariaLabel:H,rfId:k,hasHandleBounds:R})=>{const D=pe(),z=w.useRef(null),Y=w.useRef(null),G=w.useRef(E),K=w.useRef(L),J=w.useRef(r),ee=M||_||u||d||m||f,ie=jo(),te=Rt(n,D.getState,d),re=Rt(n,D.getState,m),de=Rt(n,D.getState,f),B=Rt(n,D.getState,y),q=Rt(n,D.getState,p),W=X=>{const{nodeDragThreshold:T}=D.getState();if(M&&(!C||!_||T>0)&&pr({id:n,store:D,nodeRef:z}),u){const se=D.getState().nodeInternals.get(n);se&&u(X,{...se})}},Q=X=>{if(!dr(X)&&!I)if(Zi.includes(X.key)&&M){const T=X.key==="Escape";pr({id:n,store:D,unselect:T,nodeRef:z})}else _&&c&&Object.prototype.hasOwnProperty.call(vt,X.key)&&(D.setState({ariaLiveMessage:`Moved selected node ${X.key.replace("Arrow","").toLowerCase()}. New position, x: ${~~i}, y: ${~~o}`}),ie({x:vt[X.key].x,y:vt[X.key].y,isShiftPressed:X.shiftKey}))};w.useEffect(()=>()=>{Y.current&&(O==null||O.unobserve(Y.current),Y.current=null)},[]),w.useEffect(()=>{if(z.current&&!S){const X=z.current;(!N||!R||Y.current!==X)&&(Y.current&&(O==null||O.unobserve(Y.current)),O==null||O.observe(X),Y.current=X)}},[S,N,R]),w.useEffect(()=>{const X=J.current!==r,T=G.current!==E,se=K.current!==L;z.current&&(X||T||se)&&(X&&(J.current=r),T&&(G.current=E),se&&(K.current=L),D.getState().updateNodeDimensions([{id:n,nodeElement:z.current,forceUpdate:!0}]))},[n,r,E,L]);const U=ko({nodeRef:z,disabled:S||!_,noDragClassName:g,handleSelector:P,nodeId:n,isSelectable:M,selectNodesOnDrag:C});return S?null:A.createElement("div",{className:ye(["react-flow__node",`react-flow__node-${r}`,{[$]:_},x,{selected:c,selectable:M,parent:F,dragging:U}]),ref:z,style:{zIndex:V,transform:`translate(${a}px,${l}px)`,pointerEvents:ee?"all":"none",visibility:N?"visible":"hidden",...v},"data-id":n,"data-testid":`rf__node-${n}`,onMouseEnter:te,onMouseMove:re,onMouseLeave:de,onContextMenu:B,onClick:W,onDoubleClick:q,onKeyDown:j?Q:void 0,tabIndex:j?0:void 0,role:j?"button":void 0,"aria-describedby":I?void 0:`${xo}-${k}`,"aria-label":H},A.createElement(bf,{value:n},A.createElement(e,{id:n,data:s,type:r,xPos:i,yPos:o,selected:c,isConnectable:b,sourcePosition:E,targetPosition:L,dragging:U,dragHandle:P,zIndex:V})))};return t.displayName="NodeWrapper",w.memo(t)};const ch=e=>{const t=e.getNodes().filter(n=>n.selected);return{...Kt(t,e.nodeOrigin),transformString:`translate(${e.transform[0]}px,${e.transform[1]}px) scale(${e.transform[2]})`,userSelectionActive:e.userSelectionActive}};function uh({onSelectionContextMenu:e,noPanClassName:t,disableKeyboardA11y:n}){const r=pe(),{width:s,height:i,x:o,y:a,transformString:l,userSelectionActive:c}=ae(ch,ge),u=jo(),d=w.useRef(null);if(w.useEffect(()=>{var y;n||(y=d.current)==null||y.focus({preventScroll:!0})},[n]),ko({nodeRef:d}),c||!s||!i)return null;const m=e?y=>{const p=r.getState().getNodes().filter(v=>v.selected);e(y,p)}:void 0,f=y=>{Object.prototype.hasOwnProperty.call(vt,y.key)&&u({x:vt[y.key].x,y:vt[y.key].y,isShiftPressed:y.shiftKey})};return A.createElement("div",{className:ye(["react-flow__nodesselection","react-flow__container",t]),style:{transform:l}},A.createElement("div",{ref:d,className:"react-flow__nodesselection-rect",onContextMenu:m,tabIndex:n?void 0:-1,onKeyDown:n?void 0:f,style:{width:s,height:i,top:a,left:o}}))}var dh=w.memo(uh);const fh=e=>e.nodesSelectionActive,Co=({children:e,onPaneClick:t,onPaneMouseEnter:n,onPaneMouseMove:r,onPaneMouseLeave:s,onPaneContextMenu:i,onPaneScroll:o,deleteKeyCode:a,onMove:l,onMoveStart:c,onMoveEnd:u,selectionKeyCode:d,selectionOnDrag:m,selectionMode:f,onSelectionStart:y,onSelectionEnd:p,multiSelectionKeyCode:v,panActivationKeyCode:x,zoomActivationKeyCode:_,elementsSelectable:M,zoomOnScroll:b,zoomOnPinch:j,panOnScroll:C,panOnScrollSpeed:E,panOnScrollMode:L,zoomOnDoubleClick:S,panOnDrag:O,defaultViewport:P,translateExtent:V,minZoom:F,maxZoom:g,preventScrolling:$,onSelectionContextMenu:N,noWheelClassName:I,noPanClassName:H,disableKeyboardA11y:k})=>{const R=ae(fh),D=Wt(d),z=Wt(x),Y=z||O,G=z||C,K=D||m&&Y!==!0;return Kf({deleteKeyCode:a,multiSelectionKeyCode:v}),A.createElement(eh,{onMove:l,onMoveStart:c,onMoveEnd:u,onPaneContextMenu:i,elementsSelectable:M,zoomOnScroll:b,zoomOnPinch:j,panOnScroll:G,panOnScrollSpeed:E,panOnScrollMode:L,zoomOnDoubleClick:S,panOnDrag:!D&&Y,defaultViewport:P,translateExtent:V,minZoom:F,maxZoom:g,zoomActivationKeyCode:_,preventScrolling:$,noWheelClassName:I,noPanClassName:H},A.createElement(Eo,{onSelectionStart:y,onSelectionEnd:p,onPaneClick:t,onPaneMouseEnter:n,onPaneMouseMove:r,onPaneMouseLeave:s,onPaneContextMenu:i,onPaneScroll:o,panOnDrag:Y,isSelecting:!!K,selectionMode:f},e,R&&A.createElement(dh,{onSelectionContextMenu:N,noPanClassName:H,disableKeyboardA11y:k})))};Co.displayName="FlowRenderer";var hh=w.memo(Co);function mh(e){return ae(w.useCallback(n=>e?so(n.nodeInternals,{x:0,y:0,width:n.width,height:n.height},n.transform,!0):n.getNodes(),[e]))}function ph(e){const t={input:Tt(e.input||mo),default:Tt(e.default||mr),output:Tt(e.output||go),group:Tt(e.group||Rr)},n={},r=Object.keys(e).filter(s=>!["input","default","output","group"].includes(s)).reduce((s,i)=>(s[i]=Tt(e[i]||mr),s),n);return{...t,...r}}const gh=({x:e,y:t,width:n,height:r,origin:s})=>!n||!r?{x:e,y:t}:s[0]<0||s[1]<0||s[0]>1||s[1]>1?{x:e,y:t}:{x:e-n*s[0],y:t-r*s[1]},yh=e=>({nodesDraggable:e.nodesDraggable,nodesConnectable:e.nodesConnectable,nodesFocusable:e.nodesFocusable,elementsSelectable:e.elementsSelectable,updateNodeDimensions:e.updateNodeDimensions,onError:e.onError}),$o=e=>{const{nodesDraggable:t,nodesConnectable:n,nodesFocusable:r,elementsSelectable:s,updateNodeDimensions:i,onError:o}=ae(yh,ge),a=mh(e.onlyRenderVisibleElements),l=w.useRef(),c=w.useMemo(()=>{if(typeof ResizeObserver>"u")return null;const u=new ResizeObserver(d=>{const m=d.map(f=>({id:f.target.getAttribute("data-id"),nodeElement:f.target,forceUpdate:!0}));i(m)});return l.current=u,u},[]);return w.useEffect(()=>()=>{var u;(u=l==null?void 0:l.current)==null||u.disconnect()},[]),A.createElement("div",{className:"react-flow__nodes",style:Tr},a.map(u=>{var j,C,E;let d=u.type||"default";e.nodeTypes[d]||(o==null||o("003",Be.error003(d)),d="default");const m=e.nodeTypes[d]||e.nodeTypes.default,f=!!(u.draggable||t&&typeof u.draggable>"u"),y=!!(u.selectable||s&&typeof u.selectable>"u"),p=!!(u.connectable||n&&typeof u.connectable>"u"),v=!!(u.focusable||r&&typeof u.focusable>"u"),x=e.nodeExtent?jr(u.positionAbsolute,e.nodeExtent):u.positionAbsolute,_=(x==null?void 0:x.x)??0,M=(x==null?void 0:x.y)??0,b=gh({x:_,y:M,width:u.width??0,height:u.height??0,origin:e.nodeOrigin});return A.createElement(m,{key:u.id,id:u.id,className:u.className,style:u.style,type:d,data:u.data,sourcePosition:u.sourcePosition||Z.Bottom,targetPosition:u.targetPosition||Z.Top,hidden:u.hidden,xPos:_,yPos:M,xPosOrigin:b.x,yPosOrigin:b.y,selectNodesOnDrag:e.selectNodesOnDrag,onClick:e.onNodeClick,onMouseEnter:e.onNodeMouseEnter,onMouseMove:e.onNodeMouseMove,onMouseLeave:e.onNodeMouseLeave,onContextMenu:e.onNodeContextMenu,onDoubleClick:e.onNodeDoubleClick,selected:!!u.selected,isDraggable:f,isSelectable:y,isConnectable:p,isFocusable:v,resizeObserver:c,dragHandle:u.dragHandle,zIndex:((j=u[le])==null?void 0:j.z)??0,isParent:!!((C=u[le])!=null&&C.isParent),noDragClassName:e.noDragClassName,noPanClassName:e.noPanClassName,initialized:!!u.width&&!!u.height,rfId:e.rfId,disableKeyboardA11y:e.disableKeyboardA11y,ariaLabel:u.ariaLabel,hasHandleBounds:!!((E=u[le])!=null&&E.handleBounds)})}))};$o.displayName="NodeRenderer";var xh=w.memo($o);const wh=(e,t,n)=>n===Z.Left?e-t:n===Z.Right?e+t:e,bh=(e,t,n)=>n===Z.Top?e-t:n===Z.Bottom?e+t:e,Cs="react-flow__edgeupdater",$s=({position:e,centerX:t,centerY:n,radius:r=10,onMouseDown:s,onMouseEnter:i,onMouseOut:o,type:a})=>A.createElement("circle",{onMouseDown:s,onMouseEnter:i,onMouseOut:o,className:ye([Cs,`${Cs}-${a}`]),cx:wh(t,r,e),cy:bh(n,r,e),r,stroke:"transparent",fill:"transparent"}),vh=()=>!0;var yt=e=>{const t=({id:n,className:r,type:s,data:i,onClick:o,onEdgeDoubleClick:a,selected:l,animated:c,label:u,labelStyle:d,labelShowBg:m,labelBgStyle:f,labelBgPadding:y,labelBgBorderRadius:p,style:v,source:x,target:_,sourceX:M,sourceY:b,targetX:j,targetY:C,sourcePosition:E,targetPosition:L,elementsSelectable:S,hidden:O,sourceHandleId:P,targetHandleId:V,onContextMenu:F,onMouseEnter:g,onMouseMove:$,onMouseLeave:N,reconnectRadius:I,onReconnect:H,onReconnectStart:k,onReconnectEnd:R,markerEnd:D,markerStart:z,rfId:Y,ariaLabel:G,isFocusable:K,isReconnectable:J,pathOptions:ee,interactionWidth:ie,disableKeyboardA11y:te})=>{const re=w.useRef(null),[de,B]=w.useState(!1),[q,W]=w.useState(!1),Q=pe(),U=w.useMemo(()=>`url('#${fr(z,Y)}')`,[z,Y]),X=w.useMemo(()=>`url('#${fr(D,Y)}')`,[D,Y]);if(O)return null;const T=xe=>{var Re;const{edges:Ce,addSelectedEdges:Je,unselectNodesAndEdges:et,multiSelectionActive:tt}=Q.getState(),De=Ce.find(Ct=>Ct.id===n);De&&(S&&(Q.setState({nodesSelectionActive:!1}),De.selected&&tt?(et({nodes:[],edges:[De]}),(Re=re.current)==null||Re.blur()):Je([n])),o&&o(xe,De))},se=It(n,Q.getState,a),ce=It(n,Q.getState,F),me=It(n,Q.getState,g),we=It(n,Q.getState,$),be=It(n,Q.getState,N),Ee=(xe,Ce)=>{if(xe.button!==0)return;const{edges:Je,isValidConnection:et}=Q.getState(),tt=Ce?_:x,De=(Ce?V:P)||null,Re=Ce?"target":"source",Ct=et||vh,Dn=Ce,$t=Je.find(nt=>nt.id===n);W(!0),k==null||k(xe,$t,Re);const Ln=nt=>{W(!1),R==null||R(nt,$t,Re)};co({event:xe,handleId:De,nodeId:tt,onConnect:nt=>H==null?void 0:H($t,nt),isTarget:Dn,getState:Q.getState,setState:Q.setState,isValidConnection:Ct,edgeUpdaterType:Re,onReconnectEnd:Ln})},Ge=xe=>Ee(xe,!0),oe=xe=>Ee(xe,!1),Qe=()=>B(!0),ft=()=>B(!1),ht=!S&&!o,jt=xe=>{var Ce;if(!te&&Zi.includes(xe.key)&&S){const{unselectNodesAndEdges:Je,addSelectedEdges:et,edges:tt}=Q.getState();xe.key==="Escape"?((Ce=re.current)==null||Ce.blur(),Je({edges:[tt.find(Re=>Re.id===n)]})):et([n])}};return A.createElement("g",{className:ye(["react-flow__edge",`react-flow__edge-${s}`,r,{selected:l,animated:c,inactive:ht,updating:de}]),onClick:T,onDoubleClick:se,onContextMenu:ce,onMouseEnter:me,onMouseMove:we,onMouseLeave:be,onKeyDown:K?jt:void 0,tabIndex:K?0:void 0,role:K?"button":"img","data-testid":`rf__edge-${n}`,"aria-label":G===null?void 0:G||`Edge from ${x} to ${_}`,"aria-describedby":K?`${wo}-${Y}`:void 0,ref:re},!q&&A.createElement(e,{id:n,source:x,target:_,selected:l,animated:c,label:u,labelStyle:d,labelShowBg:m,labelBgStyle:f,labelBgPadding:y,labelBgBorderRadius:p,data:i,style:v,sourceX:M,sourceY:b,targetX:j,targetY:C,sourcePosition:E,targetPosition:L,sourceHandleId:P,targetHandleId:V,markerStart:U,markerEnd:X,pathOptions:ee,interactionWidth:ie}),J&&A.createElement(A.Fragment,null,(J==="source"||J===!0)&&A.createElement($s,{position:E,centerX:M,centerY:b,radius:I,onMouseDown:Ge,onMouseEnter:Qe,onMouseOut:ft,type:"source"}),(J==="target"||J===!0)&&A.createElement($s,{position:L,centerX:j,centerY:C,radius:I,onMouseDown:oe,onMouseEnter:Qe,onMouseOut:ft,type:"target"})))};return t.displayName="EdgeWrapper",w.memo(t)};function _h(e){const t={default:yt(e.default||_n),straight:yt(e.bezier||Mr),step:yt(e.step||$r),smoothstep:yt(e.step||In),simplebezier:yt(e.simplebezier||Cr)},n={},r=Object.keys(e).filter(s=>!["default","bezier"].includes(s)).reduce((s,i)=>(s[i]=yt(e[i]||_n),s),n);return{...t,...r}}function Ms(e,t,n=null){const r=((n==null?void 0:n.x)||0)+t.x,s=((n==null?void 0:n.y)||0)+t.y,i=(n==null?void 0:n.width)||t.width,o=(n==null?void 0:n.height)||t.height;switch(e){case Z.Top:return{x:r+i/2,y:s};case Z.Right:return{x:r+i,y:s+o/2};case Z.Bottom:return{x:r+i/2,y:s+o};case Z.Left:return{x:r,y:s+o/2}}}function As(e,t){return e?e.length===1||!t?e[0]:t&&e.find(n=>n.id===t)||null:null}const Eh=(e,t,n,r,s,i)=>{const o=Ms(n,e,t),a=Ms(i,r,s);return{sourceX:o.x,sourceY:o.y,targetX:a.x,targetY:a.y}};function Nh({sourcePos:e,targetPos:t,sourceWidth:n,sourceHeight:r,targetWidth:s,targetHeight:i,width:o,height:a,transform:l}){const c={x:Math.min(e.x,t.x),y:Math.min(e.y,t.y),x2:Math.max(e.x+n,t.x+s),y2:Math.max(e.y+r,t.y+i)};c.x===c.x2&&(c.x2+=1),c.y===c.y2&&(c.y2+=1);const u=Gt({x:(0-l[0])/l[2],y:(0-l[1])/l[2],width:o/l[2],height:a/l[2]}),d=Math.max(0,Math.min(u.x2,c.x2)-Math.max(u.x,c.x)),m=Math.max(0,Math.min(u.y2,c.y2)-Math.max(u.y,c.y));return Math.ceil(d*m)>0}function Is(e){var r,s,i,o,a;const t=((r=e==null?void 0:e[le])==null?void 0:r.handleBounds)||null,n=t&&(e==null?void 0:e.width)&&(e==null?void 0:e.height)&&typeof((s=e==null?void 0:e.positionAbsolute)==null?void 0:s.x)<"u"&&typeof((i=e==null?void 0:e.positionAbsolute)==null?void 0:i.y)<"u";return[{x:((o=e==null?void 0:e.positionAbsolute)==null?void 0:o.x)||0,y:((a=e==null?void 0:e.positionAbsolute)==null?void 0:a.y)||0,width:(e==null?void 0:e.width)||0,height:(e==null?void 0:e.height)||0},t,!!n]}const Sh=[{level:0,isMaxLevel:!0,edges:[]}];function kh(e,t,n=!1){let r=-1;const s=e.reduce((o,a)=>{var u,d;const l=Se(a.zIndex);let c=l?a.zIndex:0;if(n){const m=t.get(a.target),f=t.get(a.source),y=a.selected||(m==null?void 0:m.selected)||(f==null?void 0:f.selected),p=Math.max(((u=f==null?void 0:f[le])==null?void 0:u.z)||0,((d=m==null?void 0:m[le])==null?void 0:d.z)||0,1e3);c=(l?a.zIndex:0)+(y?p:0)}return o[c]?o[c].push(a):o[c]=[a],r=c>r?c:r,o},{}),i=Object.entries(s).map(([o,a])=>{const l=+o;return{edges:a,level:l,isMaxLevel:l===r}});return i.length===0?Sh:i}function jh(e,t,n){const r=ae(w.useCallback(s=>e?s.edges.filter(i=>{const o=t.get(i.source),a=t.get(i.target);return(o==null?void 0:o.width)&&(o==null?void 0:o.height)&&(a==null?void 0:a.width)&&(a==null?void 0:a.height)&&Nh({sourcePos:o.positionAbsolute||{x:0,y:0},targetPos:a.positionAbsolute||{x:0,y:0},sourceWidth:o.width,sourceHeight:o.height,targetWidth:a.width,targetHeight:a.height,width:s.width,height:s.height,transform:s.transform})}):s.edges,[e,t]));return kh(r,t,n)}const Ch=({color:e="none",strokeWidth:t=1})=>A.createElement("polyline",{style:{stroke:e,strokeWidth:t},strokeLinecap:"round",strokeLinejoin:"round",fill:"none",points:"-5,-4 0,0 -5,4"}),$h=({color:e="none",strokeWidth:t=1})=>A.createElement("polyline",{style:{stroke:e,fill:e,strokeWidth:t},strokeLinecap:"round",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4 -5,-4"}),Rs={[bn.Arrow]:Ch,[bn.ArrowClosed]:$h};function Mh(e){const t=pe();return w.useMemo(()=>{var s,i;return Object.prototype.hasOwnProperty.call(Rs,e)?Rs[e]:((i=(s=t.getState()).onError)==null||i.call(s,"009",Be.error009(e)),null)},[e])}const Ah=({id:e,type:t,color:n,width:r=12.5,height:s=12.5,markerUnits:i="strokeWidth",strokeWidth:o,orient:a="auto-start-reverse"})=>{const l=Mh(t);return l?A.createElement("marker",{className:"react-flow__arrowhead",id:e,markerWidth:`${r}`,markerHeight:`${s}`,viewBox:"-10 -10 20 20",markerUnits:i,orient:a,refX:"0",refY:"0"},A.createElement(l,{color:n,strokeWidth:o})):null},Ih=({defaultColor:e,rfId:t})=>n=>{const r=[];return n.edges.reduce((s,i)=>([i.markerStart,i.markerEnd].forEach(o=>{if(o&&typeof o=="object"){const a=fr(o,t);r.includes(a)||(s.push({id:a,color:o.color||e,...o}),r.push(a))}}),s),[]).sort((s,i)=>s.id.localeCompare(i.id))},Mo=({defaultColor:e,rfId:t})=>{const n=ae(w.useCallback(Ih({defaultColor:e,rfId:t}),[e,t]),(r,s)=>!(r.length!==s.length||r.some((i,o)=>i.id!==s[o].id)));return A.createElement("defs",null,n.map(r=>A.createElement(Ah,{id:r.id,key:r.id,type:r.type,color:r.color,width:r.width,height:r.height,markerUnits:r.markerUnits,strokeWidth:r.strokeWidth,orient:r.orient})))};Mo.displayName="MarkerDefinitions";var Rh=w.memo(Mo);const Th=e=>({nodesConnectable:e.nodesConnectable,edgesFocusable:e.edgesFocusable,edgesUpdatable:e.edgesUpdatable,elementsSelectable:e.elementsSelectable,width:e.width,height:e.height,connectionMode:e.connectionMode,nodeInternals:e.nodeInternals,onError:e.onError}),Ao=({defaultMarkerColor:e,onlyRenderVisibleElements:t,elevateEdgesOnSelect:n,rfId:r,edgeTypes:s,noPanClassName:i,onEdgeContextMenu:o,onEdgeMouseEnter:a,onEdgeMouseMove:l,onEdgeMouseLeave:c,onEdgeClick:u,onEdgeDoubleClick:d,onReconnect:m,onReconnectStart:f,onReconnectEnd:y,reconnectRadius:p,children:v,disableKeyboardA11y:x})=>{const{edgesFocusable:_,edgesUpdatable:M,elementsSelectable:b,width:j,height:C,connectionMode:E,nodeInternals:L,onError:S}=ae(Th,ge),O=jh(t,L,n);return j?A.createElement(A.Fragment,null,O.map(({level:P,edges:V,isMaxLevel:F})=>A.createElement("svg",{key:P,style:{zIndex:P},width:j,height:C,className:"react-flow__edges react-flow__container"},F&&A.createElement(Rh,{defaultColor:e,rfId:r}),A.createElement("g",null,V.map(g=>{const[$,N,I]=Is(L.get(g.source)),[H,k,R]=Is(L.get(g.target));if(!I||!R)return null;let D=g.type||"default";s[D]||(S==null||S("011",Be.error011(D)),D="default");const z=s[D]||s.default,Y=E===ut.Strict?k.target:(k.target??[]).concat(k.source??[]),G=As(N.source,g.sourceHandle),K=As(Y,g.targetHandle),J=(G==null?void 0:G.position)||Z.Bottom,ee=(K==null?void 0:K.position)||Z.Top,ie=!!(g.focusable||_&&typeof g.focusable>"u"),te=g.reconnectable||g.updatable,re=typeof m<"u"&&(te||M&&typeof te>"u");if(!G||!K)return S==null||S("008",Be.error008(G,g)),null;const{sourceX:de,sourceY:B,targetX:q,targetY:W}=Eh($,G,J,H,K,ee);return A.createElement(z,{key:g.id,id:g.id,className:ye([g.className,i]),type:D,data:g.data,selected:!!g.selected,animated:!!g.animated,hidden:!!g.hidden,label:g.label,labelStyle:g.labelStyle,labelShowBg:g.labelShowBg,labelBgStyle:g.labelBgStyle,labelBgPadding:g.labelBgPadding,labelBgBorderRadius:g.labelBgBorderRadius,style:g.style,source:g.source,target:g.target,sourceHandleId:g.sourceHandle,targetHandleId:g.targetHandle,markerEnd:g.markerEnd,markerStart:g.markerStart,sourceX:de,sourceY:B,targetX:q,targetY:W,sourcePosition:J,targetPosition:ee,elementsSelectable:b,onContextMenu:o,onMouseEnter:a,onMouseMove:l,onMouseLeave:c,onClick:u,onEdgeDoubleClick:d,onReconnect:m,onReconnectStart:f,onReconnectEnd:y,reconnectRadius:p,rfId:r,ariaLabel:g.ariaLabel,isFocusable:ie,isReconnectable:re,pathOptions:"pathOptions"in g?g.pathOptions:void 0,interactionWidth:g.interactionWidth,disableKeyboardA11y:x})})))),v):null};Ao.displayName="EdgeRenderer";var Oh=w.memo(Ao);const Dh=e=>`translate(${e.transform[0]}px,${e.transform[1]}px) scale(${e.transform[2]})`;function Lh({children:e}){const t=ae(Dh);return A.createElement("div",{className:"react-flow__viewport react-flow__container",style:{transform:t}},e)}function Ph(e){const t=Rn(),n=w.useRef(!1);w.useEffect(()=>{!n.current&&t.viewportInitialized&&e&&(setTimeout(()=>e(t),1),n.current=!0)},[e,t.viewportInitialized])}const zh={[Z.Left]:Z.Right,[Z.Right]:Z.Left,[Z.Top]:Z.Bottom,[Z.Bottom]:Z.Top},Io=({nodeId:e,handleType:t,style:n,type:r=Xe.Bezier,CustomComponent:s,connectionStatus:i})=>{var C,E,L;const{fromNode:o,handleId:a,toX:l,toY:c,connectionMode:u}=ae(w.useCallback(S=>({fromNode:S.nodeInternals.get(e),handleId:S.connectionHandleId,toX:(S.connectionPosition.x-S.transform[0])/S.transform[2],toY:(S.connectionPosition.y-S.transform[1])/S.transform[2],connectionMode:S.connectionMode}),[e]),ge),d=(C=o==null?void 0:o[le])==null?void 0:C.handleBounds;let m=d==null?void 0:d[t];if(u===ut.Loose&&(m=m||(d==null?void 0:d[t==="source"?"target":"source"])),!o||!m)return null;const f=a?m.find(S=>S.id===a):m[0],y=f?f.x+f.width/2:(o.width??0)/2,p=f?f.y+f.height/2:o.height??0,v=(((E=o.positionAbsolute)==null?void 0:E.x)??0)+y,x=(((L=o.positionAbsolute)==null?void 0:L.y)??0)+p,_=f==null?void 0:f.position,M=_?zh[_]:null;if(!_||!M)return null;if(s)return A.createElement(s,{connectionLineType:r,connectionLineStyle:n,fromNode:o,fromHandle:f,fromX:v,fromY:x,toX:l,toY:c,fromPosition:_,toPosition:M,connectionStatus:i});let b="";const j={sourceX:v,sourceY:x,sourcePosition:_,targetX:l,targetY:c,targetPosition:M};return r===Xe.Bezier?[b]=no(j):r===Xe.Step?[b]=vn({...j,borderRadius:0}):r===Xe.SmoothStep?[b]=vn(j):r===Xe.SimpleBezier?[b]=to(j):b=`M${v},${x} ${l},${c}`,A.createElement("path",{d:b,fill:"none",className:"react-flow__connection-path",style:n})};Io.displayName="ConnectionLine";const Hh=e=>({nodeId:e.connectionNodeId,handleType:e.connectionHandleType,nodesConnectable:e.nodesConnectable,connectionStatus:e.connectionStatus,width:e.width,height:e.height});function Fh({containerStyle:e,style:t,type:n,component:r}){const{nodeId:s,handleType:i,nodesConnectable:o,width:a,height:l,connectionStatus:c}=ae(Hh,ge);return!(s&&i&&a&&o)?null:A.createElement("svg",{style:e,width:a,height:l,className:"react-flow__edges react-flow__connectionline react-flow__container"},A.createElement("g",{className:ye(["react-flow__connection",c])},A.createElement(Io,{nodeId:s,handleType:i,style:t,type:n,CustomComponent:r,connectionStatus:c})))}function Ts(e,t){return w.useRef(null),pe(),w.useMemo(()=>t(e),[e])}const Ro=({nodeTypes:e,edgeTypes:t,onMove:n,onMoveStart:r,onMoveEnd:s,onInit:i,onNodeClick:o,onEdgeClick:a,onNodeDoubleClick:l,onEdgeDoubleClick:c,onNodeMouseEnter:u,onNodeMouseMove:d,onNodeMouseLeave:m,onNodeContextMenu:f,onSelectionContextMenu:y,onSelectionStart:p,onSelectionEnd:v,connectionLineType:x,connectionLineStyle:_,connectionLineComponent:M,connectionLineContainerStyle:b,selectionKeyCode:j,selectionOnDrag:C,selectionMode:E,multiSelectionKeyCode:L,panActivationKeyCode:S,zoomActivationKeyCode:O,deleteKeyCode:P,onlyRenderVisibleElements:V,elementsSelectable:F,selectNodesOnDrag:g,defaultViewport:$,translateExtent:N,minZoom:I,maxZoom:H,preventScrolling:k,defaultMarkerColor:R,zoomOnScroll:D,zoomOnPinch:z,panOnScroll:Y,panOnScrollSpeed:G,panOnScrollMode:K,zoomOnDoubleClick:J,panOnDrag:ee,onPaneClick:ie,onPaneMouseEnter:te,onPaneMouseMove:re,onPaneMouseLeave:de,onPaneScroll:B,onPaneContextMenu:q,onEdgeContextMenu:W,onEdgeMouseEnter:Q,onEdgeMouseMove:U,onEdgeMouseLeave:X,onReconnect:T,onReconnectStart:se,onReconnectEnd:ce,reconnectRadius:me,noDragClassName:we,noWheelClassName:be,noPanClassName:Ee,elevateEdgesOnSelect:Ge,disableKeyboardA11y:oe,nodeOrigin:Qe,nodeExtent:ft,rfId:ht})=>{const jt=Ts(e,ph),xe=Ts(t,_h);return Ph(i),A.createElement(hh,{onPaneClick:ie,onPaneMouseEnter:te,onPaneMouseMove:re,onPaneMouseLeave:de,onPaneContextMenu:q,onPaneScroll:B,deleteKeyCode:P,selectionKeyCode:j,selectionOnDrag:C,selectionMode:E,onSelectionStart:p,onSelectionEnd:v,multiSelectionKeyCode:L,panActivationKeyCode:S,zoomActivationKeyCode:O,elementsSelectable:F,onMove:n,onMoveStart:r,onMoveEnd:s,zoomOnScroll:D,zoomOnPinch:z,zoomOnDoubleClick:J,panOnScroll:Y,panOnScrollSpeed:G,panOnScrollMode:K,panOnDrag:ee,defaultViewport:$,translateExtent:N,minZoom:I,maxZoom:H,onSelectionContextMenu:y,preventScrolling:k,noDragClassName:we,noWheelClassName:be,noPanClassName:Ee,disableKeyboardA11y:oe},A.createElement(Lh,null,A.createElement(Oh,{edgeTypes:xe,onEdgeClick:a,onEdgeDoubleClick:c,onlyRenderVisibleElements:V,onEdgeContextMenu:W,onEdgeMouseEnter:Q,onEdgeMouseMove:U,onEdgeMouseLeave:X,onReconnect:T,onReconnectStart:se,onReconnectEnd:ce,reconnectRadius:me,defaultMarkerColor:R,noPanClassName:Ee,elevateEdgesOnSelect:!!Ge,disableKeyboardA11y:oe,rfId:ht},A.createElement(Fh,{style:_,type:x,component:M,containerStyle:b})),A.createElement("div",{className:"react-flow__edgelabel-renderer"}),A.createElement(xh,{nodeTypes:jt,onNodeClick:o,onNodeDoubleClick:l,onNodeMouseEnter:u,onNodeMouseMove:d,onNodeMouseLeave:m,onNodeContextMenu:f,selectNodesOnDrag:g,onlyRenderVisibleElements:V,noPanClassName:Ee,noDragClassName:we,disableKeyboardA11y:oe,nodeOrigin:Qe,nodeExtent:ft,rfId:ht})))};Ro.displayName="GraphView";var Vh=w.memo(Ro);const gr=[[Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY],[Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY]],Ye={rfId:"1",width:0,height:0,transform:[0,0,1],nodeInternals:new Map,edges:[],onNodesChange:null,onEdgesChange:null,hasDefaultNodes:!1,hasDefaultEdges:!1,d3Zoom:null,d3Selection:null,d3ZoomHandler:void 0,minZoom:.5,maxZoom:2,translateExtent:gr,nodeExtent:gr,nodesSelectionActive:!1,userSelectionActive:!1,userSelectionRect:null,connectionNodeId:null,connectionHandleId:null,connectionHandleType:"source",connectionPosition:{x:0,y:0},connectionStatus:null,connectionMode:ut.Strict,domNode:null,paneDragging:!1,noPanClassName:"nopan",nodeOrigin:[0,0],nodeDragThreshold:0,snapGrid:[15,15],snapToGrid:!1,nodesDraggable:!0,nodesConnectable:!0,nodesFocusable:!0,edgesFocusable:!0,edgesUpdatable:!0,elementsSelectable:!0,elevateNodesOnSelect:!0,fitViewOnInit:!1,fitViewOnInitDone:!1,fitViewOnInitOptions:void 0,onSelectionChange:[],multiSelectionActive:!1,connectionStartHandle:null,connectionEndHandle:null,connectionClickStartHandle:null,connectOnClick:!0,ariaLiveMessage:"",autoPanOnConnect:!0,autoPanOnNodeDrag:!0,connectionRadius:20,onError:mf,isValidConnection:void 0},Bh=()=>Cl((e,t)=>({...Ye,setNodes:n=>{const{nodeInternals:r,nodeOrigin:s,elevateNodesOnSelect:i}=t();e({nodeInternals:Yn(n,r,s,i)})},getNodes:()=>Array.from(t().nodeInternals.values()),setEdges:n=>{const{defaultEdgeOptions:r={}}=t();e({edges:n.map(s=>({...r,...s}))})},setDefaultNodesAndEdges:(n,r)=>{const s=typeof n<"u",i=typeof r<"u",o=s?Yn(n,new Map,t().nodeOrigin,t().elevateNodesOnSelect):new Map;e({nodeInternals:o,edges:i?r:[],hasDefaultNodes:s,hasDefaultEdges:i})},updateNodeDimensions:n=>{const{onNodesChange:r,nodeInternals:s,fitViewOnInit:i,fitViewOnInitDone:o,fitViewOnInitOptions:a,domNode:l,nodeOrigin:c}=t(),u=l==null?void 0:l.querySelector(".react-flow__viewport");if(!u)return;const d=window.getComputedStyle(u),{m22:m}=new window.DOMMatrixReadOnly(d.transform),f=n.reduce((p,v)=>{const x=s.get(v.id);if(x!=null&&x.hidden)s.set(x.id,{...x,[le]:{...x[le],handleBounds:void 0}});else if(x){const _=kr(v.nodeElement);!!(_.width&&_.height&&(x.width!==_.width||x.height!==_.height||v.forceUpdate))&&(s.set(x.id,{...x,[le]:{...x[le],handleBounds:{source:js(".source",v.nodeElement,m,c),target:js(".target",v.nodeElement,m,c)}},..._}),p.push({id:x.id,type:"dimensions",dimensions:_}))}return p},[]);vo(s,c);const y=o||i&&!o&&_o(t,{initial:!0,...a});e({nodeInternals:new Map(s),fitViewOnInitDone:y}),(f==null?void 0:f.length)>0&&(r==null||r(f))},updateNodePositions:(n,r=!0,s=!1)=>{const{triggerNodeChanges:i}=t(),o=n.map(a=>{const l={id:a.id,type:"position",dragging:s};return r&&(l.positionAbsolute=a.positionAbsolute,l.position=a.position),l});i(o)},triggerNodeChanges:n=>{const{onNodesChange:r,nodeInternals:s,hasDefaultNodes:i,nodeOrigin:o,getNodes:a,elevateNodesOnSelect:l}=t();if(n!=null&&n.length){if(i){const c=sh(n,a()),u=Yn(c,s,o,l);e({nodeInternals:u})}r==null||r(n)}},addSelectedNodes:n=>{const{multiSelectionActive:r,edges:s,getNodes:i}=t();let o,a=null;r?o=n.map(l=>Ue(l,!0)):(o=xt(i(),n),a=xt(s,[])),on({changedNodes:o,changedEdges:a,get:t,set:e})},addSelectedEdges:n=>{const{multiSelectionActive:r,edges:s,getNodes:i}=t();let o,a=null;r?o=n.map(l=>Ue(l,!0)):(o=xt(s,n),a=xt(i(),[])),on({changedNodes:a,changedEdges:o,get:t,set:e})},unselectNodesAndEdges:({nodes:n,edges:r}={})=>{const{edges:s,getNodes:i}=t(),o=n||i(),a=r||s,l=o.map(u=>(u.selected=!1,Ue(u.id,!1))),c=a.map(u=>Ue(u.id,!1));on({changedNodes:l,changedEdges:c,get:t,set:e})},setMinZoom:n=>{const{d3Zoom:r,maxZoom:s}=t();r==null||r.scaleExtent([n,s]),e({minZoom:n})},setMaxZoom:n=>{const{d3Zoom:r,minZoom:s}=t();r==null||r.scaleExtent([s,n]),e({maxZoom:n})},setTranslateExtent:n=>{var r;(r=t().d3Zoom)==null||r.translateExtent(n),e({translateExtent:n})},resetSelectedElements:()=>{const{edges:n,getNodes:r}=t(),i=r().filter(a=>a.selected).map(a=>Ue(a.id,!1)),o=n.filter(a=>a.selected).map(a=>Ue(a.id,!1));on({changedNodes:i,changedEdges:o,get:t,set:e})},setNodeExtent:n=>{const{nodeInternals:r}=t();r.forEach(s=>{s.positionAbsolute=jr(s.position,n)}),e({nodeExtent:n,nodeInternals:new Map(r)})},panBy:n=>{const{transform:r,width:s,height:i,d3Zoom:o,d3Selection:a,translateExtent:l}=t();if(!o||!a||!n.x&&!n.y)return!1;const c=Fe.translate(r[0]+n.x,r[1]+n.y).scale(r[2]),u=[[0,0],[s,i]],d=o==null?void 0:o.constrain()(c,u,l);return o.transform(a,d),r[0]!==d.x||r[1]!==d.y||r[2]!==d.k},cancelConnection:()=>e({connectionNodeId:Ye.connectionNodeId,connectionHandleId:Ye.connectionHandleId,connectionHandleType:Ye.connectionHandleType,connectionStatus:Ye.connectionStatus,connectionStartHandle:Ye.connectionStartHandle,connectionEndHandle:Ye.connectionEndHandle}),reset:()=>e({...Ye})}),Object.is),To=({children:e})=>{const t=w.useRef(null);return t.current||(t.current=Bh()),A.createElement(af,{value:t.current},e)};To.displayName="ReactFlowProvider";const Oo=({children:e})=>w.useContext(An)?A.createElement(A.Fragment,null,e):A.createElement(To,null,e);Oo.displayName="ReactFlowWrapper";const Gh={input:mo,default:mr,output:go,group:Rr},Yh={default:_n,straight:Mr,step:$r,smoothstep:In,simplebezier:Cr},Wh=[0,0],Uh=[15,15],Xh={x:0,y:0,zoom:1},qh={width:"100%",height:"100%",overflow:"hidden",position:"relative",zIndex:0},Do=w.forwardRef(({nodes:e,edges:t,defaultNodes:n,defaultEdges:r,className:s,nodeTypes:i=Gh,edgeTypes:o=Yh,onNodeClick:a,onEdgeClick:l,onInit:c,onMove:u,onMoveStart:d,onMoveEnd:m,onConnect:f,onConnectStart:y,onConnectEnd:p,onClickConnectStart:v,onClickConnectEnd:x,onNodeMouseEnter:_,onNodeMouseMove:M,onNodeMouseLeave:b,onNodeContextMenu:j,onNodeDoubleClick:C,onNodeDragStart:E,onNodeDrag:L,onNodeDragStop:S,onNodesDelete:O,onEdgesDelete:P,onSelectionChange:V,onSelectionDragStart:F,onSelectionDrag:g,onSelectionDragStop:$,onSelectionContextMenu:N,onSelectionStart:I,onSelectionEnd:H,connectionMode:k=ut.Strict,connectionLineType:R=Xe.Bezier,connectionLineStyle:D,connectionLineComponent:z,connectionLineContainerStyle:Y,deleteKeyCode:G="Backspace",selectionKeyCode:K="Shift",selectionOnDrag:J=!1,selectionMode:ee=Yt.Full,panActivationKeyCode:ie="Space",multiSelectionKeyCode:te=wn()?"Meta":"Control",zoomActivationKeyCode:re=wn()?"Meta":"Control",snapToGrid:de=!1,snapGrid:B=Uh,onlyRenderVisibleElements:q=!1,selectNodesOnDrag:W=!0,nodesDraggable:Q,nodesConnectable:U,nodesFocusable:X,nodeOrigin:T=Wh,edgesFocusable:se,edgesUpdatable:ce,elementsSelectable:me,defaultViewport:we=Xh,minZoom:be=.5,maxZoom:Ee=2,translateExtent:Ge=gr,preventScrolling:oe=!0,nodeExtent:Qe,defaultMarkerColor:ft="#b1b1b7",zoomOnScroll:ht=!0,zoomOnPinch:jt=!0,panOnScroll:xe=!1,panOnScrollSpeed:Ce=.5,panOnScrollMode:Je=ot.Free,zoomOnDoubleClick:et=!0,panOnDrag:tt=!0,onPaneClick:De,onPaneMouseEnter:Re,onPaneMouseMove:Ct,onPaneMouseLeave:Dn,onPaneScroll:$t,onPaneContextMenu:Ln,children:Vr,onEdgeContextMenu:nt,onEdgeDoubleClick:_a,onEdgeMouseEnter:Ea,onEdgeMouseMove:Na,onEdgeMouseLeave:Sa,onEdgeUpdate:ka,onEdgeUpdateStart:ja,onEdgeUpdateEnd:Ca,onReconnect:$a,onReconnectStart:Ma,onReconnectEnd:Aa,reconnectRadius:Ia=10,edgeUpdaterRadius:Ra=10,onNodesChange:Ta,onEdgesChange:Oa,noDragClassName:Da="nodrag",noWheelClassName:La="nowheel",noPanClassName:Br="nopan",fitView:Pa=!1,fitViewOptions:za,connectOnClick:Ha=!0,attributionPosition:Fa,proOptions:Va,defaultEdgeOptions:Ba,elevateNodesOnSelect:Ga=!0,elevateEdgesOnSelect:Ya=!1,disableKeyboardA11y:Gr=!1,autoPanOnConnect:Wa=!0,autoPanOnNodeDrag:Ua=!0,connectionRadius:Xa=20,isValidConnection:qa,onError:Ka,style:Za,id:Yr,nodeDragThreshold:Qa,...Ja},el)=>{const Pn=Yr||"1";return A.createElement("div",{...Ja,style:{...Za,...qh},ref:el,className:ye(["react-flow",s]),"data-testid":"rf__wrapper",id:Yr},A.createElement(Oo,null,A.createElement(Vh,{onInit:c,onMove:u,onMoveStart:d,onMoveEnd:m,onNodeClick:a,onEdgeClick:l,onNodeMouseEnter:_,onNodeMouseMove:M,onNodeMouseLeave:b,onNodeContextMenu:j,onNodeDoubleClick:C,nodeTypes:i,edgeTypes:o,connectionLineType:R,connectionLineStyle:D,connectionLineComponent:z,connectionLineContainerStyle:Y,selectionKeyCode:K,selectionOnDrag:J,selectionMode:ee,deleteKeyCode:G,multiSelectionKeyCode:te,panActivationKeyCode:ie,zoomActivationKeyCode:re,onlyRenderVisibleElements:q,selectNodesOnDrag:W,defaultViewport:we,translateExtent:Ge,minZoom:be,maxZoom:Ee,preventScrolling:oe,zoomOnScroll:ht,zoomOnPinch:jt,zoomOnDoubleClick:et,panOnScroll:xe,panOnScrollSpeed:Ce,panOnScrollMode:Je,panOnDrag:tt,onPaneClick:De,onPaneMouseEnter:Re,onPaneMouseMove:Ct,onPaneMouseLeave:Dn,onPaneScroll:$t,onPaneContextMenu:Ln,onSelectionContextMenu:N,onSelectionStart:I,onSelectionEnd:H,onEdgeContextMenu:nt,onEdgeDoubleClick:_a,onEdgeMouseEnter:Ea,onEdgeMouseMove:Na,onEdgeMouseLeave:Sa,onReconnect:$a??ka,onReconnectStart:Ma??ja,onReconnectEnd:Aa??Ca,reconnectRadius:Ia??Ra,defaultMarkerColor:ft,noDragClassName:Da,noWheelClassName:La,noPanClassName:Br,elevateEdgesOnSelect:Ya,rfId:Pn,disableKeyboardA11y:Gr,nodeOrigin:T,nodeExtent:Qe}),A.createElement(Pf,{nodes:e,edges:t,defaultNodes:n,defaultEdges:r,onConnect:f,onConnectStart:y,onConnectEnd:p,onClickConnectStart:v,onClickConnectEnd:x,nodesDraggable:Q,nodesConnectable:U,nodesFocusable:X,edgesFocusable:se,edgesUpdatable:ce,elementsSelectable:me,elevateNodesOnSelect:Ga,minZoom:be,maxZoom:Ee,nodeExtent:Qe,onNodesChange:Ta,onEdgesChange:Oa,snapToGrid:de,snapGrid:B,connectionMode:k,translateExtent:Ge,connectOnClick:Ha,defaultEdgeOptions:Ba,fitView:Pa,fitViewOptions:za,onNodesDelete:O,onEdgesDelete:P,onNodeDragStart:E,onNodeDrag:L,onNodeDragStop:S,onSelectionDrag:g,onSelectionDragStart:F,onSelectionDragStop:$,noPanClassName:Br,nodeOrigin:T,rfId:Pn,autoPanOnConnect:Wa,autoPanOnNodeDrag:Ua,onError:Ka,connectionRadius:Xa,isValidConnection:qa,nodeDragThreshold:Qa}),A.createElement(Df,{onSelectionChange:V}),Vr,A.createElement(cf,{proOptions:Va,position:Fa}),A.createElement(Bf,{rfId:Pn,disableKeyboardA11y:Gr})))});Do.displayName="ReactFlow";const Lo=({id:e,x:t,y:n,width:r,height:s,style:i,color:o,strokeColor:a,strokeWidth:l,className:c,borderRadius:u,shapeRendering:d,onClick:m,selected:f})=>{const{background:y,backgroundColor:p}=i||{},v=o||y||p;return A.createElement("rect",{className:ye(["react-flow__minimap-node",{selected:f},c]),x:t,y:n,rx:u,ry:u,width:r,height:s,fill:v,stroke:a,strokeWidth:l,shapeRendering:d,onClick:m?x=>m(x,e):void 0})};Lo.displayName="MiniMapNode";var Kh=w.memo(Lo);const Zh=e=>e.nodeOrigin,Qh=e=>e.getNodes().filter(t=>!t.hidden&&t.width&&t.height),qn=e=>e instanceof Function?e:()=>e;function Jh({nodeStrokeColor:e="transparent",nodeColor:t="#e2e2e2",nodeClassName:n="",nodeBorderRadius:r=5,nodeStrokeWidth:s=2,nodeComponent:i=Kh,onClick:o}){const a=ae(Qh,ge),l=ae(Zh),c=qn(t),u=qn(e),d=qn(n),m=typeof window>"u"||window.chrome?"crispEdges":"geometricPrecision";return A.createElement(A.Fragment,null,a.map(f=>{const{x:y,y:p}=lt(f,l).positionAbsolute;return A.createElement(i,{key:f.id,x:y,y:p,width:f.width,height:f.height,style:f.style,selected:f.selected,className:d(f),color:c(f),borderRadius:r,strokeColor:u(f),strokeWidth:s,shapeRendering:m,onClick:o,id:f.id})}))}var em=w.memo(Jh);const tm=200,nm=150,rm=e=>{const t=e.getNodes(),n={x:-e.transform[0]/e.transform[2],y:-e.transform[1]/e.transform[2],width:e.width/e.transform[2],height:e.height/e.transform[2]};return{viewBB:n,boundingRect:t.length>0?ff(Kt(t,e.nodeOrigin),n):n,rfId:e.rfId}},sm="react-flow__minimap-desc";function Po({style:e,className:t,nodeStrokeColor:n="transparent",nodeColor:r="#e2e2e2",nodeClassName:s="",nodeBorderRadius:i=5,nodeStrokeWidth:o=2,nodeComponent:a,maskColor:l="rgb(240, 240, 240, 0.6)",maskStrokeColor:c="none",maskStrokeWidth:u=1,position:d="bottom-right",onClick:m,onNodeClick:f,pannable:y=!1,zoomable:p=!1,ariaLabel:v="React Flow mini map",inversePan:x=!1,zoomStep:_=10,offsetScale:M=5}){const b=pe(),j=w.useRef(null),{boundingRect:C,viewBB:E,rfId:L}=ae(rm,ge),S=(e==null?void 0:e.width)??tm,O=(e==null?void 0:e.height)??nm,P=C.width/S,V=C.height/O,F=Math.max(P,V),g=F*S,$=F*O,N=M*F,I=C.x-(g-C.width)/2-N,H=C.y-($-C.height)/2-N,k=g+N*2,R=$+N*2,D=`${sm}-${L}`,z=w.useRef(0);z.current=F,w.useEffect(()=>{if(j.current){const K=Ne(j.current),J=te=>{const{transform:re,d3Selection:de,d3Zoom:B}=b.getState();if(te.sourceEvent.type!=="wheel"||!de||!B)return;const q=-te.sourceEvent.deltaY*(te.sourceEvent.deltaMode===1?.05:te.sourceEvent.deltaMode?1:.002)*_,W=re[2]*Math.pow(2,q);B.scaleTo(de,W)},ee=te=>{const{transform:re,d3Selection:de,d3Zoom:B,translateExtent:q,width:W,height:Q}=b.getState();if(te.sourceEvent.type!=="mousemove"||!de||!B)return;const U=z.current*Math.max(1,re[2])*(x?-1:1),X={x:re[0]-te.sourceEvent.movementX*U,y:re[1]-te.sourceEvent.movementY*U},T=[[0,0],[W,Q]],se=Fe.translate(X.x,X.y).scale(re[2]),ce=B.constrain()(se,T,q);B.transform(de,ce)},ie=Yi().on("zoom",y?ee:null).on("zoom.wheel",p?J:null);return K.call(ie),()=>{K.on("zoom",null)}}},[y,p,x,_]);const Y=m?K=>{const J=$e(K);m(K,{x:J[0],y:J[1]})}:void 0,G=f?(K,J)=>{const ee=b.getState().nodeInternals.get(J);f(K,ee)}:void 0;return A.createElement(Sr,{position:d,style:e,className:ye(["react-flow__minimap",t]),"data-testid":"rf__minimap"},A.createElement("svg",{width:S,height:O,viewBox:`${I} ${H} ${k} ${R}`,role:"img","aria-labelledby":D,ref:j,onClick:Y},v&&A.createElement("title",{id:D},v),A.createElement(em,{onClick:G,nodeColor:r,nodeStrokeColor:n,nodeBorderRadius:i,nodeClassName:s,nodeStrokeWidth:o,nodeComponent:a}),A.createElement("path",{className:"react-flow__minimap-mask",d:`M${I-N},${H-N}h${k+N*2}v${R+N*2}h${-k-N*2}z - M${E.x},${E.y}h${E.width}v${E.height}h${-E.width}z`,fill:l,fillRule:"evenodd",stroke:c,strokeWidth:u,pointerEvents:"none"})))}Po.displayName="MiniMap";var im=w.memo(Po);function om(){return A.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32"},A.createElement("path",{d:"M32 18.133H18.133V32h-4.266V18.133H0v-4.266h13.867V0h4.266v13.867H32z"}))}function am(){return A.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 5"},A.createElement("path",{d:"M0 0h32v4.2H0z"}))}function lm(){return A.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 30"},A.createElement("path",{d:"M3.692 4.63c0-.53.4-.938.939-.938h5.215V0H4.708C2.13 0 0 2.054 0 4.63v5.216h3.692V4.631zM27.354 0h-5.2v3.692h5.17c.53 0 .984.4.984.939v5.215H32V4.631A4.624 4.624 0 0027.354 0zm.954 24.83c0 .532-.4.94-.939.94h-5.215v3.768h5.215c2.577 0 4.631-2.13 4.631-4.707v-5.139h-3.692v5.139zm-23.677.94c-.531 0-.939-.4-.939-.94v-5.138H0v5.139c0 2.577 2.13 4.707 4.708 4.707h5.138V25.77H4.631z"}))}function cm(){return A.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32"},A.createElement("path",{d:"M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0 8 0 4.571 3.429 4.571 7.619v3.048H3.048A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047zm4.724-13.866H7.467V7.619c0-2.59 2.133-4.724 4.723-4.724 2.591 0 4.724 2.133 4.724 4.724v3.048z"}))}function um(){return A.createElement("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32"},A.createElement("path",{d:"M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0c-4.114 1.828-1.37 2.133.305 2.438 1.676.305 4.42 2.59 4.42 5.181v3.048H3.047A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047z"}))}const Lt=({children:e,className:t,...n})=>A.createElement("button",{type:"button",className:ye(["react-flow__controls-button",t]),...n},e);Lt.displayName="ControlButton";const dm=e=>({isInteractive:e.nodesDraggable||e.nodesConnectable||e.elementsSelectable,minZoomReached:e.transform[2]<=e.minZoom,maxZoomReached:e.transform[2]>=e.maxZoom}),zo=({style:e,showZoom:t=!0,showFitView:n=!0,showInteractive:r=!0,fitViewOptions:s,onZoomIn:i,onZoomOut:o,onFitView:a,onInteractiveChange:l,className:c,children:u,position:d="bottom-left"})=>{const m=pe(),[f,y]=w.useState(!1),{isInteractive:p,minZoomReached:v,maxZoomReached:x}=ae(dm,ge),{zoomIn:_,zoomOut:M,fitView:b}=Rn();if(w.useEffect(()=>{y(!0)},[]),!f)return null;const j=()=>{_(),i==null||i()},C=()=>{M(),o==null||o()},E=()=>{b(s),a==null||a()},L=()=>{m.setState({nodesDraggable:!p,nodesConnectable:!p,elementsSelectable:!p}),l==null||l(!p)};return A.createElement(Sr,{className:ye(["react-flow__controls",c]),position:d,style:e,"data-testid":"rf__controls"},t&&A.createElement(A.Fragment,null,A.createElement(Lt,{onClick:j,className:"react-flow__controls-zoomin",title:"zoom in","aria-label":"zoom in",disabled:x},A.createElement(om,null)),A.createElement(Lt,{onClick:C,className:"react-flow__controls-zoomout",title:"zoom out","aria-label":"zoom out",disabled:v},A.createElement(am,null))),n&&A.createElement(Lt,{className:"react-flow__controls-fitview",onClick:E,title:"fit view","aria-label":"fit view"},A.createElement(lm,null)),r&&A.createElement(Lt,{className:"react-flow__controls-interactive",onClick:L,title:"toggle interactivity","aria-label":"toggle interactivity"},p?A.createElement(um,null):A.createElement(cm,null)),u)};zo.displayName="Controls";var fm=w.memo(zo),ke;(function(e){e.Lines="lines",e.Dots="dots",e.Cross="cross"})(ke||(ke={}));function hm({color:e,dimensions:t,lineWidth:n}){return A.createElement("path",{stroke:e,strokeWidth:n,d:`M${t[0]/2} 0 V${t[1]} M0 ${t[1]/2} H${t[0]}`})}function mm({color:e,radius:t}){return A.createElement("circle",{cx:t,cy:t,r:t,fill:e})}const pm={[ke.Dots]:"#91919a",[ke.Lines]:"#eee",[ke.Cross]:"#e2e2e2"},gm={[ke.Dots]:1,[ke.Lines]:1,[ke.Cross]:6},ym=e=>({transform:e.transform,patternId:`pattern-${e.rfId}`});function Ho({id:e,variant:t=ke.Dots,gap:n=20,size:r,lineWidth:s=1,offset:i=2,color:o,style:a,className:l}){const c=w.useRef(null),{transform:u,patternId:d}=ae(ym,ge),m=o||pm[t],f=r||gm[t],y=t===ke.Dots,p=t===ke.Cross,v=Array.isArray(n)?n:[n,n],x=[v[0]*u[2]||1,v[1]*u[2]||1],_=f*u[2],M=p?[_,_]:x,b=y?[_/i,_/i]:[M[0]/i,M[1]/i];return A.createElement("svg",{className:ye(["react-flow__background",l]),style:{...a,position:"absolute",width:"100%",height:"100%",top:0,left:0},ref:c,"data-testid":"rf__background"},A.createElement("pattern",{id:d+e,x:u[0]%x[0],y:u[1]%x[1],width:x[0],height:x[1],patternUnits:"userSpaceOnUse",patternTransform:`translate(-${b[0]},-${b[1]})`},y?A.createElement(mm,{color:m,radius:_/i}):A.createElement(hm,{dimensions:M,color:m,lineWidth:s})),A.createElement("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:`url(#${d+e})`}))}Ho.displayName="Background";var xm=w.memo(Ho);const Or=(()=>{const e=window.location.pathname.match(/^(\/view\/[^/]+)(?:\/|$)/);return e?e[1]:""})();function Fo(e){return Or+e}async function he(e){const t=await fetch(Fo(e));if(!t.ok)throw new Error(`${e}: ${t.status} ${await t.text()}`);return await t.json()}async function Ze(e,t){const n=await fetch(Fo(e),{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}),r=await n.json();if(!n.ok)throw new Vo(r.error??`${e}: ${n.status}`,n.status);return r}class Vo extends Error{constructor(n,r){super(n);ue(this,"status");this.status=r}}const yx=e=>he(e?`/api/model?subject_area=${encodeURIComponent(e)}`:"/api/model"),xx=()=>he("/api/diagnostics"),Bo=(e,t)=>he(`/api/ontology/search?q=${encodeURIComponent(e)}`+(t?`&within=${encodeURIComponent(t)}`:"")),Go=()=>he("/api/ontology/ontologies"),wm=e=>he(`/api/ontology/term?ref=${encodeURIComponent(e)}`),bm=()=>he("/api/ontology/stack"),vm=()=>he("/api/ontology/coverage"),_m=(e,t,n)=>Ze("/api/command",{op:e,payload:t,fingerprint:n??""}),Em=()=>he("/api/git/status"),Nm=()=>he("/api/git/diff"),Sm=e=>Ze("/api/git/commit",{message:e}),km=()=>Ze("/api/git/discard",{}),jm=()=>he("/api/decisions"),Os=(e,t)=>Ze(`/api/decisions/${e}/verdict`,{verdict:t}),wx=(e={})=>{const t=new URLSearchParams;return e.subject_area&&t.set("subject_area",e.subject_area),e.q&&t.set("q",e.q),he(`/api/glossary/terms?${t.toString()}`)},bx=()=>he("/api/glossary/config"),vx=e=>Ze("/api/git/propose",e),_x=(e="HEAD")=>he(`/api/git/diff/model?base=${encodeURIComponent(e)}`),Ex=(e="HEAD")=>he(`/api/git/classify?base=${encodeURIComponent(e)}`),Nx=e=>Ze("/api/git/classify",{changes:e}),Sx=e=>he(`/api/git/conflicts?base=${encodeURIComponent(e)}`),kx=(e="")=>he(`/api/git/context?user=${encodeURIComponent(e)}`),jx=(e="")=>he(`/api/git/proposals?user=${encodeURIComponent(e)}`),Cm=()=>he("/api/export"),$m=(e,t)=>{const n=t?`?dialect=${encodeURIComponent(t)}`:"";return`${Or}/api/export/${encodeURIComponent(e)}${n}`},Mm=(e,t,n)=>Ze("/api/import",{format:e,content:t,dialect:n}),Cx=async e=>{for(const t of e)await _m(t.op,t.payload)},$x=(e,t,n)=>fetch(`${Or}/api/preview`,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({changes:e,subject_area:t??""}),signal:n}).then(async r=>{if(!r.ok)throw new Vo(await r.text(),r.status);return await r.json()}),Mx=()=>he("/api/glossary/subject-areas"),Ax=e=>he(`/api/glossary/subject-area/${e}`),Ix=(e,t)=>Ze(`/api/glossary/subject-area/${e}/expand`,t),Am={business_key:"🔑",surrogate_key:"#",measure:"Σ",attribute:""};function Im(e){return e??""}const Dr="__entity_source",Lr="__entity_target",Rm=w.memo(function({data:t,selected:n}){var C;const{entity:r,color:s,dimmed:i,highlighted:o,showTypes:a,collapseDetail:l,expanded:c,onToggleExpand:u,endpointAttrs:d,highlightAttrs:m,dimAttrs:f,onHoverAttr:y}=t,p=E=>E.role==="business_key"?0:d!=null&&d.has(E.id)?1:2,v=[...r.attributes].map((E,L)=>({a:E,i:L})).sort((E,L)=>p(E.a)-p(L.a)||E.i-L.i).map(E=>E.a),x=v.filter(E=>E.role==="business_key");let _=v.filter(E=>E.role!=="business_key");const M=!!l&&!c;let b=0;if(M){const E=_.filter(L=>d==null?void 0:d.has(L.id));b=_.length-E.length,_=E}const j=(E,L)=>{const S="attr-row"+(m!=null&&m.has(E.id)?" rel-hit":"")+(f!=null&&f.has(E.id)?" rel-dim":"")+(d!=null&&d.has(E.id)?" endpoint":"");return h.jsxs("div",{className:S,onMouseEnter:y?()=>y(E.id):void 0,onMouseLeave:y?()=>y(null):void 0,children:[h.jsx(qe,{id:E.id,type:"target",position:Z.Left,className:"port attr-port"}),h.jsx(qe,{id:E.id,type:"source",position:Z.Right,className:"port attr-port"}),h.jsx("span",{className:"attr-icon",children:Am[E.role]}),h.jsx("span",{className:"attr-name"+(L?" pk":""),children:E.name}),a&&h.jsx("span",{className:"attr-type",children:Im(E.domain)}),!E.nullable&&h.jsx("span",{className:"attr-notnull",title:"not null",children:"●"})]},E.id)};return h.jsxs("div",{className:"entity-node"+(n?" selected":"")+(i?" dimmed":"")+(o?" highlighted":""),style:{borderTopColor:s},children:[h.jsx(qe,{id:Lr,type:"target",position:Z.Left,className:"port"}),h.jsx(qe,{id:Dr,type:"source",position:Z.Right,className:"port"}),h.jsxs("div",{className:"entity-header",children:[h.jsx("span",{className:"entity-name",title:((C=r.conceptual)==null?void 0:C.definition)??void 0,children:r.name}),h.jsxs("span",{className:"entity-badges",children:[r.pattern&&h.jsx("span",{className:"badge pattern",children:r.pattern}),(()=>{var S;const E=(((S=r.conceptual)==null?void 0:S.ontology_refs)??[]).filter(O=>O.uri);if(E.length===0)return null;const L=E.map(O=>O.uri).join(` -`);return h.jsxs("span",{className:"badge ontology",title:L,children:["⚙",E.length>1?` ${E.length}`:""]})})()]})]}),x.length>0&&h.jsx("div",{className:"attr-section keys",children:x.map(E=>j(E,!0))}),h.jsxs("div",{className:"attr-section",children:[_.map(E=>j(E,!1)),r.attributes.length===0&&h.jsx("div",{className:"attr-row empty",children:"no attributes"}),b>0&&h.jsx("div",{className:"attr-row more",title:"Show all columns",onClick:u?()=>u(r.id):void 0,children:`+${b} more`}),c&&!!l&&h.jsx("div",{className:"attr-row more",title:"Collapse to keys",onClick:u?()=>u(r.id):void 0,children:"− collapse"})]})]})}),Tm=["string","integer","bigint","decimal","boolean","date","timestamp"];function Om({entity:e,doc:t,caps:n,exec:r,onClose:s,onFocusEntity:i,onAlign:o,onEditMapping:a}){var m,f,y,p,v,x,_,M,b,j,C,E,L;const l=!n.canEdit,c=e.conceptual,u=t.relationships.filter(S=>S.from.entity===e.id||S.to.entity===e.id),d=S=>{var O;return((O=t.entities.find(P=>P.id===S))==null?void 0:O.name)??S};return h.jsxs("aside",{className:"detail-panel",children:[h.jsxs("div",{className:"detail-header",children:[h.jsxs("div",{style:{flex:1},children:[h.jsx(Pe,{value:e.name,className:"entity-title-input",readOnly:l,onCommit:S=>r("rename_entity",{id:e.id,name:S})}),(e.physical_name||!l)&&h.jsxs("div",{className:"physical-name-row",title:"Physical table name (erwin Physical_Name)",children:[h.jsx("span",{className:"physical-label",children:"physical"}),h.jsx(Pe,{value:e.physical_name??"",className:"physical-name-input",placeholder:l?"—":"physical table name…",readOnly:l,onCommit:S=>r("rename_entity",{id:e.id,physical_name:S})})]}),h.jsxs("div",{children:[h.jsx(Lm,{entity:e,doc:t,readOnly:l,exec:r}),h.jsx(zm,{entity:e,readOnly:l,exec:r}),e.category&&h.jsx("span",{className:"cat-badge "+e.category.role,title:e.category.role==="supertype"?`Supertype of category "${e.category.category}"`:`Subtype in "${e.category.category}" (${e.category.materialization})`,children:e.category.role==="supertype"?"◆ supertype":"◇ subtype"})]})]}),h.jsx("button",{className:"icon-btn",onClick:s,title:"Close",children:"✕"})]}),h.jsxs("section",{children:[h.jsx("h3",{children:"Definition"}),h.jsx(Pe,{value:((m=c==null?void 0:c.definition)==null?void 0:m.trim())??"",multiline:!0,placeholder:l?"—":"add a business definition…",className:"definition-input",readOnly:l,onCommit:S=>r("set_definition",{id:e.id,definition:S})})]}),h.jsxs("section",{children:[h.jsxs("h3",{children:["Ontology",!l&&h.jsxs("span",{className:"h3-actions",children:[h.jsx("button",{className:"mini-btn",onClick:()=>o(e),children:(((f=c==null?void 0:c.ontology_refs)==null?void 0:f.length)??0)>0?"Add / re-align…":"Align…"}),(((y=c==null?void 0:c.ontology_refs)==null?void 0:y.length)??0)>0&&h.jsx("button",{className:"mini-btn danger",onClick:()=>r("clear_alignment",{id:e.id}),title:"Clear every alignment on this object",children:"Clear all"})]})]}),(c==null?void 0:c.ontology_layer)&&h.jsxs("div",{className:"kv",children:[h.jsx("span",{className:"k",children:"layer"}),h.jsx("span",{className:`chip layer-${c.ontology_layer}`,children:c.ontology_layer}),c.no_industry_equivalent&&h.jsx("span",{className:"chip",title:"reviewed: no industry equivalent",children:"no industry equivalent"})]}),h.jsx(Dm,{entityId:e.id,refs:(c==null?void 0:c.ontology_refs)??[],caps:n,exec:r})]}),h.jsxs("section",{children:[h.jsxs("h3",{children:["Knowledge Graph mapping",!l&&h.jsxs("span",{className:"h3-actions",children:[h.jsx("button",{className:"mini-btn",onClick:()=>a(e),children:(p=e.term_map)!=null&&p.subject_template||(v=e.term_map)!=null&&v.class_iri?"Edit mapping…":"Map…"}),(((x=e.term_map)==null?void 0:x.subject_template)||((_=e.term_map)==null?void 0:_.class_iri))&&h.jsx("button",{className:"mini-btn danger",onClick:()=>r("clear_term_map",{id:e.id}),children:"Clear"})]})]}),(M=e.term_map)!=null&&M.subject_template||(b=e.term_map)!=null&&b.class_iri?h.jsxs(h.Fragment,{children:[((j=e.term_map)==null?void 0:j.class_iri)&&h.jsxs("div",{className:"kv",children:[h.jsx("span",{className:"k",children:"class IRI"}),h.jsx("code",{className:"v",children:e.term_map.class_iri})]}),((C=e.term_map)==null?void 0:C.subject_template)&&h.jsxs("div",{className:"kv",children:[h.jsx("span",{className:"k",children:"subject"}),h.jsx("code",{className:"v",children:e.term_map.subject_template})]})]}):h.jsxs("p",{className:"empty-hint",children:["uses the default R2RML term-map (base IRI",t.project.kg_base_iri?` ${t.project.kg_base_iri}`:""," + primary key)"]})]}),h.jsxs("section",{children:[h.jsx("h3",{children:"Stewardship"}),h.jsxs("div",{className:"kv",children:[h.jsx("span",{className:"k",children:"owner"}),h.jsx(Pe,{value:((E=c==null?void 0:c.stewardship)==null?void 0:E.owner)??"",placeholder:"—",readOnly:l,onCommit:S=>{var O;return r("set_stewardship",{id:e.id,owner:S,steward:((O=c==null?void 0:c.stewardship)==null?void 0:O.steward)??null})}})]}),h.jsxs("div",{className:"kv",children:[h.jsx("span",{className:"k",children:"steward"}),h.jsx(Pe,{value:((L=c==null?void 0:c.stewardship)==null?void 0:L.steward)??"",placeholder:"—",readOnly:l,onCommit:S=>{var O;return r("set_stewardship",{id:e.id,owner:((O=c==null?void 0:c.stewardship)==null?void 0:O.owner)??null,steward:S})}})]})]}),h.jsxs("section",{children:[h.jsxs("h3",{children:["Attributes (",e.attributes.length,")"]}),h.jsx("table",{className:"attr-table",children:h.jsx("tbody",{children:e.attributes.map(S=>h.jsx(Fm,{a:S,entity:e,doc:t,readOnly:l,exec:r},S.id))})}),!l&&h.jsx(Vm,{entity:e,exec:r})]}),e.key_groups&&e.key_groups.length>0&&h.jsxs("section",{children:[h.jsxs("h3",{children:["Keys (",e.key_groups.length,")"]}),e.key_groups.map(S=>{const O=S.members.map(P=>{var V;return((V=e.attributes.find(F=>F.id===P))==null?void 0:V.name)??"?"}).join(", ");return h.jsxs("div",{className:"key-row",children:[h.jsx("span",{className:"key-badge "+S.type,children:S.type.toUpperCase()}),h.jsx("span",{className:"key-name",children:S.name}),h.jsx("span",{className:"key-cols",children:O})]},S.id)})]}),e.udp&&Object.keys(e.udp).length>0&&h.jsxs("section",{children:[h.jsx("h3",{children:"Properties (UDP)"}),h.jsx("table",{className:"attr-table",children:h.jsx("tbody",{children:Object.entries(e.udp).map(([S,O])=>h.jsxs("tr",{className:"udp-row",children:[h.jsx("td",{className:"udp-key",children:S}),h.jsx("td",{className:"udp-val",children:String(O)})]},S))})})]}),u.length>0&&h.jsxs("section",{children:[h.jsxs("h3",{children:["Relationships (",u.length,")"]}),u.map(S=>{const O=S.from.entity===e.id?S.to.entity:S.from.entity;return h.jsxs("div",{className:"rel-row",children:[h.jsxs("div",{className:"rel-main",children:[h.jsxs("button",{className:"rel-link",onClick:()=>i(O),children:[h.jsx("span",{className:"rel-card",children:Bm(S,e.id)}),d(O)]}),(S.verb_phrase||S.inverse_verb_phrase||!l)&&h.jsxs("div",{className:"verb-phrases",title:"erwin verb phrases (parent → child, and inverse)",children:[h.jsx(Pe,{value:S.verb_phrase??"",className:"verb-input",placeholder:l?"":"verb phrase…",readOnly:l,onCommit:P=>r("update_relationship",{id:S.id,verb_phrase:P})}),h.jsx("span",{className:"verb-sep",children:"/"}),h.jsx(Pe,{value:S.inverse_verb_phrase??"",className:"verb-input",placeholder:l?"":"inverse…",readOnly:l,onCommit:P=>r("update_relationship",{id:S.id,inverse_verb_phrase:P})})]})]}),!l&&h.jsx("button",{className:"mini-btn danger",title:`delete ${S.name}`,onClick:()=>r("delete_relationship",{id:S.id}),children:"✕"})]},S.id)})]}),h.jsxs("section",{children:[h.jsx("h3",{children:"Identity"}),h.jsx("code",{className:"ulid",title:"Immutable ULID — click to copy",onClick:()=>{var S;return(S=navigator.clipboard)==null?void 0:S.writeText(e.id)},children:e.id}),!l&&h.jsx("div",{style:{marginTop:12},children:h.jsx("button",{className:"mini-btn danger",onClick:()=>{confirm(`Delete entity '${e.name}' (and its relationships)?`)&&r("delete_entity",{id:e.id,cascade:!0}).then(s)},children:"Delete entity…"})})]})]})}function Dm({entityId:e,refs:t,caps:n,exec:r}){const s=!n.canEdit,i=t.filter(o=>o.uri);return i.length===0?h.jsx("p",{className:"empty-hint",children:"not aligned to any ontology term"}):h.jsx("div",{className:"ref-list",children:i.map((o,a)=>{const l=o.status==="proposed";return h.jsxs("div",{className:"ref-card"+(l?" proposed":""),children:[h.jsxs("div",{className:"ref-head",children:[h.jsx("code",{className:"ref-uri",title:o.uri??void 0,children:o.uri}),h.jsx("span",{className:"ref-status "+(l?"proposed":"accepted"),children:l?"proposed":"accepted"})]}),h.jsxs("div",{className:"ref-meta",children:[o.predicate&&h.jsx("span",{className:"ref-pill",children:o.predicate}),o.layer&&h.jsx("span",{className:`chip layer-${o.layer}`,children:o.layer}),o.resolved_via&&h.jsxs("span",{className:"ref-via",title:"resolver that found this term",children:["via ",o.resolved_via]}),typeof o.confidence=="number"&&h.jsxs("span",{className:"ref-via",children:["conf ",Math.round(o.confidence*100),"%"]})]}),!s&&h.jsxs("div",{className:"ref-actions",children:[l&&n.canArbitrate&&h.jsx("button",{className:"mini-btn",onClick:()=>r("promote_alignment",{id:e,uri:o.uri}),title:"Accept this proposed alignment (architect action)",children:"Promote"}),h.jsx("button",{className:"mini-btn danger",onClick:()=>r("clear_alignment",{id:e,uri:o.uri}),title:"Remove this alignment",children:"Remove"})]})]},`${o.uri}-${a}`)})})}function Pe({value:e,onCommit:t,readOnly:n,multiline:r=!1,placeholder:s="",className:i=""}){const[o,a]=w.useState(e);w.useEffect(()=>a(e),[e]);const l=()=>{o.trim()!==e.trim()&&t(o.trim())};return n?h.jsx("span",{className:i,children:e||s}):r?h.jsx("textarea",{className:`edit-input ${i}`,value:o,placeholder:s,rows:3,onChange:c=>a(c.target.value),onBlur:l}):h.jsx("input",{className:`edit-input ${i}`,value:o,placeholder:s,onChange:c=>a(c.target.value),onBlur:l,onKeyDown:c=>c.key==="Enter"&&c.target.blur()})}function Lm({entity:e,doc:t,readOnly:n,exec:r}){var i,o,a;const s=((o=(i=e.conceptual)==null?void 0:i.subject_area)==null?void 0:o.id)??"";return n?(a=e.conceptual)!=null&&a.subject_area?h.jsx("span",{className:"chip",children:e.conceptual.subject_area.name}):null:h.jsxs("select",{className:"chip-select",value:s,onChange:l=>r("set_subject_area",{id:e.id,subject_area:l.target.value||null}),children:[h.jsx("option",{value:"",children:"no subject area"}),t.subject_areas.map(l=>h.jsx("option",{value:l.id,children:l.name},l.id))]})}const Pm=["","scd2","hub","link","satellite","bridge"];function zm({entity:e,readOnly:t,exec:n}){return t?e.pattern?h.jsx("span",{className:"chip pattern",children:e.pattern}):null:h.jsx("select",{className:"chip-select",value:e.pattern??"",onChange:r=>n("set_pattern",{id:e.id,pattern:r.target.value||null}),children:Pm.map(r=>h.jsx("option",{value:r,children:r||"no pattern"},r))})}const Hm=["attribute","business_key","measure","surrogate_key"];function Fm({a:e,entity:t,doc:n,readOnly:r,exec:s}){if(r)return h.jsxs("tr",{children:[h.jsxs("td",{className:e.role==="business_key"?"pk":"",children:[e.name,e.physical_name&&e.physical_name!==e.name&&h.jsx("span",{className:"physical-col",title:"Physical column name",children:e.physical_name}),e.enum_values&&e.enum_values.length>0&&h.jsx("span",{className:"enum-badge",title:`Allowed: ${e.enum_values.join(", ")}`,children:"enum"})]}),h.jsx("td",{className:"type",children:e.domain??""}),h.jsx("td",{className:"null",children:e.nullable?"":"NN"})]});const i=o=>s("update_attribute",{entity_id:t.id,attribute_id:e.id,...o});return h.jsxs("tr",{children:[h.jsxs("td",{className:e.role==="business_key"?"pk":"",children:[h.jsx(Pe,{value:e.name,readOnly:!1,onCommit:o=>i({name:o})}),(e.physical_name||!1)&&h.jsx(Pe,{value:e.physical_name??"",className:"physical-col-input",placeholder:"physical…",readOnly:!1,onCommit:o=>i({physical_name:o})}),e.enum_values&&e.enum_values.length>0&&h.jsx("span",{className:"enum-badge",title:`Allowed: ${e.enum_values.join(", ")}`,children:"enum"})]}),h.jsx("td",{className:"type",children:h.jsx("select",{className:"cell-select",value:e.domain??"string",onChange:o=>i({domain:o.target.value}),children:[...new Set([...Tm,...n.domains??[],e.domain??"string"])].sort().map(o=>h.jsx("option",{value:o,children:o},o))})}),h.jsx("td",{children:h.jsx("select",{className:"cell-select",value:e.role,onChange:o=>i({role:o.target.value}),title:"role",children:Hm.map(o=>h.jsx("option",{value:o,children:o==="business_key"?"🔑 key":o==="measure"?"Σ measure":o},o))})}),h.jsx("td",{className:"null",children:h.jsx("input",{type:"checkbox",checked:!e.nullable,title:"not null",onChange:o=>i({nullable:!o.target.checked})})}),h.jsx("td",{children:h.jsx("button",{className:"mini-btn danger",title:"delete attribute",onClick:()=>s("delete_attribute",{entity_id:t.id,attribute_id:e.id}),children:"✕"})})]})}function Vm({entity:e,exec:t}){const[n,r]=w.useState(""),s=()=>{n.trim()&&t("add_attribute",{entity_id:e.id,name:n,domain:"string"}).then(()=>r(""))};return h.jsxs("div",{className:"add-attr",children:[h.jsx("input",{className:"edit-input",placeholder:"+ add attribute…",value:n,onChange:i=>r(i.target.value),onKeyDown:i=>i.key==="Enter"&&s()}),n&&h.jsx("button",{className:"mini-btn",onClick:s,children:"Add"})]})}function Bm(e,t){const n=e.from.entity===t;switch(e.cardinality){case"many_to_one":return n?"N:1 →":"1:N ←";case"one_to_many":return n?"1:N →":"N:1 ←";case"one_to_one":return"1:1";default:return"N:M"}}var Gm="\0",rt="\0",Ds="";let Ym=class{constructor(t){ue(this,"_isDirected",!0);ue(this,"_isMultigraph",!1);ue(this,"_isCompound",!1);ue(this,"_label");ue(this,"_defaultNodeLabelFn",()=>{});ue(this,"_defaultEdgeLabelFn",()=>{});ue(this,"_nodes",{});ue(this,"_in",{});ue(this,"_preds",{});ue(this,"_out",{});ue(this,"_sucs",{});ue(this,"_edgeObjs",{});ue(this,"_edgeLabels",{});ue(this,"_nodeCount",0);ue(this,"_edgeCount",0);ue(this,"_parent");ue(this,"_children");t&&(this._isDirected=Object.hasOwn(t,"directed")?t.directed:!0,this._isMultigraph=Object.hasOwn(t,"multigraph")?t.multigraph:!1,this._isCompound=Object.hasOwn(t,"compound")?t.compound:!1),this._isCompound&&(this._parent={},this._children={},this._children[rt]={})}isDirected(){return this._isDirected}isMultigraph(){return this._isMultigraph}isCompound(){return this._isCompound}setGraph(t){return this._label=t,this}graph(){return this._label}setDefaultNodeLabel(t){return this._defaultNodeLabelFn=t,typeof t!="function"&&(this._defaultNodeLabelFn=()=>t),this}nodeCount(){return this._nodeCount}nodes(){return Object.keys(this._nodes)}sources(){var t=this;return this.nodes().filter(n=>Object.keys(t._in[n]).length===0)}sinks(){var t=this;return this.nodes().filter(n=>Object.keys(t._out[n]).length===0)}setNodes(t,n){var r=arguments,s=this;return t.forEach(function(i){r.length>1?s.setNode(i,n):s.setNode(i)}),this}setNode(t,n){return Object.hasOwn(this._nodes,t)?(arguments.length>1&&(this._nodes[t]=n),this):(this._nodes[t]=arguments.length>1?n:this._defaultNodeLabelFn(t),this._isCompound&&(this._parent[t]=rt,this._children[t]={},this._children[rt][t]=!0),this._in[t]={},this._preds[t]={},this._out[t]={},this._sucs[t]={},++this._nodeCount,this)}node(t){return this._nodes[t]}hasNode(t){return Object.hasOwn(this._nodes,t)}removeNode(t){var n=this;if(Object.hasOwn(this._nodes,t)){var r=s=>n.removeEdge(n._edgeObjs[s]);delete this._nodes[t],this._isCompound&&(this._removeFromParentsChildList(t),delete this._parent[t],this.children(t).forEach(function(s){n.setParent(s)}),delete this._children[t]),Object.keys(this._in[t]).forEach(r),delete this._in[t],delete this._preds[t],Object.keys(this._out[t]).forEach(r),delete this._out[t],delete this._sucs[t],--this._nodeCount}return this}setParent(t,n){if(!this._isCompound)throw new Error("Cannot set parent in a non-compound graph");if(n===void 0)n=rt;else{n+="";for(var r=n;r!==void 0;r=this.parent(r))if(r===t)throw new Error("Setting "+n+" as parent of "+t+" would create a cycle");this.setNode(n)}return this.setNode(t),this._removeFromParentsChildList(t),this._parent[t]=n,this._children[n][t]=!0,this}_removeFromParentsChildList(t){delete this._children[this._parent[t]][t]}parent(t){if(this._isCompound){var n=this._parent[t];if(n!==rt)return n}}children(t=rt){if(this._isCompound){var n=this._children[t];if(n)return Object.keys(n)}else{if(t===rt)return this.nodes();if(this.hasNode(t))return[]}}predecessors(t){var n=this._preds[t];if(n)return Object.keys(n)}successors(t){var n=this._sucs[t];if(n)return Object.keys(n)}neighbors(t){var n=this.predecessors(t);if(n){const s=new Set(n);for(var r of this.successors(t))s.add(r);return Array.from(s.values())}}isLeaf(t){var n;return this.isDirected()?n=this.successors(t):n=this.neighbors(t),n.length===0}filterNodes(t){var n=new this.constructor({directed:this._isDirected,multigraph:this._isMultigraph,compound:this._isCompound});n.setGraph(this.graph());var r=this;Object.entries(this._nodes).forEach(function([o,a]){t(o)&&n.setNode(o,a)}),Object.values(this._edgeObjs).forEach(function(o){n.hasNode(o.v)&&n.hasNode(o.w)&&n.setEdge(o,r.edge(o))});var s={};function i(o){var a=r.parent(o);return a===void 0||n.hasNode(a)?(s[o]=a,a):a in s?s[a]:i(a)}return this._isCompound&&n.nodes().forEach(o=>n.setParent(o,i(o))),n}setDefaultEdgeLabel(t){return this._defaultEdgeLabelFn=t,typeof t!="function"&&(this._defaultEdgeLabelFn=()=>t),this}edgeCount(){return this._edgeCount}edges(){return Object.values(this._edgeObjs)}setPath(t,n){var r=this,s=arguments;return t.reduce(function(i,o){return s.length>1?r.setEdge(i,o,n):r.setEdge(i,o),o}),this}setEdge(){var t,n,r,s,i=!1,o=arguments[0];typeof o=="object"&&o!==null&&"v"in o?(t=o.v,n=o.w,r=o.name,arguments.length===2&&(s=arguments[1],i=!0)):(t=o,n=arguments[1],r=arguments[3],arguments.length>2&&(s=arguments[2],i=!0)),t=""+t,n=""+n,r!==void 0&&(r=""+r);var a=Pt(this._isDirected,t,n,r);if(Object.hasOwn(this._edgeLabels,a))return i&&(this._edgeLabels[a]=s),this;if(r!==void 0&&!this._isMultigraph)throw new Error("Cannot set a named edge when isMultigraph = false");this.setNode(t),this.setNode(n),this._edgeLabels[a]=i?s:this._defaultEdgeLabelFn(t,n,r);var l=Wm(this._isDirected,t,n,r);return t=l.v,n=l.w,Object.freeze(l),this._edgeObjs[a]=l,Ls(this._preds[n],t),Ls(this._sucs[t],n),this._in[n][a]=l,this._out[t][a]=l,this._edgeCount++,this}edge(t,n,r){var s=arguments.length===1?Kn(this._isDirected,arguments[0]):Pt(this._isDirected,t,n,r);return this._edgeLabels[s]}edgeAsObj(){const t=this.edge(...arguments);return typeof t!="object"?{label:t}:t}hasEdge(t,n,r){var s=arguments.length===1?Kn(this._isDirected,arguments[0]):Pt(this._isDirected,t,n,r);return Object.hasOwn(this._edgeLabels,s)}removeEdge(t,n,r){var s=arguments.length===1?Kn(this._isDirected,arguments[0]):Pt(this._isDirected,t,n,r),i=this._edgeObjs[s];return i&&(t=i.v,n=i.w,delete this._edgeLabels[s],delete this._edgeObjs[s],Ps(this._preds[n],t),Ps(this._sucs[t],n),delete this._in[n][s],delete this._out[t][s],this._edgeCount--),this}inEdges(t,n){var r=this._in[t];if(r){var s=Object.values(r);return n?s.filter(i=>i.v===n):s}}outEdges(t,n){var r=this._out[t];if(r){var s=Object.values(r);return n?s.filter(i=>i.w===n):s}}nodeEdges(t,n){var r=this.inEdges(t,n);if(r)return r.concat(this.outEdges(t,n))}};function Ls(e,t){e[t]?e[t]++:e[t]=1}function Ps(e,t){--e[t]||delete e[t]}function Pt(e,t,n,r){var s=""+t,i=""+n;if(!e&&s>i){var o=s;s=i,i=o}return s+Ds+i+Ds+(r===void 0?Gm:r)}function Wm(e,t,n,r){var s=""+t,i=""+n;if(!e&&s>i){var o=s;s=i,i=o}var a={v:s,w:i};return r&&(a.name=r),a}function Kn(e,t){return Pt(e,t.v,t.w,t.name)}var Pr=Ym,Um="2.2.4",Xm={Graph:Pr,version:Um},qm=Pr,Km={write:Zm,read:ep};function Zm(e){var t={options:{directed:e.isDirected(),multigraph:e.isMultigraph(),compound:e.isCompound()},nodes:Qm(e),edges:Jm(e)};return e.graph()!==void 0&&(t.value=structuredClone(e.graph())),t}function Qm(e){return e.nodes().map(function(t){var n=e.node(t),r=e.parent(t),s={v:t};return n!==void 0&&(s.value=n),r!==void 0&&(s.parent=r),s})}function Jm(e){return e.edges().map(function(t){var n=e.edge(t),r={v:t.v,w:t.w};return t.name!==void 0&&(r.name=t.name),n!==void 0&&(r.value=n),r})}function ep(e){var t=new qm(e.options).setGraph(e.value);return e.nodes.forEach(function(n){t.setNode(n.v,n.value),n.parent&&t.setParent(n.v,n.parent)}),e.edges.forEach(function(n){t.setEdge({v:n.v,w:n.w,name:n.name},n.value)}),t}var tp=np;function np(e){var t={},n=[],r;function s(i){Object.hasOwn(t,i)||(t[i]=!0,r.push(i),e.successors(i).forEach(s),e.predecessors(i).forEach(s))}return e.nodes().forEach(function(i){r=[],s(i),r.length&&n.push(r)}),n}let rp=class{constructor(){ue(this,"_arr",[]);ue(this,"_keyIndices",{})}size(){return this._arr.length}keys(){return this._arr.map(function(t){return t.key})}has(t){return Object.hasOwn(this._keyIndices,t)}priority(t){var n=this._keyIndices[t];if(n!==void 0)return this._arr[n].priority}min(){if(this.size()===0)throw new Error("Queue underflow");return this._arr[0].key}add(t,n){var r=this._keyIndices;if(t=String(t),!Object.hasOwn(r,t)){var s=this._arr,i=s.length;return r[t]=i,s.push({key:t,priority:n}),this._decrease(i),!0}return!1}removeMin(){this._swap(0,this._arr.length-1);var t=this._arr.pop();return delete this._keyIndices[t.key],this._heapify(0),t.key}decrease(t,n){var r=this._keyIndices[t];if(n>this._arr[r].priority)throw new Error("New priority is greater than current priority. Key: "+t+" Old: "+this._arr[r].priority+" New: "+n);this._arr[r].priority=n,this._decrease(r)}_heapify(t){var n=this._arr,r=2*t,s=r+1,i=t;r>1,!(n[s].priority1;function op(e,t,n,r){return ap(e,String(t),n||ip,r||function(s){return e.outEdges(s)})}function ap(e,t,n,r){var s={},i=new sp,o,a,l=function(c){var u=c.v!==o?c.v:c.w,d=s[u],m=n(c),f=a.distance+m;if(m<0)throw new Error("dijkstra does not allow negative edge weights. Bad edge: "+c+" Weight: "+m);f0&&(o=i.removeMin(),a=s[o],a.distance!==Number.POSITIVE_INFINITY);)r(o).forEach(l);return s}var lp=Wo,cp=up;function up(e,t,n){return e.nodes().reduce(function(r,s){return r[s]=lp(e,s,t,n),r},{})}var Uo=dp;function dp(e){var t=0,n=[],r={},s=[];function i(o){var a=r[o]={onStack:!0,lowlink:t,index:t++};if(n.push(o),e.successors(o).forEach(function(u){Object.hasOwn(r,u)?r[u].onStack&&(a.lowlink=Math.min(a.lowlink,r[u].index)):(i(u),a.lowlink=Math.min(a.lowlink,r[u].lowlink))}),a.lowlink===a.index){var l=[],c;do c=n.pop(),r[c].onStack=!1,l.push(c);while(o!==c);s.push(l)}}return e.nodes().forEach(function(o){Object.hasOwn(r,o)||i(o)}),s}var fp=Uo,hp=mp;function mp(e){return fp(e).filter(function(t){return t.length>1||t.length===1&&e.hasEdge(t[0],t[0])})}var pp=yp,gp=()=>1;function yp(e,t,n){return xp(e,t||gp,n||function(r){return e.outEdges(r)})}function xp(e,t,n){var r={},s=e.nodes();return s.forEach(function(i){r[i]={},r[i][i]={distance:0},s.forEach(function(o){i!==o&&(r[i][o]={distance:Number.POSITIVE_INFINITY})}),n(i).forEach(function(o){var a=o.v===i?o.w:o.v,l=t(o);r[i][a]={distance:l,predecessor:i}})}),s.forEach(function(i){var o=r[i];s.forEach(function(a){var l=r[a];s.forEach(function(c){var u=l[i],d=o[c],m=l[c],f=u.distance+d.distance;fe.successors(a):a=>e.neighbors(a),s=n==="post"?_p:Ep,i=[],o={};return t.forEach(a=>{if(!e.hasNode(a))throw new Error("Graph does not have node: "+a);s(a,r,o,i)}),i}function _p(e,t,n,r){for(var s=[[e,!1]];s.length>0;){var i=s.pop();i[1]?r.push(i[0]):Object.hasOwn(n,i[0])||(n[i[0]]=!0,s.push([i[0],!0]),Zo(t(i[0]),o=>s.push([o,!1])))}}function Ep(e,t,n,r){for(var s=[e];s.length>0;){var i=s.pop();Object.hasOwn(n,i)||(n[i]=!0,r.push(i),Zo(t(i),o=>s.push(o)))}}function Zo(e,t){for(var n=e.length;n--;)t(e[n],n,e);return e}var Np=Ko,Sp=kp;function kp(e,t){return Np(e,t,"post")}var jp=Ko,Cp=$p;function $p(e,t){return jp(e,t,"pre")}var Mp=Pr,Ap=Yo,Ip=Rp;function Rp(e,t){var n=new Mp,r={},s=new Ap,i;function o(l){var c=l.v===i?l.w:l.v,u=s.priority(c);if(u!==void 0){var d=t(l);d0;){if(i=s.removeMin(),Object.hasOwn(r,i))n.setEdge(i,r[i]);else{if(a)throw new Error("Input graph is not connected: "+e);a=!0}e.nodeEdges(i).forEach(o)}return n}var Tp={components:tp,dijkstra:Wo,dijkstraAll:cp,findCycles:hp,floydWarshall:pp,isAcyclic:wp,postorder:Sp,preorder:Cp,prim:Ip,tarjan:Uo,topsort:qo},Hs=Xm,Ie={Graph:Hs.Graph,json:Km,alg:Tp,version:Hs.version};let Op=class{constructor(){let t={};t._next=t._prev=t,this._sentinel=t}dequeue(){let t=this._sentinel,n=t._prev;if(n!==t)return Fs(n),n}enqueue(t){let n=this._sentinel;t._prev&&t._next&&Fs(t),t._next=n._next,n._next._prev=t,n._next=t,t._prev=n}toString(){let t=[],n=this._sentinel,r=n._prev;for(;r!==n;)t.push(JSON.stringify(r,Dp)),r=r._prev;return"["+t.join(", ")+"]"}};function Fs(e){e._prev._next=e._next,e._next._prev=e._prev,delete e._next,delete e._prev}function Dp(e,t){if(e!=="_next"&&e!=="_prev")return t}var Lp=Op;let Pp=Ie.Graph,zp=Lp;var Hp=Vp;let Fp=()=>1;function Vp(e,t){if(e.nodeCount()<=1)return[];let n=Gp(e,t||Fp);return Bp(n.graph,n.buckets,n.zeroIdx).flatMap(s=>e.outEdges(s.v,s.w))}function Bp(e,t,n){let r=[],s=t[t.length-1],i=t[0],o;for(;e.nodeCount();){for(;o=i.dequeue();)Zn(e,t,n,o);for(;o=s.dequeue();)Zn(e,t,n,o);if(e.nodeCount()){for(let a=t.length-2;a>0;--a)if(o=t[a].dequeue(),o){r=r.concat(Zn(e,t,n,o,!0));break}}}return r}function Zn(e,t,n,r,s){let i=s?[]:void 0;return e.inEdges(r.v).forEach(o=>{let a=e.edge(o),l=e.node(o.v);s&&i.push({v:o.v,w:o.w}),l.out-=a,xr(t,n,l)}),e.outEdges(r.v).forEach(o=>{let a=e.edge(o),l=o.w,c=e.node(l);c.in-=a,xr(t,n,c)}),e.removeNode(r.v),i}function Gp(e,t){let n=new Pp,r=0,s=0;e.nodes().forEach(a=>{n.setNode(a,{v:a,in:0,out:0})}),e.edges().forEach(a=>{let l=n.edge(a.v,a.w)||0,c=t(a),u=l+c;n.setEdge(a.v,a.w,u),s=Math.max(s,n.node(a.v).out+=c),r=Math.max(r,n.node(a.w).in+=c)});let i=Yp(s+r+3).map(()=>new zp),o=r+1;return n.nodes().forEach(a=>{xr(i,o,n.node(a))}),{graph:n,buckets:i,zeroIdx:o}}function xr(e,t,n){n.out?n.in?e[n.out-n.in+t].enqueue(n):e[e.length-1].enqueue(n):e[0].enqueue(n)}function Yp(e){const t=[];for(let n=0;nt.setNode(n,e.node(n))),e.edges().forEach(n=>{let r=t.edge(n.v,n.w)||{weight:0,minlen:1},s=e.edge(n);t.setEdge(n.v,n.w,{weight:r.weight+s.weight,minlen:Math.max(r.minlen,s.minlen)})}),t}function Up(e){let t=new Qo({multigraph:e.isMultigraph()}).setGraph(e.graph());return e.nodes().forEach(n=>{e.children(n).length||t.setNode(n,e.node(n))}),e.edges().forEach(n=>{t.setEdge(n,e.edge(n))}),t}function Xp(e){let t=e.nodes().map(n=>{let r={};return e.outEdges(n).forEach(s=>{r[s.w]=(r[s.w]||0)+e.edge(s).weight}),r});return zr(e.nodes(),t)}function qp(e){let t=e.nodes().map(n=>{let r={};return e.inEdges(n).forEach(s=>{r[s.v]=(r[s.v]||0)+e.edge(s).weight}),r});return zr(e.nodes(),t)}function Kp(e,t){let n=e.x,r=e.y,s=t.x-n,i=t.y-r,o=e.width/2,a=e.height/2;if(!s&&!i)throw new Error("Not possible to find intersection inside of the rectangle");let l,c;return Math.abs(i)*o>Math.abs(s)*a?(i<0&&(a=-a),l=a*s/i,c=a):(s<0&&(o=-o),l=o,c=o*i/s),{x:n+l,y:r+c}}function Zp(e){let t=ra(ta(e)+1).map(()=>[]);return e.nodes().forEach(n=>{let r=e.node(n),s=r.rank;s!==void 0&&(t[s][r.order]=n)}),t}function Qp(e){let t=e.nodes().map(r=>{let s=e.node(r).rank;return s===void 0?Number.MAX_VALUE:s}),n=Tn(Math.min,t);e.nodes().forEach(r=>{let s=e.node(r);Object.hasOwn(s,"rank")&&(s.rank-=n)})}function Jp(e){let t=e.nodes().map(o=>e.node(o).rank),n=Tn(Math.min,t),r=[];e.nodes().forEach(o=>{let a=e.node(o).rank-n;r[a]||(r[a]=[]),r[a].push(o)});let s=0,i=e.graph().nodeRankFactor;Array.from(r).forEach((o,a)=>{o===void 0&&a%i!==0?--s:o!==void 0&&s&&o.forEach(l=>e.node(l).rank+=s)})}function eg(e,t,n,r){let s={width:0,height:0};return arguments.length>=4&&(s.rank=n,s.order=r),Jo(e,"border",s,t)}function tg(e,t=ea){const n=[];for(let r=0;rea){const n=tg(t);return e.apply(null,n.map(r=>e.apply(null,r)))}else return e.apply(null,t)}function ta(e){const n=e.nodes().map(r=>{let s=e.node(r).rank;return s===void 0?Number.MIN_VALUE:s});return Tn(Math.max,n)}function ng(e,t){let n={lhs:[],rhs:[]};return e.forEach(r=>{t(r)?n.lhs.push(r):n.rhs.push(r)}),n}function rg(e,t){let n=Date.now();try{return t()}finally{console.log(e+" time: "+(Date.now()-n)+"ms")}}function sg(e,t){return t()}let ig=0;function na(e){var t=++ig;return e+(""+t)}function ra(e,t,n=1){t==null&&(t=e,e=0);let r=i=>itr[t]),Object.entries(e).reduce((r,[s,i])=>(r[s]=n(i,s),r),{})}function zr(e,t){return e.reduce((n,r,s)=>(n[r]=t[s],n),{})}let lg=Hp,cg=fe.uniqueId;var ug={run:dg,undo:hg};function dg(e){(e.graph().acyclicer==="greedy"?lg(e,n(e)):fg(e)).forEach(r=>{let s=e.edge(r);e.removeEdge(r),s.forwardName=r.name,s.reversed=!0,e.setEdge(r.w,r.v,s,cg("rev"))});function n(r){return s=>r.edge(s).weight}}function fg(e){let t=[],n={},r={};function s(i){Object.hasOwn(r,i)||(r[i]=!0,n[i]=!0,e.outEdges(i).forEach(o=>{Object.hasOwn(n,o.w)?t.push(o):s(o.w)}),delete n[i])}return e.nodes().forEach(s),t}function hg(e){e.edges().forEach(t=>{let n=e.edge(t);if(n.reversed){e.removeEdge(t);let r=n.forwardName;delete n.reversed,delete n.forwardName,e.setEdge(t.w,t.v,n,r)}})}let mg=fe;var pg={run:gg,undo:xg};function gg(e){e.graph().dummyChains=[],e.edges().forEach(t=>yg(e,t))}function yg(e,t){let n=t.v,r=e.node(n).rank,s=t.w,i=e.node(s).rank,o=t.name,a=e.edge(t),l=a.labelRank;if(i===r+1)return;e.removeEdge(t);let c,u,d;for(d=0,++r;r{let n=e.node(t),r=n.edgeLabel,s;for(e.setEdge(n.edgeObj,r);n.dummy;)s=e.successors(t)[0],e.removeNode(t),r.points.push({x:n.x,y:n.y}),n.dummy==="edge-label"&&(r.x=n.x,r.y=n.y,r.width=n.width,r.height=n.height),t=s,n=e.node(t)})}const{applyWithChunking:wg}=fe;var On={longestPath:bg,slack:vg};function bg(e){var t={};function n(r){var s=e.node(r);if(Object.hasOwn(t,r))return s.rank;t[r]=!0;let i=e.outEdges(r).map(a=>a==null?Number.POSITIVE_INFINITY:n(a.w)-e.edge(a).minlen);var o=wg(Math.min,i);return o===Number.POSITIVE_INFINITY&&(o=0),s.rank=o}e.sources().forEach(n)}function vg(e,t){return e.node(t.w).rank-e.node(t.v).rank-e.edge(t).minlen}var _g=Ie.Graph,En=On.slack,sa=Eg;function Eg(e){var t=new _g({directed:!1}),n=e.nodes()[0],r=e.nodeCount();t.setNode(n,{});for(var s,i;Ng(t,e){var i=s.v,o=r===i?s.w:i;!e.hasNode(o)&&!En(t,s)&&(e.setNode(o,{}),e.setEdge(r,o,{}),n(o))})}return e.nodes().forEach(n),e.nodeCount()}function Sg(e,t){return t.edges().reduce((r,s)=>{let i=Number.POSITIVE_INFINITY;return e.hasNode(s.v)!==e.hasNode(s.w)&&(i=En(t,s)),it.node(r).rank+=n)}var jg=sa,Vs=On.slack,Cg=On.longestPath,$g=Ie.alg.preorder,Mg=Ie.alg.postorder,Ag=fe.simplify,Ig=dt;dt.initLowLimValues=Fr;dt.initCutValues=Hr;dt.calcCutValue=ia;dt.leaveEdge=aa;dt.enterEdge=la;dt.exchangeEdges=ca;function dt(e){e=Ag(e),Cg(e);var t=jg(e);Fr(t),Hr(t,e);for(var n,r;n=aa(t);)r=la(t,e,n),ca(t,e,n,r)}function Hr(e,t){var n=Mg(e,e.nodes());n=n.slice(0,n.length-1),n.forEach(r=>Rg(e,t,r))}function Rg(e,t,n){var r=e.node(n),s=r.parent;e.edge(n,s).cutvalue=ia(e,t,n)}function ia(e,t,n){var r=e.node(n),s=r.parent,i=!0,o=t.edge(n,s),a=0;return o||(i=!1,o=t.edge(s,n)),a=o.weight,t.nodeEdges(n).forEach(l=>{var c=l.v===n,u=c?l.w:l.v;if(u!==s){var d=c===i,m=t.edge(l).weight;if(a+=d?m:-m,Og(e,n,u)){var f=e.edge(n,u).cutvalue;a+=d?-f:f}}}),a}function Fr(e,t){arguments.length<2&&(t=e.nodes()[0]),oa(e,{},1,t)}function oa(e,t,n,r,s){var i=n,o=e.node(r);return t[r]=!0,e.neighbors(r).forEach(a=>{Object.hasOwn(t,a)||(n=oa(e,t,n,a,r))}),o.low=i,o.lim=n++,s?o.parent=s:delete o.parent,n}function aa(e){return e.edges().find(t=>e.edge(t).cutvalue<0)}function la(e,t,n){var r=n.v,s=n.w;t.hasEdge(r,s)||(r=n.w,s=n.v);var i=e.node(r),o=e.node(s),a=i,l=!1;i.lim>o.lim&&(a=o,l=!0);var c=t.edges().filter(u=>l===Bs(e,e.node(u.v),a)&&l!==Bs(e,e.node(u.w),a));return c.reduce((u,d)=>Vs(t,d)!t.node(s).parent),r=$g(e,n);r=r.slice(1),r.forEach(s=>{var i=e.node(s).parent,o=t.edge(s,i),a=!1;o||(o=t.edge(i,s),a=!0),t.node(s).rank=t.node(i).rank+(a?o.minlen:-o.minlen)})}function Og(e,t,n){return e.hasEdge(t,n)}function Bs(e,t,n){return n.low<=t.lim&&t.lim<=n.lim}var Dg=On,ua=Dg.longestPath,Lg=sa,Pg=Ig,zg=Hg;function Hg(e){var t=e.graph().ranker;if(t instanceof Function)return t(e);switch(e.graph().ranker){case"network-simplex":Gs(e);break;case"tight-tree":Vg(e);break;case"longest-path":Fg(e);break;case"none":break;default:Gs(e)}}var Fg=ua;function Vg(e){ua(e),Lg(e)}function Gs(e){Pg(e)}var Bg=Gg;function Gg(e){let t=Wg(e);e.graph().dummyChains.forEach(n=>{let r=e.node(n),s=r.edgeObj,i=Yg(e,t,s.v,s.w),o=i.path,a=i.lca,l=0,c=o[l],u=!0;for(;n!==s.w;){if(r=e.node(n),u){for(;(c=o[l])!==a&&e.node(c).maxRanko||a>t[l].lim));for(c=l,l=r;(l=e.parent(l))!==c;)i.push(l);return{path:s.concat(i.reverse()),lca:c}}function Wg(e){let t={},n=0;function r(s){let i=n;e.children(s).forEach(r),t[s]={low:i,lim:n++}}return e.children().forEach(r),t}let Nn=fe;var Ug={run:Xg,cleanup:Zg};function Xg(e){let t=Nn.addDummyNode(e,"root",{},"_root"),n=qg(e),r=Object.values(n),s=Nn.applyWithChunking(Math.max,r)-1,i=2*s+1;e.graph().nestingRoot=t,e.edges().forEach(a=>e.edge(a).minlen*=i);let o=Kg(e)+1;e.children().forEach(a=>da(e,t,i,o,s,n,a)),e.graph().nodeRankFactor=i}function da(e,t,n,r,s,i,o){let a=e.children(o);if(!a.length){o!==t&&e.setEdge(t,o,{weight:0,minlen:n});return}let l=Nn.addBorderNode(e,"_bt"),c=Nn.addBorderNode(e,"_bb"),u=e.node(o);e.setParent(l,o),u.borderTop=l,e.setParent(c,o),u.borderBottom=c,a.forEach(d=>{da(e,t,n,r,s,i,d);let m=e.node(d),f=m.borderTop?m.borderTop:d,y=m.borderBottom?m.borderBottom:d,p=m.borderTop?r:2*r,v=f!==y?1:s-i[o]+1;e.setEdge(l,f,{weight:p,minlen:v,nestingEdge:!0}),e.setEdge(y,c,{weight:p,minlen:v,nestingEdge:!0})}),e.parent(o)||e.setEdge(t,l,{weight:0,minlen:s+i[o]})}function qg(e){var t={};function n(r,s){var i=e.children(r);i&&i.length&&i.forEach(o=>n(o,s+1)),t[r]=s}return e.children().forEach(r=>n(r,1)),t}function Kg(e){return e.edges().reduce((t,n)=>t+e.edge(n).weight,0)}function Zg(e){var t=e.graph();e.removeNode(t.nestingRoot),delete t.nestingRoot,e.edges().forEach(n=>{var r=e.edge(n);r.nestingEdge&&e.removeEdge(n)})}let Qg=fe;var Jg=e0;function e0(e){function t(n){let r=e.children(n),s=e.node(n);if(r.length&&r.forEach(t),Object.hasOwn(s,"minRank")){s.borderLeft=[],s.borderRight=[];for(let i=s.minRank,o=s.maxRank+1;iWs(e.node(t))),e.edges().forEach(t=>Ws(e.edge(t)))}function Ws(e){let t=e.width;e.width=e.height,e.height=t}function s0(e){e.nodes().forEach(t=>Qn(e.node(t))),e.edges().forEach(t=>{let n=e.edge(t);n.points.forEach(Qn),Object.hasOwn(n,"y")&&Qn(n)})}function Qn(e){e.y=-e.y}function i0(e){e.nodes().forEach(t=>Jn(e.node(t))),e.edges().forEach(t=>{let n=e.edge(t);n.points.forEach(Jn),Object.hasOwn(n,"x")&&Jn(n)})}function Jn(e){let t=e.x;e.x=e.y,e.y=t}let Us=fe;var o0=a0;function a0(e){let t={},n=e.nodes().filter(l=>!e.children(l).length),r=n.map(l=>e.node(l).rank),s=Us.applyWithChunking(Math.max,r),i=Us.range(s+1).map(()=>[]);function o(l){if(t[l])return;t[l]=!0;let c=e.node(l);i[c.rank].push(l),e.successors(l).forEach(o)}return n.sort((l,c)=>e.node(l).rank-e.node(c).rank).forEach(o),i}let l0=fe.zipObject;var c0=u0;function u0(e,t){let n=0;for(let r=1;ru)),s=t.flatMap(c=>e.outEdges(c).map(u=>({pos:r[u.w],weight:e.edge(u).weight})).sort((u,d)=>u.pos-d.pos)),i=1;for(;i{let u=c.pos+i;a[u]+=c.weight;let d=0;for(;u>0;)u%2&&(d+=a[u+1]),u=u-1>>1,a[u]+=c.weight;l+=c.weight*d}),l}var f0=h0;function h0(e,t=[]){return t.map(n=>{let r=e.inEdges(n);if(r.length){let s=r.reduce((i,o)=>{let a=e.edge(o),l=e.node(o.v);return{sum:i.sum+a.weight*l.order,weight:i.weight+a.weight}},{sum:0,weight:0});return{v:n,barycenter:s.sum/s.weight,weight:s.weight}}else return{v:n}})}let m0=fe;var p0=g0;function g0(e,t){let n={};e.forEach((s,i)=>{let o=n[s.v]={indegree:0,in:[],out:[],vs:[s.v],i};s.barycenter!==void 0&&(o.barycenter=s.barycenter,o.weight=s.weight)}),t.edges().forEach(s=>{let i=n[s.v],o=n[s.w];i!==void 0&&o!==void 0&&(o.indegree++,i.out.push(n[s.w]))});let r=Object.values(n).filter(s=>!s.indegree);return y0(r)}function y0(e){let t=[];function n(s){return i=>{i.merged||(i.barycenter===void 0||s.barycenter===void 0||i.barycenter>=s.barycenter)&&x0(s,i)}}function r(s){return i=>{i.in.push(s),--i.indegree===0&&e.push(i)}}for(;e.length;){let s=e.pop();t.push(s),s.in.reverse().forEach(n(s)),s.out.forEach(r(s))}return t.filter(s=>!s.merged).map(s=>m0.pick(s,["vs","i","barycenter","weight"]))}function x0(e,t){let n=0,r=0;e.weight&&(n+=e.barycenter*e.weight,r+=e.weight),t.weight&&(n+=t.barycenter*t.weight,r+=t.weight),e.vs=t.vs.concat(e.vs),e.barycenter=n/r,e.weight=r,e.i=Math.min(t.i,e.i),t.merged=!0}let w0=fe;var b0=v0;function v0(e,t){let n=w0.partition(e,u=>Object.hasOwn(u,"barycenter")),r=n.lhs,s=n.rhs.sort((u,d)=>d.i-u.i),i=[],o=0,a=0,l=0;r.sort(_0(!!t)),l=Xs(i,s,l),r.forEach(u=>{l+=u.vs.length,i.push(u.vs),o+=u.barycenter*u.weight,a+=u.weight,l=Xs(i,s,l)});let c={vs:i.flat(!0)};return a&&(c.barycenter=o/a,c.weight=a),c}function Xs(e,t,n){let r;for(;t.length&&(r=t[t.length-1]).i<=n;)t.pop(),e.push(r.vs),n++;return n}function _0(e){return(t,n)=>t.barycentern.barycenter?1:e?n.i-t.i:t.i-n.i}let E0=f0,N0=p0,S0=b0;var k0=ha;function ha(e,t,n,r){let s=e.children(t),i=e.node(t),o=i?i.borderLeft:void 0,a=i?i.borderRight:void 0,l={};o&&(s=s.filter(m=>m!==o&&m!==a));let c=E0(e,s);c.forEach(m=>{if(e.children(m.v).length){let f=ha(e,m.v,n,r);l[m.v]=f,Object.hasOwn(f,"barycenter")&&C0(m,f)}});let u=N0(c,n);j0(u,l);let d=S0(u,r);if(o&&(d.vs=[o,d.vs,a].flat(!0),e.predecessors(o).length)){let m=e.node(e.predecessors(o)[0]),f=e.node(e.predecessors(a)[0]);Object.hasOwn(d,"barycenter")||(d.barycenter=0,d.weight=0),d.barycenter=(d.barycenter*d.weight+m.order+f.order)/(d.weight+2),d.weight+=2}return d}function j0(e,t){e.forEach(n=>{n.vs=n.vs.flatMap(r=>t[r]?t[r].vs:r)})}function C0(e,t){e.barycenter!==void 0?(e.barycenter=(e.barycenter*e.weight+t.barycenter*t.weight)/(e.weight+t.weight),e.weight+=t.weight):(e.barycenter=t.barycenter,e.weight=t.weight)}let $0=Ie.Graph,M0=fe;var A0=I0;function I0(e,t,n,r){r||(r=e.nodes());let s=R0(e),i=new $0({compound:!0}).setGraph({root:s}).setDefaultNodeLabel(o=>e.node(o));return r.forEach(o=>{let a=e.node(o),l=e.parent(o);(a.rank===t||a.minRank<=t&&t<=a.maxRank)&&(i.setNode(o),i.setParent(o,l||s),e[n](o).forEach(c=>{let u=c.v===o?c.w:c.v,d=i.edge(u,o),m=d!==void 0?d.weight:0;i.setEdge(u,o,{weight:e.edge(c).weight+m})}),Object.hasOwn(a,"minRank")&&i.setNode(o,{borderLeft:a.borderLeft[t],borderRight:a.borderRight[t]}))}),i}function R0(e){for(var t;e.hasNode(t=M0.uniqueId("_root")););return t}var T0=O0;function O0(e,t,n){let r={},s;n.forEach(i=>{let o=e.parent(i),a,l;for(;o;){if(a=e.parent(o),a?(l=r[a],r[a]=o):(l=s,s=o),l&&l!==o){t.setEdge(l,o);return}o=a}})}let D0=o0,L0=c0,P0=k0,z0=A0,H0=T0,F0=Ie.Graph,ln=fe;var V0=ma;function ma(e,t){if(t&&typeof t.customOrder=="function"){t.customOrder(e,ma);return}let n=ln.maxRank(e),r=qs(e,ln.range(1,n+1),"inEdges"),s=qs(e,ln.range(n-1,-1,-1),"outEdges"),i=D0(e);if(Ks(e,i),t&&t.disableOptimalOrderHeuristic)return;let o=Number.POSITIVE_INFINITY,a;for(let l=0,c=0;c<4;++l,++c){B0(l%2?r:s,l%4>=2),i=ln.buildLayerMatrix(e);let u=L0(e,i);u{r.has(i)||r.set(i,[]),r.get(i).push(o)};for(const i of e.nodes()){const o=e.node(i);if(typeof o.rank=="number"&&s(o.rank,i),typeof o.minRank=="number"&&typeof o.maxRank=="number")for(let a=o.minRank;a<=o.maxRank;a++)a!==o.rank&&s(a,i)}return t.map(function(i){return z0(e,i,n,r.get(i)||[])})}function B0(e,t){let n=new F0;e.forEach(function(r){let s=r.graph().root,i=P0(r,s,n,t);i.vs.forEach((o,a)=>r.node(o).order=a),H0(r,n,i.vs)})}function Ks(e,t){Object.values(t).forEach(n=>n.forEach((r,s)=>e.node(r).order=s))}let G0=Ie.Graph,ze=fe;var Y0={positionX:ny};function W0(e,t){let n={};function r(s,i){let o=0,a=0,l=s.length,c=i[i.length-1];return i.forEach((u,d)=>{let m=X0(e,u),f=m?e.node(m).order:l;(m||u===c)&&(i.slice(a,d+1).forEach(y=>{e.predecessors(y).forEach(p=>{let v=e.node(p),x=v.order;(x{u=i[d],e.node(u).dummy&&e.predecessors(u).forEach(m=>{let f=e.node(m);f.dummy&&(f.orderc)&&pa(n,m,u)})})}function s(i,o){let a=-1,l,c=0;return o.forEach((u,d)=>{if(e.node(u).dummy==="border"){let m=e.predecessors(u);m.length&&(l=e.node(m[0]).order,r(o,c,d,a,l),c=d,a=l)}r(o,c,o.length,l,i.length)}),o}return t.length&&t.reduce(s),n}function X0(e,t){if(e.node(t).dummy)return e.predecessors(t).find(n=>e.node(n).dummy)}function pa(e,t,n){if(t>n){let s=t;t=n,n=s}let r=e[t];r||(e[t]=r={}),r[n]=!0}function q0(e,t,n){if(t>n){let r=t;t=n,n=r}return!!e[t]&&Object.hasOwn(e[t],n)}function K0(e,t,n,r){let s={},i={},o={};return t.forEach(a=>{a.forEach((l,c)=>{s[l]=l,i[l]=l,o[l]=c})}),t.forEach(a=>{let l=-1;a.forEach(c=>{let u=r(c);if(u.length){u=u.sort((m,f)=>o[m]-o[f]);let d=(u.length-1)/2;for(let m=Math.floor(d),f=Math.ceil(d);m<=f;++m){let y=u[m];i[c]===c&&lMath.max(m,i[f.v]+o.edge(f)),0)}function u(d){let m=o.outEdges(d).reduce((y,p)=>Math.min(y,i[p.w]-o.edge(p)),Number.POSITIVE_INFINITY),f=e.node(d);m!==Number.POSITIVE_INFINITY&&f.borderType!==a&&(i[d]=Math.max(i[d],m))}return l(c,o.predecessors.bind(o)),l(u,o.successors.bind(o)),Object.keys(r).forEach(d=>i[d]=i[n[d]]),i}function Q0(e,t,n,r){let s=new G0,i=e.graph(),o=ry(i.nodesep,i.edgesep,r);return t.forEach(a=>{let l;a.forEach(c=>{let u=n[c];if(s.setNode(u),l){var d=n[l],m=s.edge(d,u);s.setEdge(d,u,Math.max(o(e,c,l),m||0))}l=c})}),s}function J0(e,t){return Object.values(t).reduce((n,r)=>{let s=Number.NEGATIVE_INFINITY,i=Number.POSITIVE_INFINITY;Object.entries(r).forEach(([a,l])=>{let c=sy(e,a)/2;s=Math.max(l+c,s),i=Math.min(l-c,i)});const o=s-i;return o{["l","r"].forEach(o=>{let a=i+o,l=e[a];if(l===t)return;let c=Object.values(l),u=r-ze.applyWithChunking(Math.min,c);o!=="l"&&(u=s-ze.applyWithChunking(Math.max,c)),u&&(e[a]=ze.mapValues(l,d=>d+u))})})}function ty(e,t){return ze.mapValues(e.ul,(n,r)=>{if(t)return e[t.toLowerCase()][r];{let s=Object.values(e).map(i=>i[r]).sort((i,o)=>i-o);return(s[1]+s[2])/2}})}function ny(e){let t=ze.buildLayerMatrix(e),n=Object.assign(W0(e,t),U0(e,t)),r={},s;["u","d"].forEach(o=>{s=o==="u"?t:Object.values(t).reverse(),["l","r"].forEach(a=>{a==="r"&&(s=s.map(d=>Object.values(d).reverse()));let l=(o==="u"?e.predecessors:e.successors).bind(e),c=K0(e,s,n,l),u=Z0(e,s,c.root,c.align,a==="r");a==="r"&&(u=ze.mapValues(u,d=>-d)),r[o+a]=u})});let i=J0(e,r);return ey(r,i),ty(r,e.graph().align)}function ry(e,t,n){return(r,s,i)=>{let o=r.node(s),a=r.node(i),l=0,c;if(l+=o.width/2,Object.hasOwn(o,"labelpos"))switch(o.labelpos.toLowerCase()){case"l":c=-o.width/2;break;case"r":c=o.width/2;break}if(c&&(l+=n?c:-c),c=0,l+=(o.dummy?t:e)/2,l+=(a.dummy?t:e)/2,l+=a.width/2,Object.hasOwn(a,"labelpos"))switch(a.labelpos.toLowerCase()){case"l":c=a.width/2;break;case"r":c=-a.width/2;break}return c&&(l+=n?c:-c),c=0,l}}function sy(e,t){return e.node(t).width}let ga=fe,iy=Y0.positionX;var oy=ay;function ay(e){e=ga.asNonCompoundGraph(e),ly(e),Object.entries(iy(e)).forEach(([t,n])=>e.node(t).x=n)}function ly(e){let t=ga.buildLayerMatrix(e),n=e.graph().ranksep,r=0;t.forEach(s=>{const i=s.reduce((o,a)=>{const l=e.node(a).height;return o>l?o:l},0);s.forEach(o=>e.node(o).y=r+i/2),r+=i+n})}let Zs=ug,Qs=pg,cy=zg,uy=fe.normalizeRanks,dy=Bg,fy=fe.removeEmptyRanks,Js=Ug,hy=Jg,ei=t0,my=V0,py=oy,je=fe,gy=Ie.Graph;var yy=xy;function xy(e,t){let n=t&&t.debugTiming?je.time:je.notime;n("layout",()=>{let r=n(" buildLayoutGraph",()=>Cy(e));n(" runLayout",()=>wy(r,n,t)),n(" updateInputGraph",()=>by(e,r))})}function wy(e,t,n){t(" makeSpaceForEdgeLabels",()=>$y(e)),t(" removeSelfEdges",()=>Py(e)),t(" acyclic",()=>Zs.run(e)),t(" nestingGraph.run",()=>Js.run(e)),t(" rank",()=>cy(je.asNonCompoundGraph(e))),t(" injectEdgeLabelProxies",()=>My(e)),t(" removeEmptyRanks",()=>fy(e)),t(" nestingGraph.cleanup",()=>Js.cleanup(e)),t(" normalizeRanks",()=>uy(e)),t(" assignRankMinMax",()=>Ay(e)),t(" removeEdgeLabelProxies",()=>Iy(e)),t(" normalize.run",()=>Qs.run(e)),t(" parentDummyChains",()=>dy(e)),t(" addBorderSegments",()=>hy(e)),t(" order",()=>my(e,n)),t(" insertSelfEdges",()=>zy(e)),t(" adjustCoordinateSystem",()=>ei.adjust(e)),t(" position",()=>py(e)),t(" positionSelfEdges",()=>Hy(e)),t(" removeBorderNodes",()=>Ly(e)),t(" normalize.undo",()=>Qs.undo(e)),t(" fixupEdgeLabelCoords",()=>Oy(e)),t(" undoCoordinateSystem",()=>ei.undo(e)),t(" translateGraph",()=>Ry(e)),t(" assignNodeIntersects",()=>Ty(e)),t(" reversePoints",()=>Dy(e)),t(" acyclic.undo",()=>Zs.undo(e))}function by(e,t){e.nodes().forEach(n=>{let r=e.node(n),s=t.node(n);r&&(r.x=s.x,r.y=s.y,r.rank=s.rank,t.children(n).length&&(r.width=s.width,r.height=s.height))}),e.edges().forEach(n=>{let r=e.edge(n),s=t.edge(n);r.points=s.points,Object.hasOwn(s,"x")&&(r.x=s.x,r.y=s.y)}),e.graph().width=t.graph().width,e.graph().height=t.graph().height}let vy=["nodesep","edgesep","ranksep","marginx","marginy"],_y={ranksep:50,edgesep:20,nodesep:50,rankdir:"tb"},Ey=["acyclicer","ranker","rankdir","align"],Ny=["width","height","rank"],ti={width:0,height:0},Sy=["minlen","weight","width","height","labeloffset"],ky={minlen:1,weight:1,width:0,height:0,labeloffset:10,labelpos:"r"},jy=["labelpos"];function Cy(e){let t=new gy({multigraph:!0,compound:!0}),n=tr(e.graph());return t.setGraph(Object.assign({},_y,er(n,vy),je.pick(n,Ey))),e.nodes().forEach(r=>{let s=tr(e.node(r));const i=er(s,Ny);Object.keys(ti).forEach(o=>{i[o]===void 0&&(i[o]=ti[o])}),t.setNode(r,i),t.setParent(r,e.parent(r))}),e.edges().forEach(r=>{let s=tr(e.edge(r));t.setEdge(r,Object.assign({},ky,er(s,Sy),je.pick(s,jy)))}),t}function $y(e){let t=e.graph();t.ranksep/=2,e.edges().forEach(n=>{let r=e.edge(n);r.minlen*=2,r.labelpos.toLowerCase()!=="c"&&(t.rankdir==="TB"||t.rankdir==="BT"?r.width+=r.labeloffset:r.height+=r.labeloffset)})}function My(e){e.edges().forEach(t=>{let n=e.edge(t);if(n.width&&n.height){let r=e.node(t.v),i={rank:(e.node(t.w).rank-r.rank)/2+r.rank,e:t};je.addDummyNode(e,"edge-proxy",i,"_ep")}})}function Ay(e){let t=0;e.nodes().forEach(n=>{let r=e.node(n);r.borderTop&&(r.minRank=e.node(r.borderTop).rank,r.maxRank=e.node(r.borderBottom).rank,t=Math.max(t,r.maxRank))}),e.graph().maxRank=t}function Iy(e){e.nodes().forEach(t=>{let n=e.node(t);n.dummy==="edge-proxy"&&(e.edge(n.e).labelRank=n.rank,e.removeNode(t))})}function Ry(e){let t=Number.POSITIVE_INFINITY,n=0,r=Number.POSITIVE_INFINITY,s=0,i=e.graph(),o=i.marginx||0,a=i.marginy||0;function l(c){let u=c.x,d=c.y,m=c.width,f=c.height;t=Math.min(t,u-m/2),n=Math.max(n,u+m/2),r=Math.min(r,d-f/2),s=Math.max(s,d+f/2)}e.nodes().forEach(c=>l(e.node(c))),e.edges().forEach(c=>{let u=e.edge(c);Object.hasOwn(u,"x")&&l(u)}),t-=o,r-=a,e.nodes().forEach(c=>{let u=e.node(c);u.x-=t,u.y-=r}),e.edges().forEach(c=>{let u=e.edge(c);u.points.forEach(d=>{d.x-=t,d.y-=r}),Object.hasOwn(u,"x")&&(u.x-=t),Object.hasOwn(u,"y")&&(u.y-=r)}),i.width=n-t+o,i.height=s-r+a}function Ty(e){e.edges().forEach(t=>{let n=e.edge(t),r=e.node(t.v),s=e.node(t.w),i,o;n.points?(i=n.points[0],o=n.points[n.points.length-1]):(n.points=[],i=s,o=r),n.points.unshift(je.intersectRect(r,i)),n.points.push(je.intersectRect(s,o))})}function Oy(e){e.edges().forEach(t=>{let n=e.edge(t);if(Object.hasOwn(n,"x"))switch((n.labelpos==="l"||n.labelpos==="r")&&(n.width-=n.labeloffset),n.labelpos){case"l":n.x-=n.width/2+n.labeloffset;break;case"r":n.x+=n.width/2+n.labeloffset;break}})}function Dy(e){e.edges().forEach(t=>{let n=e.edge(t);n.reversed&&n.points.reverse()})}function Ly(e){e.nodes().forEach(t=>{if(e.children(t).length){let n=e.node(t),r=e.node(n.borderTop),s=e.node(n.borderBottom),i=e.node(n.borderLeft[n.borderLeft.length-1]),o=e.node(n.borderRight[n.borderRight.length-1]);n.width=Math.abs(o.x-i.x),n.height=Math.abs(s.y-r.y),n.x=i.x+n.width/2,n.y=r.y+n.height/2}}),e.nodes().forEach(t=>{e.node(t).dummy==="border"&&e.removeNode(t)})}function Py(e){e.edges().forEach(t=>{if(t.v===t.w){var n=e.node(t.v);n.selfEdges||(n.selfEdges=[]),n.selfEdges.push({e:t,label:e.edge(t)}),e.removeEdge(t)}})}function zy(e){var t=je.buildLayerMatrix(e);t.forEach(n=>{var r=0;n.forEach((s,i)=>{var o=e.node(s);o.order=i+r,(o.selfEdges||[]).forEach(a=>{je.addDummyNode(e,"selfedge",{width:a.label.width,height:a.label.height,rank:o.rank,order:i+ ++r,e:a.e,label:a.label},"_se")}),delete o.selfEdges})})}function Hy(e){e.nodes().forEach(t=>{var n=e.node(t);if(n.dummy==="selfedge"){var r=e.node(n.e.v),s=r.x+r.width/2,i=r.y,o=n.x-s,a=r.height/2;e.setEdge(n.e,n.label),e.removeNode(t),n.label.points=[{x:s+2*o/3,y:i-a},{x:s+5*o/6,y:i-a},{x:s+o,y:i},{x:s+5*o/6,y:i+a},{x:s+2*o/3,y:i+a}],n.label.x=n.x,n.label.y=n.y}})}function er(e,t){return je.mapValues(je.pick(e,t),Number)}function tr(e){var t={};return e&&Object.entries(e).forEach(([n,r])=>{typeof n=="string"&&(n=n.toLowerCase()),t[n]=r}),t}let Fy=fe,Vy=Ie.Graph;var By={debugOrdering:Gy};function Gy(e){let t=Fy.buildLayerMatrix(e),n=new Vy({compound:!0,multigraph:!0}).setGraph({});return e.nodes().forEach(r=>{n.setNode(r,{label:r}),n.setParent(r,"layer"+e.node(r).rank)}),e.edges().forEach(r=>n.setEdge(r.v,r.w,{},r.name)),t.forEach((r,s)=>{let i="layer"+s;n.setNode(i,{rank:"same"}),r.reduce((o,a)=>(n.setEdge(o,a,{style:"invis"}),a))}),n}var Yy="1.1.8",Wy={graphlib:Ie,layout:yy,debug:By,util:{time:fe.time,notime:fe.notime},version:Yy};const ni=fi(Wy),_t=264,Uy=44,Xy=26,qy=14;function Sn(e){const t=Math.max(e.attributes.length,1);return Uy+t*Xy+qy}const Ky=40;function ri(e,t,n,r="auto",s,i="LR"){const o=Zy(n,s);return r==="grid"?ai(e,n,o):r==="clustered"?oi(e,t,n,o,i):r==="hierarchical"||e.length<=Ky?si(e,t,n,i):new Set(e.map(l=>o(l.id)).filter(Boolean)).size>1?oi(e,t,n,o,i):ai(e,n,o)}function Zy(e,t){return n=>{var r,s,i;if(t){const o=t.get(n);if(o)return o.name}return((i=(s=(r=e.get(n))==null?void 0:r.conceptual)==null?void 0:s.subject_area)==null?void 0:i.name)??""}}function ya(e,t,n,r=!1,s="LR"){const i=new ni.graphlib.Graph;i.setGraph({rankdir:s,nodesep:r?45:70,ranksep:r?110:150,edgesep:r?20:30,marginx:24,marginy:24,ranker:"network-simplex"}),i.setDefaultEdgeLabel(()=>({}));const o=new Set(e.map(u=>u.id));for(const u of e){const d=n.get(u.id);i.setNode(u.id,{width:_t,height:d?Sn(d):120})}for(const u of t)o.has(u.source)&&o.has(u.target)&&i.setEdge(u.source,u.target,{minlen:1,weight:2});ni.layout(i);let a=0,l=0;return{nodes:e.map(u=>{const d=i.node(u.id),m=n.get(u.id),f=m?Sn(m):120,y=d.x-_t/2,p=d.y-f/2;return a=Math.max(a,y+_t),l=Math.max(l,p+f),{...u,position:{x:y,y:p}}}),width:a,height:l}}function si(e,t,n,r="LR"){return ya(e,t,n,!1,r).nodes}function Qy(e,t){const n=a=>{const l=t.get(a);return l?Sn(l):120},r=Math.max(1,Math.round(Math.sqrt(e.length))),s=[];let i=0,o=0;for(let a=0;a{const d=u*(_t+xa);s.push({...c,position:{x:d,y:i}}),o=Math.max(o,d+_t)}),i+=Math.max(...l.map(c=>n(c.id)))+wa}return{nodes:s,width:o,height:i}}const ii=120;function oi(e,t,n,r,s="LR"){const i=new Map;for(const m of e){const f=r(m.id);(i.get(f)??i.set(f,[]).get(f)).push(m)}const a=[...i.keys()].sort((m,f)=>m===""?1:f===""?-1:m.localeCompare(f)).map(m=>{const f=i.get(m),y=new Set(f.map(_=>_.id));let p=0;for(const _ of t)y.has(_.source)&&y.has(_.target)&&p++;const x=f.length<=8&&p>=f.length-1?ya(f,t,n,!0,s):Qy(f,n);return{name:m,...x}}),l=Math.max(1,Math.ceil(Math.sqrt(a.length*1.6))),c=[];let u=0;for(let m=0;m[m.id,m.position]));return e.map(m=>({...m,position:d.get(m.id)??m.position}))}const xa=40,wa=40;function ai(e,t,n){const r=c=>{const u=t.get(c);return u?Sn(u):120},s=[...e].sort((c,u)=>{var p,v;const d=n(c.id),m=n(u.id);if(d!==m)return d.localeCompare(m);const f=((p=t.get(c.id))==null?void 0:p.name)??c.id,y=((v=t.get(u.id))==null?void 0:v.name)??u.id;return f.localeCompare(y)}),i=Math.max(1,Math.round(Math.sqrt(s.length))),o=Array.from({length:i},(c,u)=>u*(_t+xa)),a=new Map;let l=0;for(let c=0;ca.set(m.id,{x:o[f],y:l}));const d=Math.max(...u.map(m=>r(m.id)));l+=d+wa}return e.map(c=>({...c,position:a.get(c.id)??c.position}))}function Zt({title:e,onClose:t,children:n,wide:r}){return h.jsx("div",{className:"modal-backdrop",onClick:t,children:h.jsxs("div",{className:"modal"+(r?" wide":""),onClick:s=>s.stopPropagation(),children:[h.jsxs("div",{className:"modal-header",children:[h.jsx("h2",{children:e}),h.jsx("button",{className:"icon-btn",onClick:t,children:"✕"})]}),n]})})}const Jy=["skos:exactMatch","skos:closeMatch","skos:broadMatch","skos:narrowMatch","skos:relatedMatch"],ba=["industry","core","domain","specialised"];function ex({entity:e,exec:t,onClose:n}){var b,j;const[r,s]=w.useState(((b=e.conceptual)==null?void 0:b.name)??e.name),[i,o]=w.useState([]),[a,l]=w.useState(null),[c,u]=w.useState(null),[d,m]=w.useState("skos:exactMatch"),[f,y]=w.useState(((j=e.conceptual)==null?void 0:j.ontology_layer)??"core"),[p,v]=w.useState([]),[x,_]=w.useState("");w.useEffect(()=>{Go().then(C=>v(C.ontologies)).catch(()=>{})},[]),w.useEffect(()=>{const C=setTimeout(()=>{if(!r.trim())return o([]);Bo(r,x||void 0).then(E=>{o(E.results),l(E.loaded_terms)}).catch(()=>o([]))},200);return()=>clearTimeout(C)},[r,x]);const M=()=>{c&&t("set_alignment",{id:e.id,aligns_to:c.prefixed,alignment:d,layer:f,resolved_via:c.source}).then(n)};return h.jsxs(Zt,{title:`Align '${e.name}' to ontology`,onClose:n,wide:!0,children:[p.length>0&&h.jsxs("div",{className:"src-picker",children:[h.jsx("button",{className:"src-chip"+(x===""?" active":""),onClick:()=>_(""),children:"all sources"}),p.map(C=>h.jsx("button",{className:"src-chip"+(x===C.id?" active":""),title:C.count!=null?`${C.count} terms`:"live resolver",onClick:()=>_(C.id),children:C.name},C.id))]}),h.jsx("input",{autoFocus:!0,className:"edit-input modal-search",placeholder:x?`Search within ${x}…`:"Search vocabulary terms…",value:r,onChange:C=>s(C.target.value)}),a===0&&p.length===0&&h.jsx("p",{className:"empty-hint",children:"No vocabulary loaded. Declare one in mdl-project.yaml's ontology_stack (or run `mdl ontology vendor fibo`)."}),h.jsxs("div",{className:"term-results",children:[i.map(C=>h.jsxs("button",{className:"term-card"+((c==null?void 0:c.iri)===C.iri?" picked":""),onClick:()=>u(C),children:[h.jsxs("div",{className:"term-head",children:[h.jsx("span",{className:"term-label",children:C.label}),h.jsxs("span",{className:"term-source",children:[C.source_kind==="glossary-term"&&h.jsx("span",{className:"kind-badge",children:"glossary"}),C.source]})]}),h.jsx("code",{className:"term-iri",children:C.prefixed}),C.definition&&h.jsx("p",{className:"term-def",children:C.definition})]},C.iri)),r&&i.length===0&&a!==0&&h.jsxs("p",{className:"empty-hint",children:["no matches for “",r,"”"]})]}),h.jsxs("div",{className:"modal-footer",children:[h.jsxs("label",{children:["predicate",h.jsx("select",{value:d,onChange:C=>m(C.target.value),children:Jy.map(C=>h.jsx("option",{children:C},C))})]}),h.jsxs("label",{children:["layer",h.jsx("select",{value:f,onChange:C=>y(C.target.value),children:ba.map(C=>h.jsx("option",{children:C},C))})]}),h.jsxs("button",{className:"primary-btn",disabled:!c,onClick:M,children:["Align",c?` to ${c.label}`:""]})]})]})}function tx({entity:e,doc:t,exec:n,onClose:r}){var b,j,C;const[s,i]=w.useState(((b=e.term_map)==null?void 0:b.subject_template)??""),[o,a]=w.useState(((j=e.term_map)==null?void 0:j.class_iri)??""),l=new Set(e.attributes.map(E=>E.name)),u=Array.from(s.matchAll(/\{([^}]+)\}/g)).map(E=>E[1]).filter(E=>!l.has(E)),d=E=>!E||E.startsWith("http://")||E.startsWith("https://")||/^[^\s:]+:[^\s:]+/.test(E),m=u.length===0&&d(o),f=()=>{n("set_term_map",{id:e.id,subject_template:s.trim()||null,class_iri:o.trim()||null}).then(r)},y=(t.project.name||"").replace(/[^0-9a-zA-Z]+/g,"-").replace(/^-+|-+$/g,"").toLowerCase()||"modelith-model",p=t.project.kg_base_iri||`urn:${y}:`,v=(C=(e.key_groups??[]).find(E=>E.type==="pk"))==null?void 0:C.members.map(E=>{var L;return(L=e.attributes.find(S=>S.id===E))==null?void 0:L.name}).filter(Boolean),x=v&&v.length?`${p}${e.id}/${v.map(E=>`{${E}}`).join("_")}`:"(blank-node: entity has no primary key)",_=o.trim()||`${p}${e.id}`,M=s.trim()||x;return h.jsxs(Zt,{title:`Knowledge Graph mapping — ${e.name}`,onClose:r,wide:!0,children:[h.jsx("p",{className:"empty-hint",style:{marginBottom:14},children:"Override the R2RML term-map for this entity. Leave a field blank to use the default (project base IRI + primary key)."}),h.jsxs("div",{className:"form-row",children:[h.jsx("label",{htmlFor:"tm-class",children:"Class IRI"}),h.jsx("input",{id:"tm-class",className:"edit-input",value:o,placeholder:"https://acme.com/Customer or fibo-fnd:Party",onChange:E=>a(E.target.value)}),d(o)?h.jsxs("code",{className:"form-preview",children:["rr:class ",_]}):h.jsx("span",{className:"form-error",children:"not a valid IRI or prefix:local CURIE"})]}),h.jsxs("div",{className:"form-row",children:[h.jsx("label",{htmlFor:"tm-subject",children:"Subject template"}),h.jsx("input",{id:"tm-subject",className:"edit-input",value:s,placeholder:"https://acme.com/id/customer/{customer_id}",onChange:E=>i(E.target.value)}),u.length>0?h.jsxs("span",{className:"form-error",children:["unknown column",u.length>1?"s":"",": ",u.join(", ")]}):h.jsxs("code",{className:"form-preview",children:["rr:template ",M]}),h.jsxs("span",{className:"form-hint",children:["Wrap a column in ","{ }"," to fill it from each row, e.g."," ","{"+((v==null?void 0:v[0])??"id")+"}",". Columns:"," ",e.attributes.map(E=>E.name).join(", ")]})]}),h.jsxs("div",{className:"modal-footer",children:[h.jsx("button",{className:"mini-btn",onClick:r,children:"Cancel"}),h.jsx("button",{className:"primary-btn",disabled:!m,onClick:f,children:"Save mapping"})]})]})}function nx({doc:e,exec:t,onClose:n,onCreated:r}){const[s,i]=w.useState(""),[o,a]=w.useState(""),[l,c]=w.useState(""),[u,d]=w.useState(""),m=()=>{s.trim()&&t("create_entity",{name:s,definition:o||null,subject_area:l||null,layer:u||null}).then(f=>{const y=f==null?void 0:f.created_id;n(),y&&r(y)})};return h.jsxs(Zt,{title:"New entity",onClose:n,children:[h.jsxs("label",{className:"form-row",children:["name",h.jsx("input",{autoFocus:!0,className:"edit-input",placeholder:"e.g. custody_account",value:s,onChange:f=>i(f.target.value),onKeyDown:f=>f.key==="Enter"&&m()})]}),h.jsxs("label",{className:"form-row",children:["definition",h.jsx("textarea",{className:"edit-input",rows:2,placeholder:"business definition…",value:o,onChange:f=>a(f.target.value)})]}),h.jsxs("label",{className:"form-row",children:["subject area",h.jsxs("select",{value:l,onChange:f=>c(f.target.value),children:[h.jsx("option",{value:"",children:"none"}),e.subject_areas.map(f=>h.jsx("option",{value:f.id,children:f.name},f.id))]})]}),h.jsxs("label",{className:"form-row",children:["ontology layer",h.jsxs("select",{value:u,onChange:f=>d(f.target.value),children:[h.jsx("option",{value:"",children:"none"}),ba.map(f=>h.jsx("option",{children:f},f))]})]}),h.jsx("div",{className:"modal-footer",children:h.jsx("button",{className:"primary-btn",disabled:!s.trim(),onClick:m,children:"Create"})})]})}const va=["many_to_one","one_to_many","one_to_one","many_to_many"];function rx({doc:e,fromId:t,toId:n,initialFromAttr:r,initialToAttr:s,exec:i,onClose:o}){const a=e.entities.find(b=>b.id===t),l=e.entities.find(b=>b.id===n),c=w.useMemo(()=>l==null?void 0:l.attributes.find(b=>b.role==="business_key"),[l]),[u,d]=w.useState(r??""),[m,f]=w.useState(s??(c==null?void 0:c.id)??""),[y,p]=w.useState("many_to_one"),[v,x]=w.useState("mandatory");if(!a||!l)return null;const _=u==="__new__",M=()=>i("create_relationship",{from_entity:a.id,to_entity:l.id,from_attribute:_?null:u||null,to_attribute:m||null,create_from_fk:_,cardinality:y,optionality:v}).then(o);return h.jsxs(Zt,{title:`${a.name} → ${l.name}`,onClose:o,children:[h.jsxs("label",{className:"form-row",children:["cardinality (",a.name," : ",l.name,")",h.jsx("select",{value:y,onChange:b=>p(b.target.value),children:va.map(b=>h.jsx("option",{children:b},b))})]}),h.jsxs("label",{className:"form-row",children:["foreign key on ",a.name,h.jsxs("select",{value:u,onChange:b=>d(b.target.value),children:[h.jsx("option",{value:"",children:"(none)"}),h.jsxs("option",{value:"__new__",children:["➕ create column",c?` "${c.name}"`:""]}),a.attributes.map(b=>h.jsx("option",{value:b.id,children:b.name},b.id))]})]}),h.jsxs("label",{className:"form-row",children:["references on ",l.name,h.jsxs("select",{value:m,onChange:b=>f(b.target.value),children:[h.jsx("option",{value:"",children:"(none)"}),l.attributes.map(b=>h.jsxs("option",{value:b.id,children:[b.name,b.role==="business_key"?" 🔑":""]},b.id))]})]}),h.jsxs("label",{className:"form-row",children:["optionality",h.jsxs("select",{value:v,onChange:b=>x(b.target.value),children:[h.jsx("option",{children:"mandatory"}),h.jsx("option",{children:"optional"})]})]}),h.jsx("div",{className:"modal-footer",children:h.jsx("button",{className:"primary-btn",onClick:M,children:"Create relationship"})})]})}function sx({rel:e,doc:t,exec:n,onClose:r}){const s=x=>{var _;return((_=t.entities.find(M=>M.id===x))==null?void 0:_.name)??"?"},[i,o]=w.useState(e.name),[a,l]=w.useState(e.cardinality),[c,u]=w.useState(e.optionality),[d,m]=w.useState(e.identifying),[f,y]=w.useState(!1),p=async()=>{i.trim()&&i.trim()!==e.name&&await n("rename_relationship",{id:e.id,name:i.trim()}),(a!==e.cardinality||c!==e.optionality||d!==e.identifying)&&await n("update_relationship",{id:e.id,cardinality:a,optionality:c,identifying:d}),r()},v=()=>n("delete_relationship",{id:e.id}).then(r);return h.jsxs(Zt,{title:`${s(e.from.entity)} → ${s(e.to.entity)}`,onClose:r,children:[h.jsxs("label",{className:"form-row",children:["relationship name",h.jsx("input",{value:i,onChange:x=>o(x.target.value),autoFocus:!0})]}),h.jsxs("label",{className:"form-row",children:["cardinality",h.jsx("select",{value:a,onChange:x=>l(x.target.value),children:va.map(x=>h.jsx("option",{children:x},x))})]}),h.jsxs("label",{className:"form-row",children:["optionality",h.jsxs("select",{value:c,onChange:x=>u(x.target.value),children:[h.jsx("option",{value:"mandatory",children:"mandatory"}),h.jsx("option",{value:"optional",children:"optional"})]})]}),h.jsxs("label",{className:"form-row",children:["identifying",h.jsxs("select",{value:d?"yes":"no",onChange:x=>m(x.target.value==="yes"),children:[h.jsx("option",{value:"no",children:"no — parent key is a plain reference"}),h.jsx("option",{value:"yes",children:"yes — parent key is part of the child's identity"})]})]}),h.jsxs("div",{className:"modal-footer",style:{justifyContent:"space-between"},children:[f?h.jsx("button",{className:"danger-btn",onClick:v,children:"Confirm delete"}):h.jsx("button",{className:"mini-btn danger",onClick:()=>y(!0),children:"Delete relationship"}),h.jsx("button",{className:"primary-btn",onClick:p,children:"Save"})]})]})}const ix=w.memo(function({id:t,sourceX:n,sourceY:r,targetX:s,targetY:i,sourcePosition:o,targetPosition:a,data:l,selected:c}){const[u]=vn({sourceX:n,sourceY:r,sourcePosition:o,targetX:s,targetY:i,targetPosition:a,borderRadius:10}),d=l==null?void 0:l.relationship,m=(l==null?void 0:l.dimmed)??!1,f=(d==null?void 0:d.cardinality)??"many_to_one",y=(d==null?void 0:d.optionality)==="optional",p=(d==null?void 0:d.identifying)??!1,v=f==="many_to_one"||f==="many_to_many",x=f==="one_to_many"||f==="many_to_many",_="rel-edge"+(c?" selected":"")+(m?" dimmed":""),M=((l==null?void 0:l.memberCount)??0)>1,b=l==null?void 0:l.onHoverEdge;return h.jsxs("g",{className:_,children:[h.jsx("path",{id:t,className:"rel-path",d:u,fill:"none",strokeDasharray:p?void 0:"6 4"}),h.jsx("path",{d:u,fill:"none",strokeWidth:14,stroke:"transparent",onMouseEnter:b?()=>b(d.id):void 0,onMouseLeave:b?()=>b(null):void 0}),h.jsx(li,{x:n,y:r,side:o,many:v,optional:y}),h.jsx(li,{x:s,y:i,side:a,many:x,optional:!1}),(c||M)&&d&&h.jsxs("text",{className:"rel-label",x:(n+s)/2,y:(r+i)/2-8,children:[c?d.verb_phrase||d.name:"",M?`${c?" ":""}(${l.memberCount})`:""]})]})});function li({x:e,y:t,side:n,many:r,optional:s}){const i=n===Z.Left?-1:1,o=7,a=12,l=[];return r?l.push(h.jsx("path",{className:"rel-glyph",d:`M ${e+i*a} ${t} L ${e} ${t-o} M ${e+i*a} ${t} L ${e} ${t} M ${e+i*a} ${t} L ${e} ${t+o}`,fill:"none"},"foot")):l.push(h.jsx("line",{className:"rel-glyph",x1:e+i*(a-3),y1:t-o,x2:e+i*(a-3),y2:t+o},"one")),s?l.push(h.jsx("circle",{className:"rel-glyph ring",cx:e+i*(a+6),cy:t,r:4},"opt")):l.push(h.jsx("line",{className:"rel-glyph",x1:e+i*(a+5),y1:t-o,x2:e+i*(a+5),y2:t+o},"mand")),h.jsx(h.Fragment,{children:l})}const ox={entity:Rm},ax={relationship:ix},ci=["#e0a63a","#e8825a","#d98ba8","#c4a3e0","#7fb0d8","#7fc9a0","#e6c14a"],ui="#8a7d6a";function lx(e,t){const n=(i,o)=>{var a;return!!o&&!!((a=t.get(i))!=null&&a.attributes.some(l=>l.id===o))},r=e.from.attributes[0],s=e.to.attributes[0];return{sourceHandle:n(e.from.entity,r)?r:Dr,targetHandle:n(e.to.entity,s)?s:Lr}}function Dx({doc:e,caps:t,exec:n,selectedId:r,onSelect:s,query:i="",showTypes:o=!0,collapseDetail:a=!1,expandedEntities:l,onToggleExpand:c,activeAreas:u,onError:d,handleRef:m}){const{fitView:f,fitBounds:y,getNodes:p}=Rn(),[v,x]=w.useState([]),[_,M]=w.useState([]),b=w.useRef(!1),[j,C]=w.useState(null),[E,L]=w.useState(null),[S,O]=w.useState(!1),[P,V]=w.useState(null),[F,g]=w.useState(null),[$,N]=w.useState(null),[I,H]=w.useState(null),k=!t.canEdit,R=w.useMemo(()=>{const B=new Map;return e.subject_areas.forEach((q,W)=>B.set(q.id,ci[W%ci.length])),B},[e]),D=w.useMemo(()=>{const B=new Map;return e.entities.forEach(q=>B.set(q.id,q)),B},[e]),z=w.useMemo(()=>{const B=new Map,q=new Map;return e.subject_areas.forEach(W=>{(W.members??[]).forEach(Q=>q.set(Q,{id:W.id,name:W.name}))}),e.entities.forEach(W=>{var T,se;const Q=(T=W.conceptual)!=null&&T.id?q.get(W.conceptual.id):void 0,U=(se=W.conceptual)==null?void 0:se.subject_area,X=Q??(U?{id:U.id,name:U.name??U.id}:void 0);X&&B.set(W.id,X)}),B},[e]),Y=w.useCallback(B=>{var W;if(!u||u.size===0)return!1;const q=(W=z.get(B))==null?void 0:W.id;return!(q&&u.has(q))},[u,z]),G=w.useMemo(()=>{const B=new Map,q=(W,Q)=>{if(!Q.length)return;const U=B.get(W)??new Set;Q.forEach(X=>U.add(X)),B.set(W,U)};for(const W of e.relationships)q(W.from.entity,W.from.attributes),q(W.to.entity,W.to.attributes);return B},[e]);w.useEffect(()=>{var X;const B=i.trim().toLowerCase(),q=new Set;if(B)for(const T of e.entities)(T.name.toLowerCase()+" "+(((X=T.conceptual)==null?void 0:X.name.toLowerCase())??"")+" "+T.attributes.map(ce=>ce.name.toLowerCase()).join(" ")).includes(B)&&q.add(T.id);const W=new Set;if(r){W.add(r);for(const T of e.relationships)T.from.entity===r&&W.add(T.to.entity),T.to.entity===r&&W.add(T.from.entity)}const Q=e.entities.map(T=>{const se=B!==""&&!q.has(T.id),ce=r!==null&&!W.has(T.id);return{id:T.id,type:"entity",position:{x:0,y:0},hidden:Y(T.id),data:{entity:T,color:(()=>{const me=z.get(T.id);return me?R.get(me.id)??ui:ui})(),dimmed:se||ce,highlighted:B!==""&&q.has(T.id),showTypes:o,collapseDetail:a,expanded:(l==null?void 0:l.has(T.id))??!1,onToggleExpand:c,endpointAttrs:G.get(T.id),highlightAttrs:void 0,onHoverAttr:N}}}),U=e.relationships.filter(T=>D.has(T.from.entity)&&D.has(T.to.entity)).map(T=>{const{sourceHandle:se,targetHandle:ce}=lx(T,D),me=r!==null&&T.from.entity!==r&&T.to.entity!==r;return{id:T.id,source:T.from.entity,target:T.to.entity,sourceHandle:se,targetHandle:ce,type:"relationship",data:{relationship:T,dimmed:me,memberCount:Math.max(T.from.attributes.length,T.to.attributes.length),onHoverEdge:H}}});x(T=>{const se=new Map(T.map(oe=>[oe.id,oe.position])),ce=Q.every(oe=>se.has(oe.id)),me=((u==null?void 0:u.size)??0)>0;if(b.current&&ce&&T.length>=Q.length&&!me)return Q.map(oe=>({...oe,position:se.get(oe.id)??oe.position}));const we=me?Q.filter(oe=>!oe.hidden):Q,be=ri(we,U,D,"auto",z),Ee=new Map(be.map(oe=>[oe.id,oe.position])),Ge=Q.map(oe=>Ee.has(oe.id)?{...oe,position:Ee.get(oe.id)}:se.has(oe.id)&&b.current?{...oe,position:se.get(oe.id)}:oe);return b.current=!0,requestAnimationFrame(()=>f({padding:.15,duration:300})),Ge}),M(U)},[e,i,r,o,a,l,c,R,D,z,Y,u,G,f]);const K=w.useMemo(()=>{const B=new Set,q=new Set,W=new Map,Q=(U,X)=>{if(!X.length)return;const T=W.get(U)??new Set;X.forEach(se=>T.add(se)),W.set(U,T)};if($)for(const U of e.relationships)(U.from.attributes.includes($)||U.to.attributes.includes($))&&(B.add(U.id),q.add(U.from.entity),q.add(U.to.entity),Q(U.from.entity,U.from.attributes),Q(U.to.entity,U.to.attributes));if(I){const U=e.relationships.find(X=>X.id===I);U&&(Q(U.from.entity,U.from.attributes),Q(U.to.entity,U.to.attributes))}return{active:$!==null,relsForAttr:B,entsForAttr:q,hitAttrsByEntity:W}},[e,$,I]);w.useEffect(()=>{var Q;const B=i.trim().toLowerCase(),q=new Set;if(B)for(const U of e.entities)(U.name.toLowerCase()+" "+(((Q=U.conceptual)==null?void 0:Q.name.toLowerCase())??"")+" "+U.attributes.map(T=>T.name.toLowerCase()).join(" ")).includes(B)&&q.add(U.id);const W=new Set;if(r){W.add(r);for(const U of e.relationships)U.from.entity===r&&W.add(U.to.entity),U.to.entity===r&&W.add(U.from.entity)}x(U=>U.map(X=>{const T=B!==""&&!q.has(X.id),se=r!==null&&!W.has(X.id),ce=K.active&&!K.entsForAttr.has(X.id),me=T||se||ce,we=B!==""&&q.has(X.id)||K.active&&K.entsForAttr.has(X.id),be=K.hitAttrsByEntity.get(X.id);return X.data.dimmed===me&&X.data.highlighted===we&&X.data.highlightAttrs===be?X:{...X,data:{...X.data,dimmed:me,highlighted:we,highlightAttrs:be}}})),M(U=>U.map(X=>{var we,be;const T=(we=X.data)==null?void 0:we.relationship,se=r!==null&&T!==void 0&&T.from.entity!==r&&T.to.entity!==r,ce=K.active&&!K.relsForAttr.has(X.id),me=se||ce;return((be=X.data)==null?void 0:be.dimmed)===me?X:{...X,data:{...X.data,dimmed:me}}}))},[K,i,r,e]),w.useEffect(()=>{var Q;const B=i.trim().toLowerCase();if(!B)return;const q=new Set;for(const U of e.entities)(U.name.toLowerCase()+" "+(((Q=U.conceptual)==null?void 0:Q.name.toLowerCase())??"")+" "+U.attributes.map(T=>T.name.toLowerCase()).join(" ")).includes(B)&&q.add(U.id);if(!q.size)return;const W=requestAnimationFrame(()=>{const U=p().filter(T=>q.has(T.id));if(!U.length)return;const X=kf(U);y(X,{padding:.35,duration:400})});return()=>cancelAnimationFrame(W)},[i,e,p,y]);const J=w.useCallback((B="auto",q="LR")=>{x(W=>ri(W,_,D,B,z,q)),requestAnimationFrame(()=>f({padding:.15,duration:300}))},[_,D,z,f]),ee=w.useCallback(B=>{s(B),x(q=>(q.find(Q=>Q.id===B)&&requestAnimationFrame(()=>f({nodes:[{id:B}],padding:.4,duration:400})),q))},[f,s]);w.useImperativeHandle(m,()=>({relayout:J,fitView:()=>f({padding:.15,duration:300}),focusEntity:ee,newEntity:()=>O(!0)}),[J,f,ee]);const ie=w.useCallback(B=>{if(k||!B.source||!B.target||B.source===B.target)return;const q=B.sourceHandle&&B.sourceHandle!==Dr?B.sourceHandle:void 0,W=B.targetHandle&&B.targetHandle!==Lr?B.targetHandle:void 0;V({from:B.source,to:B.target,fromAttr:q,toAttr:W})},[k]),te=w.useCallback(async(B,q)=>{try{return await n(B,q)}catch(W){throw d==null||d(W instanceof Error?W.message:String(W)),W}},[n,d]),re=r?D.get(r)??null:null,de=e.relationships.find(B=>B.id===F)??null;return h.jsxs(h.Fragment,{children:[h.jsxs(Do,{nodes:v,edges:_,nodeTypes:ox,edgeTypes:ax,onNodeClick:(B,q)=>s(q.id),onEdgeClick:(B,q)=>!k&&g(q.id),onPaneClick:()=>{s(null),g(null)},onNodeDragStop:(B,q)=>x(W=>W.map(Q=>Q.id===q.id?{...Q,position:q.position}:Q)),onConnect:ie,nodesConnectable:!k,minZoom:.05,onlyRenderVisibleElements:!0,proOptions:{hideAttribution:!0},fitView:!0,children:[h.jsx(xm,{variant:ke.Dots,gap:22,size:1.5,color:"#33291f"}),h.jsx(im,{pannable:!0,zoomable:!0,nodeColor:B=>{var q;return((q=B.data)==null?void 0:q.color)??"#5a4f42"},maskColor:"rgba(20, 17, 15, 0.75)"}),h.jsx(fm,{showInteractive:!1})]}),re&&h.jsx(Om,{entity:re,doc:e,caps:t,exec:te,onClose:()=>s(null),onFocusEntity:ee,onAlign:C,onEditMapping:L}),j&&h.jsx(ex,{entity:j,exec:te,onClose:()=>C(null)}),E&&h.jsx(tx,{entity:E,doc:e,exec:te,onClose:()=>L(null)}),S&&h.jsx(nx,{doc:e,exec:te,onClose:()=>O(!1),onCreated:ee}),P&&h.jsx(rx,{doc:e,fromId:P.from,toId:P.to,initialFromAttr:P.fromAttr,initialToAttr:P.toAttr,exec:te,onClose:()=>V(null)}),de&&h.jsx(sx,{rel:de,doc:e,exec:te,onClose:()=>g(null)})]})}function Lx({tab:e,onClose:t,readOnly:n,refreshKey:r,onModelChanged:s,onFocusEntity:i}){return h.jsxs("aside",{className:"side-panel",children:[h.jsxs("div",{className:"detail-header",children:[h.jsxs("h2",{children:[e==="ontology"&&"Ontology",e==="layers"&&"Ontology layers",e==="changes"&&"Uncommitted changes",e==="decisions"&&"Decision ledger"]}),h.jsx("button",{className:"icon-btn",onClick:t,children:"✕"})]}),e==="ontology"&&h.jsx(cx,{}),e==="layers"&&h.jsx(dx,{refreshKey:r,onFocusEntity:i}),e==="changes"&&h.jsx(fx,{readOnly:n,refreshKey:r,onModelChanged:s}),e==="decisions"&&h.jsx(hx,{readOnly:n})]})}function cx(){const[e,t]=w.useState(""),[n,r]=w.useState([]),[s,i]=w.useState({loaded:0,vocabs:[]}),[o,a]=w.useState(null),[l,c]=w.useState([]),[u,d]=w.useState("");w.useEffect(()=>{Go().then(f=>c(f.ontologies)).catch(()=>{})},[]),w.useEffect(()=>{const f=setTimeout(()=>{Bo(e||"a",u||void 0).then(y=>{r(e?y.results:[]),i({loaded:y.loaded_terms,vocabs:y.vocabularies})}).catch(()=>{})},200);return()=>clearTimeout(f)},[e,u]);const m=w.useCallback(f=>{wm(f).then(a).catch(()=>{})},[]);return o?h.jsxs("div",{className:"panel-body",children:[h.jsx("button",{className:"mini-btn",onClick:()=>a(null),children:"← back"}),h.jsx("h3",{style:{marginTop:12},children:o.label}),h.jsx("code",{className:"term-iri",children:o.prefixed}),o.definition&&h.jsx("p",{className:"term-def",children:o.definition}),h.jsxs("div",{className:"kv",children:[h.jsx("span",{className:"k",children:"source"}),h.jsx("span",{className:"v",children:o.source})]}),o.broader.length>0&&h.jsxs(h.Fragment,{children:[h.jsx("h4",{children:"broader"}),o.broader.map(f=>h.jsxs("button",{className:"rel-link",onClick:()=>m(f.iri),children:["↑ ",f.label]},f.iri))]}),o.narrower.length>0&&h.jsxs(h.Fragment,{children:[h.jsx("h4",{children:"narrower"}),o.narrower.map(f=>h.jsxs("button",{className:"rel-link",onClick:()=>m(f.iri),children:["↓ ",f.label]},f.iri))]})]}):h.jsxs("div",{className:"panel-body",children:[l.length>0&&h.jsxs("div",{className:"src-picker",children:[h.jsx("button",{className:"src-chip"+(u===""?" active":""),onClick:()=>d(""),children:"all sources"}),l.map(f=>h.jsxs("button",{className:"src-chip"+(u===f.id?" active":""),title:(f.description??"")+(f.count!=null?` · ${f.count} terms`:" · live"),onClick:()=>d(f.id),children:[f.name,f.layer&&h.jsx("span",{className:`src-layer layer-${f.layer}`,children:f.layer})]},f.id))]}),h.jsx("input",{className:"edit-input",placeholder:u?`Search within ${u}…`:"Search vocabulary terms…",value:e,onChange:f=>t(f.target.value)}),h.jsx("p",{className:"meta-line",children:l.length>0?`${l.length} source${l.length>1?"s":""}: ${s.vocabs.join(", ")}`+(s.loaded>0?` · ${s.loaded} local terms indexed`:""):"no vocabulary loaded — declare ontology_stack in mdl-project.yaml or run `mdl ontology vendor fibo`"}),h.jsx("div",{className:"term-results",children:n.map(f=>h.jsxs("button",{className:"term-card",onClick:()=>m(f.prefixed),children:[h.jsxs("div",{className:"term-head",children:[h.jsx("span",{className:"term-label",children:f.label}),h.jsxs("span",{className:"term-source",children:[f.source_kind==="glossary-term"&&h.jsx("span",{className:"kind-badge",title:"glossary term",children:"glossary"}),f.source]})]}),h.jsx("code",{className:"term-iri",children:f.prefixed}),f.definition&&h.jsx("p",{className:"term-def",children:f.definition})]},f.iri))})]})}const ux=["industry","core","domain","specialised"];function dx({refreshKey:e,onFocusEntity:t}){const[n,r]=w.useState(null),[s,i]=w.useState(null);if(w.useEffect(()=>{bm().then(r).catch(()=>{}),vm().then(i).catch(()=>{})},[e]),!n)return h.jsx("div",{className:"panel-body",children:"loading…"});const o=new Set((s==null?void 0:s.core_uncovered)??[]);return h.jsxs("div",{className:"panel-body",children:[s&&h.jsxs("div",{className:"coverage-banner"+(s.coverage_pct<100?" warn":""),children:["industry alignment coverage: ",h.jsxs("b",{children:[s.coverage_pct,"%"]})," (",s.core_with_industry,"+",s.core_exempt,"/",s.total_core," core terms)"]}),h.jsxs("div",{className:"layer-band external",children:[h.jsx("h4",{children:"industry (external vocabularies)"}),n.external_terms.length===0&&h.jsx("p",{className:"empty-hint",children:"no aligned terms yet"}),n.external_terms.map(a=>h.jsxs("div",{className:"stack-term external",title:a.definition??void 0,children:[a.label,h.jsx("span",{className:"term-source",children:a.source})]},a.iri))]}),ux.slice(1).map(a=>h.jsxs("div",{className:"layer-band",children:[h.jsx("h4",{children:a}),(n.layers[a]??[]).length===0&&h.jsx("p",{className:"empty-hint",children:"—"}),(n.layers[a]??[]).map(l=>{var c;return h.jsxs("button",{className:"stack-term"+(o.has(l.name)?" uncovered":""),title:l.definition??void 0,onClick:()=>t(l.id),children:[l.name,(l.aligned_refs??(l.aligned_to?[l.aligned_to]:[])).map((u,d)=>h.jsxs("span",{className:"align-arrow"+(u.resolved?"":" unresolved")+(u.status==="proposed"?" proposed":""),title:u.ref+(u.resolved_via?` (via ${u.resolved_via})`:""),children:["↑ ",u.label,u.status==="proposed"?" ·prop":""]},`${u.ref}-${d}`)),!l.aligned_to&&(((c=l.aligned_refs)==null?void 0:c.length)??0)===0&&!l.no_industry_equivalent&&h.jsx("span",{className:"align-arrow missing",children:"unaligned"})]},l.id)})]},a))]})}function fx({readOnly:e,refreshKey:t,onModelChanged:n}){const[r,s]=w.useState(null),[i,o]=w.useState(""),[a,l]=w.useState(""),[c,u]=w.useState(!1),d=w.useCallback(()=>{Em().then(s).catch(()=>s(null)),Nm().then(m=>o([m.diff,...m.untracked].filter(Boolean).join(` - -`))).catch(()=>o(""))},[]);return w.useEffect(d,[d,t]),r!=null&&r.git?r.clean?h.jsx("div",{className:"panel-body ok",children:"✓ working tree clean"}):h.jsxs("div",{className:"panel-body",children:[h.jsx("ul",{className:"dirty-list",children:r.dirty.map(m=>h.jsxs("li",{children:[h.jsx("code",{className:"dirty-state",children:m.state})," ",m.path]},m.path))}),h.jsx("pre",{className:"diff-view",children:i.split(` -`).map((m,f)=>h.jsx("span",{className:m.startsWith("+")&&!m.startsWith("+++")?"diff-add":m.startsWith("-")&&!m.startsWith("---")?"diff-del":m.startsWith("@@")?"diff-hunk":"",children:m+` -`},f))}),!e&&h.jsxs(h.Fragment,{children:[h.jsx("input",{className:"edit-input",placeholder:"commit message…",value:a,onChange:m=>l(m.target.value)}),h.jsxs("div",{className:"modal-footer",children:[h.jsx("button",{className:"mini-btn danger",disabled:c,onClick:()=>{confirm("Discard ALL uncommitted model changes?")&&(u(!0),km().then(()=>{u(!1),d(),n()}))},children:"Discard all"}),h.jsx("button",{className:"primary-btn",disabled:c||!a.trim(),onClick:()=>{u(!0),Sm(a).then(()=>{u(!1),l(""),d()})},children:"Commit"})]})]})]}):h.jsx("div",{className:"panel-body",children:"model directory is not in a git repo"})}function hx({readOnly:e}){const[t,n]=w.useState([]),r=w.useCallback(()=>{jm().then(i=>n(i.decisions)).catch(()=>n([]))},[]);if(w.useEffect(r,[r]),t.length===0)return h.jsx("div",{className:"panel-body",children:"no recorded decisions (run `mdl reverse` to propose)"});const s={accepted:"✓",rejected:"✗",proposed:"?"};return h.jsx("div",{className:"panel-body",children:t.map(i=>h.jsxs("div",{className:"decision "+i.verdict,children:[h.jsxs("div",{className:"decision-head",children:[h.jsx("span",{className:"decision-mark",children:s[i.verdict]}),h.jsx("span",{className:"chip",children:i.confidence}),h.jsx("span",{className:"chip",children:i.signal})]}),h.jsx("p",{className:"decision-subject",children:i.subject}),!e&&i.verdict==="proposed"&&h.jsxs("div",{className:"decision-actions",children:[h.jsx("button",{className:"mini-btn",onClick:()=>Os(i.signal_key,"accepted").then(r),children:"Accept"}),h.jsx("button",{className:"mini-btn danger",onClick:()=>Os(i.signal_key,"rejected").then(r),children:"Reject"})]})]},i.signal_key))})}function Px({exec:e,canEdit:t,onImported:n,submitLabel:r="Import & review",buttonClass:s="erd-action ghost",applyBatch:i,openImport:o=!1}){const[a,l]=w.useState(o&&t?"import":null),[c,u]=w.useState([]),[d,m]=w.useState("postgres"),f=w.useRef(null);w.useEffect(()=>{Cm().then(p=>u(p.formats)).catch(()=>u([]))},[]),w.useEffect(()=>{if(!a)return;const p=v=>{f.current&&!f.current.contains(v.target)&&l(null)};return document.addEventListener("mousedown",p),()=>document.removeEventListener("mousedown",p)},[a]);const y=c.find(p=>p.id==="sql");return h.jsxs("div",{className:"ie-wrap",ref:f,children:[h.jsxs("button",{className:s+(a==="export"?" on":""),onClick:()=>l(a==="export"?null:"export"),children:[h.jsx("span",{className:"erd-ico","aria-hidden":"true",children:"↧"}),"Export ",h.jsx("span",{className:"erd-caret",children:"▾"})]}),t&&h.jsxs("button",{className:s+(a==="import"?" on":""),onClick:()=>l(a==="import"?null:"import"),children:[h.jsx("span",{className:"erd-ico","aria-hidden":"true",children:"↥"}),"Import ",h.jsx("span",{className:"erd-caret",children:"▾"})]}),a==="export"&&h.jsxs("div",{className:"ie-menu",role:"menu",children:[(y==null?void 0:y.dialects)&&h.jsxs("label",{className:"ie-dialect",children:[h.jsx("span",{children:"SQL dialect"}),h.jsx("select",{value:d,onChange:p=>m(p.target.value),children:y.dialects.map(p=>h.jsx("option",{value:p,children:p},p))})]}),c.map(p=>h.jsx("a",{className:"ie-item",href:$m(p.id,p.id==="sql"?d:void 0),download:!0,onClick:()=>l(null),children:p.label},p.id))]}),a==="import"&&h.jsx(mx,{exec:e,submitLabel:r,buttonClass:s,applyBatch:i,onClose:()=>l(null),onImported:p=>{l(null),n==null||n(p)}})]})}const di=[{id:"sql",label:"SQL DDL",hint:"CREATE TABLE … PRIMARY KEY / FOREIGN KEY"},{id:"mermaid",label:"Mermaid erDiagram",hint:"structural: entities, attributes, relationships"},{id:"json-schema",label:"JSON Schema",hint:"each object definition becomes an entity"},{id:"erwin",label:"erwin XML",hint:"entities, keys, relationships, subject areas, subtypes"}];function mx({exec:e,submitLabel:t,buttonClass:n,applyBatch:r,onClose:s,onImported:i}){var b;const[o,a]=w.useState("sql"),[l,c]=w.useState("postgres"),[u,d]=w.useState(""),[m,f]=w.useState(!1),[y,p]=w.useState(null),[v,x]=w.useState([]),_=j=>{j&&j.text().then(d).catch(()=>p("could not read that file"))},M=async()=>{f(!0),p(null),x([]);try{const j=await Mm(o,u,o==="sql"?l:void 0);if(!j.changes.length){p(j.warnings[0]??"nothing to import from that document"),f(!1);return}if(r)await r(j.changes);else for(const C of j.changes)await e(C.op,C.payload);x(j.warnings),i(j.tables)}catch(j){p(j instanceof Error?j.message:String(j))}finally{f(!1)}};return h.jsxs("div",{className:"ie-menu ie-import",role:"dialog",children:[h.jsx("div",{className:"ie-tabs",children:di.map(j=>h.jsx("button",{className:"ie-tab"+(o===j.id?" active":""),onClick:()=>a(j.id),children:j.label},j.id))}),h.jsx("p",{className:"ie-hint",children:(b=di.find(j=>j.id===o))==null?void 0:b.hint}),o==="sql"&&h.jsxs("label",{className:"ie-dialect",children:[h.jsx("span",{children:"dialect"}),h.jsx("select",{value:l,onChange:j=>c(j.target.value),children:["postgres","snowflake","mysql","duckdb"].map(j=>h.jsx("option",{children:j},j))})]}),h.jsx("textarea",{className:"ie-textarea",placeholder:`Paste ${o} here, or choose a file…`,value:u,onChange:j=>d(j.target.value),rows:8}),h.jsx("input",{type:"file",className:"ie-file",accept:".sql,.mmd,.md,.json,.xml,.txt",onChange:j=>{var C;return _(((C=j.target.files)==null?void 0:C[0])??null)}}),o==="mermaid"&&h.jsx("p",{className:"ie-warn",children:"Mermaid is a diagram format: types and keys are approximate and relationships are inferred from the lines."}),v.map((j,C)=>h.jsx("p",{className:"ie-warn",children:j},C)),y&&h.jsx("p",{className:"ie-error",children:y}),h.jsxs("div",{className:"ie-foot",children:[h.jsx("button",{className:n,onClick:s,children:"Cancel"}),h.jsx("button",{className:n,disabled:m||!u.trim(),onClick:M,children:m?"Importing…":t})]})]})}export{Vo as A,xm as B,fm as C,Rm as E,Px as I,dx as L,Dx as M,cx as O,ci as P,To as R,Lx as S,xx as a,Cx as b,kx as c,Mx as d,Ax as e,yx as f,Em as g,Ix as h,jx as i,vx as j,_x as k,Ex as l,Sx as m,Nx as n,Bo as o,$x as p,wx as q,bx as r,_m as s,ri as t,Do as u,ix as v,im as w}; diff --git a/packages/server/src/mdl_server/static/index.html b/packages/server/src/mdl_server/static/index.html index 47f766d..3ef1a9a 100644 --- a/packages/server/src/mdl_server/static/index.html +++ b/packages/server/src/mdl_server/static/index.html @@ -4,9 +4,9 @@ Modelith - + - + diff --git a/packages/server/src/mdl_server/static/mocks.html b/packages/server/src/mdl_server/static/mocks.html index 9fd9841..66810f1 100644 --- a/packages/server/src/mdl_server/static/mocks.html +++ b/packages/server/src/mdl_server/static/mocks.html @@ -4,10 +4,10 @@ Modelith — Model Git-Ops mocks - + - +
diff --git a/packages/server/src/mdl_server/static/sme.html b/packages/server/src/mdl_server/static/sme.html index 85a3038..ccd2daa 100644 --- a/packages/server/src/mdl_server/static/sme.html +++ b/packages/server/src/mdl_server/static/sme.html @@ -4,11 +4,11 @@ Modelith Glossary - + - + - +
diff --git a/packages/server/tests/test_import_erwin_api.py b/packages/server/tests/test_import_erwin_api.py index d5f554b..42f0cff 100644 --- a/packages/server/tests/test_import_erwin_api.py +++ b/packages/server/tests/test_import_erwin_api.py @@ -31,3 +31,51 @@ def test_api_import_empty_content_422(tmp_path): client = TestClient(create_app(tmp_path)) r = client.post("/api/import", json={"format": "erwin", "content": ""}) assert r.status_code == 422 + + +def test_import_preview_returns_diff_doc_and_changes(tmp_path): + """Pre-write review: /api/import/preview returns a ModelDiffDoc (the review view's shape) + PLUS the import's changes + warnings, and writes nothing.""" + (tmp_path / "mdl-project.yaml").write_text("name: t\ndbt_target: duckdb\n") + client = TestClient(create_app(tmp_path)) + r = client.post("/api/import/preview", json={"format": "erwin", "content": _erwin_xml()}) + assert r.status_code == 200, r.text + doc = r.json() + # the ModelDiffDoc contract the canvas review view consumes + assert doc["ok"] is True + assert "objects" in doc and isinstance(doc["objects"], list) + assert "max_severity" in doc and "has_breaking" in doc + assert doc["base"]["label"] == "current model" + assert doc["head"]["label"] == "erwin import" + # into an empty model, the 3 erwin entities are all ADDED + names = {o.get("name_after") for o in doc["objects"]} + assert {"counterparty", "trade", "institution"} <= names + assert all(o["change"] == "added" for o in doc["objects"] if o["object_kind"] == "logical_entity") + # the write payload rides along for the apply action + ops = {c["op"] for c in doc["changes"]} + assert "create_entity" in ops + assert isinstance(doc["warnings"], list) + # it wrote nothing — the model dir still has only the project file + assert not (tmp_path / "logical").exists() + + +def test_import_preview_non_erwin_422(tmp_path): + (tmp_path / "mdl-project.yaml").write_text("name: t\ndbt_target: duckdb\n") + client = TestClient(create_app(tmp_path)) + r = client.post("/api/import/preview", json={"format": "sql", "content": "CREATE TABLE t(x int);"}) + assert r.status_code == 422 + + +def test_import_stash_roundtrip_is_one_shot(tmp_path): + """A host (VS Code) stashes .xml content; the canvas fetches it once by token.""" + (tmp_path / "mdl-project.yaml").write_text("name: t\ndbt_target: duckdb\n") + client = TestClient(create_app(tmp_path)) + put = client.post("/api/import/stash", json={"content": ""}) + assert put.status_code == 200 + token = put.json()["token"] + got = client.get(f"/api/import/stash/{token}") + assert got.status_code == 200 and got.json()["content"] == "" + # consumed -> a second read is 404 + assert client.get(f"/api/import/stash/{token}").status_code == 404 + # empty content is rejected + assert client.post("/api/import/stash", json={"content": ""}).status_code == 422 diff --git a/packages/server/tests/test_review_diff_contract.py b/packages/server/tests/test_review_diff_contract.py new file mode 100644 index 0000000..2f431ad --- /dev/null +++ b/packages/server/tests/test_review_diff_contract.py @@ -0,0 +1,72 @@ +"""System test: the ModelDiffDoc the review view (canvas DiffView Phase 1) consumes. + +The canvas review view filters and per-field-selects over the diff the server produces +from /api/preview. This asserts the exact wire contract that per-field selection depends +on — every changed object carries a stable ulid, and its field changes carry a `field` +key — so a frontend `(ulid, field)` selection maps to a real server change. If this shape +drifts, the canvas selection silently breaks; this test is the guard. +""" + +from __future__ import annotations + + +def _le(client, name: str) -> str: + doc = client.get("/api/model").json() + return next(e for e in doc["entities"] if e["name"] == name)["id"] + + +def test_preview_diff_has_ulid_and_field_keyed_changes(client): + """A modify preview yields a diff whose objects have ulids and whose field changes + have `field` keys — the (ulid, field) identity the review view selects over.""" + r = client.post( + "/api/preview", + json={ + "changes": [ + {"op": "rename_entity", "payload": {"id": _le(client, "trade"), "name": "deal"}} + ] + }, + ) + assert r.status_code == 200 + doc = r.json() + assert doc["ok"] + diff = doc["diff"] + assert diff["objects"], "a rename should produce at least one changed object" + + obj = diff["objects"][0] + # the identity half of a (ulid, field) selection key + assert obj["ulid"], "every changed object carries a stable ulid" + assert obj["change"] in ("added", "removed", "modified") + # the field half — each field change is independently addressable + for f in obj["fields"]: + assert "field" in f and f["field"], "each field change has a stable field key" + assert "severity" in f + assert f["severity"] in ("breaking", "additive", "cosmetic", "unmanaged") + + +def test_preview_diff_change_types_cover_the_filter_categories(client): + """The review view's filters (additions/modifications/renames/deletions) key off + `change` and `renamed`. A rename must be flagged renamed=True with change=modified, + so the 'Renames' filter isolates it — the exact field the frontend filters on.""" + r = client.post( + "/api/preview", + json={ + "changes": [ + {"op": "rename_entity", "payload": {"id": _le(client, "counterparty"), "name": "party"}} + ] + }, + ) + diff = r.json()["diff"] + renamed = [o for o in diff["objects"] if o["renamed"]] + assert renamed, "a rename must surface as a renamed object for the Renames filter" + assert all(o["change"] == "modified" for o in renamed) + + +def test_preview_diff_is_stable_for_selection(client): + """The same staged change previewed twice yields the same object ulids — so a + per-field selection the user made does not shift under them on a re-preview.""" + change = [ + {"op": "rename_entity", "payload": {"id": _le(client, "trade"), "name": "deal"}} + ] + first = client.post("/api/preview", json={"changes": change}).json()["diff"] + second = client.post("/api/preview", json={"changes": change}).json()["diff"] + assert [o["ulid"] for o in first["objects"]] == [o["ulid"] for o in second["objects"]] diff --git a/specs/modelith-semantic-compare-merge-spec.md b/specs/modelith-semantic-compare-merge-spec.md new file mode 100644 index 0000000..93cf9f6 --- /dev/null +++ b/specs/modelith-semantic-compare-merge-spec.md @@ -0,0 +1,208 @@ +# Semantic model compare & merge — one review view across every change flow + +## Context + +Modelith presents model changes in many flows — staged edits (preview), SME proposals, git-ref diffs, +drift, reverse-inference acceptance, imports, merge conflicts — but the review experience is fragmented +and the richest view is trapped in one corner of the Studio Canvas (the SME propose flow). A mature +commercial modeling tool (Hackolade Studio) ships a 3-pane semantic compare & merge (left / merged / +right) with per-change accept/reject for additions, modifications, moves and deletions, matching-method +and display filters, and conflict markers. That is the bar for a data-modeling tool. + +This is also the paid wedge made visible. The GTM thesis is that the commercial product is +drift-enforcement-in-CI, whose hard SLO is "classify a change as breaking/additive/cosmetic and name the +exact dbt models a breaking change will take down, at PR time." A rich, shared diff/merge view is how +that classification lands in the product. It ships FREE for local review (the bottom-up funnel); the +*blocking* CI gate, shared policy, and report stay the paid server boundary. The incumbent gates all of +this behind a desktop license key; Modelith gives compare/merge away and charges for the team gate. + +**The foundation already exists** (validated by codebase exploration): +- One canonical semantic-diff payload — `ModelDiffDoc`: ULID-keyed, nested object→fields→children, + severity-tagged (breaking/additive/cosmetic/unmanaged), per-field before/after. Built by + `ModelDiff.to_doc()` (`packages/core/src/mdl_core/diff.py:283`), serialized by `render_json` + (`packages/core/src/mdl_core/diff_render.py:29`), mirrored at `canvas/src/types.ts:351`. Server + enriches it with `path` (source file per object) and `breaks` (dbt models a breaking change would + break) via `_attach_paths`/`_attach_breaks` (`packages/server/src/mdl_server/git_api.py:417,430`). +- One shape-aware renderer — `canvas/src/sme/DiffView.tsx` (word-diff for prose, +/− chips for lists, + scalar before→after, break-impact panel), already prop-driven and API-free. +- An ER diff overlay — `canvas/src/sme/ModelDiagram.tsx` tints `EntityNode`/`RelationshipEdge` by a + `severityByUlid` map. +- A review shell — `canvas/src/sme/ReviewScreen.tsx` (changes/diagram tabs, route/reviewer panel, + conflict banner). +- VS Code already embeds the Canvas via an iframe webview parameterized by `?query` (`?import=1`), + `vscode/src/canvasPanel.ts:59,169` — so a review route renders in VS Code with no new rendering code. +- Flows already producing `ModelDiffDoc`: preview (`/api/preview` → `PreviewDoc.diff`), propose + (`/api/git/propose`), git-diff (`/api/git/diff/model|refs`). A name-keyed variant + `diff_models_by_name` (`diff.py:550`) exists for fresh-ULID comparisons (import/compare). + +**The gaps this spec closes:** +1. Selection is per-OBJECT, not per-FIELD, and there is no 3-pane merge / conflict resolution. +2. Drift (`DriftReport`), reverse-decisions (ledger), and conflicts (`ConflictDoc`) don't speak + `ModelDiffDoc` — they need adapters into it (severity vocabulary is already shared). +3. Import writes-then-git-diffs instead of a semantic "review before it lands." +4. VS Code has no semantic diff (only native text diff + a drift tree); `compareReversed` is a + text-diff outlier. +5. Accept/apply semantics differ per flow (PR / ledger verdict / reconcile / write) — the view needs a + pluggable apply action, not one hardcoded to propose. + +Intended outcome: a modeler reviews any model change — staged edit, drift, inferred relationship, erwin +import, branch comparison, merge conflict — in the SAME rich, filterable, per-change-selectable view, +in both the Canvas and VS Code. + +## Design + +### One payload, one component, pluggable sources and sinks + +``` + SOURCES (adapters → ModelDiffDoc) SHARED VIEW SINKS (pluggable apply) + preview ─┐ ┌───────────────┐ propose → PR + git-diff/refs ┼─ already ModelDiffDoc ─▶│ ReviewView │──accept──▶ ledger → verdict write + propose ─┘ │ DiffView++ │ drift → --reconcile fold + drift ───────── DriftReport ─adapter─▶│ filters │ import → write files + decisions ────── Decision[] ─adapter─▶│ per-field │ (read-only sources: no sink) + import ───────── diff_by_name ────────▶ │ ER overlay │ + conflicts ────── merge_driver ─3-way──▶ │ 3-pane merge │ + └───────────────┘ +``` + +The whole design is: everything converges on `ModelDiffDoc`, one React component renders it, and each +flow supplies (a) a fetch that returns the doc and (b) an apply action. `ModelDiffDoc` is not changed in +shape; where a 3-pane merge needs base/ours/theirs, that is carried as an optional wrapper, not a new +per-node schema. + +### The shared component: `ReviewView` + +Generalize `DiffView`/`ReviewScreen` into a reusable `ReviewView` that stays prop-driven and API-free +(so VS Code hosts it verbatim in the webview). It renders a `ModelDiffDoc` and takes: +- `diff: ModelDiffDoc` (2-way) or `merge: { base, ours, theirs, conflicts }` (3-way). +- `selection`: per-FIELD selection — keys are `(ulid, field)` not just object ULIDs, so a user can + accept the definition change but reject the domain change on one attribute (the competitor's + per-addition/modification/move toggles). Widen the existing staging set (`SmeApp.excluded`, + `canvas/src/staging/useStaging.ts`) from object to field granularity; keep the dependency-locking + (`dependentKeys`) so changes that must travel together stay linked. +- `filters`: client-side over the doc — show all / only differences / only additions / only deletions / + only modifications / only moves / only conflicts (severity + ChangeType are already on each node). + This is the competitor's left rail. +- `actions: { label, apply(selection) }[]`: the pluggable action bar. Same component drives Propose + (PR), Accept (ledger verdict), Reconcile (drift fold), Apply-import (write files). Read-only sources + pass none. +- `mode`: `"unified"` (default 2-pane master-detail, today's view) or `"three-pane"` (base | merged | + right, for merge/conflict sources) reusing `FieldDiff` in each pane. +- ER overlay tab stays (`ModelDiagram` + `severityByUlid`), now available to every source. + +Reuse, do not rewrite: `FieldDiff`/`wordDiff` (shape-aware rendering), `ModelDiagram` (ER overlay), +`ReviewScreen`'s route/reviewer/conflict panels. + +### Source adapters → `ModelDiffDoc` + +Keep `diff_models` pure; adapters live beside the server enrichers and reuse `_attach_paths`/ +`_attach_breaks` so every source gets source-file + break-impact enrichment. +- **Drift → ModelDiffDoc**: `drift_to_diff(report, model)` maps each `DriftItem` (name-keyed, + manifest-shaped, `packages/reverse/src/mdl_reverse/drift.py`) onto an `ObjectChange`/`FieldChange` + (name-keyed, like the `--against` path), preserving `payload` for the reconcile action and the shared + severity. New endpoint `GET /api/drift?target=` returns the adapted doc (drift has no server endpoint + today — it is CLI/CI-only). Apply action = `mdl drift --reconcile` fold for additive/cosmetic. +- **Decisions → ModelDiffDoc**: `decisions_to_diff(ledger, model)` turns each proposed `Decision` (an + inferred relationship, a stripped key, an SCD2 pattern; `packages/reverse/src/mdl_reverse/ledger.py`) + into a proposed `ObjectChange` with its `evidence` as detail. Apply action = `set_verdict` + (accept/reject) — reuse `POST /api/decisions/{signal_key}/verdict`. +- **Import (pre-write) → ModelDiffDoc**: wire `diff_models_by_name(current_model, imported_model)` + (`diff.py:550`, name-keyed since imported ULIDs are fresh) so erwin/DDL imports show a semantic diff + BEFORE writing. New endpoint `POST /api/import/preview` returns the doc; apply action writes the + files. This is the highest-value new flow — today imports write then git-diff. +- **Conflicts → 3-way (last)**: `merge_model_files` already computes structural base/ours/theirs + conflicts (`packages/core/src/mdl_core/merge_driver.py:31`); `conflicts_to_diff` feeds the 3-pane + mode. Lowest priority (furthest from the current shape); design the 3-pane contract for it, implement + drift/decisions/import first. + +### Routing in the Canvas + +Add a source-parameterized review route to the hash router (`canvas/src/sme/SmeApp.tsx` already +hash-routes tabs): `#review?source=drift`, `?source=diff&base=main&head=`, `?source=import`, +`?source=decisions`. A small per-source loader fetches the adapted doc and mounts `ReviewView` with the +right actions. Re-point the architect canvas's raw `
` textual git diff (`ChangesView`,
+`canvas/src/SidePanel.tsx:291`) and `DecisionsView` at the shared component so the direct-write app gets
+the rich review too.
+
+### Surfacing in VS Code (via the existing webview — no new rendering code)
+
+Primary path: commands `modelith.reviewDrift`, `modelith.reviewChanges` (working tree vs base),
+`modelith.reviewImport`, `modelith.reviewDecisions`, each calling `canvas.open(dir, "review&source=…")`
+so `ReviewView` renders in the `modelithCanvas` iframe webview exactly as `?import=1` does today. Keep
+the native Drift tree (`vscode/src/driftView.ts`) and Reverse Review tree (`vscode/src/reverseView.ts`)
+as fast glance-able entry points, and add an "Open in review" action on each that launches the webview
+for the deep-dive. Re-point `modelith.compareReversed` (`vscode/src/extension.ts:1472`) from the native
+text diff of `mdl model render` to the webview review over `diff_models_by_name`→`ModelDiffDoc`.
+
+## Open-core boundary (which parts are free vs paid)
+
+- **Free** (local, complete): the entire `ReviewView` — 2-pane and 3-pane, per-field selection, filters,
+  ER overlay — for reviewing staged edits, imports, local `mdl drift`, branch/ref diffs, and resolving a
+  local merge conflict. This is the bottom-up funnel; it must never be crippled.
+- **Paid (Team, server boundary)**: the *blocking* CI gate that runs the same classification in the
+  org's CI with a shared policy file and a posted PR report; CODEOWNERS-routed proposal review with PR
+  state; hosted SME Studio. The view is free; enforcing it across a team is the wedge.
+
+## Phasing (each phase shippable)
+
+1. **[SHIPPED] Per-field selection + filters + pluggable actions** on the existing 2-pane `ReviewView`,
+   wired to flows that ALREADY produce `ModelDiffDoc` (preview, propose, git-diff/refs). Immediate UX
+   win, no adapters. Modernizes the SME review on its own.
+2. **[SHIPPED] Import pre-write review** (import adapter + canvas route + VS Code command) — highest-value
+   new flow; erwin import becomes "review before it lands," reusing phase 1. Delivered as
+   `POST /api/import/preview` (parse-without-write → enriched `ModelDiffDoc`), the `ReviewScreen`
+   `action` prop + "Apply import" (writes only selected new objects), and the `modelith.reviewImport`
+   command framed in the Reverse Review view, with a one-shot `/api/import/stash` channel so a VS Code
+   `.xml` pre-fills the review.
+3. **Drift review** (drift adapter + `/api/drift` + canvas route + VS Code command + tree "Open in
+   review").
+4. **Decisions review** (decisions adapter + route + VS Code).
+5. **3-pane merge / conflict resolution** (3-pane mode + conflicts adapter) — full compare/merge parity.
+   Last, since it is furthest from the current shape; the common 2-way review ships long before it.
+6. Re-point `compareReversed`; retire the architect `
` git diff for the shared component.
+
+## Critical files
+
+- `canvas/src/sme/DiffView.tsx`, `ReviewScreen.tsx`, `ModelDiagram.tsx` — the component to generalize.
+- `canvas/src/staging/useStaging.ts`, `sme/SmeApp.tsx` — selection state, widened to per-field.
+- `canvas/src/types.ts` — `ModelDiffDoc` and friends (shared contract; optional 3-way wrapper).
+- `canvas/src/api.ts` — new fetches (`/api/drift`, `/api/import/preview`, decisions-as-diff).
+- `packages/server/src/mdl_server/git_api.py` — reuse `_attach_paths`/`_attach_breaks`; new endpoints.
+- `packages/server/src/mdl_server/` — new adapter module(s): `drift_to_diff`, `decisions_to_diff`.
+- `packages/core/src/mdl_core/diff.py` — `diff_models_by_name` (reuse); shared adapter helpers.
+- `vscode/src/extension.ts`, `canvasPanel.ts`, `driftView.ts`, `reverseView.ts` — review commands +
+  `canvas.open(dir, "review&source=…")`; re-point `compareReversed`.
+
+## Verification
+
+- `uv run pytest && uv run ruff check packages/` — adapters produce valid `ModelDiffDoc` the canvas
+  types accept; new endpoints return the right shape; existing diff/drift tests unchanged.
+- `cd canvas && npm run build` (Node 20) — generalized `ReviewView` typechecks; per-field selection +
+  filters render.
+- `cd vscode && npm run typecheck && npm run regression` (Node 20) — review commands registered
+  (Gate 3), all gates green.
+- Manual per phase: open the review from each wired flow in the Canvas AND VS Code (webview); toggle
+  per-field selections + filters; exercise each source's apply action; import shows a semantic diff
+  before writing.
+- Clean-install Docker check (`./sandbox/clean-install/run.sh`) still green (server/import path).
+
+## Non-goals / explicitly rejected
+
+- A monolithic desktop-IDE workspace (Object Browser + Properties pane + central pane): fights the
+  git-native, CLI-first, every-surface-a-client architecture. Modelith's equivalent is Canvas +
+  Inspector + VS Code.
+- An in-app Git panel (branch/commit/PR management inside the tool): anti-strategic. Modelith IS
+  git-native; re-centralizing git state contradicts the core differentiator.
+- Changing `ModelDiffDoc`'s per-node shape. Merge state (base/ours/theirs) is an optional wrapper, not a
+  schema change, so the one payload and one renderer stay singular.
+
+## Risk posture
+
+- Additive and phased: phase 1 modernizes the existing review with no adapters and no new payload; later
+  phases add one source at a time behind the same component. Each phase ships alone.
+- One payload, one renderer: adapters converge on `ModelDiffDoc`, so there is exactly one review UI to
+  maintain; the two intentional deviations (drift name-keying, compareReversed text) are reconciled by
+  adopting the existing `diff_models_by_name`, not by inventing a shape.
+- VS Code reuse via the existing iframe webview + `?query` means the extension gains the full semantic
+  review with essentially no new rendering code — the lowest-risk cross-frontend path.
+- The 3-pane merge/conflict work is isolated to the last phase, so the hard part never blocks the wins.
diff --git a/vscode/package.json b/vscode/package.json
index 88a0ddc..b2fec66 100644
--- a/vscode/package.json
+++ b/vscode/package.json
@@ -2,7 +2,7 @@
   "name": "modelith-vscode",
   "displayName": "Modelith",
   "description": "Ontology-anchored, git-native data modeling for dbt — validate, generate, drift, and the Modelith canvas inside VS Code.",
-  "version": "0.3.18",
+  "version": "0.3.19",
   "publisher": "BosonResearch",
   "license": "Apache-2.0",
   "icon": "icon.png",
@@ -90,11 +90,17 @@
     },
     "views": {
       "modelith": [
+        {
+          "id": "modelithModel",
+          "name": "Model",
+          "icon": "$(symbol-class)",
+          "contextualTitle": "Modelith Model"
+        },
         {
           "id": "modelithConfig",
-          "name": "Warehouse Config",
+          "name": "Warehouse Mapping",
           "icon": "$(settings-gear)",
-          "contextualTitle": "Modelith Warehouse Config"
+          "contextualTitle": "Modelith Warehouse Mapping"
         },
         {
           "id": "modelithReverse",
@@ -235,12 +241,21 @@
       },
       {
         "command": "modelith.configRefresh",
-        "title": "Modelith: Refresh Warehouse Config",
+        "title": "Modelith: Refresh Warehouse Mapping",
         "icon": "$(refresh)"
       },
       {
         "command": "modelith.configFocusView",
-        "title": "Modelith: Show Warehouse Config"
+        "title": "Modelith: Show Warehouse Mapping"
+      },
+      {
+        "command": "modelith.refreshModel",
+        "title": "Modelith: Refresh Model tree",
+        "icon": "$(refresh)"
+      },
+      {
+        "command": "modelith.openModelObject",
+        "title": "Modelith: Open model object"
       },
       {
         "command": "modelith.configOpenProject",
@@ -290,6 +305,11 @@
         "title": "Modelith: Import Erwin XML",
         "icon": "$(cloud-download)"
       },
+      {
+        "command": "modelith.reviewImport",
+        "title": "Modelith: Review Erwin Import",
+        "icon": "$(diff)"
+      },
       {
         "command": "modelith.stopServer",
         "title": "Modelith: Stop Canvas Server"
@@ -494,6 +514,11 @@
           "when": "resourceExtname == .xml",
           "group": "modelith@1"
         },
+        {
+          "command": "modelith.reviewImport",
+          "when": "resourceExtname == .xml",
+          "group": "modelith@2"
+        },
         {
           "command": "modelith.liftModel",
           "when": "resourceExtname == .sql",
@@ -528,6 +553,11 @@
         }
       ],
       "view/title": [
+        {
+          "command": "modelith.refreshModel",
+          "when": "view == modelithModel",
+          "group": "navigation@1"
+        },
         {
           "command": "modelith.configSuggest",
           "when": "view == modelithConfig",
@@ -568,6 +598,11 @@
           "when": "view == modelithReverse",
           "group": "navigation@3"
         },
+        {
+          "command": "modelith.reviewImport",
+          "when": "view == modelithReverse",
+          "group": "navigation@4"
+        },
         {
           "command": "modelith.compareReversed",
           "when": "view == modelithReverse",
diff --git a/vscode/scripts/treeview.test.mjs b/vscode/scripts/treeview.test.mjs
index 8ff9ddf..153eaa8 100644
--- a/vscode/scripts/treeview.test.mjs
+++ b/vscode/scripts/treeview.test.mjs
@@ -20,11 +20,12 @@ const VSCODE_STUB = `
 export const TreeItemCollapsibleState = { None: 0, Collapsed: 1, Expanded: 2 };
 export class ThemeIcon { constructor(id, color) { this.id = id; this.color = color; } }
 export class ThemeColor { constructor(id) { this.id = id; } }
-export class MarkdownString { constructor(v) { this.value = v; } }
+export class MarkdownString { constructor(v) { this.value = v ?? ""; } appendMarkdown(v) { this.value += v; return this; } }
 export class TreeItem {
   constructor(label, collapsibleState) { this.label = label; this.collapsibleState = collapsibleState; }
 }
 export class EventEmitter { constructor(){ this.event = () => ({ dispose(){} }); } fire(){} dispose(){} }
+export const Uri = { file: (p) => ({ fsPath: p, path: p, scheme: "file" }) };
 export const window = { createOutputChannel: () => ({ appendLine(){}, append(){}, show(){} }) };
 export const workspace = { getConfiguration: () => ({ get: () => undefined }) };
 // ./mdl exports the provider imports — never called here (we drive getChildren directly).
@@ -226,6 +227,71 @@ console.log("\nWarehouse Config — unclassified custom prefixes surface for ass
   ok(!top.some((n) => n.kind === "prefixGroup" && n.prefix !== "pres_art_"), "only real unclassified prefixes group");
 }
 
+// --- Model frame: entity → attribute drill-down + click-to-open the YAML ------------
+const { ModelTreeProvider } = await load("modelView.ts");
+console.log("\nModel tree — entities expand to attributes; click opens the YAML");
+{
+  const p = new ModelTreeProvider({ appendLine() {}, append() {}, show() {} });
+  // inject the model dir + entities (bypass the CLI); getChildren renders from them
+  p.modelDir = "/tmp/proj/model";
+  p.entities = [
+    {
+      name: "counterparty",
+      physical_name: "COUNTERPARTY",
+      subject_area: "Trading",
+      definition: "A trading partner.",
+      pattern: null,
+      file: "logical/entities/counterparty.yaml",
+      attributes: [
+        { name: "counterparty_id", physical_name: null, domain: "id_bigint", role: "business_key", nullable: false, is_pk: true },
+        { name: "legal_name", physical_name: null, domain: "string", role: "attribute", nullable: true, is_pk: false },
+      ],
+    },
+    { name: "trade", physical_name: null, subject_area: "Trading", definition: null, pattern: null, file: "logical/entities/trade.yaml", attributes: [] },
+  ];
+
+  // top level = one row per entity, each collapsible when it has attributes
+  const top = p.getChildren();
+  const topItems = top.map((n) => p.getTreeItem(n));
+  ok(labels(topItems).join(",") === "counterparty,trade", `entities render as rows: ${labels(topItems)}`);
+  const cpItem = topItems[0];
+  ok(cpItem.collapsibleState === 1, "an entity with attributes is collapsible (drill-down)");
+  ok(String(cpItem.description).includes("2 attr"), `entity row shows an attribute count: ${cpItem.description}`);
+  ok(topItems[1].collapsibleState === 0, "an entity with no attributes is a leaf");
+
+  // clicking an entity opens its YAML (the openModelObject command with file + name)
+  ok(cpItem.command?.command === "modelith.openModelObject", "entity click opens the model object");
+  ok(String(cpItem.command.arguments[0].fsPath ?? cpItem.command.arguments[0].path).includes("counterparty.yaml"),
+    "entity click targets its own logical YAML");
+
+  // expanding the entity yields its attributes, PK first-classed
+  const cpNode = top[0];
+  const attrRows = p.getChildren(cpNode);
+  const attrItems = attrRows.map((n) => p.getTreeItem(n));
+  ok(labels(attrItems).join(",") === "counterparty_id,legal_name", `attributes render in order: ${labels(attrItems)}`);
+  ok(attrItems[0].iconPath?.id === "key", "the primary-key attribute gets the key icon");
+  ok(attrItems[1].iconPath?.id === "symbol-field", "a non-key attribute gets the field icon");
+  ok(String(attrItems[0].description).includes("pk"), `pk attribute is marked: ${attrItems[0].description}`);
+  // clicking an attribute opens the OWNING entity's YAML
+  ok(attrItems[0].command?.command === "modelith.openModelObject", "attribute click opens the model object");
+  ok(String(attrItems[0].command.arguments[0].fsPath ?? attrItems[0].command.arguments[0].path).includes("counterparty.yaml"),
+    "attribute click opens the owning entity's YAML");
+}
+
+console.log("\nModel tree — resting states");
+{
+  const p = new ModelTreeProvider({ appendLine() {}, append() {}, show() {} });
+  // no model dir -> explains itself
+  const rows = p.getChildren().map((n) => p.getTreeItem(n));
+  ok(String(rows[0].label).includes("No model"), "no-model state explains itself, not blank");
+
+  const p2 = new ModelTreeProvider({ appendLine() {}, append() {}, show() {} });
+  p2.modelDir = "/tmp/proj/model";
+  p2.entities = [];
+  const rows2 = p2.getChildren().map((n) => p2.getTreeItem(n));
+  ok(String(rows2[0].label).includes("No entities"), "empty model points at init/import, not blank");
+}
+
 rmSync(dir, { recursive: true, force: true });
 console.log();
 if (failed) { console.error(`✗ ${failed} assertion(s) failed`); process.exit(1); }
diff --git a/vscode/src/canvasPanel.ts b/vscode/src/canvasPanel.ts
index 18a0e2d..098a58d 100644
--- a/vscode/src/canvasPanel.ts
+++ b/vscode/src/canvasPanel.ts
@@ -56,12 +56,15 @@ export class CanvasManager {
    * wizard the toolbar button opens is already up when the panel appears. When a
    * query is given we rewrite the iframe even on an already-open panel, so the
    * wizard opens whether or not the canvas was already showing. */
-  async open(modelDir: string, query?: string): Promise {
+  async open(modelDir: string, query?: string, path = ""): Promise {
     const cfg = vscode.workspace.getConfiguration("modelith");
     await this.ensureServer(modelDir);
     const local = vscode.Uri.parse(`http://127.0.0.1:${this.port}/`);
     const external = await vscode.env.asExternalUri(local);
-    const url = external.toString().replace(/\/$/, "") + "/" + (query ? `?${query}` : "");
+    // `path` selects which SPA (default "" = architect canvas; "sme" = the SME review app
+    // served at /sme). `query` (e.g. import=1) is appended as-is.
+    const base = external.toString().replace(/\/$/, "") + "/" + path;
+    const url = base + (query ? `?${query}` : "");
 
     if (cfg.get("canvas.display") === "external") {
       await vscode.env.openExternal(vscode.Uri.parse(url));
@@ -87,6 +90,29 @@ export class CanvasManager {
     this.panel.onDidDispose(() => (this.panel = undefined));
   }
 
+  /** Open the SME review app with the erwin import panel. If `content` is given (a .xml the
+   * host read from disk — the webview cannot read local files), stash it on the server first
+   * and open /sme?import= so the panel is pre-filled; otherwise open /sme?import=1 for
+   * a paste-or-pick. */
+  async openImportReview(modelDir: string, content?: string): Promise {
+    await this.ensureServer(modelDir);
+    let query = "import=1";
+    if (content) {
+      try {
+        const res = await fetch(`http://127.0.0.1:${this.port}/api/import/stash`, {
+          method: "POST",
+          headers: { "content-type": "application/json" },
+          body: JSON.stringify({ content }),
+        });
+        const data = (await res.json()) as { ok?: boolean; token?: string };
+        if (data.ok && data.token) query = `import=${encodeURIComponent(data.token)}`;
+      } catch {
+        // stash failed -> fall back to the paste-or-pick panel
+      }
+    }
+    await this.open(modelDir, query, "sme");
+  }
+
   /** Re-hydrate a webview panel VS Code restored after a window reload. The
    * `mdl serve` child process died with the old extension host, so the restored
    * iframe points at a dead port (blank canvas). Adopt the panel, restart the
diff --git a/vscode/src/extension.ts b/vscode/src/extension.ts
index 06e105f..266c97e 100644
--- a/vscode/src/extension.ts
+++ b/vscode/src/extension.ts
@@ -6,6 +6,7 @@ import type { LanguageClient } from "vscode-languageclient/node";
 import { CanvasManager } from "./canvasPanel";
 import { registerChatParticipant } from "./chatParticipant";
 import { ConfigTreeProvider } from "./configView";
+import { ModelTreeProvider, openModelObject } from "./modelView";
 import { DocsProvider } from "./docsView";
 import { DriftCodeActionProvider, DriftManager } from "./driftDiagnostics";
 import { DriftTreeProvider } from "./driftView";
@@ -306,12 +307,32 @@ export async function activate(ctx: vscode.ExtensionContext): Promise {
     stateWatcher.onDidDelete(onStateChange),
   );
 
-  // Warehouse Config: a live view of how the reverse: config classifies every dbt model,
-  // grouped by role, with Suggest/Import in its title bar. The home of the config workflow.
+  // Warehouse Mapping: a live view of how the reverse: config classifies every dbt model
+  // INTO entities, grouped by role, with Suggest/Import in its title bar. Distinct from the
+  // Model tree below (which is the logical model itself); this one answers "how does my
+  // warehouse map to entities?".
   const configTree = new ConfigTreeProvider(out);
   ctx.subscriptions.push(vscode.window.registerTreeDataProvider("modelithConfig", configTree));
   void configTree.refresh();
 
+  // Model: the logical model as an entity → attribute tree; clicking opens the YAML.
+  const modelTree = new ModelTreeProvider(out);
+  ctx.subscriptions.push(vscode.window.registerTreeDataProvider("modelithModel", modelTree));
+  ctx.subscriptions.push(
+    vscode.commands.registerCommand(
+      "modelith.openModelObject",
+      (uri: vscode.Uri, reveal: string) => openModelObject(uri, reveal),
+    ),
+    vscode.commands.registerCommand("modelith.refreshModel", () => modelTree.refresh()),
+    // keep the Model tree current when a logical entity YAML is saved (editor or CLI edit)
+    vscode.workspace.onDidSaveTextDocument((doc) => {
+      if (doc.uri.fsPath.includes(`${path.sep}logical${path.sep}`) && doc.uri.fsPath.endsWith(".yaml")) {
+        void modelTree.refresh();
+      }
+    }),
+  );
+  void modelTree.refresh();
+
   // Active-model indicator: which model dir the panels read. In a multi-model workspace
   // (e.g. an original model/ plus a fresh model_reversed/) auto-discovery picks the
   // shallowest, which may not be the one the user is reviewing. This status-bar item
@@ -619,6 +640,43 @@ export async function activate(ctx: vscode.ExtensionContext): Promise {
     }),
   );
 
+  cmd("modelith.reviewImport", (arg: unknown) =>
+    withModelDir(async (dir) => {
+      if (vscode.workspace.getConfiguration("modelith").get("canvas.readOnly")) {
+        void vscode.window.showWarningMessage(
+          "Modelith: the canvas is in read-only mode — turn off modelith.canvas.readOnly to import.",
+        );
+        return;
+      }
+      try {
+        // Resolve an erwin XML: the clicked file (explorer right-click), else a picker. If the
+        // user cancels the picker we still open the panel empty (they can paste).
+        let fileUri = arg instanceof vscode.Uri ? arg : undefined;
+        if (!fileUri) {
+          const picked = await vscode.window.showOpenDialog({
+            title: "Review Erwin XML before import",
+            canSelectMany: false,
+            filters: { "erwin XML": ["xml"] },
+            openLabel: "Review",
+          });
+          fileUri = picked?.[0];
+        }
+        // Read the file here (the webview can't) and hand the content to the SME review app via
+        // a one-shot server stash. An erwin import there is shown as a SEMANTIC diff you review
+        // (filters, per-field selection, break impact) BEFORE anything is written; "Apply
+        // import" writes only the entities you keep.
+        let content: string | undefined;
+        if (fileUri) {
+          content = Buffer.from(await vscode.workspace.fs.readFile(fileUri)).toString("utf8");
+        }
+        await canvas.openImportReview(dir, content);
+      } catch (e) {
+        if (isMdlNotFound(e)) throw e; // let cmd() offer the one-click installer
+        void vscode.window.showErrorMessage(`Modelith canvas: ${e}`);
+      }
+    }),
+  );
+
   // Import an erwin XML export into a fresh Modelith model. An erwin export is a whole
   // model (like a reverse), so this WRITES a model dir via the CLI (10MB-safe, server-
   // free) and opens it — not a canvas paste. Reachable from the palette, the Reverse
diff --git a/vscode/src/modelView.ts b/vscode/src/modelView.ts
new file mode 100644
index 0000000..4976e50
--- /dev/null
+++ b/vscode/src/modelView.ts
@@ -0,0 +1,189 @@
+import * as path from "path";
+import * as vscode from "vscode";
+import { findMdl, findModelDir, runMdl } from "./mdl";
+
+/** The Model tree: the LOGICAL model as an entity → attribute drill-down. Each entity
+ * expands to its attributes (PK marked), and clicking an entity or attribute opens the
+ * entity's `logical/entities/.yaml` at the right line. This is the "what is my
+ * model" view — distinct from the Warehouse Mapping tree, which shows how dbt models
+ * classify into entities. Fed by `mdl model tree --format json`, so it always reflects
+ * the committed model, never a stale copy. */
+
+export interface TreeAttribute {
+  name: string;
+  physical_name: string | null;
+  domain: string | null;
+  role: string;
+  nullable: boolean;
+  is_pk: boolean;
+}
+export interface TreeEntity {
+  name: string;
+  physical_name: string | null;
+  subject_area: string | null;
+  definition: string | null;
+  pattern: string | null;
+  file: string | null;
+  attributes: TreeAttribute[];
+}
+
+type Node = EntityNode | AttributeNode | StatusNode;
+interface EntityNode {
+  kind: "entity";
+  entity: TreeEntity;
+}
+interface AttributeNode {
+  kind: "attribute";
+  entity: TreeEntity;
+  attr: TreeAttribute;
+}
+/** A resting row when the model is empty / unreadable, so the pane explains itself
+ * instead of rendering blank. */
+interface StatusNode {
+  kind: "status";
+  label: string;
+  icon: vscode.ThemeIcon;
+}
+
+export class ModelTreeProvider implements vscode.TreeDataProvider {
+  private readonly emitter = new vscode.EventEmitter();
+  readonly onDidChangeTreeData = this.emitter.event;
+  private entities: TreeEntity[] = [];
+  private modelDir: string | undefined;
+
+  constructor(private readonly out: vscode.OutputChannel) {}
+
+  /** Re-read the model from `mdl model tree --format json`. */
+  async refresh(): Promise {
+    const dir = await findModelDir();
+    this.modelDir = dir;
+    if (!dir) {
+      this.entities = [];
+      this.emitter.fire(undefined);
+      return;
+    }
+    try {
+      const bin = await findMdl(dir);
+      const r = await runMdl(bin, ["model", "tree", "-m", ".", "--format", "json"], dir);
+      this.entities =
+        r.code === 0 && r.stdout.trim()
+          ? ((JSON.parse(r.stdout) as { entities?: TreeEntity[] }).entities ?? [])
+          : [];
+    } catch (e) {
+      this.out.appendLine(`[model] could not read the model tree: ${e}`);
+      this.entities = [];
+    }
+    this.emitter.fire(undefined);
+  }
+
+  getTreeItem(node: Node): vscode.TreeItem {
+    if (node.kind === "status") {
+      const ti = new vscode.TreeItem(node.label, vscode.TreeItemCollapsibleState.None);
+      ti.iconPath = node.icon;
+      return ti;
+    }
+    if (node.kind === "entity") {
+      const e = node.entity;
+      const ti = new vscode.TreeItem(
+        e.name,
+        e.attributes.length
+          ? vscode.TreeItemCollapsibleState.Collapsed
+          : vscode.TreeItemCollapsibleState.None,
+      );
+      ti.iconPath = new vscode.ThemeIcon("symbol-class");
+      const bits: string[] = [`${e.attributes.length} attr`];
+      if (e.subject_area) bits.push(e.subject_area);
+      if (e.pattern) bits.push(e.pattern);
+      ti.description = bits.join(" · ");
+      const md = new vscode.MarkdownString();
+      md.appendMarkdown(`**${e.name}**${e.physical_name ? ` · \`${e.physical_name}\`` : ""}\n\n`);
+      if (e.definition) md.appendMarkdown(`${e.definition}\n\n`);
+      if (e.subject_area) md.appendMarkdown(`Subject area: ${e.subject_area}\n\n`);
+      ti.tooltip = md;
+      ti.contextValue = "modelEntity";
+      // click opens the entity's logical YAML
+      ti.command = this.openCommand(e, e.name);
+      return ti;
+    }
+    // attribute row
+    const a = node.attr;
+    const ti = new vscode.TreeItem(a.name, vscode.TreeItemCollapsibleState.None);
+    ti.iconPath = new vscode.ThemeIcon(a.is_pk ? "key" : "symbol-field");
+    const bits: string[] = [];
+    if (a.domain) bits.push(a.domain);
+    if (a.is_pk) bits.push("pk");
+    if (!a.nullable) bits.push("not null");
+    ti.description = bits.join(" · ");
+    if (a.physical_name) {
+      const md = new vscode.MarkdownString();
+      md.appendMarkdown(`**${a.name}** · \`${a.physical_name}\`\n\n${a.domain ?? ""}`);
+      ti.tooltip = md;
+    }
+    ti.contextValue = "modelAttribute";
+    // click opens the owning entity's YAML at the attribute line
+    ti.command = this.openCommand(node.entity, a.name);
+    return ti;
+  }
+
+  /** A command that opens the entity's source YAML, revealing the given search term
+   * (the entity or attribute name) so the cursor lands near it. */
+  private openCommand(entity: TreeEntity, reveal: string): vscode.Command | undefined {
+    if (!entity.file || !this.modelDir) return undefined;
+    const uri = vscode.Uri.file(path.join(this.modelDir, entity.file));
+    return {
+      command: "modelith.openModelObject",
+      title: "Open in the model YAML",
+      arguments: [uri, reveal],
+    };
+  }
+
+  getChildren(node?: Node): Node[] {
+    if (!node) {
+      if (!this.modelDir) {
+        return [
+          {
+            kind: "status",
+            label: "No model in this workspace",
+            icon: new vscode.ThemeIcon("info"),
+          },
+        ];
+      }
+      if (!this.entities.length) {
+        return [
+          {
+            kind: "status",
+            label: "No entities yet — run mdl init or import a model",
+            icon: new vscode.ThemeIcon("info"),
+          },
+        ];
+      }
+      return this.entities.map((entity) => ({ kind: "entity" as const, entity }));
+    }
+    if (node.kind === "entity") {
+      return node.entity.attributes.map((attr) => ({
+        kind: "attribute" as const,
+        entity: node.entity,
+        attr,
+      }));
+    }
+    return [];
+  }
+}
+
+/** Open a model object's YAML and move the cursor to the first line mentioning `reveal`
+ * (the entity or attribute name), so a click lands where the user expected. */
+export async function openModelObject(uri: vscode.Uri, reveal: string): Promise {
+  const doc = await vscode.workspace.openTextDocument(uri);
+  const editor = await vscode.window.showTextDocument(doc);
+  const text = doc.getText();
+  // match `name: ` first (the authored field), else a bare mention
+  const idx =
+    text.indexOf(`: ${reveal}\n`) >= 0
+      ? text.indexOf(`: ${reveal}\n`)
+      : text.indexOf(reveal);
+  if (idx >= 0) {
+    const pos = doc.positionAt(idx);
+    editor.selection = new vscode.Selection(pos, pos);
+    editor.revealRange(new vscode.Range(pos, pos), vscode.TextEditorRevealType.InCenter);
+  }
+}