mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-01 13:59:54 +00:00
This reverts commit 28382b7e45.
This commit is contained in:
109
.eslintrc.js
109
.eslintrc.js
@@ -1,55 +1,56 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
es2021: true,
|
||||
node: true,
|
||||
"jest/globals": true,
|
||||
},
|
||||
extends: "eslint:recommended",
|
||||
overrides: [],
|
||||
parserOptions: {
|
||||
ecmaVersion: "latest",
|
||||
sourceType: "module",
|
||||
},
|
||||
plugins: ["jest"],
|
||||
globals: {
|
||||
gl: true,
|
||||
GL: true,
|
||||
LS: true,
|
||||
Uint8Array: true,
|
||||
Uint32Array: true,
|
||||
Float32Array: true,
|
||||
LGraphCanvas: true,
|
||||
LGraph: true,
|
||||
LGraphNode: true,
|
||||
LiteGraph: true,
|
||||
LGraphTexture: true,
|
||||
Mesh: true,
|
||||
Shader: true,
|
||||
enableWebGLCanvas: true,
|
||||
vec2: true,
|
||||
vec3: true,
|
||||
vec4: true,
|
||||
DEG2RAD: true,
|
||||
isPowerOfTwo: true,
|
||||
cloneCanvas: true,
|
||||
createCanvas: true,
|
||||
hex2num: true,
|
||||
colorToString: true,
|
||||
showElement: true,
|
||||
quat: true,
|
||||
AudioSynth: true,
|
||||
SillyClient: true,
|
||||
},
|
||||
rules: {
|
||||
"no-console": "off",
|
||||
"no-empty": "warn",
|
||||
"no-redeclare": "warn",
|
||||
"no-inner-declarations": "warn",
|
||||
"no-constant-condition": "warn",
|
||||
"no-unused-vars": "warn",
|
||||
"no-mixed-spaces-and-tabs": "warn",
|
||||
"no-unreachable": "warn",
|
||||
curly: ["warn", "all"],
|
||||
},
|
||||
};
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es2021": true,
|
||||
"node": true,
|
||||
"jest/globals": true
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
"overrides": [
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module"
|
||||
},
|
||||
"plugins": ["jest"],
|
||||
"globals": {
|
||||
"gl": true,
|
||||
"GL": true,
|
||||
"LS": true,
|
||||
"Uint8Array": true,
|
||||
"Uint32Array": true,
|
||||
"Float32Array": true,
|
||||
"LGraphCanvas": true,
|
||||
"LGraph": true,
|
||||
"LGraphNode": true,
|
||||
"LiteGraph": true,
|
||||
"LGraphTexture": true,
|
||||
"Mesh": true,
|
||||
"Shader": true,
|
||||
"enableWebGLCanvas": true,
|
||||
"vec2": true,
|
||||
"vec3": true,
|
||||
"vec4": true,
|
||||
"DEG2RAD": true,
|
||||
"isPowerOfTwo": true,
|
||||
"cloneCanvas": true,
|
||||
"createCanvas": true,
|
||||
"hex2num": true,
|
||||
"colorToString": true,
|
||||
"showElement": true,
|
||||
"quat": true,
|
||||
"AudioSynth": true,
|
||||
"SillyClient": true
|
||||
},
|
||||
"rules": {
|
||||
"no-console": "off",
|
||||
"no-empty": "warn",
|
||||
"no-redeclare": "warn",
|
||||
"no-inner-declarations": "warn",
|
||||
"no-constant-condition": "warn",
|
||||
"no-unused-vars": "warn",
|
||||
"no-mixed-spaces-and-tabs": "warn",
|
||||
"no-unreachable": "warn",
|
||||
"curly": ["warn", "all"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
npx lint-staged
|
||||
@@ -1,23 +1,23 @@
|
||||
import type { JestConfigWithTsJest } from "ts-jest";
|
||||
import type { JestConfigWithTsJest } from 'ts-jest'
|
||||
|
||||
const jestConfig: JestConfigWithTsJest = {
|
||||
testMatch: ["**/test/**/*.test.ts"],
|
||||
testEnvironment: "jsdom",
|
||||
moduleFileExtensions: ["js", "jsx", "json", "ts"],
|
||||
testMatch: ['**/test/**/*.test.ts'],
|
||||
testEnvironment: 'jsdom',
|
||||
moduleFileExtensions: ['js', 'jsx', 'json', 'ts'],
|
||||
transform: {
|
||||
"^.+\\.m?[tj]sx?$": [
|
||||
"ts-jest",
|
||||
'^.+\\.m?[tj]sx?$': [
|
||||
'ts-jest',
|
||||
{
|
||||
tsconfig: "./tsconfig.json",
|
||||
},
|
||||
],
|
||||
tsconfig: './tsconfig.json',
|
||||
}
|
||||
]
|
||||
},
|
||||
clearMocks: true,
|
||||
resetModules: true,
|
||||
testTimeout: 10000,
|
||||
moduleNameMapper: {
|
||||
"^@/(.*)$": "<rootDir>/src/$1",
|
||||
'^@/(.*)$': '<rootDir>/src/$1',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export default jestConfig;
|
||||
export default jestConfig
|
||||
|
||||
779
package-lock.json
generated
779
package-lock.json
generated
@@ -11,10 +11,7 @@
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^22.1.0",
|
||||
"husky": "^9.1.6",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"lint-staged": "^15.2.10",
|
||||
"prettier": "^3.3.3",
|
||||
"ts-jest": "^29.2.4",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.2.2",
|
||||
@@ -2778,93 +2775,6 @@
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/cli-cursor": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz",
|
||||
"integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"restore-cursor": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/cli-truncate": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz",
|
||||
"integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"slice-ansi": "^5.0.0",
|
||||
"string-width": "^7.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/cli-truncate/node_modules/ansi-regex": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
|
||||
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/cli-truncate/node_modules/emoji-regex": {
|
||||
"version": "10.4.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz",
|
||||
"integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/cli-truncate/node_modules/string-width": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
|
||||
"integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^10.3.0",
|
||||
"get-east-asian-width": "^1.0.0",
|
||||
"strip-ansi": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/cli-truncate/node_modules/strip-ansi": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
|
||||
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/cliui": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||
@@ -2921,13 +2831,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/colorette": {
|
||||
"version": "2.0.20",
|
||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
|
||||
"integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/combined-stream": {
|
||||
"version": "1.0.8",
|
||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||
@@ -2941,16 +2844,6 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/commander": {
|
||||
"version": "12.1.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
|
||||
"integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/compare-versions": {
|
||||
"version": "6.1.1",
|
||||
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.1.tgz",
|
||||
@@ -3023,6 +2916,7 @@
|
||||
"integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"path-key": "^3.1.0",
|
||||
"shebang-command": "^2.0.0",
|
||||
@@ -3247,19 +3141,6 @@
|
||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/environment": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz",
|
||||
"integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/error-ex": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
||||
@@ -3394,13 +3275,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eventemitter3": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
|
||||
"integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/execa": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
|
||||
@@ -3634,19 +3508,6 @@
|
||||
"node": "6.* || 8.* || >= 10.*"
|
||||
}
|
||||
},
|
||||
"node_modules/get-east-asian-width": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz",
|
||||
"integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/get-package-type": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
|
||||
@@ -3807,22 +3668,6 @@
|
||||
"node": ">=10.17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/husky": {
|
||||
"version": "9.1.6",
|
||||
"resolved": "https://registry.npmjs.org/husky/-/husky-9.1.6.tgz",
|
||||
"integrity": "sha512-sqbjZKK7kf44hfdE94EoX8MZNk0n7HeW37O4YrVGCF4wzgQjp+akPAkfUK5LZ6KuR/6sqeAVuXHji+RzQgOn5A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"husky": "bin.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/typicode"
|
||||
}
|
||||
},
|
||||
"node_modules/iconv-lite": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
@@ -3981,7 +3826,8 @@
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
"license": "ISC",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/istanbul-lib-coverage": {
|
||||
"version": "3.2.2",
|
||||
@@ -4895,19 +4741,6 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/lilconfig": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz",
|
||||
"integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/antonk52"
|
||||
}
|
||||
},
|
||||
"node_modules/lines-and-columns": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
|
||||
@@ -4916,294 +4749,6 @@
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/lint-staged": {
|
||||
"version": "15.2.10",
|
||||
"resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.10.tgz",
|
||||
"integrity": "sha512-5dY5t743e1byO19P9I4b3x8HJwalIznL5E1FWYnU6OWw33KxNBSLAc6Cy7F2PsFEO8FKnLwjwm5hx7aMF0jzZg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"chalk": "~5.3.0",
|
||||
"commander": "~12.1.0",
|
||||
"debug": "~4.3.6",
|
||||
"execa": "~8.0.1",
|
||||
"lilconfig": "~3.1.2",
|
||||
"listr2": "~8.2.4",
|
||||
"micromatch": "~4.0.8",
|
||||
"pidtree": "~0.6.0",
|
||||
"string-argv": "~0.3.2",
|
||||
"yaml": "~2.5.0"
|
||||
},
|
||||
"bin": {
|
||||
"lint-staged": "bin/lint-staged.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.12.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/lint-staged"
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged/node_modules/chalk": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
|
||||
"integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.17.0 || ^14.13 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/chalk?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged/node_modules/execa": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz",
|
||||
"integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cross-spawn": "^7.0.3",
|
||||
"get-stream": "^8.0.1",
|
||||
"human-signals": "^5.0.0",
|
||||
"is-stream": "^3.0.0",
|
||||
"merge-stream": "^2.0.0",
|
||||
"npm-run-path": "^5.1.0",
|
||||
"onetime": "^6.0.0",
|
||||
"signal-exit": "^4.1.0",
|
||||
"strip-final-newline": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.17"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sindresorhus/execa?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged/node_modules/get-stream": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz",
|
||||
"integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged/node_modules/human-signals": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz",
|
||||
"integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"engines": {
|
||||
"node": ">=16.17.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged/node_modules/is-stream": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
|
||||
"integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged/node_modules/mimic-fn": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
|
||||
"integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged/node_modules/npm-run-path": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz",
|
||||
"integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"path-key": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged/node_modules/onetime": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
|
||||
"integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mimic-fn": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged/node_modules/path-key": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
|
||||
"integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged/node_modules/signal-exit": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
|
||||
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/lint-staged/node_modules/strip-final-newline": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
|
||||
"integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/listr2": {
|
||||
"version": "8.2.5",
|
||||
"resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz",
|
||||
"integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"cli-truncate": "^4.0.0",
|
||||
"colorette": "^2.0.20",
|
||||
"eventemitter3": "^5.0.1",
|
||||
"log-update": "^6.1.0",
|
||||
"rfdc": "^1.4.1",
|
||||
"wrap-ansi": "^9.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/listr2/node_modules/ansi-regex": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
|
||||
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/listr2/node_modules/ansi-styles": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
|
||||
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/listr2/node_modules/emoji-regex": {
|
||||
"version": "10.4.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz",
|
||||
"integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/listr2/node_modules/string-width": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
|
||||
"integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^10.3.0",
|
||||
"get-east-asian-width": "^1.0.0",
|
||||
"strip-ansi": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/listr2/node_modules/strip-ansi": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
|
||||
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/listr2/node_modules/wrap-ansi": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz",
|
||||
"integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^6.2.1",
|
||||
"string-width": "^7.0.0",
|
||||
"strip-ansi": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/local-pkg": {
|
||||
"version": "0.5.0",
|
||||
"resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz",
|
||||
@@ -5249,160 +4794,6 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/log-update": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz",
|
||||
"integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-escapes": "^7.0.0",
|
||||
"cli-cursor": "^5.0.0",
|
||||
"slice-ansi": "^7.1.0",
|
||||
"strip-ansi": "^7.1.0",
|
||||
"wrap-ansi": "^9.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/log-update/node_modules/ansi-escapes": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz",
|
||||
"integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"environment": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/log-update/node_modules/ansi-regex": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
|
||||
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/log-update/node_modules/ansi-styles": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
|
||||
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/log-update/node_modules/emoji-regex": {
|
||||
"version": "10.4.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz",
|
||||
"integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/log-update/node_modules/is-fullwidth-code-point": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz",
|
||||
"integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"get-east-asian-width": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/log-update/node_modules/slice-ansi": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz",
|
||||
"integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^6.2.1",
|
||||
"is-fullwidth-code-point": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/slice-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/log-update/node_modules/string-width": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
|
||||
"integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"emoji-regex": "^10.3.0",
|
||||
"get-east-asian-width": "^1.0.0",
|
||||
"strip-ansi": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/log-update/node_modules/strip-ansi": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
|
||||
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-regex": "^6.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/log-update/node_modules/wrap-ansi": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz",
|
||||
"integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^6.2.1",
|
||||
"string-width": "^7.0.0",
|
||||
"strip-ansi": "^7.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
|
||||
@@ -5478,12 +4869,13 @@
|
||||
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
|
||||
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/micromatch": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
|
||||
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
|
||||
"version": "4.0.7",
|
||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
|
||||
"integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -5528,19 +4920,6 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/mimic-function": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz",
|
||||
"integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
|
||||
@@ -5811,6 +5190,7 @@
|
||||
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
@@ -5849,19 +5229,6 @@
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/pidtree": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz",
|
||||
"integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"pidtree": "bin/pidtree.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/pirates": {
|
||||
"version": "4.0.6",
|
||||
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
|
||||
@@ -5928,22 +5295,6 @@
|
||||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz",
|
||||
"integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/pretty-format": {
|
||||
"version": "29.7.0",
|
||||
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
|
||||
@@ -6118,59 +5469,6 @@
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/restore-cursor": {
|
||||
"version": "5.1.0",
|
||||
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz",
|
||||
"integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"onetime": "^7.0.0",
|
||||
"signal-exit": "^4.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/restore-cursor/node_modules/onetime": {
|
||||
"version": "7.0.0",
|
||||
"resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz",
|
||||
"integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"mimic-function": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/restore-cursor/node_modules/signal-exit": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
|
||||
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/rfdc": {
|
||||
"version": "1.4.1",
|
||||
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
|
||||
"integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.20.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.20.0.tgz",
|
||||
@@ -6244,6 +5542,7 @@
|
||||
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"shebang-regex": "^3.0.0"
|
||||
},
|
||||
@@ -6257,6 +5556,7 @@
|
||||
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
@@ -6287,49 +5587,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/slice-ansi": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz",
|
||||
"integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^6.0.0",
|
||||
"is-fullwidth-code-point": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/slice-ansi?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/slice-ansi/node_modules/ansi-styles": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
|
||||
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/slice-ansi/node_modules/is-fullwidth-code-point": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz",
|
||||
"integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/source-map": {
|
||||
"version": "0.6.1",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||
@@ -6995,6 +6252,7 @@
|
||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
},
|
||||
@@ -7105,19 +6363,6 @@
|
||||
"license": "ISC",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/yaml": {
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz",
|
||||
"integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"yaml": "bin.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
}
|
||||
},
|
||||
"node_modules/yargs": {
|
||||
"version": "17.7.2",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
|
||||
|
||||
11
package.json
11
package.json
@@ -24,8 +24,6 @@
|
||||
"dev": "vite",
|
||||
"preview": "vite preview",
|
||||
"test": "jest",
|
||||
"format": "prettier --write './**/*.{js,ts}'",
|
||||
"prepare": "husky || true",
|
||||
"deprecated-test:allVersions": "./utils/test.sh",
|
||||
"deprecated-prettier": "npx prettier --write src/**/*.* css/**/*.*",
|
||||
"deprecated-lint": "npx eslint src",
|
||||
@@ -47,20 +45,11 @@
|
||||
"devDependencies": {
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/node": "^22.1.0",
|
||||
"husky": "^9.1.6",
|
||||
"jest-environment-jsdom": "^29.7.0",
|
||||
"lint-staged": "^15.2.10",
|
||||
"prettier": "^3.3.3",
|
||||
"ts-jest": "^29.2.4",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.2.2",
|
||||
"vite": "^5.3.4",
|
||||
"vite-plugin-dts": "^4.2.1"
|
||||
},
|
||||
"lint-staged": {
|
||||
"./**/*.{js,ts}": [
|
||||
"prettier --write",
|
||||
"git add"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// @ts-nocheck
|
||||
import type { IContextMenuOptions, IContextMenuValue } from "./interfaces";
|
||||
import type { IContextMenuOptions, IContextMenuValue } from "./interfaces"
|
||||
import { LiteGraph } from "./litegraph";
|
||||
|
||||
/* LiteGraph GUI elements used for canvas editing *************************************/
|
||||
@@ -16,140 +16,133 @@ import { LiteGraph } from "./litegraph";
|
||||
* - event: you can pass a MouseEvent, this way the ContextMenu appears in that position
|
||||
*/
|
||||
export class ContextMenu {
|
||||
options?: IContextMenuOptions;
|
||||
parentMenu?: ContextMenu;
|
||||
root: HTMLDivElement;
|
||||
current_submenu?: ContextMenu;
|
||||
lock?: boolean;
|
||||
options?: IContextMenuOptions
|
||||
parentMenu?: ContextMenu
|
||||
root: HTMLDivElement
|
||||
current_submenu?: ContextMenu
|
||||
lock?: boolean
|
||||
|
||||
constructor(
|
||||
values: IContextMenuValue[] | string[],
|
||||
options: IContextMenuOptions,
|
||||
) {
|
||||
options = options || {};
|
||||
this.options = options;
|
||||
var that = this;
|
||||
constructor(values: IContextMenuValue[] | string[], options: IContextMenuOptions) {
|
||||
options = options || {};
|
||||
this.options = options;
|
||||
var that = this;
|
||||
|
||||
//to link a menu with its parent
|
||||
if (options.parentMenu) {
|
||||
if (!(options.parentMenu instanceof ContextMenu)) {
|
||||
console.error("parentMenu must be of class ContextMenu, ignoring it");
|
||||
options.parentMenu = null;
|
||||
} else {
|
||||
this.parentMenu = options.parentMenu;
|
||||
this.parentMenu.lock = true;
|
||||
this.parentMenu.current_submenu = this;
|
||||
}
|
||||
if (options.parentMenu.options?.className === "dark") {
|
||||
options.className = "dark";
|
||||
}
|
||||
}
|
||||
|
||||
var eventClass = null;
|
||||
if (options.event)
|
||||
//use strings because comparing classes between windows doesnt work
|
||||
eventClass = options.event.constructor.name;
|
||||
if (
|
||||
eventClass !== "MouseEvent" &&
|
||||
eventClass !== "CustomEvent" &&
|
||||
eventClass !== "PointerEvent"
|
||||
) {
|
||||
console.error(
|
||||
"Event passed to ContextMenu is not of type MouseEvent or CustomEvent. Ignoring it. (" +
|
||||
eventClass +
|
||||
")",
|
||||
);
|
||||
options.event = null;
|
||||
}
|
||||
|
||||
var root = document.createElement("div");
|
||||
root.className = "litegraph litecontextmenu litemenubar-panel";
|
||||
if (options.className) {
|
||||
root.className += " " + options.className;
|
||||
}
|
||||
root.style.minWidth = 100;
|
||||
root.style.minHeight = 100;
|
||||
root.style.pointerEvents = "none";
|
||||
setTimeout(function () {
|
||||
root.style.pointerEvents = "auto";
|
||||
}, 100); //delay so the mouse up event is not caught by this element
|
||||
|
||||
//this prevents the default context browser menu to open in case this menu was created when pressing right button
|
||||
LiteGraph.pointerListenerAdd(
|
||||
root,
|
||||
"up",
|
||||
function (e) {
|
||||
//console.log("pointerevents: ContextMenu up root prevent");
|
||||
e.preventDefault();
|
||||
return true;
|
||||
},
|
||||
true,
|
||||
);
|
||||
root.addEventListener(
|
||||
"contextmenu",
|
||||
function (e) {
|
||||
if (e.button != 2) {
|
||||
//right button
|
||||
return false;
|
||||
//to link a menu with its parent
|
||||
if (options.parentMenu) {
|
||||
if (!(options.parentMenu instanceof ContextMenu)) {
|
||||
console.error(
|
||||
"parentMenu must be of class ContextMenu, ignoring it"
|
||||
);
|
||||
options.parentMenu = null;
|
||||
} else {
|
||||
this.parentMenu = options.parentMenu;
|
||||
this.parentMenu.lock = true;
|
||||
this.parentMenu.current_submenu = this;
|
||||
}
|
||||
if (options.parentMenu.options?.className === "dark") {
|
||||
options.className = "dark";
|
||||
}
|
||||
}
|
||||
e.preventDefault();
|
||||
return false;
|
||||
},
|
||||
true,
|
||||
);
|
||||
|
||||
LiteGraph.pointerListenerAdd(
|
||||
root,
|
||||
"down",
|
||||
function (e) {
|
||||
//console.log("pointerevents: ContextMenu down");
|
||||
if (e.button == 2) {
|
||||
that.close();
|
||||
e.preventDefault();
|
||||
return true;
|
||||
var eventClass = null;
|
||||
if (options.event) //use strings because comparing classes between windows doesnt work
|
||||
eventClass = options.event.constructor.name;
|
||||
if (eventClass !== "MouseEvent" &&
|
||||
eventClass !== "CustomEvent" &&
|
||||
eventClass !== "PointerEvent") {
|
||||
console.error(
|
||||
"Event passed to ContextMenu is not of type MouseEvent or CustomEvent. Ignoring it. (" + eventClass + ")"
|
||||
);
|
||||
options.event = null;
|
||||
}
|
||||
},
|
||||
true,
|
||||
);
|
||||
|
||||
function on_mouse_wheel(e) {
|
||||
var pos = parseInt(root.style.top);
|
||||
root.style.top = (pos + e.deltaY * options.scroll_speed).toFixed() + "px";
|
||||
e.preventDefault();
|
||||
return true;
|
||||
}
|
||||
var root = document.createElement("div");
|
||||
root.className = "litegraph litecontextmenu litemenubar-panel";
|
||||
if (options.className) {
|
||||
root.className += " " + options.className;
|
||||
}
|
||||
root.style.minWidth = 100;
|
||||
root.style.minHeight = 100;
|
||||
root.style.pointerEvents = "none";
|
||||
setTimeout(function () {
|
||||
root.style.pointerEvents = "auto";
|
||||
}, 100); //delay so the mouse up event is not caught by this element
|
||||
|
||||
if (!options.scroll_speed) {
|
||||
options.scroll_speed = 0.1;
|
||||
}
|
||||
|
||||
root.addEventListener("wheel", on_mouse_wheel, true);
|
||||
root.addEventListener("mousewheel", on_mouse_wheel, true);
|
||||
|
||||
this.root = root;
|
||||
//this prevents the default context browser menu to open in case this menu was created when pressing right button
|
||||
LiteGraph.pointerListenerAdd(root, "up",
|
||||
function (e) {
|
||||
//console.log("pointerevents: ContextMenu up root prevent");
|
||||
e.preventDefault();
|
||||
return true;
|
||||
},
|
||||
true
|
||||
);
|
||||
root.addEventListener(
|
||||
"contextmenu",
|
||||
function (e) {
|
||||
if (e.button != 2) {
|
||||
//right button
|
||||
return false;
|
||||
}
|
||||
e.preventDefault();
|
||||
return false;
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
//title
|
||||
if (options.title) {
|
||||
var element = document.createElement("div");
|
||||
element.className = "litemenu-title";
|
||||
element.innerHTML = options.title;
|
||||
root.appendChild(element);
|
||||
}
|
||||
LiteGraph.pointerListenerAdd(root, "down",
|
||||
function (e) {
|
||||
//console.log("pointerevents: ContextMenu down");
|
||||
if (e.button == 2) {
|
||||
that.close();
|
||||
e.preventDefault();
|
||||
return true;
|
||||
}
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
//entries
|
||||
var num = 0;
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
var name = values.constructor == Array ? values[i] : i;
|
||||
if (name != null && name.constructor !== String) {
|
||||
name = name.content === undefined ? String(name) : name.content;
|
||||
}
|
||||
var value = values[i];
|
||||
this.addItem(name, value, options);
|
||||
num++;
|
||||
}
|
||||
function on_mouse_wheel(e) {
|
||||
var pos = parseInt(root.style.top);
|
||||
root.style.top =
|
||||
(pos + e.deltaY * options.scroll_speed).toFixed() + "px";
|
||||
e.preventDefault();
|
||||
return true;
|
||||
}
|
||||
|
||||
//close on leave? touch enabled devices won't work TODO use a global device detector and condition on that
|
||||
/*LiteGraph.pointerListenerAdd(root,"leave", function(e) {
|
||||
if (!options.scroll_speed) {
|
||||
options.scroll_speed = 0.1;
|
||||
}
|
||||
|
||||
root.addEventListener("wheel", on_mouse_wheel, true);
|
||||
root.addEventListener("mousewheel", on_mouse_wheel, true);
|
||||
|
||||
this.root = root;
|
||||
|
||||
//title
|
||||
if (options.title) {
|
||||
var element = document.createElement("div");
|
||||
element.className = "litemenu-title";
|
||||
element.innerHTML = options.title;
|
||||
root.appendChild(element);
|
||||
}
|
||||
|
||||
//entries
|
||||
var num = 0;
|
||||
for (var i = 0; i < values.length; i++) {
|
||||
var name = values.constructor == Array ? values[i] : i;
|
||||
if (name != null && name.constructor !== String) {
|
||||
name = name.content === undefined ? String(name) : name.content;
|
||||
}
|
||||
var value = values[i];
|
||||
this.addItem(name, value, options);
|
||||
num++;
|
||||
}
|
||||
|
||||
//close on leave? touch enabled devices won't work TODO use a global device detector and condition on that
|
||||
/*LiteGraph.pointerListenerAdd(root,"leave", function(e) {
|
||||
console.log("pointerevents: ContextMenu leave");
|
||||
if (that.lock) {
|
||||
return;
|
||||
@@ -160,298 +153,275 @@ export class ContextMenu {
|
||||
root.closing_timer = setTimeout(that.close.bind(that, e), 500);
|
||||
//that.close(e);
|
||||
});*/
|
||||
LiteGraph.pointerListenerAdd(root, "enter", function (e) {
|
||||
//console.log("pointerevents: ContextMenu enter");
|
||||
if (root.closing_timer) {
|
||||
clearTimeout(root.closing_timer);
|
||||
}
|
||||
});
|
||||
LiteGraph.pointerListenerAdd(root, "enter", function (e) {
|
||||
//console.log("pointerevents: ContextMenu enter");
|
||||
if (root.closing_timer) {
|
||||
clearTimeout(root.closing_timer);
|
||||
}
|
||||
});
|
||||
|
||||
//insert before checking position
|
||||
var root_document = document;
|
||||
if (options.event) {
|
||||
root_document = options.event.target.ownerDocument;
|
||||
}
|
||||
|
||||
if (!root_document) {
|
||||
root_document = document;
|
||||
}
|
||||
|
||||
if (root_document.fullscreenElement)
|
||||
root_document.fullscreenElement.appendChild(root);
|
||||
else root_document.body.appendChild(root);
|
||||
|
||||
//compute best position
|
||||
var left = options.left || 0;
|
||||
var top = options.top || 0;
|
||||
if (options.event) {
|
||||
left = options.event.clientX - 10;
|
||||
top = options.event.clientY - 10;
|
||||
if (options.title) {
|
||||
top -= 20;
|
||||
}
|
||||
|
||||
if (options.parentMenu) {
|
||||
var rect = options.parentMenu.root.getBoundingClientRect();
|
||||
left = rect.left + rect.width;
|
||||
}
|
||||
|
||||
var body_rect = document.body.getBoundingClientRect();
|
||||
var root_rect = root.getBoundingClientRect();
|
||||
if (body_rect.height == 0)
|
||||
console.error(
|
||||
"document.body height is 0. That is dangerous, set html,body { height: 100%; }",
|
||||
);
|
||||
|
||||
if (body_rect.width && left > body_rect.width - root_rect.width - 10) {
|
||||
left = body_rect.width - root_rect.width - 10;
|
||||
}
|
||||
if (body_rect.height && top > body_rect.height - root_rect.height - 10) {
|
||||
top = body_rect.height - root_rect.height - 10;
|
||||
}
|
||||
}
|
||||
|
||||
root.style.left = left + "px";
|
||||
root.style.top = top + "px";
|
||||
|
||||
if (options.scale) {
|
||||
root.style.transform = "scale(" + options.scale + ")";
|
||||
}
|
||||
}
|
||||
|
||||
addItem(
|
||||
name: string,
|
||||
value: IContextMenuValue,
|
||||
options: IContextMenuOptions,
|
||||
): HTMLElement {
|
||||
var that = this;
|
||||
options = options || {};
|
||||
|
||||
var element = document.createElement("div");
|
||||
element.className = "litemenu-entry submenu";
|
||||
|
||||
var disabled = false;
|
||||
|
||||
if (value === null) {
|
||||
element.classList.add("separator");
|
||||
//element.innerHTML = "<hr/>"
|
||||
//continue;
|
||||
} else {
|
||||
element.innerHTML = value && value.title ? value.title : name;
|
||||
element.value = value;
|
||||
element.setAttribute("role", "menuitem");
|
||||
|
||||
if (value) {
|
||||
if (value.disabled) {
|
||||
disabled = true;
|
||||
element.classList.add("disabled");
|
||||
element.setAttribute("aria-disabled", "true");
|
||||
//insert before checking position
|
||||
var root_document = document;
|
||||
if (options.event) {
|
||||
root_document = options.event.target.ownerDocument;
|
||||
}
|
||||
if (value.submenu || value.has_submenu) {
|
||||
element.classList.add("has_submenu");
|
||||
element.setAttribute("aria-haspopup", "true");
|
||||
element.setAttribute("aria-expanded", "false");
|
||||
|
||||
if (!root_document) {
|
||||
root_document = document;
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof value == "function") {
|
||||
element.dataset["value"] = name;
|
||||
element.onclick_callback = value;
|
||||
} else {
|
||||
element.dataset["value"] = value;
|
||||
}
|
||||
if (root_document.fullscreenElement)
|
||||
root_document.fullscreenElement.appendChild(root);
|
||||
|
||||
if (value.className) {
|
||||
element.className += " " + value.className;
|
||||
}
|
||||
}
|
||||
|
||||
this.root.appendChild(element);
|
||||
if (!disabled) {
|
||||
element.addEventListener("click", inner_onclick);
|
||||
}
|
||||
if (!disabled && options.autoopen) {
|
||||
LiteGraph.pointerListenerAdd(element, "enter", inner_over);
|
||||
}
|
||||
else
|
||||
root_document.body.appendChild(root);
|
||||
|
||||
function setAriaExpanded() {
|
||||
const entries = that.root.querySelectorAll(
|
||||
"div.litemenu-entry.has_submenu",
|
||||
);
|
||||
if (entries) {
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
entries[i].setAttribute("aria-expanded", "false");
|
||||
//compute best position
|
||||
var left = options.left || 0;
|
||||
var top = options.top || 0;
|
||||
if (options.event) {
|
||||
left = options.event.clientX - 10;
|
||||
top = options.event.clientY - 10;
|
||||
if (options.title) {
|
||||
top -= 20;
|
||||
}
|
||||
|
||||
if (options.parentMenu) {
|
||||
var rect = options.parentMenu.root.getBoundingClientRect();
|
||||
left = rect.left + rect.width;
|
||||
}
|
||||
|
||||
var body_rect = document.body.getBoundingClientRect();
|
||||
var root_rect = root.getBoundingClientRect();
|
||||
if (body_rect.height == 0)
|
||||
console.error("document.body height is 0. That is dangerous, set html,body { height: 100%; }");
|
||||
|
||||
if (body_rect.width && left > body_rect.width - root_rect.width - 10) {
|
||||
left = body_rect.width - root_rect.width - 10;
|
||||
}
|
||||
if (body_rect.height && top > body_rect.height - root_rect.height - 10) {
|
||||
top = body_rect.height - root_rect.height - 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
element.setAttribute("aria-expanded", "true");
|
||||
}
|
||||
|
||||
function inner_over(e) {
|
||||
var value = this.value;
|
||||
if (!value || !value.has_submenu) {
|
||||
return;
|
||||
}
|
||||
//if it is a submenu, autoopen like the item was clicked
|
||||
inner_onclick.call(this, e);
|
||||
setAriaExpanded();
|
||||
}
|
||||
root.style.left = left + "px";
|
||||
root.style.top = top + "px";
|
||||
|
||||
//menu option clicked
|
||||
function inner_onclick(e) {
|
||||
var value = this.value;
|
||||
var close_parent = true;
|
||||
|
||||
if (that.current_submenu) {
|
||||
that.current_submenu.close(e);
|
||||
}
|
||||
if (value?.has_submenu || value?.submenu) {
|
||||
setAriaExpanded();
|
||||
}
|
||||
|
||||
//global callback
|
||||
if (options.callback) {
|
||||
var r = options.callback.call(
|
||||
this,
|
||||
value,
|
||||
options,
|
||||
e,
|
||||
that,
|
||||
options.node,
|
||||
);
|
||||
if (r === true) {
|
||||
close_parent = false;
|
||||
if (options.scale) {
|
||||
root.style.transform = "scale(" + options.scale + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//special cases
|
||||
if (value) {
|
||||
if (
|
||||
value.callback &&
|
||||
!options.ignore_item_callbacks &&
|
||||
value.disabled !== true
|
||||
) {
|
||||
//item callback
|
||||
var r = value.callback.call(
|
||||
this,
|
||||
value,
|
||||
options,
|
||||
e,
|
||||
that,
|
||||
options.extra,
|
||||
);
|
||||
if (r === true) {
|
||||
close_parent = false;
|
||||
}
|
||||
addItem(name: string, value: IContextMenuValue, options: IContextMenuOptions): HTMLElement {
|
||||
var that = this;
|
||||
options = options || {};
|
||||
|
||||
var element = document.createElement("div");
|
||||
element.className = "litemenu-entry submenu";
|
||||
|
||||
var disabled = false;
|
||||
|
||||
if (value === null) {
|
||||
element.classList.add("separator");
|
||||
//element.innerHTML = "<hr/>"
|
||||
//continue;
|
||||
} else {
|
||||
element.innerHTML = value && value.title ? value.title : name;
|
||||
element.value = value;
|
||||
element.setAttribute("role", "menuitem");
|
||||
|
||||
if (value) {
|
||||
if (value.disabled) {
|
||||
disabled = true;
|
||||
element.classList.add("disabled");
|
||||
element.setAttribute("aria-disabled", "true");
|
||||
}
|
||||
if (value.submenu || value.has_submenu) {
|
||||
element.classList.add("has_submenu");
|
||||
element.setAttribute("aria-haspopup", "true");
|
||||
element.setAttribute("aria-expanded", "false");
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof value == "function") {
|
||||
element.dataset["value"] = name;
|
||||
element.onclick_callback = value;
|
||||
} else {
|
||||
element.dataset["value"] = value;
|
||||
}
|
||||
|
||||
if (value.className) {
|
||||
element.className += " " + value.className;
|
||||
}
|
||||
}
|
||||
if (value.submenu) {
|
||||
if (!value.submenu.options) {
|
||||
throw "ContextMenu submenu needs options";
|
||||
}
|
||||
var submenu = new that.constructor(value.submenu.options, {
|
||||
callback: value.submenu.callback,
|
||||
event: e,
|
||||
parentMenu: that,
|
||||
ignore_item_callbacks: value.submenu.ignore_item_callbacks,
|
||||
title: value.submenu.title,
|
||||
extra: value.submenu.extra,
|
||||
autoopen: options.autoopen,
|
||||
});
|
||||
close_parent = false;
|
||||
|
||||
this.root.appendChild(element);
|
||||
if (!disabled) {
|
||||
element.addEventListener("click", inner_onclick);
|
||||
}
|
||||
if (!disabled && options.autoopen) {
|
||||
LiteGraph.pointerListenerAdd(element, "enter", inner_over);
|
||||
}
|
||||
}
|
||||
|
||||
if (close_parent && !that.lock) {
|
||||
that.close();
|
||||
}
|
||||
function setAriaExpanded() {
|
||||
const entries = that.root.querySelectorAll("div.litemenu-entry.has_submenu");
|
||||
if (entries) {
|
||||
for (let i = 0; i < entries.length; i++) {
|
||||
entries[i].setAttribute("aria-expanded", "false");
|
||||
}
|
||||
}
|
||||
element.setAttribute("aria-expanded", "true");
|
||||
}
|
||||
|
||||
function inner_over(e) {
|
||||
var value = this.value;
|
||||
if (!value || !value.has_submenu) {
|
||||
return;
|
||||
}
|
||||
//if it is a submenu, autoopen like the item was clicked
|
||||
inner_onclick.call(this, e);
|
||||
setAriaExpanded();
|
||||
}
|
||||
|
||||
//menu option clicked
|
||||
function inner_onclick(e) {
|
||||
var value = this.value;
|
||||
var close_parent = true;
|
||||
|
||||
if (that.current_submenu) {
|
||||
that.current_submenu.close(e);
|
||||
}
|
||||
if (value?.has_submenu || value?.submenu) {
|
||||
setAriaExpanded();
|
||||
}
|
||||
|
||||
//global callback
|
||||
if (options.callback) {
|
||||
var r = options.callback.call(
|
||||
this,
|
||||
value,
|
||||
options,
|
||||
e,
|
||||
that,
|
||||
options.node
|
||||
);
|
||||
if (r === true) {
|
||||
close_parent = false;
|
||||
}
|
||||
}
|
||||
|
||||
//special cases
|
||||
if (value) {
|
||||
if (value.callback &&
|
||||
!options.ignore_item_callbacks &&
|
||||
value.disabled !== true) {
|
||||
//item callback
|
||||
var r = value.callback.call(
|
||||
this,
|
||||
value,
|
||||
options,
|
||||
e,
|
||||
that,
|
||||
options.extra
|
||||
);
|
||||
if (r === true) {
|
||||
close_parent = false;
|
||||
}
|
||||
}
|
||||
if (value.submenu) {
|
||||
if (!value.submenu.options) {
|
||||
throw "ContextMenu submenu needs options";
|
||||
}
|
||||
var submenu = new that.constructor(value.submenu.options, {
|
||||
callback: value.submenu.callback,
|
||||
event: e,
|
||||
parentMenu: that,
|
||||
ignore_item_callbacks: value.submenu.ignore_item_callbacks,
|
||||
title: value.submenu.title,
|
||||
extra: value.submenu.extra,
|
||||
autoopen: options.autoopen
|
||||
});
|
||||
close_parent = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (close_parent && !that.lock) {
|
||||
that.close();
|
||||
}
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
close(e?: MouseEvent, ignore_parent_menu?: boolean): void {
|
||||
if (this.root.parentNode) {
|
||||
this.root.parentNode.removeChild(this.root);
|
||||
}
|
||||
if (this.parentMenu && !ignore_parent_menu) {
|
||||
this.parentMenu.lock = false;
|
||||
this.parentMenu.current_submenu = null;
|
||||
if (e === undefined) {
|
||||
this.parentMenu.close();
|
||||
} else if (e &&
|
||||
!ContextMenu.isCursorOverElement(e, this.parentMenu.root)) {
|
||||
ContextMenu.trigger(this.parentMenu.root, LiteGraph.pointerevents_method + "leave", e);
|
||||
}
|
||||
}
|
||||
if (this.current_submenu) {
|
||||
this.current_submenu.close(e, true);
|
||||
}
|
||||
|
||||
close(e?: MouseEvent, ignore_parent_menu?: boolean): void {
|
||||
if (this.root.parentNode) {
|
||||
this.root.parentNode.removeChild(this.root);
|
||||
}
|
||||
if (this.parentMenu && !ignore_parent_menu) {
|
||||
this.parentMenu.lock = false;
|
||||
this.parentMenu.current_submenu = null;
|
||||
if (e === undefined) {
|
||||
this.parentMenu.close();
|
||||
} else if (
|
||||
e &&
|
||||
!ContextMenu.isCursorOverElement(e, this.parentMenu.root)
|
||||
) {
|
||||
ContextMenu.trigger(
|
||||
this.parentMenu.root,
|
||||
LiteGraph.pointerevents_method + "leave",
|
||||
e,
|
||||
);
|
||||
}
|
||||
}
|
||||
if (this.current_submenu) {
|
||||
this.current_submenu.close(e, true);
|
||||
if (this.root.closing_timer) {
|
||||
clearTimeout(this.root.closing_timer);
|
||||
}
|
||||
|
||||
// TODO implement : LiteGraph.contextMenuClosed(); :: keep track of opened / closed / current ContextMenu
|
||||
// on key press, allow filtering/selecting the context menu elements
|
||||
}
|
||||
|
||||
if (this.root.closing_timer) {
|
||||
clearTimeout(this.root.closing_timer);
|
||||
//this code is used to trigger events easily (used in the context menu mouseleave
|
||||
static trigger(element: HTMLDivElement, event_name: string, params: MouseEvent, origin?: undefined) {
|
||||
var evt = document.createEvent("CustomEvent");
|
||||
evt.initCustomEvent(event_name, true, true, params); //canBubble, cancelable, detail
|
||||
evt.srcElement = origin;
|
||||
if (element.dispatchEvent) {
|
||||
element.dispatchEvent(evt);
|
||||
} else if (element.__events) {
|
||||
element.__events.dispatchEvent(evt);
|
||||
}
|
||||
//else nothing seems binded here so nothing to do
|
||||
return evt;
|
||||
}
|
||||
|
||||
// TODO implement : LiteGraph.contextMenuClosed(); :: keep track of opened / closed / current ContextMenu
|
||||
// on key press, allow filtering/selecting the context menu elements
|
||||
}
|
||||
//returns the top most menu
|
||||
getTopMenu(): ContextMenu {
|
||||
if (this.options.parentMenu) {
|
||||
return this.options.parentMenu.getTopMenu();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
//this code is used to trigger events easily (used in the context menu mouseleave
|
||||
static trigger(
|
||||
element: HTMLDivElement,
|
||||
event_name: string,
|
||||
params: MouseEvent,
|
||||
origin?: undefined,
|
||||
) {
|
||||
var evt = document.createEvent("CustomEvent");
|
||||
evt.initCustomEvent(event_name, true, true, params); //canBubble, cancelable, detail
|
||||
evt.srcElement = origin;
|
||||
if (element.dispatchEvent) {
|
||||
element.dispatchEvent(evt);
|
||||
} else if (element.__events) {
|
||||
element.__events.dispatchEvent(evt);
|
||||
getFirstEvent(): MouseEvent {
|
||||
if (this.options.parentMenu) {
|
||||
return this.options.parentMenu.getFirstEvent();
|
||||
}
|
||||
return this.options.event;
|
||||
}
|
||||
//else nothing seems binded here so nothing to do
|
||||
return evt;
|
||||
}
|
||||
|
||||
//returns the top most menu
|
||||
getTopMenu(): ContextMenu {
|
||||
if (this.options.parentMenu) {
|
||||
return this.options.parentMenu.getTopMenu();
|
||||
static isCursorOverElement(event: MouseEvent, element: HTMLDivElement): boolean {
|
||||
var left = event.clientX;
|
||||
var top = event.clientY;
|
||||
var rect = element.getBoundingClientRect();
|
||||
if (!rect) {
|
||||
return false;
|
||||
}
|
||||
if (top > rect.top &&
|
||||
top < rect.top + rect.height &&
|
||||
left > rect.left &&
|
||||
left < rect.left + rect.width) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
getFirstEvent(): MouseEvent {
|
||||
if (this.options.parentMenu) {
|
||||
return this.options.parentMenu.getFirstEvent();
|
||||
}
|
||||
return this.options.event;
|
||||
}
|
||||
|
||||
static isCursorOverElement(
|
||||
event: MouseEvent,
|
||||
element: HTMLDivElement,
|
||||
): boolean {
|
||||
var left = event.clientX;
|
||||
var top = event.clientY;
|
||||
var rect = element.getBoundingClientRect();
|
||||
if (!rect) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
top > rect.top &&
|
||||
top < rect.top + rect.height &&
|
||||
left > rect.left &&
|
||||
left < rect.left + rect.width
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,161 +4,165 @@ import { clamp } from "./litegraph";
|
||||
//used by some widgets to render a curve editor
|
||||
|
||||
export class CurveEditor {
|
||||
constructor(points) {
|
||||
this.points = points;
|
||||
this.selected = -1;
|
||||
this.nearest = -1;
|
||||
this.size = null; //stores last size used
|
||||
this.must_update = true;
|
||||
this.margin = 5;
|
||||
}
|
||||
|
||||
static sampleCurve(f, points) {
|
||||
if (!points) return;
|
||||
for (var i = 0; i < points.length - 1; ++i) {
|
||||
var p = points[i];
|
||||
var pn = points[i + 1];
|
||||
if (pn[0] < f) continue;
|
||||
var r = pn[0] - p[0];
|
||||
if (Math.abs(r) < 0.00001) return p[1];
|
||||
var local_f = (f - p[0]) / r;
|
||||
return p[1] * (1.0 - local_f) + pn[1] * local_f;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
draw(ctx, size, graphcanvas, background_color, line_color, inactive) {
|
||||
var points = this.points;
|
||||
if (!points) return;
|
||||
this.size = size;
|
||||
var w = size[0] - this.margin * 2;
|
||||
var h = size[1] - this.margin * 2;
|
||||
|
||||
line_color = line_color || "#666";
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(this.margin, this.margin);
|
||||
|
||||
if (background_color) {
|
||||
ctx.fillStyle = "#111";
|
||||
ctx.fillRect(0, 0, w, h);
|
||||
ctx.fillStyle = "#222";
|
||||
ctx.fillRect(w * 0.5, 0, 1, h);
|
||||
ctx.strokeStyle = "#333";
|
||||
ctx.strokeRect(0, 0, w, h);
|
||||
}
|
||||
ctx.strokeStyle = line_color;
|
||||
if (inactive) ctx.globalAlpha = 0.5;
|
||||
ctx.beginPath();
|
||||
for (var i = 0; i < points.length; ++i) {
|
||||
var p = points[i];
|
||||
ctx.lineTo(p[0] * w, (1.0 - p[1]) * h);
|
||||
}
|
||||
ctx.stroke();
|
||||
ctx.globalAlpha = 1;
|
||||
if (!inactive)
|
||||
for (var i = 0; i < points.length; ++i) {
|
||||
var p = points[i];
|
||||
ctx.fillStyle =
|
||||
this.selected == i ? "#FFF" : this.nearest == i ? "#DDD" : "#AAA";
|
||||
ctx.beginPath();
|
||||
ctx.arc(p[0] * w, (1.0 - p[1]) * h, 2, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
//localpos is mouse in curve editor space
|
||||
onMouseDown(localpos, graphcanvas) {
|
||||
var points = this.points;
|
||||
if (!points) return;
|
||||
if (localpos[1] < 0) return;
|
||||
|
||||
//this.captureInput(true);
|
||||
var w = this.size[0] - this.margin * 2;
|
||||
var h = this.size[1] - this.margin * 2;
|
||||
var x = localpos[0] - this.margin;
|
||||
var y = localpos[1] - this.margin;
|
||||
var pos = [x, y];
|
||||
var max_dist = 30 / graphcanvas.ds.scale;
|
||||
//search closer one
|
||||
this.selected = this.getCloserPoint(pos, max_dist);
|
||||
//create one
|
||||
if (this.selected == -1) {
|
||||
var point = [x / w, 1 - y / h];
|
||||
points.push(point);
|
||||
points.sort(function (a, b) {
|
||||
return a[0] - b[0];
|
||||
});
|
||||
this.selected = points.indexOf(point);
|
||||
this.must_update = true;
|
||||
}
|
||||
if (this.selected != -1) return true;
|
||||
}
|
||||
|
||||
onMouseMove(localpos, graphcanvas) {
|
||||
var points = this.points;
|
||||
if (!points) return;
|
||||
var s = this.selected;
|
||||
if (s < 0) return;
|
||||
var x = (localpos[0] - this.margin) / (this.size[0] - this.margin * 2);
|
||||
var y = (localpos[1] - this.margin) / (this.size[1] - this.margin * 2);
|
||||
var curvepos = [localpos[0] - this.margin, localpos[1] - this.margin];
|
||||
var max_dist = 30 / graphcanvas.ds.scale;
|
||||
this._nearest = this.getCloserPoint(curvepos, max_dist);
|
||||
var point = points[s];
|
||||
if (point) {
|
||||
var is_edge_point = s == 0 || s == points.length - 1;
|
||||
if (
|
||||
!is_edge_point &&
|
||||
(localpos[0] < -10 ||
|
||||
localpos[0] > this.size[0] + 10 ||
|
||||
localpos[1] < -10 ||
|
||||
localpos[1] > this.size[1] + 10)
|
||||
) {
|
||||
points.splice(s, 1);
|
||||
constructor(points) {
|
||||
this.points = points;
|
||||
this.selected = -1;
|
||||
return;
|
||||
}
|
||||
if (!is_edge_point)
|
||||
//not edges
|
||||
point[0] = clamp(x, 0, 1);
|
||||
else point[0] = s == 0 ? 0 : 1;
|
||||
point[1] = 1.0 - clamp(y, 0, 1);
|
||||
points.sort(function (a, b) {
|
||||
return a[0] - b[0];
|
||||
});
|
||||
this.selected = points.indexOf(point);
|
||||
this.must_update = true;
|
||||
this.nearest = -1;
|
||||
this.size = null; //stores last size used
|
||||
this.must_update = true;
|
||||
this.margin = 5;
|
||||
}
|
||||
}
|
||||
|
||||
onMouseUp(localpos, graphcanvas) {
|
||||
this.selected = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
getCloserPoint(pos, max_dist) {
|
||||
var points = this.points;
|
||||
if (!points) return -1;
|
||||
max_dist = max_dist || 30;
|
||||
var w = this.size[0] - this.margin * 2;
|
||||
var h = this.size[1] - this.margin * 2;
|
||||
var num = points.length;
|
||||
var p2 = [0, 0];
|
||||
var min_dist = 1000000;
|
||||
var closest = -1;
|
||||
var last_valid = -1;
|
||||
for (var i = 0; i < num; ++i) {
|
||||
var p = points[i];
|
||||
p2[0] = p[0] * w;
|
||||
p2[1] = (1.0 - p[1]) * h;
|
||||
if (p2[0] < pos[0]) last_valid = i;
|
||||
var dist = vec2.distance(pos, p2);
|
||||
if (dist > min_dist || dist > max_dist) continue;
|
||||
closest = i;
|
||||
min_dist = dist;
|
||||
static sampleCurve(f, points) {
|
||||
if (!points)
|
||||
return;
|
||||
for (var i = 0; i < points.length - 1; ++i) {
|
||||
var p = points[i];
|
||||
var pn = points[i + 1];
|
||||
if (pn[0] < f)
|
||||
continue;
|
||||
var r = (pn[0] - p[0]);
|
||||
if (Math.abs(r) < 0.00001)
|
||||
return p[1];
|
||||
var local_f = (f - p[0]) / r;
|
||||
return p[1] * (1.0 - local_f) + pn[1] * local_f;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
draw(ctx, size, graphcanvas, background_color, line_color, inactive) {
|
||||
var points = this.points;
|
||||
if (!points)
|
||||
return;
|
||||
this.size = size;
|
||||
var w = size[0] - this.margin * 2;
|
||||
var h = size[1] - this.margin * 2;
|
||||
|
||||
line_color = line_color || "#666";
|
||||
|
||||
ctx.save();
|
||||
ctx.translate(this.margin, this.margin);
|
||||
|
||||
if (background_color) {
|
||||
ctx.fillStyle = "#111";
|
||||
ctx.fillRect(0, 0, w, h);
|
||||
ctx.fillStyle = "#222";
|
||||
ctx.fillRect(w * 0.5, 0, 1, h);
|
||||
ctx.strokeStyle = "#333";
|
||||
ctx.strokeRect(0, 0, w, h);
|
||||
}
|
||||
ctx.strokeStyle = line_color;
|
||||
if (inactive)
|
||||
ctx.globalAlpha = 0.5;
|
||||
ctx.beginPath();
|
||||
for (var i = 0; i < points.length; ++i) {
|
||||
var p = points[i];
|
||||
ctx.lineTo(p[0] * w, (1.0 - p[1]) * h);
|
||||
}
|
||||
ctx.stroke();
|
||||
ctx.globalAlpha = 1;
|
||||
if (!inactive)
|
||||
for (var i = 0; i < points.length; ++i) {
|
||||
var p = points[i];
|
||||
ctx.fillStyle = this.selected == i ? "#FFF" : (this.nearest == i ? "#DDD" : "#AAA");
|
||||
ctx.beginPath();
|
||||
ctx.arc(p[0] * w, (1.0 - p[1]) * h, 2, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
}
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
//localpos is mouse in curve editor space
|
||||
onMouseDown(localpos, graphcanvas) {
|
||||
var points = this.points;
|
||||
if (!points)
|
||||
return;
|
||||
if (localpos[1] < 0)
|
||||
return;
|
||||
|
||||
//this.captureInput(true);
|
||||
var w = this.size[0] - this.margin * 2;
|
||||
var h = this.size[1] - this.margin * 2;
|
||||
var x = localpos[0] - this.margin;
|
||||
var y = localpos[1] - this.margin;
|
||||
var pos = [x, y];
|
||||
var max_dist = 30 / graphcanvas.ds.scale;
|
||||
//search closer one
|
||||
this.selected = this.getCloserPoint(pos, max_dist);
|
||||
//create one
|
||||
if (this.selected == -1) {
|
||||
var point = [x / w, 1 - y / h];
|
||||
points.push(point);
|
||||
points.sort(function (a, b) { return a[0] - b[0]; });
|
||||
this.selected = points.indexOf(point);
|
||||
this.must_update = true;
|
||||
}
|
||||
if (this.selected != -1)
|
||||
return true;
|
||||
}
|
||||
|
||||
onMouseMove(localpos, graphcanvas) {
|
||||
var points = this.points;
|
||||
if (!points)
|
||||
return;
|
||||
var s = this.selected;
|
||||
if (s < 0)
|
||||
return;
|
||||
var x = (localpos[0] - this.margin) / (this.size[0] - this.margin * 2);
|
||||
var y = (localpos[1] - this.margin) / (this.size[1] - this.margin * 2);
|
||||
var curvepos = [(localpos[0] - this.margin), (localpos[1] - this.margin)];
|
||||
var max_dist = 30 / graphcanvas.ds.scale;
|
||||
this._nearest = this.getCloserPoint(curvepos, max_dist);
|
||||
var point = points[s];
|
||||
if (point) {
|
||||
var is_edge_point = s == 0 || s == points.length - 1;
|
||||
if (!is_edge_point && (localpos[0] < -10 || localpos[0] > this.size[0] + 10 || localpos[1] < -10 || localpos[1] > this.size[1] + 10)) {
|
||||
points.splice(s, 1);
|
||||
this.selected = -1;
|
||||
return;
|
||||
}
|
||||
if (!is_edge_point) //not edges
|
||||
point[0] = clamp(x, 0, 1);
|
||||
|
||||
|
||||
else
|
||||
point[0] = s == 0 ? 0 : 1;
|
||||
point[1] = 1.0 - clamp(y, 0, 1);
|
||||
points.sort(function (a, b) { return a[0] - b[0]; });
|
||||
this.selected = points.indexOf(point);
|
||||
this.must_update = true;
|
||||
}
|
||||
}
|
||||
|
||||
onMouseUp(localpos, graphcanvas) {
|
||||
this.selected = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
getCloserPoint(pos, max_dist) {
|
||||
var points = this.points;
|
||||
if (!points)
|
||||
return -1;
|
||||
max_dist = max_dist || 30;
|
||||
var w = (this.size[0] - this.margin * 2);
|
||||
var h = (this.size[1] - this.margin * 2);
|
||||
var num = points.length;
|
||||
var p2 = [0, 0];
|
||||
var min_dist = 1000000;
|
||||
var closest = -1;
|
||||
var last_valid = -1;
|
||||
for (var i = 0; i < num; ++i) {
|
||||
var p = points[i];
|
||||
p2[0] = p[0] * w;
|
||||
p2[1] = (1.0 - p[1]) * h;
|
||||
if (p2[0] < pos[0])
|
||||
last_valid = i;
|
||||
var dist = vec2.distance(pos, p2);
|
||||
if (dist > min_dist || dist > max_dist)
|
||||
continue;
|
||||
closest = i;
|
||||
min_dist = dist;
|
||||
}
|
||||
return closest;
|
||||
}
|
||||
return closest;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,248 +1,235 @@
|
||||
import type { Point, Rect, Rect32 } from "./interfaces";
|
||||
import type { Point, Rect, Rect32 } from "./interfaces"
|
||||
import { LiteGraph } from "./litegraph";
|
||||
|
||||
//****************************************
|
||||
//Scale and Offset
|
||||
|
||||
export class DragAndScale {
|
||||
max_scale: number;
|
||||
min_scale: number;
|
||||
offset: Point;
|
||||
scale: number;
|
||||
enabled: boolean;
|
||||
last_mouse: Point;
|
||||
element?: HTMLCanvasElement;
|
||||
visible_area: Rect32;
|
||||
_binded_mouse_callback;
|
||||
dragging?: boolean;
|
||||
viewport?: Rect;
|
||||
max_scale: number
|
||||
min_scale: number
|
||||
offset: Point
|
||||
scale: number
|
||||
enabled: boolean
|
||||
last_mouse: Point
|
||||
element?: HTMLCanvasElement
|
||||
visible_area: Rect32
|
||||
_binded_mouse_callback
|
||||
dragging?: boolean
|
||||
viewport?: Rect
|
||||
|
||||
onredraw?(das: DragAndScale): void;
|
||||
/** @deprecated */
|
||||
onmouse?(e: any): boolean;
|
||||
onredraw?(das: DragAndScale): void
|
||||
/** @deprecated */
|
||||
onmouse?(e: any): boolean
|
||||
|
||||
constructor(element?: HTMLCanvasElement, skip_events?: boolean) {
|
||||
this.offset = new Float32Array([0, 0]);
|
||||
this.scale = 1;
|
||||
this.max_scale = 10;
|
||||
this.min_scale = 0.1;
|
||||
this.onredraw = null;
|
||||
this.enabled = true;
|
||||
this.last_mouse = [0, 0];
|
||||
this.element = null;
|
||||
this.visible_area = new Float32Array(4);
|
||||
constructor(element?: HTMLCanvasElement, skip_events?: boolean) {
|
||||
this.offset = new Float32Array([0, 0]);
|
||||
this.scale = 1;
|
||||
this.max_scale = 10;
|
||||
this.min_scale = 0.1;
|
||||
this.onredraw = null;
|
||||
this.enabled = true;
|
||||
this.last_mouse = [0, 0];
|
||||
this.element = null;
|
||||
this.visible_area = new Float32Array(4);
|
||||
|
||||
if (element) {
|
||||
this.element = element;
|
||||
if (!skip_events) {
|
||||
this.bindEvents(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bindEvents(element) {
|
||||
this.last_mouse = new Float32Array(2);
|
||||
|
||||
this._binded_mouse_callback = this.onMouse.bind(this);
|
||||
|
||||
LiteGraph.pointerListenerAdd(element, "down", this._binded_mouse_callback);
|
||||
LiteGraph.pointerListenerAdd(element, "move", this._binded_mouse_callback);
|
||||
LiteGraph.pointerListenerAdd(element, "up", this._binded_mouse_callback);
|
||||
|
||||
element.addEventListener("mousewheel", this._binded_mouse_callback, false);
|
||||
element.addEventListener("wheel", this._binded_mouse_callback, false);
|
||||
}
|
||||
|
||||
computeVisibleArea(viewport: Rect): void {
|
||||
if (!this.element) {
|
||||
this.visible_area[0] =
|
||||
this.visible_area[1] =
|
||||
this.visible_area[2] =
|
||||
this.visible_area[3] =
|
||||
0;
|
||||
return;
|
||||
}
|
||||
var width = this.element.width;
|
||||
var height = this.element.height;
|
||||
var startx = -this.offset[0];
|
||||
var starty = -this.offset[1];
|
||||
if (viewport) {
|
||||
startx += viewport[0] / this.scale;
|
||||
starty += viewport[1] / this.scale;
|
||||
width = viewport[2];
|
||||
height = viewport[3];
|
||||
}
|
||||
var endx = startx + width / this.scale;
|
||||
var endy = starty + height / this.scale;
|
||||
this.visible_area[0] = startx;
|
||||
this.visible_area[1] = starty;
|
||||
this.visible_area[2] = endx - startx;
|
||||
this.visible_area[3] = endy - starty;
|
||||
}
|
||||
|
||||
onMouse(e) {
|
||||
if (!this.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
var canvas = this.element;
|
||||
var rect = canvas.getBoundingClientRect();
|
||||
var x = e.clientX - rect.left;
|
||||
var y = e.clientY - rect.top;
|
||||
e.canvasx = x;
|
||||
e.canvasy = y;
|
||||
e.dragging = this.dragging;
|
||||
|
||||
var is_inside =
|
||||
!this.viewport ||
|
||||
(this.viewport &&
|
||||
x >= this.viewport[0] &&
|
||||
x < this.viewport[0] + this.viewport[2] &&
|
||||
y >= this.viewport[1] &&
|
||||
y < this.viewport[1] + this.viewport[3]);
|
||||
|
||||
//console.log("pointerevents: DragAndScale onMouse "+e.type+" "+is_inside);
|
||||
var ignore = false;
|
||||
if (this.onmouse) {
|
||||
ignore = this.onmouse(e);
|
||||
}
|
||||
|
||||
if (e.type == LiteGraph.pointerevents_method + "down" && is_inside) {
|
||||
this.dragging = true;
|
||||
LiteGraph.pointerListenerRemove(
|
||||
canvas,
|
||||
"move",
|
||||
this._binded_mouse_callback,
|
||||
);
|
||||
LiteGraph.pointerListenerAdd(
|
||||
document,
|
||||
"move",
|
||||
this._binded_mouse_callback,
|
||||
);
|
||||
LiteGraph.pointerListenerAdd(document, "up", this._binded_mouse_callback);
|
||||
} else if (e.type == LiteGraph.pointerevents_method + "move") {
|
||||
if (!ignore) {
|
||||
var deltax = x - this.last_mouse[0];
|
||||
var deltay = y - this.last_mouse[1];
|
||||
if (this.dragging) {
|
||||
this.mouseDrag(deltax, deltay);
|
||||
if (element) {
|
||||
this.element = element;
|
||||
if (!skip_events) {
|
||||
this.bindEvents(element);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (e.type == LiteGraph.pointerevents_method + "up") {
|
||||
this.dragging = false;
|
||||
LiteGraph.pointerListenerRemove(
|
||||
document,
|
||||
"move",
|
||||
this._binded_mouse_callback,
|
||||
);
|
||||
LiteGraph.pointerListenerRemove(
|
||||
document,
|
||||
"up",
|
||||
this._binded_mouse_callback,
|
||||
);
|
||||
LiteGraph.pointerListenerAdd(canvas, "move", this._binded_mouse_callback);
|
||||
} else if (
|
||||
is_inside &&
|
||||
(e.type == "mousewheel" ||
|
||||
e.type == "wheel" ||
|
||||
e.type == "DOMMouseScroll")
|
||||
) {
|
||||
e.eventType = "mousewheel";
|
||||
if (e.type == "wheel") {
|
||||
e.wheel = -e.deltaY;
|
||||
} else {
|
||||
e.wheel = e.wheelDeltaY != null ? e.wheelDeltaY : e.detail * -60;
|
||||
}
|
||||
|
||||
//from stack overflow
|
||||
e.delta = e.wheelDelta ? e.wheelDelta / 40 : e.deltaY ? -e.deltaY / 3 : 0;
|
||||
this.changeDeltaScale(1.0 + e.delta * 0.05);
|
||||
}
|
||||
|
||||
this.last_mouse[0] = x;
|
||||
this.last_mouse[1] = y;
|
||||
bindEvents(element) {
|
||||
this.last_mouse = new Float32Array(2);
|
||||
|
||||
if (is_inside) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
this._binded_mouse_callback = this.onMouse.bind(this);
|
||||
|
||||
toCanvasContext(ctx: CanvasRenderingContext2D): void {
|
||||
ctx.scale(this.scale, this.scale);
|
||||
ctx.translate(this.offset[0], this.offset[1]);
|
||||
}
|
||||
LiteGraph.pointerListenerAdd(element, "down", this._binded_mouse_callback);
|
||||
LiteGraph.pointerListenerAdd(element, "move", this._binded_mouse_callback);
|
||||
LiteGraph.pointerListenerAdd(element, "up", this._binded_mouse_callback);
|
||||
|
||||
convertOffsetToCanvas(pos: Point): Point {
|
||||
//return [pos[0] / this.scale - this.offset[0], pos[1] / this.scale - this.offset[1]];
|
||||
return [
|
||||
(pos[0] + this.offset[0]) * this.scale,
|
||||
(pos[1] + this.offset[1]) * this.scale,
|
||||
];
|
||||
}
|
||||
|
||||
convertCanvasToOffset(pos: Point, out?: Point): Point {
|
||||
out = out || [0, 0];
|
||||
out[0] = pos[0] / this.scale - this.offset[0];
|
||||
out[1] = pos[1] / this.scale - this.offset[1];
|
||||
return out;
|
||||
}
|
||||
|
||||
mouseDrag(x, y) {
|
||||
this.offset[0] += x / this.scale;
|
||||
this.offset[1] += y / this.scale;
|
||||
|
||||
if (this.onredraw) {
|
||||
this.onredraw(this);
|
||||
}
|
||||
}
|
||||
|
||||
changeScale(value: number, zooming_center?: Point): void {
|
||||
if (value < this.min_scale) {
|
||||
value = this.min_scale;
|
||||
} else if (value > this.max_scale) {
|
||||
value = this.max_scale;
|
||||
element.addEventListener(
|
||||
"mousewheel",
|
||||
this._binded_mouse_callback,
|
||||
false
|
||||
);
|
||||
element.addEventListener("wheel", this._binded_mouse_callback, false);
|
||||
}
|
||||
|
||||
if (value == this.scale) {
|
||||
return;
|
||||
computeVisibleArea(viewport: Rect): void {
|
||||
if (!this.element) {
|
||||
this.visible_area[0] = this.visible_area[1] = this.visible_area[2] = this.visible_area[3] = 0;
|
||||
return;
|
||||
}
|
||||
var width = this.element.width;
|
||||
var height = this.element.height;
|
||||
var startx = -this.offset[0];
|
||||
var starty = -this.offset[1];
|
||||
if (viewport) {
|
||||
startx += viewport[0] / this.scale;
|
||||
starty += viewport[1] / this.scale;
|
||||
width = viewport[2];
|
||||
height = viewport[3];
|
||||
}
|
||||
var endx = startx + width / this.scale;
|
||||
var endy = starty + height / this.scale;
|
||||
this.visible_area[0] = startx;
|
||||
this.visible_area[1] = starty;
|
||||
this.visible_area[2] = endx - startx;
|
||||
this.visible_area[3] = endy - starty;
|
||||
}
|
||||
|
||||
if (!this.element) {
|
||||
return;
|
||||
onMouse(e) {
|
||||
if (!this.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
var canvas = this.element;
|
||||
var rect = canvas.getBoundingClientRect();
|
||||
var x = e.clientX - rect.left;
|
||||
var y = e.clientY - rect.top;
|
||||
e.canvasx = x;
|
||||
e.canvasy = y;
|
||||
e.dragging = this.dragging;
|
||||
|
||||
var is_inside = !this.viewport || (this.viewport && x >= this.viewport[0] && x < (this.viewport[0] + this.viewport[2]) && y >= this.viewport[1] && y < (this.viewport[1] + this.viewport[3]));
|
||||
|
||||
//console.log("pointerevents: DragAndScale onMouse "+e.type+" "+is_inside);
|
||||
var ignore = false;
|
||||
if (this.onmouse) {
|
||||
ignore = this.onmouse(e);
|
||||
}
|
||||
|
||||
if (e.type == LiteGraph.pointerevents_method + "down" && is_inside) {
|
||||
this.dragging = true;
|
||||
LiteGraph.pointerListenerRemove(canvas, "move", this._binded_mouse_callback);
|
||||
LiteGraph.pointerListenerAdd(document, "move", this._binded_mouse_callback);
|
||||
LiteGraph.pointerListenerAdd(document, "up", this._binded_mouse_callback);
|
||||
} else if (e.type == LiteGraph.pointerevents_method + "move") {
|
||||
if (!ignore) {
|
||||
var deltax = x - this.last_mouse[0];
|
||||
var deltay = y - this.last_mouse[1];
|
||||
if (this.dragging) {
|
||||
this.mouseDrag(deltax, deltay);
|
||||
}
|
||||
}
|
||||
} else if (e.type == LiteGraph.pointerevents_method + "up") {
|
||||
this.dragging = false;
|
||||
LiteGraph.pointerListenerRemove(document, "move", this._binded_mouse_callback);
|
||||
LiteGraph.pointerListenerRemove(document, "up", this._binded_mouse_callback);
|
||||
LiteGraph.pointerListenerAdd(canvas, "move", this._binded_mouse_callback);
|
||||
} else if (is_inside &&
|
||||
(e.type == "mousewheel" ||
|
||||
e.type == "wheel" ||
|
||||
e.type == "DOMMouseScroll")) {
|
||||
e.eventType = "mousewheel";
|
||||
if (e.type == "wheel") {
|
||||
e.wheel = -e.deltaY;
|
||||
} else {
|
||||
e.wheel =
|
||||
e.wheelDeltaY != null ? e.wheelDeltaY : e.detail * -60;
|
||||
}
|
||||
|
||||
//from stack overflow
|
||||
e.delta = e.wheelDelta
|
||||
? e.wheelDelta / 40
|
||||
: e.deltaY
|
||||
? -e.deltaY / 3
|
||||
: 0;
|
||||
this.changeDeltaScale(1.0 + e.delta * 0.05);
|
||||
}
|
||||
|
||||
this.last_mouse[0] = x;
|
||||
this.last_mouse[1] = y;
|
||||
|
||||
if (is_inside) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
var rect = this.element.getBoundingClientRect();
|
||||
if (!rect) {
|
||||
return;
|
||||
toCanvasContext(ctx: CanvasRenderingContext2D): void {
|
||||
ctx.scale(this.scale, this.scale);
|
||||
ctx.translate(this.offset[0], this.offset[1]);
|
||||
}
|
||||
|
||||
zooming_center = zooming_center || [rect.width * 0.5, rect.height * 0.5];
|
||||
var center = this.convertCanvasToOffset(zooming_center);
|
||||
this.scale = value;
|
||||
if (Math.abs(this.scale - 1) < 0.01) {
|
||||
this.scale = 1;
|
||||
convertOffsetToCanvas(pos: Point): Point {
|
||||
//return [pos[0] / this.scale - this.offset[0], pos[1] / this.scale - this.offset[1]];
|
||||
return [
|
||||
(pos[0] + this.offset[0]) * this.scale,
|
||||
(pos[1] + this.offset[1]) * this.scale
|
||||
];
|
||||
}
|
||||
|
||||
var new_center = this.convertCanvasToOffset(zooming_center);
|
||||
var delta_offset = [new_center[0] - center[0], new_center[1] - center[1]];
|
||||
|
||||
this.offset[0] += delta_offset[0];
|
||||
this.offset[1] += delta_offset[1];
|
||||
|
||||
if (this.onredraw) {
|
||||
this.onredraw(this);
|
||||
convertCanvasToOffset(pos: Point, out?: Point): Point {
|
||||
out = out || [0, 0];
|
||||
out[0] = pos[0] / this.scale - this.offset[0];
|
||||
out[1] = pos[1] / this.scale - this.offset[1];
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
changeDeltaScale(value: number, zooming_center?: Point) {
|
||||
this.changeScale(this.scale * value, zooming_center);
|
||||
}
|
||||
mouseDrag(x, y) {
|
||||
this.offset[0] += x / this.scale;
|
||||
this.offset[1] += y / this.scale;
|
||||
|
||||
reset(): void {
|
||||
this.scale = 1;
|
||||
this.offset[0] = 0;
|
||||
this.offset[1] = 0;
|
||||
}
|
||||
if (this.onredraw) {
|
||||
this.onredraw(this);
|
||||
}
|
||||
}
|
||||
|
||||
changeScale(value: number, zooming_center?: Point): void {
|
||||
if (value < this.min_scale) {
|
||||
value = this.min_scale;
|
||||
} else if (value > this.max_scale) {
|
||||
value = this.max_scale;
|
||||
}
|
||||
|
||||
if (value == this.scale) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.element) {
|
||||
return;
|
||||
}
|
||||
|
||||
var rect = this.element.getBoundingClientRect();
|
||||
if (!rect) {
|
||||
return;
|
||||
}
|
||||
|
||||
zooming_center = zooming_center || [
|
||||
rect.width * 0.5,
|
||||
rect.height * 0.5
|
||||
];
|
||||
var center = this.convertCanvasToOffset(zooming_center);
|
||||
this.scale = value;
|
||||
if (Math.abs(this.scale - 1) < 0.01) {
|
||||
this.scale = 1;
|
||||
}
|
||||
|
||||
var new_center = this.convertCanvasToOffset(zooming_center);
|
||||
var delta_offset = [
|
||||
new_center[0] - center[0],
|
||||
new_center[1] - center[1]
|
||||
];
|
||||
|
||||
this.offset[0] += delta_offset[0];
|
||||
this.offset[1] += delta_offset[1];
|
||||
|
||||
if (this.onredraw) {
|
||||
this.onredraw(this);
|
||||
}
|
||||
}
|
||||
|
||||
changeDeltaScale(value: number, zooming_center?: Point) {
|
||||
this.changeScale(this.scale * value, zooming_center);
|
||||
}
|
||||
|
||||
reset(): void {
|
||||
this.scale = 1;
|
||||
this.offset[0] = 0;
|
||||
this.offset[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
2957
src/LGraph.ts
2957
src/LGraph.ts
File diff suppressed because it is too large
Load Diff
@@ -54,7 +54,11 @@ export class LGraphBadge {
|
||||
return textWidth + this.padding * 2;
|
||||
}
|
||||
|
||||
draw(ctx: CanvasRenderingContext2D, x: number, y: number): void {
|
||||
draw(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
x: number,
|
||||
y: number,
|
||||
): void {
|
||||
if (!this.visible) return;
|
||||
|
||||
ctx.save();
|
||||
@@ -78,7 +82,7 @@ export class LGraphBadge {
|
||||
ctx.fillText(
|
||||
this.text,
|
||||
x + badgeX + this.padding,
|
||||
y + this.height - this.padding,
|
||||
y + this.height - this.padding
|
||||
);
|
||||
|
||||
ctx.restore();
|
||||
|
||||
16513
src/LGraphCanvas.ts
16513
src/LGraphCanvas.ts
File diff suppressed because it is too large
Load Diff
@@ -1,289 +1,278 @@
|
||||
// @ts-nocheck
|
||||
import type { Point, Size } from "./interfaces";
|
||||
import type { LGraph } from "./LGraph";
|
||||
import type { Point, Size } from "./interfaces"
|
||||
import type { LGraph } from "./LGraph"
|
||||
import { LiteGraph } from "./litegraph";
|
||||
import { LGraphCanvas } from "./LGraphCanvas";
|
||||
import { overlapBounding } from "./LiteGraphGlobal";
|
||||
import { LGraphNode } from "./LGraphNode";
|
||||
|
||||
export interface IGraphGroup {
|
||||
_pos: Point;
|
||||
_size: Size;
|
||||
title: string;
|
||||
_pos: Point
|
||||
_size: Size
|
||||
title: string
|
||||
}
|
||||
|
||||
export interface IGraphGroupFlags extends Record<string, unknown> {
|
||||
pinned?: true;
|
||||
pinned?: true
|
||||
}
|
||||
|
||||
export class LGraphGroup {
|
||||
pos: Point;
|
||||
color: string;
|
||||
title: string;
|
||||
font?: string;
|
||||
font_size: number;
|
||||
_bounding: Float32Array;
|
||||
_pos: Point;
|
||||
_size: Size;
|
||||
_nodes: LGraphNode[];
|
||||
graph?: LGraph;
|
||||
flags: IGraphGroupFlags;
|
||||
size?: Size;
|
||||
pos: Point
|
||||
color: string
|
||||
title: string
|
||||
font?: string
|
||||
font_size: number
|
||||
_bounding: Float32Array
|
||||
_pos: Point
|
||||
_size: Size
|
||||
_nodes: LGraphNode[]
|
||||
graph?: LGraph
|
||||
flags: IGraphGroupFlags
|
||||
size?: Size
|
||||
|
||||
constructor(title?: string) {
|
||||
this._ctor(title);
|
||||
}
|
||||
constructor(title?: string) {
|
||||
this._ctor(title);
|
||||
}
|
||||
|
||||
_ctor(title?: string) {
|
||||
this.title = title || "Group";
|
||||
this.font_size = LiteGraph.DEFAULT_GROUP_FONT || 24;
|
||||
this.color = LGraphCanvas.node_colors.pale_blue
|
||||
? LGraphCanvas.node_colors.pale_blue.groupcolor
|
||||
: "#AAA";
|
||||
this._bounding = new Float32Array([10, 10, 140, 80]);
|
||||
this._pos = this._bounding.subarray(0, 2);
|
||||
this._size = this._bounding.subarray(2, 4);
|
||||
this._nodes = [];
|
||||
this.graph = null;
|
||||
this.flags = {};
|
||||
_ctor(title?: string) {
|
||||
this.title = title || "Group";
|
||||
this.font_size = LiteGraph.DEFAULT_GROUP_FONT || 24;
|
||||
this.color = LGraphCanvas.node_colors.pale_blue
|
||||
? LGraphCanvas.node_colors.pale_blue.groupcolor
|
||||
: "#AAA";
|
||||
this._bounding = new Float32Array([10, 10, 140, 80]);
|
||||
this._pos = this._bounding.subarray(0, 2);
|
||||
this._size = this._bounding.subarray(2, 4);
|
||||
this._nodes = [];
|
||||
this.graph = null;
|
||||
this.flags = {};
|
||||
|
||||
Object.defineProperty(this, "pos", {
|
||||
set: function (v) {
|
||||
if (!v || v.length < 2) {
|
||||
return;
|
||||
Object.defineProperty(this, "pos", {
|
||||
set: function (v) {
|
||||
if (!v || v.length < 2) {
|
||||
return;
|
||||
}
|
||||
this._pos[0] = v[0];
|
||||
this._pos[1] = v[1];
|
||||
},
|
||||
get: function () {
|
||||
return this._pos;
|
||||
},
|
||||
enumerable: true
|
||||
});
|
||||
|
||||
Object.defineProperty(this, "size", {
|
||||
set: function (v) {
|
||||
if (!v || v.length < 2) {
|
||||
return;
|
||||
}
|
||||
this._size[0] = Math.max(140, v[0]);
|
||||
this._size[1] = Math.max(80, v[1]);
|
||||
},
|
||||
get: function () {
|
||||
return this._size;
|
||||
},
|
||||
enumerable: true
|
||||
});
|
||||
}
|
||||
|
||||
get nodes() {
|
||||
return this._nodes;
|
||||
}
|
||||
|
||||
get titleHeight() {
|
||||
return this.font_size * 1.4;
|
||||
}
|
||||
|
||||
get selected() {
|
||||
return !!this.graph?.list_of_graphcanvas?.some(c => c.selected_group === this);
|
||||
}
|
||||
|
||||
get pinned() {
|
||||
return !!this.flags.pinned;
|
||||
}
|
||||
|
||||
pin() {
|
||||
this.flags.pinned = true;
|
||||
}
|
||||
|
||||
unpin() {
|
||||
delete this.flags.pinned;
|
||||
}
|
||||
|
||||
configure(o) {
|
||||
this.title = o.title;
|
||||
this._bounding.set(o.bounding);
|
||||
this.color = o.color;
|
||||
this.flags = o.flags || this.flags;
|
||||
if (o.font_size) {
|
||||
this.font_size = o.font_size;
|
||||
}
|
||||
this._pos[0] = v[0];
|
||||
this._pos[1] = v[1];
|
||||
},
|
||||
get: function () {
|
||||
return this._pos;
|
||||
},
|
||||
enumerable: true,
|
||||
});
|
||||
|
||||
Object.defineProperty(this, "size", {
|
||||
set: function (v) {
|
||||
if (!v || v.length < 2) {
|
||||
return;
|
||||
}
|
||||
this._size[0] = Math.max(140, v[0]);
|
||||
this._size[1] = Math.max(80, v[1]);
|
||||
},
|
||||
get: function () {
|
||||
return this._size;
|
||||
},
|
||||
enumerable: true,
|
||||
});
|
||||
}
|
||||
|
||||
get nodes() {
|
||||
return this._nodes;
|
||||
}
|
||||
|
||||
get titleHeight() {
|
||||
return this.font_size * 1.4;
|
||||
}
|
||||
|
||||
get selected() {
|
||||
return !!this.graph?.list_of_graphcanvas?.some(
|
||||
(c) => c.selected_group === this,
|
||||
);
|
||||
}
|
||||
|
||||
get pinned() {
|
||||
return !!this.flags.pinned;
|
||||
}
|
||||
|
||||
pin() {
|
||||
this.flags.pinned = true;
|
||||
}
|
||||
|
||||
unpin() {
|
||||
delete this.flags.pinned;
|
||||
}
|
||||
|
||||
configure(o) {
|
||||
this.title = o.title;
|
||||
this._bounding.set(o.bounding);
|
||||
this.color = o.color;
|
||||
this.flags = o.flags || this.flags;
|
||||
if (o.font_size) {
|
||||
this.font_size = o.font_size;
|
||||
}
|
||||
}
|
||||
|
||||
serialize() {
|
||||
var b = this._bounding;
|
||||
return {
|
||||
title: this.title,
|
||||
bounding: [
|
||||
Math.round(b[0]),
|
||||
Math.round(b[1]),
|
||||
Math.round(b[2]),
|
||||
Math.round(b[3]),
|
||||
],
|
||||
color: this.color,
|
||||
font_size: this.font_size,
|
||||
flags: this.flags,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the group on the canvas
|
||||
* @param {LGraphCanvas} graphCanvas
|
||||
* @param {CanvasRenderingContext2D} ctx
|
||||
*/
|
||||
draw(graphCanvas, ctx) {
|
||||
const padding = 4;
|
||||
|
||||
ctx.fillStyle = this.color;
|
||||
ctx.strokeStyle = this.color;
|
||||
const [x, y] = this._pos;
|
||||
const [width, height] = this._size;
|
||||
ctx.globalAlpha = 0.25 * graphCanvas.editor_alpha;
|
||||
ctx.beginPath();
|
||||
ctx.rect(x + 0.5, y + 0.5, width, height);
|
||||
ctx.fill();
|
||||
ctx.globalAlpha = graphCanvas.editor_alpha;
|
||||
ctx.stroke();
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x + width, y + height);
|
||||
ctx.lineTo(x + width - 10, y + height);
|
||||
ctx.lineTo(x + width, y + height - 10);
|
||||
ctx.fill();
|
||||
|
||||
const font_size = this.font_size || LiteGraph.DEFAULT_GROUP_FONT_SIZE;
|
||||
ctx.font = font_size + "px Arial";
|
||||
ctx.textAlign = "left";
|
||||
ctx.fillText(
|
||||
this.title + (this.pinned ? "📌" : ""),
|
||||
x + padding,
|
||||
y + font_size,
|
||||
);
|
||||
|
||||
if (LiteGraph.highlight_selected_group && this.selected) {
|
||||
graphCanvas.drawSelectionBounding(ctx, this._bounding, {
|
||||
shape: LiteGraph.BOX_SHAPE,
|
||||
title_height: this.titleHeight,
|
||||
title_mode: LiteGraph.NORMAL_TITLE,
|
||||
fgcolor: this.color,
|
||||
padding,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
resize(width, height) {
|
||||
if (this.pinned) {
|
||||
return;
|
||||
}
|
||||
this._size[0] = width;
|
||||
this._size[1] = height;
|
||||
}
|
||||
|
||||
move(deltax, deltay, ignore_nodes) {
|
||||
if (this.pinned) {
|
||||
return;
|
||||
}
|
||||
this._pos[0] += deltax;
|
||||
this._pos[1] += deltay;
|
||||
if (ignore_nodes) {
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < this._nodes.length; ++i) {
|
||||
var node = this._nodes[i];
|
||||
node.pos[0] += deltax;
|
||||
node.pos[1] += deltay;
|
||||
}
|
||||
}
|
||||
|
||||
recomputeInsideNodes() {
|
||||
this._nodes.length = 0;
|
||||
var nodes = this.graph._nodes;
|
||||
var node_bounding = new Float32Array(4);
|
||||
|
||||
for (var i = 0; i < nodes.length; ++i) {
|
||||
var node = nodes[i];
|
||||
node.getBounding(node_bounding);
|
||||
if (!overlapBounding(this._bounding, node_bounding)) {
|
||||
continue;
|
||||
} //out of the visible area
|
||||
this._nodes.push(node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add nodes to the group and adjust the group's position and size accordingly
|
||||
* @param {LGraphNode[]} nodes - The nodes to add to the group
|
||||
* @param {number} [padding=10] - The padding around the group
|
||||
* @returns {void}
|
||||
*/
|
||||
addNodes(nodes, padding = 10) {
|
||||
if (!this._nodes && nodes.length === 0) return;
|
||||
|
||||
const allNodes = [...(this._nodes || []), ...nodes];
|
||||
|
||||
const bounds = allNodes.reduce(
|
||||
(acc, node) => {
|
||||
const [x, y] = node.pos;
|
||||
const [width, height] = node.size;
|
||||
const isReroute = node.type === "Reroute";
|
||||
const isCollapsed = node.flags?.collapsed;
|
||||
|
||||
const top = y - (isReroute ? 0 : LiteGraph.NODE_TITLE_HEIGHT);
|
||||
const bottom = isCollapsed
|
||||
? top + LiteGraph.NODE_TITLE_HEIGHT
|
||||
: y + height;
|
||||
const right =
|
||||
isCollapsed && node._collapsed_width
|
||||
? x + Math.round(node._collapsed_width)
|
||||
: x + width;
|
||||
|
||||
serialize() {
|
||||
var b = this._bounding;
|
||||
return {
|
||||
left: Math.min(acc.left, x),
|
||||
top: Math.min(acc.top, top),
|
||||
right: Math.max(acc.right, right),
|
||||
bottom: Math.max(acc.bottom, bottom),
|
||||
title: this.title,
|
||||
bounding: [
|
||||
Math.round(b[0]),
|
||||
Math.round(b[1]),
|
||||
Math.round(b[2]),
|
||||
Math.round(b[3])
|
||||
],
|
||||
color: this.color,
|
||||
font_size: this.font_size,
|
||||
flags: this.flags,
|
||||
};
|
||||
},
|
||||
{ left: Infinity, top: Infinity, right: -Infinity, bottom: -Infinity },
|
||||
);
|
||||
}
|
||||
|
||||
this.pos = [bounds.left - padding, bounds.top - padding - this.titleHeight];
|
||||
/**
|
||||
* Draws the group on the canvas
|
||||
* @param {LGraphCanvas} graphCanvas
|
||||
* @param {CanvasRenderingContext2D} ctx
|
||||
*/
|
||||
draw(graphCanvas, ctx) {
|
||||
const padding = 4;
|
||||
|
||||
this.size = [
|
||||
bounds.right - bounds.left + padding * 2,
|
||||
bounds.bottom - bounds.top + padding * 2 + this.titleHeight,
|
||||
];
|
||||
}
|
||||
ctx.fillStyle = this.color;
|
||||
ctx.strokeStyle = this.color;
|
||||
const [x, y] = this._pos;
|
||||
const [width, height] = this._size;
|
||||
ctx.globalAlpha = 0.25 * graphCanvas.editor_alpha;
|
||||
ctx.beginPath();
|
||||
ctx.rect(x + 0.5, y + 0.5, width, height);
|
||||
ctx.fill();
|
||||
ctx.globalAlpha = graphCanvas.editor_alpha;
|
||||
ctx.stroke();
|
||||
|
||||
getMenuOptions() {
|
||||
return [
|
||||
{
|
||||
content: this.pinned ? "Unpin" : "Pin",
|
||||
callback: () => {
|
||||
this.pinned ? this.unpin() : this.pin();
|
||||
this.setDirtyCanvas(false, true);
|
||||
},
|
||||
},
|
||||
null,
|
||||
{ content: "Title", callback: LGraphCanvas.onShowPropertyEditor },
|
||||
{
|
||||
content: "Color",
|
||||
has_submenu: true,
|
||||
callback: LGraphCanvas.onMenuNodeColors,
|
||||
},
|
||||
{
|
||||
content: "Font size",
|
||||
property: "font_size",
|
||||
type: "Number",
|
||||
callback: LGraphCanvas.onShowPropertyEditor,
|
||||
},
|
||||
null,
|
||||
{ content: "Remove", callback: LGraphCanvas.onMenuNodeRemove },
|
||||
];
|
||||
}
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(x + width, y + height);
|
||||
ctx.lineTo(x + width - 10, y + height);
|
||||
ctx.lineTo(x + width, y + height - 10);
|
||||
ctx.fill();
|
||||
|
||||
isPointInside = LGraphNode.prototype.isPointInside;
|
||||
setDirtyCanvas = LGraphNode.prototype.setDirtyCanvas;
|
||||
const font_size = this.font_size || LiteGraph.DEFAULT_GROUP_FONT_SIZE;
|
||||
ctx.font = font_size + "px Arial";
|
||||
ctx.textAlign = "left";
|
||||
ctx.fillText(this.title + (this.pinned ? "📌" : ""), x + padding, y + font_size);
|
||||
|
||||
if (LiteGraph.highlight_selected_group && this.selected) {
|
||||
graphCanvas.drawSelectionBounding(ctx, this._bounding, {
|
||||
shape: LiteGraph.BOX_SHAPE,
|
||||
title_height: this.titleHeight,
|
||||
title_mode: LiteGraph.NORMAL_TITLE,
|
||||
fgcolor: this.color,
|
||||
padding,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
resize(width, height) {
|
||||
if (this.pinned) {
|
||||
return;
|
||||
}
|
||||
this._size[0] = width;
|
||||
this._size[1] = height;
|
||||
}
|
||||
|
||||
move(deltax, deltay, ignore_nodes) {
|
||||
if (this.pinned) {
|
||||
return;
|
||||
}
|
||||
this._pos[0] += deltax;
|
||||
this._pos[1] += deltay;
|
||||
if (ignore_nodes) {
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < this._nodes.length; ++i) {
|
||||
var node = this._nodes[i];
|
||||
node.pos[0] += deltax;
|
||||
node.pos[1] += deltay;
|
||||
}
|
||||
}
|
||||
|
||||
recomputeInsideNodes() {
|
||||
this._nodes.length = 0;
|
||||
var nodes = this.graph._nodes;
|
||||
var node_bounding = new Float32Array(4);
|
||||
|
||||
for (var i = 0; i < nodes.length; ++i) {
|
||||
var node = nodes[i];
|
||||
node.getBounding(node_bounding);
|
||||
if (!overlapBounding(this._bounding, node_bounding)) {
|
||||
continue;
|
||||
} //out of the visible area
|
||||
this._nodes.push(node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add nodes to the group and adjust the group's position and size accordingly
|
||||
* @param {LGraphNode[]} nodes - The nodes to add to the group
|
||||
* @param {number} [padding=10] - The padding around the group
|
||||
* @returns {void}
|
||||
*/
|
||||
addNodes(nodes, padding = 10) {
|
||||
if (!this._nodes && nodes.length === 0) return;
|
||||
|
||||
const allNodes = [...(this._nodes || []), ...nodes];
|
||||
|
||||
const bounds = allNodes.reduce((acc, node) => {
|
||||
const [x, y] = node.pos;
|
||||
const [width, height] = node.size;
|
||||
const isReroute = node.type === "Reroute";
|
||||
const isCollapsed = node.flags?.collapsed;
|
||||
|
||||
const top = y - (isReroute ? 0 : LiteGraph.NODE_TITLE_HEIGHT);
|
||||
const bottom = isCollapsed ? top + LiteGraph.NODE_TITLE_HEIGHT : y + height;
|
||||
const right = isCollapsed && node._collapsed_width ? x + Math.round(node._collapsed_width) : x + width;
|
||||
|
||||
return {
|
||||
left: Math.min(acc.left, x),
|
||||
top: Math.min(acc.top, top),
|
||||
right: Math.max(acc.right, right),
|
||||
bottom: Math.max(acc.bottom, bottom)
|
||||
};
|
||||
}, { left: Infinity, top: Infinity, right: -Infinity, bottom: -Infinity });
|
||||
|
||||
this.pos = [
|
||||
bounds.left - padding,
|
||||
bounds.top - padding - this.titleHeight
|
||||
];
|
||||
|
||||
this.size = [
|
||||
bounds.right - bounds.left + padding * 2,
|
||||
bounds.bottom - bounds.top + padding * 2 + this.titleHeight
|
||||
];
|
||||
}
|
||||
|
||||
getMenuOptions() {
|
||||
return [
|
||||
{
|
||||
content: this.pinned ? "Unpin" : "Pin",
|
||||
callback: () => {
|
||||
this.pinned ? this.unpin() : this.pin();
|
||||
this.setDirtyCanvas(false, true);
|
||||
},
|
||||
},
|
||||
null,
|
||||
{ content: "Title", callback: LGraphCanvas.onShowPropertyEditor },
|
||||
{
|
||||
content: "Color",
|
||||
has_submenu: true,
|
||||
callback: LGraphCanvas.onMenuNodeColors
|
||||
},
|
||||
{
|
||||
content: "Font size",
|
||||
property: "font_size",
|
||||
type: "Number",
|
||||
callback: LGraphCanvas.onShowPropertyEditor
|
||||
},
|
||||
null,
|
||||
{ content: "Remove", callback: LGraphCanvas.onMenuNodeRemove }
|
||||
];
|
||||
}
|
||||
|
||||
isPointInside = LGraphNode.prototype.isPointInside
|
||||
setDirtyCanvas = LGraphNode.prototype.setDirtyCanvas
|
||||
}
|
||||
|
||||
5408
src/LGraphNode.ts
5408
src/LGraphNode.ts
File diff suppressed because it is too large
Load Diff
111
src/LLink.ts
111
src/LLink.ts
@@ -1,69 +1,62 @@
|
||||
import type { ISlotType } from "./interfaces";
|
||||
import type { NodeId } from "./LGraphNode";
|
||||
import type { ISlotType } from "./interfaces"
|
||||
import type { NodeId } from "./LGraphNode"
|
||||
|
||||
export type LinkId = number | string;
|
||||
export type LinkId = number | string
|
||||
|
||||
export type SerialisedLLinkArray = [
|
||||
LinkId,
|
||||
NodeId,
|
||||
number,
|
||||
NodeId,
|
||||
number,
|
||||
ISlotType,
|
||||
];
|
||||
export type SerialisedLLinkArray = [LinkId, NodeId, number, NodeId, number, ISlotType]
|
||||
|
||||
//this is the class in charge of storing link information
|
||||
export class LLink {
|
||||
id?: LinkId;
|
||||
type?: ISlotType;
|
||||
origin_id?: NodeId;
|
||||
origin_slot?: number;
|
||||
target_id?: NodeId;
|
||||
target_slot?: number;
|
||||
data?: number | string | boolean | { toToolTip?(): string };
|
||||
_data?: unknown;
|
||||
_pos: Float32Array;
|
||||
_last_time?: number;
|
||||
id?: LinkId
|
||||
type?: ISlotType
|
||||
origin_id?: NodeId
|
||||
origin_slot?: number
|
||||
target_id?: NodeId
|
||||
target_slot?: number
|
||||
data?: number | string | boolean | { toToolTip?(): string }
|
||||
_data?: unknown
|
||||
_pos: Float32Array
|
||||
_last_time?: number
|
||||
|
||||
constructor(id, type, origin_id, origin_slot, target_id, target_slot) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
this.origin_id = origin_id;
|
||||
this.origin_slot = origin_slot;
|
||||
this.target_id = target_id;
|
||||
this.target_slot = target_slot;
|
||||
constructor(id, type, origin_id, origin_slot, target_id, target_slot) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
this.origin_id = origin_id;
|
||||
this.origin_slot = origin_slot;
|
||||
this.target_id = target_id;
|
||||
this.target_slot = target_slot;
|
||||
|
||||
this._data = null;
|
||||
this._pos = new Float32Array(2); //center
|
||||
}
|
||||
|
||||
// configure(o: LLink | SerialisedLLinkArray) {
|
||||
configure(o) {
|
||||
if (o.constructor === Array) {
|
||||
this.id = o[0];
|
||||
this.origin_id = o[1];
|
||||
this.origin_slot = o[2];
|
||||
this.target_id = o[3];
|
||||
this.target_slot = o[4];
|
||||
this.type = o[5];
|
||||
} else {
|
||||
this.id = o.id;
|
||||
this.type = o.type;
|
||||
this.origin_id = o.origin_id;
|
||||
this.origin_slot = o.origin_slot;
|
||||
this.target_id = o.target_id;
|
||||
this.target_slot = o.target_slot;
|
||||
this._data = null;
|
||||
this._pos = new Float32Array(2); //center
|
||||
}
|
||||
}
|
||||
|
||||
serialize(): SerialisedLLinkArray {
|
||||
return [
|
||||
this.id,
|
||||
this.origin_id,
|
||||
this.origin_slot,
|
||||
this.target_id,
|
||||
this.target_slot,
|
||||
this.type,
|
||||
];
|
||||
}
|
||||
// configure(o: LLink | SerialisedLLinkArray) {
|
||||
configure(o) {
|
||||
if (o.constructor === Array) {
|
||||
this.id = o[0];
|
||||
this.origin_id = o[1];
|
||||
this.origin_slot = o[2];
|
||||
this.target_id = o[3];
|
||||
this.target_slot = o[4];
|
||||
this.type = o[5];
|
||||
} else {
|
||||
this.id = o.id;
|
||||
this.type = o.type;
|
||||
this.origin_id = o.origin_id;
|
||||
this.origin_slot = o.origin_slot;
|
||||
this.target_id = o.target_id;
|
||||
this.target_slot = o.target_slot;
|
||||
}
|
||||
}
|
||||
|
||||
serialize(): SerialisedLLinkArray {
|
||||
return [
|
||||
this.id,
|
||||
this.origin_id,
|
||||
this.origin_slot,
|
||||
this.target_id,
|
||||
this.target_slot,
|
||||
this.type
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
import type { Vector2 } from "./litegraph";
|
||||
import type { INodeSlot } from "./interfaces";
|
||||
import type { INodeSlot } from "./interfaces"
|
||||
|
||||
export enum SlotType {
|
||||
Array = "array",
|
||||
@@ -44,7 +44,7 @@ export function drawSlot(
|
||||
low_quality?: boolean;
|
||||
render_text?: boolean;
|
||||
do_stroke?: boolean;
|
||||
} = {},
|
||||
} = {}
|
||||
) {
|
||||
// Save the current fillStyle and strokeStyle
|
||||
const originalFillStyle = ctx.fillStyle;
|
||||
@@ -82,7 +82,7 @@ export function drawSlot(
|
||||
pos[0] - 4 + x * spacing,
|
||||
pos[1] - 4 + y * spacing,
|
||||
cellSize,
|
||||
cellSize,
|
||||
cellSize
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,149 +1,138 @@
|
||||
import type { ContextMenu } from "./ContextMenu";
|
||||
import type { LGraphNode } from "./LGraphNode";
|
||||
import type { LinkDirection, RenderShape } from "./types/globalEnums";
|
||||
import type { LinkId } from "./LLink";
|
||||
import type { SlotDirection } from "./draw";
|
||||
import type { ContextMenu } from "./ContextMenu"
|
||||
import type { LGraphNode } from "./LGraphNode"
|
||||
import type { LinkDirection, RenderShape } from "./types/globalEnums"
|
||||
import type { LinkId } from "./LLink"
|
||||
import type { SlotDirection } from "./draw"
|
||||
|
||||
export type Dictionary<T> = { [key: string]: T };
|
||||
export type Dictionary<T> = { [key: string]: T }
|
||||
|
||||
export type CanvasColour = string | CanvasGradient | CanvasPattern;
|
||||
export type CanvasColour = string | CanvasGradient | CanvasPattern
|
||||
|
||||
export interface IInputOrOutput {
|
||||
// If an input, this will be defined
|
||||
input?: INodeInputSlot;
|
||||
// If an output, this will be defined
|
||||
output?: INodeOutputSlot;
|
||||
// If an input, this will be defined
|
||||
input?: INodeInputSlot
|
||||
// If an output, this will be defined
|
||||
output?: INodeOutputSlot
|
||||
}
|
||||
|
||||
export interface IFoundSlot extends IInputOrOutput {
|
||||
// Slot index
|
||||
slot: number;
|
||||
// Centre point of the rendered slot connection
|
||||
link_pos: Point;
|
||||
// Slot index
|
||||
slot: number
|
||||
// Centre point of the rendered slot connection
|
||||
link_pos: Point
|
||||
}
|
||||
|
||||
/** A point on the canvas: x, y */
|
||||
export type Point = [x: number, y: number] | Float32Array | Float64Array;
|
||||
export type Point = [x: number, y: number] | Float32Array | Float64Array
|
||||
|
||||
/** A size: width, height */
|
||||
export type Size =
|
||||
| [width: number, height: number]
|
||||
| Float32Array
|
||||
| Float64Array;
|
||||
export type Size = [width: number, height: number] | Float32Array | Float64Array
|
||||
|
||||
/** A very firm array */
|
||||
type ArRect = [x: number, y: number, width: number, height: number];
|
||||
type ArRect = [x: number, y: number, width: number, height: number]
|
||||
|
||||
/** A rectangle starting at top-left coordinates: x, y, width, height */
|
||||
export type Rect = ArRect | Float32Array | Float64Array;
|
||||
export type Rect = ArRect | Float32Array | Float64Array
|
||||
|
||||
// TODO: Need regular arrays also?
|
||||
export type Rect32 = Float32Array;
|
||||
export type Rect32 = Float32Array
|
||||
|
||||
/** Union of property names that are of type Match */
|
||||
export type KeysOfType<T, Match> = {
|
||||
[P in keyof T]: T[P] extends Match ? P : never;
|
||||
}[keyof T];
|
||||
export type KeysOfType<T, Match> = { [P in keyof T]: T[P] extends Match ? P : never }[keyof T]
|
||||
|
||||
/** A new type that contains only the properties of T that are of type Match */
|
||||
export type PickByType<T, Match> = { [P in keyof T]: Extract<T[P], Match> };
|
||||
export type PickByType<T, Match> = { [P in keyof T]: Extract<T[P], Match> }
|
||||
|
||||
/** The names of all methods and functions in T */
|
||||
export type MethodNames<T> = KeysOfType<T, (...args: any) => any>;
|
||||
export type MethodNames<T> = KeysOfType<T, (...args: any) => any>
|
||||
|
||||
export interface IBoundaryNodes {
|
||||
top: LGraphNode;
|
||||
right: LGraphNode;
|
||||
bottom: LGraphNode;
|
||||
left: LGraphNode;
|
||||
top: LGraphNode
|
||||
right: LGraphNode
|
||||
bottom: LGraphNode
|
||||
left: LGraphNode
|
||||
}
|
||||
|
||||
export type Direction = "top" | "bottom" | "left" | "right";
|
||||
export type Direction = "top" | "bottom" | "left" | "right"
|
||||
|
||||
// TODO: Rename IOptionalSlotsData
|
||||
export interface IOptionalInputsData {
|
||||
content: string;
|
||||
value?;
|
||||
className?: string;
|
||||
content: string
|
||||
value?
|
||||
className?: string
|
||||
}
|
||||
|
||||
export type ISlotType = number | string;
|
||||
export type ISlotType = number | string
|
||||
|
||||
export interface INodeSlot {
|
||||
name: string;
|
||||
type: ISlotType;
|
||||
dir?: LinkDirection & SlotDirection;
|
||||
removable?: boolean;
|
||||
shape?: RenderShape;
|
||||
not_subgraph_input?: boolean;
|
||||
color_off?: CanvasColour;
|
||||
color_on?: CanvasColour;
|
||||
label?: string;
|
||||
locked?: boolean;
|
||||
nameLocked?: boolean;
|
||||
pos?: Point;
|
||||
widget?: unknown;
|
||||
name: string
|
||||
type: ISlotType
|
||||
dir?: LinkDirection & SlotDirection
|
||||
removable?: boolean
|
||||
shape?: RenderShape
|
||||
not_subgraph_input?: boolean
|
||||
color_off?: CanvasColour
|
||||
color_on?: CanvasColour
|
||||
label?: string
|
||||
locked?: boolean
|
||||
nameLocked?: boolean
|
||||
pos?: Point
|
||||
widget?: unknown
|
||||
}
|
||||
|
||||
export interface INodeFlags {
|
||||
skip_repeated_outputs?: boolean;
|
||||
allow_interaction?: boolean;
|
||||
pinned?: boolean;
|
||||
collapsed?: boolean;
|
||||
skip_repeated_outputs?: boolean
|
||||
allow_interaction?: boolean
|
||||
pinned?: boolean
|
||||
collapsed?: boolean
|
||||
}
|
||||
|
||||
export interface INodeInputSlot extends INodeSlot {
|
||||
link?: LinkId;
|
||||
not_subgraph_input?: boolean;
|
||||
link?: LinkId
|
||||
not_subgraph_input?: boolean
|
||||
}
|
||||
|
||||
export interface INodeOutputSlot extends INodeSlot {
|
||||
links?: LinkId[];
|
||||
_data?: unknown;
|
||||
slot_index?: number;
|
||||
not_subgraph_output?: boolean;
|
||||
links?: LinkId[]
|
||||
_data?: unknown
|
||||
slot_index?: number
|
||||
not_subgraph_output?: boolean
|
||||
}
|
||||
|
||||
/** Links */
|
||||
export interface ConnectingLink extends IInputOrOutput {
|
||||
node: LGraphNode;
|
||||
slot: number;
|
||||
pos: Point;
|
||||
direction?: LinkDirection;
|
||||
node: LGraphNode
|
||||
slot: number
|
||||
pos: Point
|
||||
direction?: LinkDirection
|
||||
}
|
||||
|
||||
/** ContextMenu */
|
||||
export interface IContextMenuOptions {
|
||||
ignore_item_callbacks?: boolean;
|
||||
title?: string;
|
||||
parentMenu?: ContextMenu;
|
||||
className?: string;
|
||||
event?: MouseEvent;
|
||||
extra?: unknown;
|
||||
scroll_speed?: number;
|
||||
left?: number;
|
||||
top?: number;
|
||||
scale?: string;
|
||||
node?: LGraphNode;
|
||||
autoopen?: boolean;
|
||||
callback?(
|
||||
value?: unknown,
|
||||
options?: unknown,
|
||||
event?: MouseEvent,
|
||||
previous_menu?: ContextMenu,
|
||||
node?: LGraphNode,
|
||||
): void;
|
||||
ignore_item_callbacks?: boolean
|
||||
title?: string
|
||||
parentMenu?: ContextMenu
|
||||
className?: string
|
||||
event?: MouseEvent
|
||||
extra?: unknown
|
||||
scroll_speed?: number
|
||||
left?: number
|
||||
top?: number
|
||||
scale?: string
|
||||
node?: LGraphNode
|
||||
autoopen?: boolean
|
||||
callback?(value?: unknown, options?: unknown, event?: MouseEvent, previous_menu?: ContextMenu, node?: LGraphNode): void
|
||||
}
|
||||
|
||||
export interface IContextMenuValue {
|
||||
title?: string;
|
||||
content: string;
|
||||
has_submenu?: boolean;
|
||||
disabled?: boolean;
|
||||
className?: any;
|
||||
submenu?: unknown;
|
||||
property?: string;
|
||||
type?: string;
|
||||
slot?: IFoundSlot;
|
||||
callback?: IContextMenuOptions["callback"];
|
||||
title?: string
|
||||
content: string
|
||||
has_submenu?: boolean
|
||||
disabled?: boolean
|
||||
className?: any
|
||||
submenu?: unknown
|
||||
property?: string
|
||||
type?: string
|
||||
slot?: IFoundSlot
|
||||
callback?: IContextMenuOptions["callback"]
|
||||
}
|
||||
|
||||
197
src/litegraph.ts
197
src/litegraph.ts
@@ -1,161 +1,106 @@
|
||||
import type { Point, ConnectingLink } from "./interfaces";
|
||||
import type {
|
||||
INodeSlot,
|
||||
INodeInputSlot,
|
||||
INodeOutputSlot,
|
||||
CanvasColour,
|
||||
Direction,
|
||||
IBoundaryNodes,
|
||||
IContextMenuOptions,
|
||||
IContextMenuValue,
|
||||
IFoundSlot,
|
||||
IInputOrOutput,
|
||||
INodeFlags,
|
||||
IOptionalInputsData,
|
||||
ISlotType,
|
||||
KeysOfType,
|
||||
MethodNames,
|
||||
PickByType,
|
||||
Rect,
|
||||
Rect32,
|
||||
Size,
|
||||
} from "./interfaces";
|
||||
import type { SlotShape, LabelPosition, SlotDirection, SlotType } from "./draw";
|
||||
import type { IWidget } from "./types/widgets";
|
||||
import type { TitleMode } from "./types/globalEnums";
|
||||
import { LiteGraphGlobal } from "./LiteGraphGlobal";
|
||||
import { loadPolyfills } from "./polyfills";
|
||||
import type { Point, ConnectingLink } from "./interfaces"
|
||||
import type { INodeSlot, INodeInputSlot, INodeOutputSlot, CanvasColour, Direction, IBoundaryNodes, IContextMenuOptions, IContextMenuValue, IFoundSlot, IInputOrOutput, INodeFlags, IOptionalInputsData, ISlotType, KeysOfType, MethodNames, PickByType, Rect, Rect32, Size } from "./interfaces"
|
||||
import type { SlotShape, LabelPosition, SlotDirection, SlotType } from "./draw"
|
||||
import type { IWidget } from "./types/widgets"
|
||||
import type { TitleMode } from "./types/globalEnums"
|
||||
import { LiteGraphGlobal } from "./LiteGraphGlobal"
|
||||
import { loadPolyfills } from "./polyfills"
|
||||
|
||||
import { LGraph } from "./LGraph";
|
||||
import { LGraphCanvas } from "./LGraphCanvas";
|
||||
import { DragAndScale } from "./DragAndScale";
|
||||
import { LGraphNode } from "./LGraphNode";
|
||||
import { LGraphGroup } from "./LGraphGroup";
|
||||
import { LLink } from "./LLink";
|
||||
import { ContextMenu } from "./ContextMenu";
|
||||
import { CurveEditor } from "./CurveEditor";
|
||||
import { LGraphBadge, BadgePosition } from "./LGraphBadge";
|
||||
import { LGraph } from "./LGraph"
|
||||
import { LGraphCanvas } from "./LGraphCanvas"
|
||||
import { DragAndScale } from "./DragAndScale"
|
||||
import { LGraphNode } from "./LGraphNode"
|
||||
import { LGraphGroup } from "./LGraphGroup"
|
||||
import { LLink } from "./LLink"
|
||||
import { ContextMenu } from "./ContextMenu"
|
||||
import { CurveEditor } from "./CurveEditor"
|
||||
import { LGraphBadge, BadgePosition } from "./LGraphBadge"
|
||||
|
||||
export const LiteGraph = new LiteGraphGlobal();
|
||||
export {
|
||||
LGraph,
|
||||
LGraphCanvas,
|
||||
DragAndScale,
|
||||
LGraphNode,
|
||||
LGraphGroup,
|
||||
LLink,
|
||||
ContextMenu,
|
||||
CurveEditor,
|
||||
};
|
||||
export {
|
||||
INodeSlot,
|
||||
INodeInputSlot,
|
||||
INodeOutputSlot,
|
||||
ConnectingLink,
|
||||
CanvasColour,
|
||||
Direction,
|
||||
IBoundaryNodes,
|
||||
IContextMenuOptions,
|
||||
IContextMenuValue,
|
||||
IFoundSlot,
|
||||
IInputOrOutput,
|
||||
INodeFlags,
|
||||
IOptionalInputsData,
|
||||
ISlotType,
|
||||
KeysOfType,
|
||||
MethodNames,
|
||||
PickByType,
|
||||
Rect,
|
||||
Rect32,
|
||||
Size,
|
||||
};
|
||||
export { IWidget };
|
||||
export { LGraphBadge, BadgePosition };
|
||||
export { SlotShape, LabelPosition, SlotDirection, SlotType };
|
||||
export const LiteGraph = new LiteGraphGlobal()
|
||||
export { LGraph, LGraphCanvas, DragAndScale, LGraphNode, LGraphGroup, LLink, ContextMenu, CurveEditor }
|
||||
export { INodeSlot, INodeInputSlot, INodeOutputSlot, ConnectingLink, CanvasColour, Direction, IBoundaryNodes, IContextMenuOptions, IContextMenuValue, IFoundSlot, IInputOrOutput, INodeFlags, IOptionalInputsData, ISlotType, KeysOfType, MethodNames, PickByType, Rect, Rect32, Size }
|
||||
export { IWidget }
|
||||
export { LGraphBadge, BadgePosition }
|
||||
export { SlotShape, LabelPosition, SlotDirection, SlotType }
|
||||
|
||||
// TODO: Remove legacy accessors
|
||||
LiteGraph.LGraph = LGraph;
|
||||
LiteGraph.LLink = LLink;
|
||||
LiteGraph.LGraphNode = LGraphNode;
|
||||
LiteGraph.LGraphGroup = LGraphGroup;
|
||||
LiteGraph.DragAndScale = DragAndScale;
|
||||
LiteGraph.LGraphCanvas = LGraphCanvas;
|
||||
LiteGraph.ContextMenu = ContextMenu;
|
||||
LiteGraph.CurveEditor = CurveEditor;
|
||||
LiteGraph.LGraph = LGraph
|
||||
LiteGraph.LLink = LLink
|
||||
LiteGraph.LGraphNode = LGraphNode
|
||||
LiteGraph.LGraphGroup = LGraphGroup
|
||||
LiteGraph.DragAndScale = DragAndScale
|
||||
LiteGraph.LGraphCanvas = LGraphCanvas
|
||||
LiteGraph.ContextMenu = ContextMenu
|
||||
LiteGraph.CurveEditor = CurveEditor
|
||||
|
||||
export function clamp(v: number, a: number, b: number): number {
|
||||
return a > v ? a : b < v ? b : v;
|
||||
}
|
||||
return a > v ? a : b < v ? b : v
|
||||
};
|
||||
|
||||
// Load legacy polyfills
|
||||
loadPolyfills();
|
||||
loadPolyfills()
|
||||
|
||||
// Backwards compat
|
||||
|
||||
// Type definitions for litegraph.js 0.7.0
|
||||
// Project: litegraph.js
|
||||
// Definitions by: NateScarlet <https://github.com/NateScarlet>
|
||||
export type Vector2 = Point;
|
||||
export type Vector4 = [number, number, number, number];
|
||||
export type Vector2 = Point
|
||||
export type Vector4 = [number, number, number, number]
|
||||
|
||||
export interface IContextMenuItem {
|
||||
content: string;
|
||||
callback?: ContextMenuEventListener;
|
||||
/** Used as innerHTML for extra child element */
|
||||
title?: string;
|
||||
disabled?: boolean;
|
||||
has_submenu?: boolean;
|
||||
submenu?: {
|
||||
options: IContextMenuItem[];
|
||||
} & IContextMenuOptions;
|
||||
className?: string;
|
||||
content: string
|
||||
callback?: ContextMenuEventListener
|
||||
/** Used as innerHTML for extra child element */
|
||||
title?: string
|
||||
disabled?: boolean
|
||||
has_submenu?: boolean
|
||||
submenu?: {
|
||||
options: IContextMenuItem[]
|
||||
} & IContextMenuOptions
|
||||
className?: string
|
||||
}
|
||||
|
||||
export type ContextMenuEventListener = (
|
||||
value: IContextMenuItem,
|
||||
options: IContextMenuOptions,
|
||||
event: MouseEvent,
|
||||
parentMenu: ContextMenu | undefined,
|
||||
node: LGraphNode,
|
||||
) => boolean | void;
|
||||
value: IContextMenuItem,
|
||||
options: IContextMenuOptions,
|
||||
event: MouseEvent,
|
||||
parentMenu: ContextMenu | undefined,
|
||||
node: LGraphNode
|
||||
) => boolean | void
|
||||
|
||||
export interface LinkReleaseContext {
|
||||
node_to?: LGraphNode;
|
||||
node_from?: LGraphNode;
|
||||
slot_from: INodeSlot;
|
||||
type_filter_in?: string;
|
||||
type_filter_out?: string;
|
||||
node_to?: LGraphNode
|
||||
node_from?: LGraphNode
|
||||
slot_from: INodeSlot
|
||||
type_filter_in?: string
|
||||
type_filter_out?: string
|
||||
}
|
||||
|
||||
export interface LinkReleaseContextExtended {
|
||||
links: ConnectingLink[];
|
||||
links: ConnectingLink[]
|
||||
}
|
||||
|
||||
export type LiteGraphCanvasEventType =
|
||||
| "empty-release"
|
||||
| "empty-double-click"
|
||||
| "group-double-click";
|
||||
export type LiteGraphCanvasEventType = "empty-release" | "empty-double-click" | "group-double-click"
|
||||
|
||||
export interface LiteGraphCanvasEvent
|
||||
extends CustomEvent<{
|
||||
subType: string;
|
||||
originalEvent: Event;
|
||||
linkReleaseContext?: LinkReleaseContextExtended;
|
||||
group?: LGraphGroup;
|
||||
}> {}
|
||||
export interface LiteGraphCanvasEvent extends CustomEvent<{
|
||||
subType: string
|
||||
originalEvent: Event
|
||||
linkReleaseContext?: LinkReleaseContextExtended
|
||||
group?: LGraphGroup
|
||||
}> { }
|
||||
|
||||
export interface LiteGraphCanvasGroupEvent
|
||||
extends CustomEvent<{
|
||||
subType: "group-double-click";
|
||||
originalEvent: MouseEvent;
|
||||
group: LGraphGroup;
|
||||
}> {}
|
||||
export interface LiteGraphCanvasGroupEvent extends CustomEvent<{
|
||||
subType: "group-double-click"
|
||||
originalEvent: MouseEvent
|
||||
group: LGraphGroup
|
||||
}> { }
|
||||
|
||||
/** https://github.com/jagenjo/litegraph.js/blob/master/guides/README.md#lgraphnode */
|
||||
|
||||
export interface LGraphNodeConstructor<T extends LGraphNode = LGraphNode> {
|
||||
nodeData: any;
|
||||
new (): T;
|
||||
nodeData: any
|
||||
new(): T
|
||||
}
|
||||
|
||||
// End backwards compat
|
||||
|
||||
135
src/polyfills.ts
135
src/polyfills.ts
@@ -1,84 +1,85 @@
|
||||
|
||||
//API *************************************************
|
||||
//like rect but rounded corners
|
||||
export function loadPolyfills() {
|
||||
if (
|
||||
typeof window != "undefined" &&
|
||||
window.CanvasRenderingContext2D &&
|
||||
!window.CanvasRenderingContext2D.prototype.roundRect
|
||||
) {
|
||||
if (typeof (window) != "undefined" && window.CanvasRenderingContext2D && !window.CanvasRenderingContext2D.prototype.roundRect) {
|
||||
// @ts-expect-error Slightly broken polyfill - radius_low not impl. anywhere
|
||||
window.CanvasRenderingContext2D.prototype.roundRect = function (
|
||||
x,
|
||||
y,
|
||||
w,
|
||||
h,
|
||||
radius,
|
||||
radius_low,
|
||||
x,
|
||||
y,
|
||||
w,
|
||||
h,
|
||||
radius,
|
||||
radius_low
|
||||
) {
|
||||
var top_left_radius = 0;
|
||||
var top_right_radius = 0;
|
||||
var bottom_left_radius = 0;
|
||||
var bottom_right_radius = 0;
|
||||
var top_left_radius = 0;
|
||||
var top_right_radius = 0;
|
||||
var bottom_left_radius = 0;
|
||||
var bottom_right_radius = 0;
|
||||
|
||||
if (radius === 0) {
|
||||
this.rect(x, y, w, h);
|
||||
return;
|
||||
}
|
||||
if (radius === 0) {
|
||||
this.rect(x, y, w, h);
|
||||
return;
|
||||
}
|
||||
|
||||
if (radius_low === undefined) radius_low = radius;
|
||||
if (radius_low === undefined)
|
||||
radius_low = radius;
|
||||
|
||||
//make it compatible with official one
|
||||
if (radius != null && radius.constructor === Array) {
|
||||
if (radius.length == 1)
|
||||
top_left_radius =
|
||||
top_right_radius =
|
||||
bottom_left_radius =
|
||||
bottom_right_radius =
|
||||
radius[0];
|
||||
else if (radius.length == 2) {
|
||||
top_left_radius = bottom_right_radius = radius[0];
|
||||
top_right_radius = bottom_left_radius = radius[1];
|
||||
} else if (radius.length == 4) {
|
||||
top_left_radius = radius[0];
|
||||
top_right_radius = radius[1];
|
||||
bottom_left_radius = radius[2];
|
||||
bottom_right_radius = radius[3];
|
||||
} else return;
|
||||
} //old using numbers
|
||||
else {
|
||||
top_left_radius = radius || 0;
|
||||
top_right_radius = radius || 0;
|
||||
bottom_left_radius = radius_low || 0;
|
||||
bottom_right_radius = radius_low || 0;
|
||||
}
|
||||
//make it compatible with official one
|
||||
if (radius != null && radius.constructor === Array) {
|
||||
if (radius.length == 1)
|
||||
top_left_radius = top_right_radius = bottom_left_radius = bottom_right_radius = radius[0];
|
||||
else if (radius.length == 2) {
|
||||
top_left_radius = bottom_right_radius = radius[0];
|
||||
top_right_radius = bottom_left_radius = radius[1];
|
||||
}
|
||||
else if (radius.length == 4) {
|
||||
top_left_radius = radius[0];
|
||||
top_right_radius = radius[1];
|
||||
bottom_left_radius = radius[2];
|
||||
bottom_right_radius = radius[3];
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else //old using numbers
|
||||
{
|
||||
top_left_radius = radius || 0;
|
||||
top_right_radius = radius || 0;
|
||||
bottom_left_radius = radius_low || 0;
|
||||
bottom_right_radius = radius_low || 0;
|
||||
}
|
||||
|
||||
//top right
|
||||
this.moveTo(x + top_left_radius, y);
|
||||
this.lineTo(x + w - top_right_radius, y);
|
||||
this.quadraticCurveTo(x + w, y, x + w, y + top_right_radius);
|
||||
//top right
|
||||
this.moveTo(x + top_left_radius, y);
|
||||
this.lineTo(x + w - top_right_radius, y);
|
||||
this.quadraticCurveTo(x + w, y, x + w, y + top_right_radius);
|
||||
|
||||
//bottom right
|
||||
this.lineTo(x + w, y + h - bottom_right_radius);
|
||||
this.quadraticCurveTo(x + w, y + h, x + w - bottom_right_radius, y + h);
|
||||
//bottom right
|
||||
this.lineTo(x + w, y + h - bottom_right_radius);
|
||||
this.quadraticCurveTo(
|
||||
x + w,
|
||||
y + h,
|
||||
x + w - bottom_right_radius,
|
||||
y + h
|
||||
);
|
||||
|
||||
//bottom left
|
||||
this.lineTo(x + bottom_right_radius, y + h);
|
||||
this.quadraticCurveTo(x, y + h, x, y + h - bottom_left_radius);
|
||||
//bottom left
|
||||
this.lineTo(x + bottom_right_radius, y + h);
|
||||
this.quadraticCurveTo(x, y + h, x, y + h - bottom_left_radius);
|
||||
|
||||
//top left
|
||||
this.lineTo(x, y + bottom_left_radius);
|
||||
this.quadraticCurveTo(x, y, x + top_left_radius, y);
|
||||
//top left
|
||||
this.lineTo(x, y + bottom_left_radius);
|
||||
this.quadraticCurveTo(x, y, x + top_left_radius, y);
|
||||
};
|
||||
} //if
|
||||
}//if
|
||||
|
||||
if (typeof window != "undefined" && !window["requestAnimationFrame"]) {
|
||||
if (typeof window != "undefined" && !window["requestAnimationFrame"]) {
|
||||
window.requestAnimationFrame =
|
||||
// @ts-expect-error Legacy code
|
||||
window.webkitRequestAnimationFrame ||
|
||||
// @ts-expect-error Legacy code
|
||||
window.mozRequestAnimationFrame ||
|
||||
function (callback) {
|
||||
window.setTimeout(callback, 1000 / 60);
|
||||
};
|
||||
}
|
||||
// @ts-expect-error Legacy code
|
||||
window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame ||
|
||||
function (callback) {
|
||||
window.setTimeout(callback, 1000 / 60);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -4,46 +4,37 @@
|
||||
|
||||
/** For Canvas*Event - adds graph space co-ordinates (property names are shipped) */
|
||||
export interface ICanvasPosition {
|
||||
/** X co-ordinate of the event, in graph space (NOT canvas space) */
|
||||
canvasX?: number;
|
||||
/** Y co-ordinate of the event, in graph space (NOT canvas space) */
|
||||
canvasY?: number;
|
||||
/** X co-ordinate of the event, in graph space (NOT canvas space) */
|
||||
canvasX?: number
|
||||
/** Y co-ordinate of the event, in graph space (NOT canvas space) */
|
||||
canvasY?: number
|
||||
}
|
||||
|
||||
/** For Canvas*Event */
|
||||
export interface IDeltaPosition {
|
||||
deltaX?: number;
|
||||
deltaY?: number;
|
||||
deltaX?: number
|
||||
deltaY?: number
|
||||
}
|
||||
|
||||
/** PointerEvent with canvasX/Y and deltaX/Y properties */
|
||||
export interface CanvasPointerEvent extends PointerEvent, CanvasMouseEvent {}
|
||||
export interface CanvasPointerEvent extends PointerEvent, CanvasMouseEvent { }
|
||||
|
||||
/** MouseEvent with canvasX/Y and deltaX/Y properties */
|
||||
export interface CanvasMouseEvent
|
||||
extends MouseEvent,
|
||||
ICanvasPosition,
|
||||
IDeltaPosition {
|
||||
dragging?: boolean;
|
||||
click_time?: number;
|
||||
dataTransfer?: unknown;
|
||||
export interface CanvasMouseEvent extends MouseEvent, ICanvasPosition, IDeltaPosition {
|
||||
dragging?: boolean
|
||||
click_time?: number
|
||||
dataTransfer?: unknown
|
||||
}
|
||||
|
||||
/** WheelEvent with canvasX/Y properties */
|
||||
export interface CanvasWheelEvent extends WheelEvent, ICanvasPosition {
|
||||
dragging?: boolean;
|
||||
click_time?: number;
|
||||
dataTransfer?: unknown;
|
||||
dragging?: boolean
|
||||
click_time?: number
|
||||
dataTransfer?: unknown
|
||||
}
|
||||
|
||||
/** DragEvent with canvasX/Y and deltaX/Y properties */
|
||||
export interface CanvasDragEvent
|
||||
extends DragEvent,
|
||||
ICanvasPosition,
|
||||
IDeltaPosition {}
|
||||
export interface CanvasDragEvent extends DragEvent, ICanvasPosition, IDeltaPosition { }
|
||||
|
||||
/** TouchEvent with canvasX/Y and deltaX/Y properties */
|
||||
export interface CanvasTouchEvent
|
||||
extends TouchEvent,
|
||||
ICanvasPosition,
|
||||
IDeltaPosition {}
|
||||
export interface CanvasTouchEvent extends TouchEvent, ICanvasPosition, IDeltaPosition { }
|
||||
|
||||
@@ -1,51 +1,51 @@
|
||||
/** Node slot type - input or output */
|
||||
export enum NodeSlotType {
|
||||
INPUT = 1,
|
||||
OUTPUT = 2,
|
||||
INPUT = 1,
|
||||
OUTPUT = 2,
|
||||
}
|
||||
|
||||
/** Shape that an object will render as - used by nodes and slots */
|
||||
export enum RenderShape {
|
||||
BOX = 1,
|
||||
ROUND = 2,
|
||||
CIRCLE = 3,
|
||||
CARD = 4,
|
||||
ARROW = 5,
|
||||
/** intended for slot arrays */
|
||||
GRID = 6,
|
||||
BOX = 1,
|
||||
ROUND = 2,
|
||||
CIRCLE = 3,
|
||||
CARD = 4,
|
||||
ARROW = 5,
|
||||
/** intended for slot arrays */
|
||||
GRID = 6,
|
||||
}
|
||||
|
||||
/** The direction that a link point will flow towards - e.g. horizontal outputs are right by default */
|
||||
export enum LinkDirection {
|
||||
NONE = 0,
|
||||
UP = 1,
|
||||
DOWN = 2,
|
||||
LEFT = 3,
|
||||
RIGHT = 4,
|
||||
CENTER = 5,
|
||||
NONE = 0,
|
||||
UP = 1,
|
||||
DOWN = 2,
|
||||
LEFT = 3,
|
||||
RIGHT = 4,
|
||||
CENTER = 5,
|
||||
}
|
||||
|
||||
/** The path calculation that links follow */
|
||||
export enum LinkRenderType {
|
||||
/** Juts out from the input & output a little @see LinkDirection, then a straight line between them */
|
||||
STRAIGHT_LINK = 0,
|
||||
/** 90° angles, clean and box-like */
|
||||
LINEAR_LINK = 1,
|
||||
/** Smooth curved links - default */
|
||||
SPLINE_LINK = 2,
|
||||
/** Juts out from the input & output a little @see LinkDirection, then a straight line between them */
|
||||
STRAIGHT_LINK = 0,
|
||||
/** 90° angles, clean and box-like */
|
||||
LINEAR_LINK = 1,
|
||||
/** Smooth curved links - default */
|
||||
SPLINE_LINK = 2,
|
||||
}
|
||||
|
||||
export enum TitleMode {
|
||||
NORMAL_TITLE = 0,
|
||||
NO_TITLE = 1,
|
||||
TRANSPARENT_TITLE = 2,
|
||||
AUTOHIDE_TITLE = 3,
|
||||
NORMAL_TITLE = 0,
|
||||
NO_TITLE = 1,
|
||||
TRANSPARENT_TITLE = 2,
|
||||
AUTOHIDE_TITLE = 3,
|
||||
}
|
||||
|
||||
export enum LGraphEventMode {
|
||||
ALWAYS = 0,
|
||||
ON_EVENT = 1,
|
||||
NEVER = 2,
|
||||
ON_TRIGGER = 3,
|
||||
BYPASS = 4,
|
||||
ALWAYS = 0,
|
||||
ON_EVENT = 1,
|
||||
NEVER = 2,
|
||||
ON_TRIGGER = 3,
|
||||
BYPASS = 4,
|
||||
}
|
||||
|
||||
@@ -1,76 +1,61 @@
|
||||
import type {
|
||||
CanvasColour,
|
||||
Dictionary,
|
||||
INodeFlags,
|
||||
INodeInputSlot,
|
||||
INodeOutputSlot,
|
||||
Point,
|
||||
Rect,
|
||||
Size,
|
||||
} from "@/interfaces";
|
||||
import type { LGraph } from "@/LGraph";
|
||||
import type { IGraphGroupFlags, LGraphGroup } from "@/LGraphGroup";
|
||||
import type { LGraphNode, NodeId } from "@/LGraphNode";
|
||||
import type { LiteGraph } from "@/litegraph";
|
||||
import type { LinkId, LLink } from "@/LLink";
|
||||
import type { TWidgetValue } from "@/types/widgets";
|
||||
import type { CanvasColour, Dictionary, INodeFlags, INodeInputSlot, INodeOutputSlot, Point, Rect, Size } from "@/interfaces"
|
||||
import type { LGraph } from "@/LGraph"
|
||||
import type { IGraphGroupFlags, LGraphGroup } from "@/LGraphGroup"
|
||||
import type { LGraphNode, NodeId } from "@/LGraphNode"
|
||||
import type { LiteGraph } from "@/litegraph"
|
||||
import type { LinkId, LLink } from "@/LLink"
|
||||
import type { TWidgetValue } from "@/types/widgets"
|
||||
|
||||
/** Serialised LGraphNode */
|
||||
export interface ISerialisedNode {
|
||||
title?: string;
|
||||
id?: NodeId;
|
||||
type?: string;
|
||||
pos?: Point;
|
||||
size?: Size;
|
||||
flags?: INodeFlags;
|
||||
order?: number;
|
||||
mode?: number;
|
||||
outputs?: INodeOutputSlot[];
|
||||
inputs?: INodeInputSlot[];
|
||||
properties?: Dictionary<unknown>;
|
||||
shape?: Rect;
|
||||
boxcolor?: CanvasColour;
|
||||
color?: CanvasColour;
|
||||
bgcolor?: string;
|
||||
widgets_values?: TWidgetValue[];
|
||||
title?: string
|
||||
id?: NodeId
|
||||
type?: string
|
||||
pos?: Point
|
||||
size?: Size
|
||||
flags?: INodeFlags
|
||||
order?: number
|
||||
mode?: number
|
||||
outputs?: INodeOutputSlot[]
|
||||
inputs?: INodeInputSlot[]
|
||||
properties?: Dictionary<unknown>
|
||||
shape?: Rect
|
||||
boxcolor?: CanvasColour
|
||||
color?: CanvasColour
|
||||
bgcolor?: string
|
||||
widgets_values?: TWidgetValue[]
|
||||
}
|
||||
|
||||
/** Contains serialised graph elements */
|
||||
export type ISerialisedGraph<
|
||||
TNode = ReturnType<LGraphNode["serialize"]>,
|
||||
TLink = ReturnType<LLink["serialize"]>,
|
||||
TGroup = ReturnType<LGraphGroup["serialize"]>,
|
||||
TNode = ReturnType<LGraphNode["serialize"]>,
|
||||
TLink = ReturnType<LLink["serialize"]>,
|
||||
TGroup = ReturnType<LGraphGroup["serialize"]>
|
||||
> = {
|
||||
last_node_id: LGraph["last_node_id"];
|
||||
last_link_id: LGraph["last_link_id"];
|
||||
last_reroute_id: LGraph["last_reroute_id"];
|
||||
nodes: TNode[];
|
||||
links: TLink[] | LLink[];
|
||||
groups: TGroup[];
|
||||
config: LGraph["config"];
|
||||
version: typeof LiteGraph.VERSION;
|
||||
extra?: unknown;
|
||||
};
|
||||
last_node_id: LGraph["last_node_id"]
|
||||
last_link_id: LGraph["last_link_id"]
|
||||
last_reroute_id: LGraph["last_reroute_id"]
|
||||
nodes: TNode[]
|
||||
links: TLink[] | LLink[]
|
||||
groups: TGroup[]
|
||||
config: LGraph["config"]
|
||||
version: typeof LiteGraph.VERSION
|
||||
extra?: unknown
|
||||
}
|
||||
|
||||
/** Serialised LGraphGroup */
|
||||
export interface ISerialisedGroup {
|
||||
title: string;
|
||||
bounding: number[];
|
||||
color: string;
|
||||
font_size: number;
|
||||
flags?: IGraphGroupFlags;
|
||||
title: string
|
||||
bounding: number[]
|
||||
color: string
|
||||
font_size: number
|
||||
flags?: IGraphGroupFlags
|
||||
}
|
||||
|
||||
export type TClipboardLink = [
|
||||
targetRelativeIndex: number,
|
||||
originSlot: number,
|
||||
nodeRelativeIndex: number,
|
||||
targetSlot: number,
|
||||
targetNodeId: NodeId,
|
||||
];
|
||||
export type TClipboardLink = [targetRelativeIndex: number, originSlot: number, nodeRelativeIndex: number, targetSlot: number, targetNodeId: NodeId]
|
||||
|
||||
/** */
|
||||
export interface IClipboardContents {
|
||||
nodes?: ISerialisedNode[];
|
||||
links?: TClipboardLink[];
|
||||
nodes?: ISerialisedNode[]
|
||||
links?: TClipboardLink[]
|
||||
}
|
||||
|
||||
@@ -1,29 +1,28 @@
|
||||
import { CanvasColour, Point, Size } from "@/interfaces";
|
||||
import type { LGraphCanvas, LGraphNode } from "@/litegraph";
|
||||
import type { CanvasMouseEvent } from "./events";
|
||||
import { CanvasColour, Point, Size } from "@/interfaces"
|
||||
import type { LGraphCanvas, LGraphNode } from "@/litegraph"
|
||||
import type { CanvasMouseEvent } from "./events"
|
||||
|
||||
export interface IWidgetOptions<TValue = unknown>
|
||||
extends Record<string, unknown> {
|
||||
on?: string;
|
||||
off?: string;
|
||||
max?: number;
|
||||
min?: number;
|
||||
slider_color?: CanvasColour;
|
||||
marker_color?: CanvasColour;
|
||||
precision?: number;
|
||||
read_only?: boolean;
|
||||
step?: number;
|
||||
y?: number;
|
||||
multiline?: boolean;
|
||||
// TODO: Confirm this
|
||||
property?: string;
|
||||
export interface IWidgetOptions<TValue = unknown> extends Record<string, unknown> {
|
||||
on?: string
|
||||
off?: string
|
||||
max?: number
|
||||
min?: number
|
||||
slider_color?: CanvasColour
|
||||
marker_color?: CanvasColour
|
||||
precision?: number
|
||||
read_only?: boolean
|
||||
step?: number
|
||||
y?: number
|
||||
multiline?: boolean
|
||||
// TODO: Confirm this
|
||||
property?: string
|
||||
|
||||
hasOwnProperty?(arg0: string): any;
|
||||
// values?(widget?: IWidget, node?: LGraphNode): any
|
||||
values?: TValue[];
|
||||
callback?: IWidget["callback"];
|
||||
hasOwnProperty?(arg0: string): any
|
||||
// values?(widget?: IWidget, node?: LGraphNode): any
|
||||
values?: TValue[]
|
||||
callback?: IWidget["callback"]
|
||||
|
||||
onHide?(widget: IWidget): void;
|
||||
onHide?(widget: IWidget): void
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -35,113 +34,91 @@ export interface IWidgetOptions<TValue = unknown>
|
||||
* Recommend declaration merging any properties that use IWidget (e.g. {@link LGraphNode.widgets}) with a new type alias.
|
||||
* @see ICustomWidget
|
||||
*/
|
||||
export type IWidget =
|
||||
| IBooleanWidget
|
||||
| INumericWidget
|
||||
| IStringWidget
|
||||
| IMultilineStringWidget
|
||||
| IComboWidget
|
||||
| ICustomWidget;
|
||||
export type IWidget = IBooleanWidget | INumericWidget | IStringWidget | IMultilineStringWidget | IComboWidget | ICustomWidget
|
||||
|
||||
export interface IBooleanWidget extends IBaseWidget {
|
||||
type?: "toggle";
|
||||
value: boolean;
|
||||
type?: "toggle"
|
||||
value: boolean
|
||||
}
|
||||
|
||||
/** Any widget that uses a numeric backing */
|
||||
export interface INumericWidget extends IBaseWidget {
|
||||
type?: "slider" | "number";
|
||||
value: number;
|
||||
type?: "slider" | "number"
|
||||
value: number
|
||||
}
|
||||
|
||||
/** A combo-box widget (dropdown, select, etc) */
|
||||
export interface IComboWidget extends IBaseWidget {
|
||||
type?: "combo";
|
||||
value: string | number;
|
||||
options: IWidgetOptions<string>;
|
||||
type?: "combo"
|
||||
value: string | number
|
||||
options: IWidgetOptions<string>
|
||||
}
|
||||
|
||||
export type IStringWidgetType =
|
||||
| IStringWidget["type"]
|
||||
| IMultilineStringWidget["type"];
|
||||
export type IStringWidgetType = IStringWidget["type"] | IMultilineStringWidget["type"]
|
||||
|
||||
/** A widget with a string value */
|
||||
export interface IStringWidget extends IBaseWidget {
|
||||
type?: "string" | "text" | "button";
|
||||
value: string;
|
||||
type?: "string" | "text" | "button"
|
||||
value: string
|
||||
}
|
||||
|
||||
/** A widget with a string value and a multiline text input */
|
||||
export interface IMultilineStringWidget<
|
||||
TElement extends HTMLElement = HTMLTextAreaElement,
|
||||
> extends IBaseWidget {
|
||||
type?: "multiline";
|
||||
value: string;
|
||||
export interface IMultilineStringWidget<TElement extends HTMLElement = HTMLTextAreaElement> extends IBaseWidget {
|
||||
type?: "multiline"
|
||||
value: string
|
||||
|
||||
/** HTML textarea element */
|
||||
element?: TElement;
|
||||
/** HTML textarea element */
|
||||
element?: TElement
|
||||
}
|
||||
|
||||
/** A custom widget - accepts any value and has no built-in special handling */
|
||||
export interface ICustomWidget<TElement extends HTMLElement = HTMLElement>
|
||||
extends IBaseWidget<TElement> {
|
||||
type?: "custom";
|
||||
value: string | object;
|
||||
export interface ICustomWidget<TElement extends HTMLElement = HTMLElement> extends IBaseWidget<TElement> {
|
||||
type?: "custom"
|
||||
value: string | object
|
||||
|
||||
element?: TElement;
|
||||
element?: TElement
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Valid widget types. TS cannot provide easily extensible type safety for this at present.
|
||||
* Override linkedWidgets[]
|
||||
* Values not in this list will not result in litegraph errors, however they will be treated the same as "custom".
|
||||
*/
|
||||
export type TWidgetType = IWidget["type"];
|
||||
export type TWidgetValue = IWidget["value"];
|
||||
export type TWidgetType = IWidget["type"]
|
||||
export type TWidgetValue = IWidget["value"]
|
||||
|
||||
/**
|
||||
* The base type for all widgets. Should not be implemented directly.
|
||||
* @see IWidget
|
||||
*/
|
||||
export interface IBaseWidget<TElement extends HTMLElement = HTMLElement> {
|
||||
linkedWidgets?: IWidget[];
|
||||
linkedWidgets?: IWidget[]
|
||||
|
||||
options: IWidgetOptions;
|
||||
marker?: number;
|
||||
label?: string;
|
||||
clicked?: boolean;
|
||||
name?: string;
|
||||
/** Widget type (see {@link TWidgetType}) */
|
||||
type?: TWidgetType;
|
||||
value?: TWidgetValue;
|
||||
y?: number;
|
||||
last_y?: number;
|
||||
width?: number;
|
||||
disabled?: boolean;
|
||||
options: IWidgetOptions
|
||||
marker?: number
|
||||
label?: string
|
||||
clicked?: boolean
|
||||
name?: string
|
||||
/** Widget type (see {@link TWidgetType}) */
|
||||
type?: TWidgetType
|
||||
value?: TWidgetValue
|
||||
y?: number
|
||||
last_y?: number
|
||||
width?: number
|
||||
disabled?: boolean
|
||||
|
||||
tooltip?: string;
|
||||
tooltip?: string
|
||||
|
||||
/** HTML widget element */
|
||||
element?: TElement;
|
||||
/** HTML widget element */
|
||||
element?: TElement
|
||||
|
||||
// TODO: Confirm this format
|
||||
callback?(
|
||||
value: any,
|
||||
canvas?: LGraphCanvas,
|
||||
node?: LGraphNode,
|
||||
pos?: Point,
|
||||
e?: CanvasMouseEvent,
|
||||
): void;
|
||||
onRemove?(): void;
|
||||
beforeQueued?(): void;
|
||||
// TODO: Confirm this format
|
||||
callback?(value: any, canvas?: LGraphCanvas, node?: LGraphNode, pos?: Point, e?: CanvasMouseEvent): void
|
||||
onRemove?(): void
|
||||
beforeQueued?(): void
|
||||
|
||||
mouse?(event: CanvasMouseEvent, arg1: number[], node: LGraphNode): boolean;
|
||||
draw?(
|
||||
ctx: CanvasRenderingContext2D,
|
||||
node: LGraphNode,
|
||||
widget_width: number,
|
||||
y: number,
|
||||
H: number,
|
||||
): void;
|
||||
computeSize?(width: number): Size;
|
||||
mouse?(event: CanvasMouseEvent, arg1: number[], node: LGraphNode): boolean
|
||||
draw?(ctx: CanvasRenderingContext2D, node: LGraphNode, widget_width: number, y: number, H: number): void
|
||||
computeSize?(width: number): Size
|
||||
}
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
import { LGraph, LiteGraph } from "../dist/litegraph.es.js";
|
||||
import {
|
||||
LGraph,
|
||||
LiteGraph,
|
||||
} from "../dist/litegraph.es.js";
|
||||
|
||||
describe("LegacyLGraph Compatibility Layer", () => {
|
||||
test("LGraph can be instantiated", () => {
|
||||
const graph = new LGraph({ extra: "TestGraph" });
|
||||
const graph = new LGraph({extra: "TestGraph"});
|
||||
expect(graph).toBeInstanceOf(LGraph);
|
||||
expect(graph.extra).toBe("TestGraph");
|
||||
});
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { LGraphNode } from "../dist/litegraph.es.js";
|
||||
import {
|
||||
LGraphNode,
|
||||
} from "../dist/litegraph.es.js";
|
||||
|
||||
describe("LGraphNode", () => {
|
||||
it("should serialize position correctly", () => {
|
||||
@@ -9,4 +11,4 @@ describe("LGraphNode", () => {
|
||||
expect(node.pos).toEqual(new Float32Array([10, 10]));
|
||||
expect(node.serialize().pos).toEqual(new Float32Array([10, 10]));
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user