diff --git a/package-lock.json b/package-lock.json index 031025d..84724ab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,8 +14,10 @@ }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "^2.4.2", + "@xyflow/svelte": "^0.0.12", "svelte": "^4.0.5", "svelte-dnd-action": "^0.9.25", + "svelvet": "^8.1.0", "uuid": "^9.0.0", "vite": "^4.4.5" } @@ -465,6 +467,12 @@ "resolved": "https://registry.npmjs.org/@leeoniya/ufuzzy/-/ufuzzy-1.0.8.tgz", "integrity": "sha512-HQ6aJlYpWLq1f9AiApJl0aOIXlJUtuhBOYfSfv5rt3XNYkCBveojtnL6FvOVpJ2gEJ2wqgMW8xOHkLVYAbXghg==" }, + "node_modules/@svelte-put/shortcut": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@svelte-put/shortcut/-/shortcut-3.0.0.tgz", + "integrity": "sha512-nZg3pwpTi9wUsvQPlqOzEsxZcF2jmY5j+VBq/20IUjjd2OpM92XqZAga0PCCjE6OuEobOt58UMnC2QZgOvk0tQ==", + "dev": true + }, "node_modules/@sveltejs/vite-plugin-svelte": { "version": "2.4.5", "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-2.4.5.tgz", @@ -504,12 +512,300 @@ "vite": "^4.0.0" } }, + "node_modules/@types/d3": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.0.tgz", + "integrity": "sha512-jIfNVK0ZlxcuRDKtRS/SypEyOQ6UHaFQBKv032X45VvxSJ6Yi5G9behy9h6tNTHTDGh5Vq+KbmBjUWLgY4meCA==", + "dev": true, + "dependencies": { + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" + } + }, + "node_modules/@types/d3-array": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.0.6.tgz", + "integrity": "sha512-NHkizg870sKYQn45oZT5ItoHqcgRgJD7KAiWZp4Udc6YdrFH2W0tZ2vv4shRHP+SXHoJ1G8B4I1GWb5oQSGypA==", + "dev": true + }, + "node_modules/@types/d3-axis": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.3.tgz", + "integrity": "sha512-SE3x/pLO/+GIHH17mvs1uUVPkZ3bHquGzvZpPAh4yadRy71J93MJBpgK/xY8l9gT28yTN1g9v3HfGSFeBMmwZw==", + "dev": true, + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-brush": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.3.tgz", + "integrity": "sha512-MQ1/M/B5ifTScHSe5koNkhxn2mhUPqXjGuKjjVYckplAPjP9t2I2sZafb/YVHDwhoXWZoSav+Q726eIbN3qprA==", + "dev": true, + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-chord": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.3.tgz", + "integrity": "sha512-keuSRwO02c7PBV3JMWuctIfdeJrVFI7RpzouehvBWL4/GGUB3PBNg/9ZKPZAgJphzmS2v2+7vr7BGDQw1CAulw==", + "dev": true + }, + "node_modules/@types/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-HKuicPHJuvPgCD+np6Se9MQvS6OCbJmOjGvylzMJRlDwUXjKTTXs6Pwgk79O09Vj/ho3u1ofXnhFOaEWWPrlwA==", + "dev": true + }, + "node_modules/@types/d3-contour": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.3.tgz", + "integrity": "sha512-x7G/tdDZt4m09XZnG2SutbIuQqmkNYqR9uhDMdPlpJbcwepkEjEWG29euFcgVA1k6cn92CHdDL9Z+fOnxnbVQw==", + "dev": true, + "dependencies": { + "@types/d3-array": "*", + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-delaunay": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.1.tgz", + "integrity": "sha512-tLxQ2sfT0p6sxdG75c6f/ekqxjyYR0+LwPrsO1mbC9YDBzPJhs2HbJJRrn8Ez1DBoHRo2yx7YEATI+8V1nGMnQ==", + "dev": true + }, + "node_modules/@types/d3-dispatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.3.tgz", + "integrity": "sha512-Df7KW3Re7G6cIpIhQtqHin8yUxUHYAqiE41ffopbmU5+FifYUNV7RVyTg8rQdkEagg83m14QtS8InvNb95Zqug==", + "dev": true + }, + "node_modules/@types/d3-drag": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.3.tgz", + "integrity": "sha512-82AuQMpBQjuXeIX4tjCYfWjpm3g7aGCfx6dFlxX2JlRaiME/QWcHzBsINl7gbHCODA2anPYlL31/Trj/UnjK9A==", + "dev": true, + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-dsv": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.2.tgz", + "integrity": "sha512-DooW5AOkj4AGmseVvbwHvwM/Ltu0Ks0WrhG6r5FG9riHT5oUUTHz6xHsHqJSVU8ZmPkOqlUEY2obS5C9oCIi2g==", + "dev": true + }, + "node_modules/@types/d3-ease": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.0.tgz", + "integrity": "sha512-aMo4eaAOijJjA6uU+GIeW018dvy9+oH5Y2VPPzjjfxevvGQ/oRDs+tfYC9b50Q4BygRR8yE2QCLsrT0WtAVseA==", + "dev": true + }, + "node_modules/@types/d3-fetch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.3.tgz", + "integrity": "sha512-/EsDKRiQkby3Z/8/AiZq8bsuLDo/tYHnNIZkUpSeEHWV7fHUl6QFBjvMPbhkKGk9jZutzfOkGygCV7eR/MkcXA==", + "dev": true, + "dependencies": { + "@types/d3-dsv": "*" + } + }, + "node_modules/@types/d3-force": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.5.tgz", + "integrity": "sha512-EGG+IWx93ESSXBwfh/5uPuR9Hp8M6o6qEGU7bBQslxCvrdUBQZha/EFpu/VMdLU4B0y4Oe4h175nSm7p9uqFug==", + "dev": true + }, + "node_modules/@types/d3-format": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.1.tgz", + "integrity": "sha512-5KY70ifCCzorkLuIkDe0Z9YTf9RR2CjBX1iaJG+rgM/cPP+sO+q9YdQ9WdhQcgPj1EQiJ2/0+yUkkziTG6Lubg==", + "dev": true + }, + "node_modules/@types/d3-geo": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.0.4.tgz", + "integrity": "sha512-kmUK8rVVIBPKJ1/v36bk2aSgwRj2N/ZkjDT+FkMT5pgedZoPlyhaG62J+9EgNIgUXE6IIL0b7bkLxCzhE6U4VQ==", + "dev": true, + "dependencies": { + "@types/geojson": "*" + } + }, + "node_modules/@types/d3-hierarchy": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.3.tgz", + "integrity": "sha512-GpSK308Xj+HeLvogfEc7QsCOcIxkDwLhFYnOoohosEzOqv7/agxwvJER1v/kTC+CY1nfazR0F7gnHo7GE41/fw==", + "dev": true + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-jx5leotSeac3jr0RePOH1KdR9rISG91QIE4Q2PYTu4OymLTZfA3SrnURSLzKH48HmXVUru50b8nje4E79oQSQw==", + "dev": true, + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.0.0.tgz", + "integrity": "sha512-0g/A+mZXgFkQxN3HniRDbXMN79K3CdTpLsevj+PXiTcb2hVyvkZUBg37StmgCQkaD84cUJ4uaDAWq7UJOQy2Tg==", + "dev": true + }, + "node_modules/@types/d3-polygon": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.0.tgz", + "integrity": "sha512-D49z4DyzTKXM0sGKVqiTDTYr+DHg/uxsiWDAkNrwXYuiZVd9o9wXZIo+YsHkifOiyBkmSWlEngHCQme54/hnHw==", + "dev": true + }, + "node_modules/@types/d3-quadtree": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.2.tgz", + "integrity": "sha512-QNcK8Jguvc8lU+4OfeNx+qnVy7c0VrDJ+CCVFS9srBo2GL9Y18CnIxBdTF3v38flrGy5s1YggcoAiu6s4fLQIw==", + "dev": true + }, + "node_modules/@types/d3-random": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.1.tgz", + "integrity": "sha512-IIE6YTekGczpLYo/HehAy3JGF1ty7+usI97LqraNa8IiDur+L44d0VOjAvFQWJVdZOJHukUJw+ZdZBlgeUsHOQ==", + "dev": true + }, + "node_modules/@types/d3-scale": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.4.tgz", + "integrity": "sha512-eq1ZeTj0yr72L8MQk6N6heP603ubnywSDRfNpi5enouR112HzGLS6RIvExCzZTraFF4HdzNpJMwA/zGiMoHUUw==", + "dev": true, + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-scale-chromatic": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz", + "integrity": "sha512-dsoJGEIShosKVRBZB0Vo3C8nqSDqVGujJU6tPznsBJxNJNwMF8utmS83nvCBKQYPpjCzaaHcrf66iTRpZosLPw==", + "dev": true + }, + "node_modules/@types/d3-selection": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.6.tgz", + "integrity": "sha512-2ACr96USZVjXR9KMD9IWi1Epo4rSDKnUtYn6q2SPhYxykvXTw9vR77lkFNruXVg4i1tzQtBxeDMx0oNvJWbF1w==", + "dev": true + }, + "node_modules/@types/d3-shape": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.2.tgz", + "integrity": "sha512-NN4CXr3qeOUNyK5WasVUV8NCSAx/CRVcwcb0BuuS1PiTqwIm6ABi1SyasLZ/vsVCFDArF+W4QiGzSry1eKYQ7w==", + "dev": true, + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.0.tgz", + "integrity": "sha512-sZLCdHvBUcNby1cB6Fd3ZBrABbjz3v1Vm90nysCQ6Vt7vd6e/h9Lt7SiJUoEX0l4Dzc7P5llKyhqSi1ycSf1Hg==", + "dev": true + }, + "node_modules/@types/d3-time-format": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.0.tgz", + "integrity": "sha512-yjfBUe6DJBsDin2BMIulhSHmr5qNR5Pxs17+oW4DoVPyVIXZ+m6bs7j1UVKP08Emv6jRmYrYqxYzO63mQxy1rw==", + "dev": true + }, + "node_modules/@types/d3-timer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.0.tgz", + "integrity": "sha512-HNB/9GHqu7Fo8AQiugyJbv6ZxYz58wef0esl4Mv828w1ZKpAshw/uFWVDUcIB9KKFeFKoxS3cHY07FFgtTRZ1g==", + "dev": true + }, + "node_modules/@types/d3-transition": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.4.tgz", + "integrity": "sha512-512a4uCOjUzsebydItSXsHrPeQblCVk8IKjqCUmrlvBWkkVh3donTTxmURDo1YPwIVDh5YVwCAO6gR4sgimCPQ==", + "dev": true, + "dependencies": { + "@types/d3-selection": "*" + } + }, + "node_modules/@types/d3-zoom": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-3.0.4.tgz", + "integrity": "sha512-cqkuY1ah9ZQre2POqjSLcM8g40UVya/qwEUrNYP2/rCVljbmqKCVcv+ebvwhlI5azIbSEL7m+os6n+WlYA43aA==", + "dev": true, + "dependencies": { + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" + } + }, "node_modules/@types/estree": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", "dev": true }, + "node_modules/@types/geojson": { + "version": "7946.0.10", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz", + "integrity": "sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA==", + "dev": true + }, + "node_modules/@xyflow/svelte": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/@xyflow/svelte/-/svelte-0.0.12.tgz", + "integrity": "sha512-BXwOauzjInjPBdJb1GaKVCYIxyznQKzuEltnPb3i3/EO9GJHx1xcD/c8aBUBBnAG7EWBKtuiyDGk/EBW8MEmsg==", + "dev": true, + "dependencies": { + "@svelte-put/shortcut": "^3.0.0", + "@xyflow/system": "0.0.2", + "classcat": "^5.0.4" + }, + "peerDependencies": { + "svelte": "^3.0.0 || ^4.0.0" + } + }, + "node_modules/@xyflow/system": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@xyflow/system/-/system-0.0.2.tgz", + "integrity": "sha512-xtDf35E4Bwmt9IutmhNLna/vMNN3uRA/kwYUYTAifnWSCUaKENBqMOX4xAGNljBJX1yjo7FNlMRgn347raN69Q==", + "dev": true, + "dependencies": { + "@types/d3": "^7.4.0", + "@types/d3-drag": "^3.0.1", + "@types/d3-selection": "^3.0.3", + "@types/d3-zoom": "^3.0.1", + "d3-drag": "^3.0.0", + "d3-selection": "^3.0.0", + "d3-zoom": "^3.0.0" + } + }, "node_modules/acorn": { "version": "8.10.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", @@ -540,6 +836,12 @@ "dequal": "^2.0.3" } }, + "node_modules/classcat": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/classcat/-/classcat-5.0.4.tgz", + "integrity": "sha512-sbpkOw6z413p+HDGcBENe498WM9woqWHiJxCq7nvmxe9WmrUmqfAcxpIwAiMtM5Q3AhYkzXcNQHqsWq0mND51g==", + "dev": true + }, "node_modules/code-red": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/code-red/-/code-red-1.0.4.tgz", @@ -566,6 +868,111 @@ "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" } }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-dispatch": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", + "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-drag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-3.0.0.tgz", + "integrity": "sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==", + "dev": true, + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-selection": "3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "dev": true, + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-selection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", + "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-transition": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", + "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", + "dev": true, + "dependencies": { + "d3-color": "1 - 3", + "d3-dispatch": "1 - 3", + "d3-ease": "1 - 3", + "d3-interpolate": "1 - 3", + "d3-timer": "1 - 3" + }, + "engines": { + "node": ">=12" + }, + "peerDependencies": { + "d3-selection": "2 - 3" + } + }, + "node_modules/d3-zoom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-3.0.0.tgz", + "integrity": "sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==", + "dev": true, + "dependencies": { + "d3-dispatch": "1 - 3", + "d3-drag": "2 - 3", + "d3-interpolate": "1 - 3", + "d3-selection": "2 - 3", + "d3-transition": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -842,6 +1249,15 @@ "svelte": "^3.19.0 || ^4.0.0" } }, + "node_modules/svelvet": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/svelvet/-/svelvet-8.1.0.tgz", + "integrity": "sha512-rH67tgb7e2aTBQZBCW+V5hSvulLwvzBiOml9Dzdz2ATkgQr58mHi2WtlQFOOb+eZt6zH/J10a2MataC29Qdpuw==", + "dev": true, + "peerDependencies": { + "svelte": ">=3.59.2 || ^4.0.0" + } + }, "node_modules/uuid": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", diff --git a/package.json b/package.json index 5e9ed9f..6ad48bb 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,10 @@ }, "devDependencies": { "@sveltejs/vite-plugin-svelte": "^2.4.2", + "@xyflow/svelte": "^0.0.12", "svelte": "^4.0.5", "svelte-dnd-action": "^0.9.25", + "svelvet": "^8.1.0", "uuid": "^9.0.0", "vite": "^4.4.5" }, diff --git a/src/App.svelte b/src/App.svelte index 0002249..5175345 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -1,10 +1,17 @@ + diff --git a/src/Graph.svelte b/src/Graph.svelte new file mode 100644 index 0000000..608da7a --- /dev/null +++ b/src/Graph.svelte @@ -0,0 +1,76 @@ + + + +
+ + +
+
+ + + + +
+
+
+
+ + diff --git a/src/GraphOld.svelte b/src/GraphOld.svelte new file mode 100644 index 0000000..a1f6b1a --- /dev/null +++ b/src/GraphOld.svelte @@ -0,0 +1,138 @@ + + + + {#each $nodes as n, index} + +
+
+ {n.data.name} +
+ +
+
+ {#each n.data.inputs as inp, index} + +
{inp}
+
+ {/each} +
+
+ {#each n.data.outputs as out} + +
{out}
+
+ {/each} +
+
+ {/each} +
+ + diff --git a/src/Input.svelte b/src/Input.svelte index 7d17220..a355aa5 100644 --- a/src/Input.svelte +++ b/src/Input.svelte @@ -1,11 +1,11 @@ diff --git a/src/app.css b/src/app.css index f485d16..6e78712 100644 --- a/src/app.css +++ b/src/app.css @@ -2,12 +2,12 @@ box-sizing: border-box; } :root { - /* --b1: #004dff; */ - /* --b2: #f19696b3; */ - --b1: #004dff; - --b2: #ffdadab3; - /* --b1: #ff0000; */ - /* --b2: #b6e3f2b3; */ + /* --b1: #004dff; */ + /* --b2: #f19696b3; */ + --b1: #004dff; + --b2: #ffdadab3; + /* --b1: #ff0000; */ + /* --b2: #b6e3f2b3; */ } a { @@ -15,8 +15,8 @@ a { } a:hover { - background-color: var(--b1); - color: #fff; + background-color: var(--b1); + color: #fff; } body { @@ -24,6 +24,11 @@ body { font: 16px Times, serif; + margin: 0; +} + +input { + outline: none; } textrea, select, @@ -32,26 +37,26 @@ button { font: inherit; } -button, input:not([type="range"]) , select { - border: 1px solid var(--b1); - background-color: white; - box-shadow: 2px 2px 0px var(--b2); +button, +input:not([type="range"]), +select { + border: 1px solid var(--b1); + background-color: white; + box-shadow: 2px 2px 0px var(--b2); } button:active { - position: relative; - top: 2px; - left: 2px; - box-shadow: none; -} -video { - width: 100%; + position: relative; + top: 2px; + left: 2px; + box-shadow: none; } + input[type="range"] { - -webkit-appearance: none; - appearance: none; - background: transparent; - cursor: pointer; + -webkit-appearance: none; + appearance: none; + background: transparent; + cursor: pointer; } /* Removes default focus */ @@ -62,45 +67,53 @@ input[type="range"]:focus { /***** Chrome, Safari, Opera and Edge Chromium styles *****/ /* slider track */ input[type="range"]::-webkit-slider-runnable-track { - background-color: var(--b1); - border-radius: 0; - height: 0.3rem; + background-color: var(--b1); + border-radius: 0; + height: 0.3rem; } /* slider thumb */ input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; /* Override default look */ - appearance: none; - margin-top: -5px; /* Centers thumb on the track */ + appearance: none; + margin-top: -5px; /* Centers thumb on the track */ - /*custom styles*/ - background-color: var(--b1); - height: 15px; - width: 10px; + /*custom styles*/ + background-color: var(--b1); + height: 15px; + width: 10px; } -input[type="range"]:focus::-webkit-slider-thumb { +input[type="range"]:focus::-webkit-slider-thumb { /* border: 1px solid #053a5f; */ } /******** Firefox styles ********/ /* slider track */ input[type="range"]::-moz-range-track { - background-color: var(--b1); - border-radius: 0; - height: 0.3rem; + background-color: var(--b1); + border-radius: 0; + height: 0.3rem; } /* slider thumb */ input[type="range"]::-moz-range-thumb { - border: none; /*Removes extra border that FF applies*/ - border-radius: 0; /*Removes default border-radius that FF applies*/ + border: none; /*Removes extra border that FF applies*/ + border-radius: 0; /*Removes default border-radius that FF applies*/ - /*custom styles*/ - background-color: var(--b1); - height: 15px; - width: 10px; + /*custom styles*/ + background-color: var(--b1); + height: 15px; + width: 10px; } input[type="range"]:focus::-moz-range-thumb { } +.svelte-flow__node { + border-radius: 0px !important; + border: 1px solid var(--b1) !important; +} + +.svelte-flow__attribution { + display: none !important; +} diff --git a/src/nodes/FilterNode.svelte b/src/nodes/FilterNode.svelte new file mode 100644 index 0000000..e69de29 diff --git a/src/nodes/InputNode.svelte b/src/nodes/InputNode.svelte new file mode 100644 index 0000000..e69de29 diff --git a/src/nodes/Node.svelte b/src/nodes/Node.svelte new file mode 100644 index 0000000..fb25537 --- /dev/null +++ b/src/nodes/Node.svelte @@ -0,0 +1,96 @@ + + +
+
+
{data.nodeType}
+ +
+
+ {#if data.nodeType == "input"} + + {:else} + {data.name} + {/if} +
+
+{#each data.inputs as inp, index} + {inp} +{/each} +{#each data.outputs as out, index} + {out} +{/each} + + diff --git a/src/nodes/OutputNode.svelte b/src/nodes/OutputNode.svelte new file mode 100644 index 0000000..e69de29 diff --git a/src/stores.js b/src/stores.js index c6e1556..be462dd 100644 --- a/src/stores.js +++ b/src/stores.js @@ -1,5 +1,407 @@ -import { writable } from 'svelte/store'; +import { v4 as uuidv4 } from "uuid"; +import { writable, derived, get } from "svelte/store"; -export const inputs = writable(["punch.mp4"]); -export const output = writable("out.mp4"); -export const filters = writable([]); +// export const inputs = writable([]); +// export const output = writable("out.mp4"); +// export const filters = writable([]); +export const nodes = writable([]); +export const edges = writable([]); +export const auto = writable(true); +export const selectedFilter = writable(); + +const PREFIX = ""; + +addNode({ name: "punch.mp4" }, "input"); +addNode({ name: "out.mp4" }, "output"); + +function makeFilterArgs(f) { + let fCommand = f.name; + if (f.params && f.params.length > 0) { + let params = f.params + .map((p) => { + if (p.value === "" || p.value === null || p.value === p.default) return null; + return `${p.name}=${p.value}`; + }) + .filter((p) => p !== null) + .join(":"); + if (params) fCommand += "=" + params; + } + return fCommand; +} + +export const previewCommandSvelvet = derived([edges, nodes], ([$edges, $nodes]) => { + // [0:v]f1=val,f2=val[out] -map out + // [0:v]f1=val,f2=val[1];[1][1:v]overlay[out] -map out` + + let finalCommand = []; + + let filtergraph = []; + + const inputs = $nodes.filter((n) => n.nodeType == "input"); + const outputs = $nodes.filter((n) => n.nodeType == "output"); + + const inputIds = {}; + for (let i = 0; i < inputs.length; i++) { + const inp = inputs[i]; + inputIds[inp.id] = i; + } + + const edgeIds = {}; + for (let i = 0; i < $edges.length; i++) { + const e = $edges[i]; + edgeIds[e.id] = i + 1; + + const source = $nodes.find((n) => PREFIX + n.id === e.source); + const target = $nodes.find((n) => PREFIX + n.id === e.target); + + if (!source || !target) continue; + + if (source.nodeType === "input") { + if (e.sourceAnchor.startsWith("A-v")) { + edgeIds[e.id] = inputIds[source.id] + ":v"; + } + if (e.sourceAnchor.startsWith("A-a")) { + edgeIds[e.id] = inputIds[source.id] + ":a"; + } + } + + if (target.nodeType === "output") { + edgeIds[e.id] = "out"; + } + } + + for (let n of $nodes.filter((n) => n.nodeType == "filter")) { + let cmd = ""; + + const outs = $edges.filter((e) => e.source == PREFIX + n.id); + const ins = $edges.filter((e) => e.target == PREFIX + n.id); + + if (outs.length == 0 && ins.length == 0) continue; + + for (let i of ins) { + const eid = edgeIds[i.id]; + cmd += `[${eid}]`; + } + cmd += makeFilterArgs(n.data); + for (let o of outs) { + const eid = edgeIds[o.id]; + cmd += `[${eid}]`; + } + filtergraph.push(cmd); + } + + finalCommand.push("ffmpeg"); + + for (let inp of inputs) { + finalCommand.push("-i"); + finalCommand.push(inp.data.name); + } + + finalCommand.push("-filter_complex"); + + finalCommand.push('"' + filtergraph.join(";") + '"'); + + for (let out of outputs) { + finalCommand.push("-map"); + finalCommand.push('"[out]"'); + } + + for (let inp of inputs) { + finalCommand.push("-map"); + finalCommand.push(inputIds[inp.id] + ":a"); + } + + for (let out of outputs) { + finalCommand.push(out.data.name); + } + + const entireCommand = finalCommand.join(" "); + return entireCommand; +}); + +export const previewCommand = derived([edges, nodes], ([$edges, $nodes]) => { + // [0:v]f1=val,f2=val[out] -map out + // [0:v]f1=val,f2=val[1];[1][1:v]overlay[out] -map out` + + let hasVid = false; + let hasAud = false; + + let finalCommand = []; + + let filtergraph = []; + + const inputs = $nodes.filter((n) => n.nodeType == "input"); + const outputs = $nodes.filter((n) => n.nodeType == "output"); + + const inputIds = {}; + for (let i = 0; i < inputs.length; i++) { + const inp = inputs[i]; + inputIds[inp.id] = i; + } + + const edgeIds = {}; + for (let i = 0; i < $edges.length; i++) { + const e = $edges[i]; + edgeIds[e.id] = i + 1; + + const source = $nodes.find((n) => n.id === e.source); + const target = $nodes.find((n) => n.id === e.target); + + if (source && target) { + + if (source.nodeType === "input") { + if (e.sourceHandle.includes("v")) { + edgeIds[e.id] = inputIds[source.id] + ":v"; + } + if (e.sourceHandle.includes("a")) { + edgeIds[e.id] = inputIds[source.id] + ":a"; + } + } + + if (target.nodeType === "output") { + const outType = e.targetHandle.includes("a") ? "aud_out" : "vid_out"; + edgeIds[e.id] = outType; + } + } + } + + for (let n of $nodes.filter((n) => n.nodeType == "filter")) { + let cmd = ""; + + const outs = $edges.filter((e) => e.source == n.id); + const ins = $edges.filter((e) => e.target == n.id); + + if (outs.length == 0 && ins.length == 0) continue; + + for (let i of ins) { + const eid = edgeIds[i.id]; + cmd += `[${eid}]`; + } + cmd += makeFilterArgs(n.data); + for (let o of outs) { + const eid = edgeIds[o.id]; + cmd += `[${eid}]`; + } + filtergraph.push(cmd); + } + + finalCommand.push("ffmpeg"); + + for (let inp of inputs) { + finalCommand.push("-i"); + finalCommand.push(inp.data.name); + } + + if (filtergraph.length > 0) { + const fg = '"' + filtergraph.join(";") + '"'; + hasVid = fg.includes(":v]"); + hasAud = fg.includes(":a]"); + + finalCommand.push("-filter_complex"); + finalCommand.push(fg); + + finalCommand.push("-map"); + if (hasAud) { + finalCommand.push('"[aud_out]"'); + } else { + finalCommand.push("0:a"); + } + + if (hasVid) { + finalCommand.push("-map"); + finalCommand.push('"[vid_out]"'); + } + } + + // for (let inp of inputs) { + // finalCommand.push("-map"); + // finalCommand.push(inputIds[inp.id] + ":a"); + // } + + for (let out of outputs) { + finalCommand.push(out.data.name); + } + + const entireCommand = finalCommand.join(" "); + return entireCommand; +}); + +export const previewCommandOld = derived(nodes, ($nodes) => { + const cInputs = $nodes + .filter((n) => n.nodeType === "input") + .map((i) => `-i ${i.data.name}`) + .join(" "); + + const cOutput = $nodes + .filter((n) => n.nodeType === "output") + .map((i) => `${i.data.name}`) + .join(" "); + + const cFilters = $nodes + .filter((n) => n.nodeType === "filter") + .map((n) => n.data) + .map(makeFilterArgs) + .join(","); + + let out = `ffmpeg ${cInputs}`; + + if (cFilters) out += ` -filter_complex "${cFilters}"`; + + out += ` ${cOutput}`; + return out; +}); + +export const inputs = derived(nodes, ($nodes) => { + return $nodes.filter((n) => n.nodeType === "input").map((n) => n.data); +}); + +export const filters = derived(nodes, ($nodes) => { + return $nodes.filter((n) => n.nodeType === "filter").map((n) => n.data); +}); + +export const output = derived(nodes, ($nodes) => { + return $nodes.filter((n) => n.nodeType === "output").map((n) => n.data); +}); + +nodes.subscribe(($nodes) => { + const isAuto = get(auto); + if (!isAuto) return; + + const outputNodes = $nodes.filter((n) => n.nodeType === "output"); + const inputNodes = $nodes.filter((n) => n.nodeType === "input"); + const filterNodes = $nodes.filter((n) => n.nodeType === "filter"); + const orderedNodes = [].concat(filterNodes, outputNodes).filter((n) => n != undefined); + + const filled = []; + let newEdges = []; + + function connectNode(n1, rest) { + for (let i = 0; i < n1.data.outputs.length; i++) { + const edgeType = n1.data.outputs[i]; + for (let j = 0; j < rest.length; j++) { + let found = false; + const n2 = rest[j]; + for (let k = 0; k < n2.data.inputs.length; k++) { + const targetEdgeType = n2.data.inputs[k]; + if (edgeType === targetEdgeType && !filled.includes(n2.id + k)) { + newEdges.push({ + id: uuidv4(), + type: "default", + source: n1.id, + target: n2.id, + sourceHandle: edgeType + "_" + i, + targetHandle: edgeType + "_" + k, + }); + filled.push(n2.id + k); + found = true; + break; + } + } + if (found) break; + } + } + const nextNode = rest.shift(); + if (nextNode) { + connectNode(nextNode, rest); + } + } + + for (let inpNode of inputNodes) { + connectNode(inpNode, [...orderedNodes]); + } + // console.log("new", newEdges); + edges.set(newEdges); +}); + +export function addNode(data, type) { + let ins = []; + let outs = []; + + if (type === "input") { + outs = ["v", "a"]; + } else if (type === "output") { + ins = ["v", "a"]; + } else if (type === "filter") { + const [_ins, _outs] = data.type.split("->"); + ins = _ins.toLowerCase().split(""); + outs = _outs.toLowerCase().split(""); + if (data.params) { + data.params = data.params.map((p) => { + p.value = null; + if (p.default != null) p.value = p.default; + return p; + }); + } + } + + data.nodeType = type; + data.inputs = ins; + data.outputs = outs; + + let node = { + id: uuidv4(), + type: "ffmpeg", + data: data, + nodeType: type, + position: { x: 0, y: 0 }, + }; + + nodes.update((_nodes) => { + _nodes.push(node); + + const isAuto = get(auto); + + if (isAuto) { + const w = 120; + const h = 50; + const margin = 50; + let prev = null; + + for (let n of _nodes) { + if (n.nodeType === "input") { + n.position = { x: 0, y: prev ? prev.position.y + h + margin : 0 }; + prev = n; + } + } + + for (let n of _nodes) { + if (n.nodeType === "filter") { + let _w = prev && prev.width ? prev.width : w; + n.position = { x: prev ? prev.position.x + _w + margin : 0, y: -50 }; + prev = n; + } + } + + for (let n of _nodes) { + if (n.nodeType === "output") { + let _w = prev && prev.width ? prev.width : w; + n.position = { x: prev ? prev.position.x + _w + margin : 0, y: 0 }; + } + } + } + if (node.nodeType === "filter") { + selectedFilter.set(_nodes.length - 1); + } + return _nodes; + }); + + +} + +export function removeNode(id) { + nodes.update((_nodes) => { + const index = _nodes.findIndex((n) => n.id === id); + _nodes.splice(index, 1); + return _nodes; + }); + + edges.update((_edges) => { + for (let i = _edges.length - 1; i--; i >= 0) { + const e = _edges[i]; + if ("N-" + e.source === id || "N-" + e.target === id) { + _edges.splice(i, 1); + } + } + return _edges; + }); +}