From c4f8ebb41b42532cb6e1b4e1cb261968ea2eada3 Mon Sep 17 00:00:00 2001 From: seb Date: Mon, 28 Sep 2026 06:49:46 +0200 Subject: [PATCH] u --- package-lock.json | 1179 ++++++++++++++++- package.json | 5 + src/api/ApiClient.js | 13 +- src/api/index.js | 129 +- src/appRouter.jsx | 2 + src/automats/warehouseAutomat.js | 11 + .../article/ArticleStockAdjustDialog.jsx | 181 ++- src/components/article/ArticleTileTab.jsx | 2 +- .../article/boxes/ArticleViewStock.jsx | 293 ++-- .../article/tabs/ArticleLabelTab.jsx | 254 +++- src/nav.js | 2 + src/pages/artikel/lager.jsx | 310 +++-- src/pages/artikel/marken.jsx | 4 - src/pages/artikel/vorlagen.jsx | 594 +++++++++ src/pages/lieferung/lieferanten.jsx | 4 - 15 files changed, 2659 insertions(+), 324 deletions(-) create mode 100644 src/pages/artikel/vorlagen.jsx diff --git a/package-lock.json b/package-lock.json index cea77cb..c5b7c7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,12 +16,12 @@ "@mui/material": "^9.4.0", "@shopify/draggable": "^1.2.1", "dashgui": "file:../dashgui", - "eslint": "^10.11.0", "jsbarcode": "^3.12.3", "notistack": "^3.0.2", "pdfconvert-wasm": "^0.3.0", "react": "^19.3.0", "react-automat": "file:../automat", + "react-canvas-label-editor": "github:sebseb7/react-canvas-label-editor", "react-dom": "^19.3.0", "react-router-dom": "^7.18.4", "sortablejs": "^1.15.7", @@ -30,6 +30,7 @@ "devDependencies": { "@eslint/js": "^10.0.1", "@vitejs/plugin-react": "6.1.1", + "eslint": "^10.11.0", "eslint-plugin-react-hooks": "^7.1.1", "globals": "^17.12.0", "qrcode": "^1.5.4", @@ -1620,6 +1621,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.2.0.tgz", "integrity": "sha512-CTLKqLItRCEixEAewD3/j9DB3/o96gpTPD4eJ1v+DGOlxZRZncRQkGYqqnAGCscYd6RNeXfGeiuCphsPtqyIfQ==", + "dev": true, "license": "MIT", "dependencies": { "@cacheable/utils": "^2.5.0", @@ -1632,12 +1634,23 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.5.0.tgz", "integrity": "sha512-buipgOVDkkPXNR5+xBpDw7Zk2n1EvU7qBJCNUcL7rhQ//kfpOXPAvQ511Os0vpLYJ1pZnvudNytkQt2hst3wqA==", + "dev": true, "license": "MIT", "dependencies": { "hashery": "^1.5.1", "keyv": "^5.6.0" } }, + "node_modules/@emnapi/runtime": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.3.tgz", + "integrity": "sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@emotion/babel-plugin": { "version": "11.13.5", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz", @@ -1788,6 +1801,7 @@ "version": "4.10.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", + "dev": true, "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.4.3" @@ -1806,6 +1820,7 @@ "version": "3.4.3", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1818,6 +1833,7 @@ "version": "4.12.2", "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" @@ -1827,6 +1843,7 @@ "version": "0.23.5", "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@eslint/object-schema": "^3.0.5", @@ -1841,6 +1858,7 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.7.0.tgz", "integrity": "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@eslint/core": "^1.2.1" @@ -1853,6 +1871,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@types/json-schema": "^7.0.15" @@ -1886,6 +1905,7 @@ "version": "3.0.5", "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", + "dev": true, "license": "Apache-2.0", "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" @@ -1895,6 +1915,7 @@ "version": "0.7.3", "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.3.tgz", "integrity": "sha512-IkO+/KEUvwbVpiURZg+P7zF74z5Jxe0UgJxVni+RtoHQ6IZieXaO02kmadomap/q+l6bc/jdPGGqTjhuZnuz1Q==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@eslint/core": "^1.2.1", @@ -1908,6 +1929,7 @@ "version": "0.19.2", "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@humanfs/types": "^0.15.0" @@ -1920,6 +1942,7 @@ "version": "0.16.8", "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@humanfs/core": "^0.19.2", @@ -1934,6 +1957,7 @@ "version": "0.15.0", "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=18.18.0" @@ -1943,6 +1967,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=12.22" @@ -1956,6 +1981,7 @@ "version": "0.4.3", "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">=18.18" @@ -1965,6 +1991,554 @@ "url": "https://github.com/sponsors/nzakas" } }, + "node_modules/@img/colour": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.1.0.tgz", + "integrity": "sha512-Td76q7j57o/tLVdgS746cYARfSyxk8iEfRxewL9h4OMzYhbW4TAcppl0mT4eyqXddh6L/jwoM75mo7ixa/pCeQ==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.35.5.tgz", + "integrity": "sha512-QRUlFQ0WxvdWyqqG/WtI3iupfD5rBzmCHXSdPsY91sAtVtTo7Q4cb6zOccZ3gqEqkr0f1As1ehLqmEpDsRf+lg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.3.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.35.5.tgz", + "integrity": "sha512-+BR255RhDlpygUpOc/Jdt1nT6DQ3XG/ERo5wbcdOf5Q320dKtPCKPLR1LJs9VGXRaMa8l1uUa0tkCNOXiAxZUw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.3.4" + } + }, + "node_modules/@img/sharp-freebsd-wasm32": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-freebsd-wasm32/-/sharp-freebsd-wasm32-0.35.5.tgz", + "integrity": "sha512-Y/z91nEZ4uIBX5X3nfTovjU9lHNKFYbL2lpHCLVNmXQK03VIZvXBBt0KxbPGp2SdGSF+2mQU4e+hQaWOt86iAw==", + "license": "Apache-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "dependencies": { + "@img/sharp-wasm32": "0.35.5" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.3.4.tgz", + "integrity": "sha512-5R89nBYiRdUlSWJxPhO+GVtaXzXSxKnRu/xqMn3KTA3L9EB9Oy/P+Nn2f2vlhPuUdy/Zusb2DarbyTpGCfEDuw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.3.4.tgz", + "integrity": "sha512-iR2OKH80yi0U+dUplyh3/xdpFvps6YkCwsXenIJxqxR1v9o+xtKTGbS9H7cps+2Vxjc8B1j96p75NmTGjIhtpQ==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.3.4.tgz", + "integrity": "sha512-LmRtTsOHuvM2+wlO2Db37dx5MiZhB0FvSunciw48YjdOkZz9KAiRbm8ujeMOA1INqmei5NapFxYEK1D1ZSidmw==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.3.4.tgz", + "integrity": "sha512-Y3dgX/6lE2QhQb+Gxy0WZxfg9MEm/JBjamZpS2IklP7xIQoKN4hzAm7KcMVGtaVDt3neE9OKBC7vAfonA/Lr1A==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.3.4.tgz", + "integrity": "sha512-Le6boB8Tai0Nis+gIxIpKx68UDVVIqdR8Tin5Yf1z2LJJQLDJvCDRqRu+jC2qCoD+eIomonmOwB4smBRxfVpYQ==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.3.4.tgz", + "integrity": "sha512-aHkkIEHPRdQEegJN20MLmGtxYD9R2wQr3Cwpddnu5+YKMt6Uzax7S9h5gpZTo8wyrGuZSlfQ63OevL5mTyOC7Q==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.3.4.tgz", + "integrity": "sha512-ra/mB6MikESDUO7Yg+Mi95bFBb9GsObURuhnOv3OqknjGe9sZrG8tCe9q0xSIGrtLgvgw0gKnFWcK4blSgQOuQ==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.3.4.tgz", + "integrity": "sha512-GJ//SSXbnwSDes02umB3nDJLFcQzw8a18V8fyhqr6tV515tOEMdImjjxj1AoafMRz56F3PHgftnj1QEKSU1zkw==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.3.4.tgz", + "integrity": "sha512-hvulFwtjUcagsis6BBxHwGFwWoNZjgYmULGVrZcyfNbjA8hKILbRxGg15/7w5HDyXHXUos/j6baAWqnCyQ2DWA==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.3.4.tgz", + "integrity": "sha512-6zXKeE/p39I1AmA3cJG35eyBGNqNddLnUXjhwBnsGjFPWqf5VKkDBEqaEkPDoTEtkxwi2vv8Tcr2mDyP4So7Fg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.35.5.tgz", + "integrity": "sha512-LEaXK2WdXVK5ykcw0buWyPMsmLLL2vpHLD6yrNSW+JGEL3BZPA4tpKN6iaMc4AxTTAoaX/sU1rOL51lcIz48ZQ==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.3.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.35.5.tgz", + "integrity": "sha512-LYVx5JTsOM2CBzmxreh+nl64/3H6Xb09iSLknqH47z2T2DFFxDeFLP5y4dJwe6H7uGQlHPyEEtIqyo3DYsRwdQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.3.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.35.5.tgz", + "integrity": "sha512-QVxAAq8evVRI9ia2vqgwrmWucn5Dfv+JdWzj75pD8omHLPSP7f8p20O8jxzjCcuCEQEOtYOZUmX1hkiZ0kdevA==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.3.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.35.5.tgz", + "integrity": "sha512-LtdreXguaavKODPIfzJ4kffx7UNt1omwtK0rch4EBbbSTXPnxWmYSayXdLJw0fJzQ97kHt1gL/yh4tvU+nCyRQ==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.3.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.35.5.tgz", + "integrity": "sha512-UZasTOFiYzotTsGOCu42BfUzP6Tu6Do/947iRm1RsLKvlllxwGcn4RN27LibGWceix4Y+Pmw3jsnTcCQIgWjqA==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.3.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.35.5.tgz", + "integrity": "sha512-SxFtLTeJInhAA9Q836kux2vZNeOBQEx658qvbboZScr0wIARym3IcGmW7KpVD5sbVg0Ojy+udFQdayYIZyoNog==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.3.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.35.5.tgz", + "integrity": "sha512-9HbMclmI1zlNkFRs3z9/eBtDjfD0sGlrX1z6b1qwmiFY5ElDLh4BC0LPBdVp7z1DXFiKlIcznf+ZlsuZzLxQqg==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.3.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.35.5.tgz", + "integrity": "sha512-4KOphqB035HrVdqLZfCgMzzERrQkkzOwRhl4OAkRO1YCldbaFjySXMaK534Mo0V+LndnlJk+sbUyLeU0ULyD1A==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.3.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.35.5.tgz", + "integrity": "sha512-Ptsga1su4tQx+LLF1ECS9U6nz5kmrXKo6XVbtR48Ke3ZRxxgaWBu7IDtEe1quo8hiupwm6WFqxVlXaSf7IINGQ==", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.11.3" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-webcontainers-wasm32": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-webcontainers-wasm32/-/sharp-webcontainers-wasm32-0.35.5.tgz", + "integrity": "sha512-hfhF/FmoQyTUkA0bIKFOtw536BQSeBMe6BF6QyWlrPxT754+TFLaZ7sKKTfvvM0yJgKgaYTwnFCIZ/GuDw5SUA==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/sharp-wasm32": "0.35.5" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.35.5.tgz", + "integrity": "sha512-X4t7g+7ZA5DKblCBEXGjUqqemj4vczING/5viFwAL8h4N3qYeyjwdCvRLHi4EdOUI+2Z7UFlp1VM+p/AuEtm6Q==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.35.5.tgz", + "integrity": "sha512-5Zm82LoBc43nhwNybZlG7Y1KO//Zhsn306fQl29ZOuStHLGTo3BWL83q3cznX0poxSAMuYL1On/BHBxkBeKr6A==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.35.5.tgz", + "integrity": "sha512-x76eH0vEiHlcMQu8Y8IenntaACtddpT6W0wmXtWrnKcnKI7ME5DdgqhAD6SEWOEl1v2zDvkZDhFA9KnURwpfqg==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@isaacs/cliui": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-9.0.0.tgz", @@ -2051,6 +2625,7 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.1.tgz", "integrity": "sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==", + "dev": true, "license": "MIT", "dependencies": { "hashery": "^1.4.0", @@ -2067,6 +2642,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz", "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==", + "dev": true, "license": "MIT" }, "node_modules/@mui/core-downloads-tracker": { @@ -3157,18 +3733,21 @@ "version": "4.3.1", "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "dev": true, "license": "MIT" }, "node_modules/@types/estree": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, "license": "MIT" }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, "license": "MIT" }, "node_modules/@types/parse-json": { @@ -3250,6 +3829,7 @@ "version": "8.18.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -3262,6 +3842,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" @@ -3271,6 +3852,7 @@ "version": "6.15.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", @@ -3287,7 +3869,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -3297,7 +3878,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -3452,11 +4032,32 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, "license": "MIT", "engines": { "node": "18 || 20 || >=22" } }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/baseline-browser-mapping": { "version": "2.11.25", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.25.tgz", @@ -3470,10 +4071,22 @@ "node": ">=6.0.0" } }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, "node_modules/brace-expansion": { "version": "5.0.12", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.12.tgz", "integrity": "sha512-YovQ3rzhaLMIrDjNDMkNS01tea93qhEhG5xy8f6+R0l+dw3Ki+5sCoIoI942iuLZTHWogWktgwVDhU09iNEimQ==", + "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^4.0.2" @@ -3516,6 +4129,30 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -3527,6 +4164,7 @@ "version": "2.5.0", "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.5.0.tgz", "integrity": "sha512-60cyAOytib/OzBw1JNSoSV/boK1AtHryDIjvVBk7XbN4ugfkM3+Sry7fEjNgPMGgOjuaZPAp8ruZ0Cxafwyq9g==", + "dev": true, "license": "MIT", "dependencies": { "@cacheable/memory": "^2.2.0", @@ -3599,7 +4237,6 @@ "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -3626,11 +4263,30 @@ ], "license": "CC-BY-4.0" }, + "node_modules/canvas": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-3.2.3.tgz", + "integrity": "sha512-PzE5nJZPz72YUAfo8oTp0u3fqqY7IzlTubneAihqDYAUcBk7ryeCmBbdJBEdaH0bptSOe2VT2Zwcb3UaFyaSWw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^7.0.0", + "prebuild-install": "^7.1.3" + }, + "engines": { + "node": "^18.12.0 || >= 20.9.0" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, "node_modules/cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, "license": "ISC", "dependencies": { "string-width": "^4.2.0", @@ -3651,7 +4307,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -3664,7 +4319,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, "node_modules/commander": { @@ -3749,6 +4403,7 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -3854,16 +4509,40 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, "license": "MIT" }, "node_modules/deepmerge": { @@ -3916,7 +4595,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "dev": true, "license": "Apache-2.0", "engines": { "node": ">=8" @@ -3926,7 +4604,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", - "dev": true, "license": "MIT" }, "node_modules/dom-helpers": { @@ -3981,9 +4658,17 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/error-ex": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", @@ -4176,6 +4861,7 @@ "version": "10.11.0", "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.11.0.tgz", "integrity": "sha512-P7a6UEEqb9G95MYAtqkmsTbVXIYyzIfl6NGOIJk162PaahFxFyeGcrlXYFSiagECg4sEm8IseJdZBKR3rx6MsQ==", + "dev": true, "license": "MIT", "workspaces": [ "packages/*" @@ -4254,6 +4940,7 @@ "version": "9.1.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "@types/esrecurse": "^4.3.1", @@ -4272,6 +4959,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, "license": "Apache-2.0", "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" @@ -4284,6 +4972,7 @@ "version": "11.2.0", "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.16.0", @@ -4301,6 +4990,7 @@ "version": "1.7.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" @@ -4313,6 +5003,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" @@ -4325,6 +5016,7 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=4.0" @@ -4341,6 +5033,7 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" @@ -4359,22 +5052,34 @@ "url": "https://github.com/bgub/eta?sponsor=1" } }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, "license": "MIT" }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, "license": "MIT" }, "node_modules/fast-uri": { @@ -4416,6 +5121,7 @@ "version": "11.1.5", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.5.tgz", "integrity": "sha512-+PFTHITI08JIGhnNpGNI8T8inUpgZfk3GNEqfT9R2zZV2iFXg3CvqzSl/uEhs7TSGujYRELEANyDvS8Fj7+S7Q==", + "dev": true, "license": "MIT", "dependencies": { "flat-cache": "^6.1.23" @@ -4471,6 +5177,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, "license": "MIT", "dependencies": { "locate-path": "^6.0.0", @@ -4487,6 +5194,7 @@ "version": "6.1.23", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.23.tgz", "integrity": "sha512-f++BY9pTk+983xK1FLzlLpmM0i0z+jHmx3QESGkURMXujQZz1k5wzwX6hjnQ8goaD0B+sYnDK1yZ6MTyZfUaqA==", + "dev": true, "license": "MIT", "dependencies": { "cacheable": "^2.5.0", @@ -4498,6 +5206,7 @@ "version": "3.4.4", "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "dev": true, "license": "ISC" }, "node_modules/for-each": { @@ -4533,6 +5242,12 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, "node_modules/fs-extra": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", @@ -4631,7 +5346,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" @@ -4701,6 +5415,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, "node_modules/glob": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", @@ -4730,6 +5450,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.3" @@ -4872,6 +5593,7 @@ "version": "1.5.1", "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.5.1.tgz", "integrity": "sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==", + "dev": true, "license": "MIT", "dependencies": { "hookified": "^1.15.0" @@ -4928,6 +5650,7 @@ "version": "1.15.1", "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.15.1.tgz", "integrity": "sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==", + "dev": true, "license": "MIT" }, "node_modules/idb": { @@ -4937,10 +5660,31 @@ "dev": true, "license": "ISC" }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, "license": "MIT", "engines": { "node": ">= 4" @@ -4966,11 +5710,24 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.8.19" } }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, "node_modules/internal-slot": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", @@ -5146,6 +5903,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -5171,7 +5929,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -5201,6 +5958,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -5448,6 +6206,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, "license": "ISC" }, "node_modules/jackspeak": { @@ -5518,12 +6277,14 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, "license": "MIT" }, "node_modules/json5": { @@ -5566,6 +6327,7 @@ "version": "5.6.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", + "dev": true, "license": "MIT", "dependencies": { "@keyv/serialize": "^1.1.1" @@ -5585,6 +6347,7 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", @@ -5877,6 +6640,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, "license": "MIT", "dependencies": { "p-locate": "^5.0.0" @@ -5937,10 +6701,23 @@ "node": ">= 0.4" } }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/minimatch": { "version": "10.2.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "brace-expansion": "^5.0.8" @@ -5952,6 +6729,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/minipass": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", @@ -5962,6 +6748,12 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -5987,10 +6779,47 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-abi": { + "version": "3.96.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.96.0.tgz", + "integrity": "sha512-rebQ/lz7i0EkoLzUVSrKRzA69zMkwLp95kKMWoMDkkM00Suxz0D7zEQPwRml5fQum24mj7bPvmlgLAmu2JCiYg==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-abi/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", "license": "MIT" }, "node_modules/node-releases": { @@ -6087,10 +6916,20 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, "license": "MIT", "dependencies": { "deep-is": "^0.1.3", @@ -6127,6 +6966,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" @@ -6142,6 +6982,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, "license": "MIT", "dependencies": { "p-limit": "^3.0.2" @@ -6157,7 +6998,6 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -6213,6 +7053,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -6289,7 +7130,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10.13.0" @@ -6334,10 +7174,38 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "deprecated": "No longer maintained. Please contact the author of the relevant native addon; alternatives are available.", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.8.0" @@ -6373,10 +7241,21 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "license": "MIT" }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -6386,6 +7265,7 @@ "version": "0.10.1", "resolved": "https://registry.npmjs.org/qified/-/qified-0.10.1.tgz", "integrity": "sha512-+Owyggi9IxT1ePKGafcI87ubSmxol6smwJ+RAHDQlx9+9cPwFWDiKFFCPuWhr9ignlGpZ9vDQLw67N4dcTVFEA==", + "dev": true, "license": "MIT", "dependencies": { "hookified": "^2.1.1" @@ -6398,13 +7278,13 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/hookified/-/hookified-2.2.0.tgz", "integrity": "sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==", + "dev": true, "license": "MIT" }, "node_modules/qrcode": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", - "dev": true, "license": "MIT", "dependencies": { "dijkstrajs": "^1.0.1", @@ -6418,6 +7298,21 @@ "node": ">=10.13.0" } }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, "node_modules/react": { "version": "19.3.0", "resolved": "https://registry.npmjs.org/react/-/react-19.3.0.tgz", @@ -6431,6 +7326,20 @@ "resolved": "../automat", "link": true }, + "node_modules/react-canvas-label-editor": { + "version": "18.0.0", + "resolved": "git+ssh://git@github.com/sebseb7/react-canvas-label-editor.git#7f0e31b66ff22da011e872b201017398b14e9dd9", + "dependencies": { + "canvas": "^3.2.3", + "jsbarcode": "^3.12.3", + "qrcode": "^1.5.4", + "sharp": "^0.35.3" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, "node_modules/react-dom": { "version": "19.3.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.3.0.tgz", @@ -6503,6 +7412,20 @@ "react-dom": ">=16.6.0" } }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/reflect.getprototypeof": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", @@ -6609,7 +7532,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -6629,7 +7551,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true, "license": "ISC" }, "node_modules/resolve": { @@ -6762,6 +7683,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/safe-push-apply": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", @@ -6827,7 +7768,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true, "license": "ISC" }, "node_modules/set-cookie-parser": { @@ -6885,10 +7825,72 @@ "node": ">= 0.4" } }, + "node_modules/sharp": { + "version": "0.35.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.35.5.tgz", + "integrity": "sha512-Ywn4OnzGukp7CDMrp08RQ50YKmuwG47brZgIVPTvBaaAfQlRlygrRqSrxdCiL9M+LlzLBiJ68IR1QqvzHyjC7g==", + "license": "Apache-2.0", + "dependencies": { + "@img/colour": "^1.1.0", + "detect-libc": "^2.1.2", + "semver": "^7.8.5" + }, + "engines": { + "node": ">=20.9.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.35.5", + "@img/sharp-darwin-x64": "0.35.5", + "@img/sharp-freebsd-wasm32": "0.35.5", + "@img/sharp-libvips-darwin-arm64": "1.3.4", + "@img/sharp-libvips-darwin-x64": "1.3.4", + "@img/sharp-libvips-linux-arm": "1.3.4", + "@img/sharp-libvips-linux-arm64": "1.3.4", + "@img/sharp-libvips-linux-ppc64": "1.3.4", + "@img/sharp-libvips-linux-riscv64": "1.3.4", + "@img/sharp-libvips-linux-s390x": "1.3.4", + "@img/sharp-libvips-linux-x64": "1.3.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.3.4", + "@img/sharp-libvips-linuxmusl-x64": "1.3.4", + "@img/sharp-linux-arm": "0.35.5", + "@img/sharp-linux-arm64": "0.35.5", + "@img/sharp-linux-ppc64": "0.35.5", + "@img/sharp-linux-riscv64": "0.35.5", + "@img/sharp-linux-s390x": "0.35.5", + "@img/sharp-linux-x64": "0.35.5", + "@img/sharp-linuxmusl-arm64": "0.35.5", + "@img/sharp-linuxmusl-x64": "0.35.5", + "@img/sharp-webcontainers-wasm32": "0.35.5", + "@img/sharp-win32-arm64": "0.35.5", + "@img/sharp-win32-ia32": "0.35.5", + "@img/sharp-win32-x64": "0.35.5" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + } + } + }, + "node_modules/sharp/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -6901,6 +7903,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -6995,6 +7998,51 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "node_modules/smob": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/smob/-/smob-1.6.2.tgz", @@ -7065,11 +8113,19 @@ "node": ">= 0.4" } }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -7187,7 +8243,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -7206,6 +8261,15 @@ "node": ">=10" } }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/stylis": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", @@ -7224,6 +8288,34 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tar-fs": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.5.tgz", + "integrity": "sha512-OboTd8mmMhZDNPV+UjQcK9yKAatXu2aJ+r1w4im1Otd4M4fl2hwvdoXUxIYHFTHWK/3y3FarBP70v3vwmGlOxw==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/temp-dir": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", @@ -7295,10 +8387,30 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD", + "optional": true + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" @@ -7529,11 +8641,18 @@ "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, "node_modules/vite": { "version": "8.3.1", "resolved": "https://registry.npmjs.org/vite/-/vite-8.3.1.tgz", @@ -7653,6 +8772,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -7735,7 +8855,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", - "dev": true, "license": "ISC" }, "node_modules/which-typed-array": { @@ -7764,6 +8883,7 @@ "version": "1.2.5", "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -8044,7 +9164,6 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -8055,11 +9174,16 @@ "node": ">=8" } }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, "node_modules/y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true, "license": "ISC" }, "node_modules/yallist": { @@ -8073,7 +9197,6 @@ "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, "license": "MIT", "dependencies": { "cliui": "^6.0.0", @@ -8096,7 +9219,6 @@ "version": "18.1.3", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, "license": "ISC", "dependencies": { "camelcase": "^5.0.0", @@ -8110,7 +9232,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, "license": "MIT", "dependencies": { "locate-path": "^5.0.0", @@ -8124,7 +9245,6 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, "license": "MIT", "dependencies": { "p-locate": "^4.1.0" @@ -8137,7 +9257,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, "license": "MIT", "dependencies": { "p-try": "^2.0.0" @@ -8153,7 +9272,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, "license": "MIT", "dependencies": { "p-limit": "^2.2.0" @@ -8166,6 +9284,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, "license": "MIT", "engines": { "node": ">=10" diff --git a/package.json b/package.json index 2d6d24b..e246e56 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "pdfconvert-wasm": "^0.3.0", "react": "^19.3.0", "react-automat": "file:../automat", + "react-canvas-label-editor": "github:sebseb7/react-canvas-label-editor", "react-dom": "^19.3.0", "react-router-dom": "^7.18.4", "sortablejs": "^1.15.7", @@ -42,5 +43,9 @@ "qrcode": "^1.5.4", "vite": "^8.3.1", "vite-plugin-pwa": "^1.3.0" + }, + "allowScripts": { + "canvas@3.2.3": true, + "github:sebseb7/react-canvas-label-editor#7f0e31b66ff22da011e872b201017398b14e9dd9": true } } diff --git a/src/api/ApiClient.js b/src/api/ApiClient.js index 10954d1..6934640 100644 --- a/src/api/ApiClient.js +++ b/src/api/ApiClient.js @@ -103,6 +103,8 @@ export class ApiClient { create: (body) => this.#json('POST', '/api/warehouse', { body }), /** PATCH /api/warehouse/{id} → 200 { warehouse: Warehouse } */ update: (id, body) => this.#json('PATCH', `/api/warehouse/${enc(id)}`, { body }), + /** PUT /api/warehouse/order → 200 { warehouseIds: number[] } */ + order: (body) => this.#json('PUT', '/api/warehouse/order', { body }), /** DELETE /api/warehouse/{id} → 204 */ delete: (id) => this.#empty('DELETE', `/api/warehouse/${enc(id)}`), }; @@ -353,7 +355,7 @@ export class ApiClient { * `onHistory(history, total)` — returns `{ unwatch, setSkipAndOffset }`. */ historyWatch: (sku, onHistory) => this.watchArticleHistory(sku, onHistory), - /** PATCH /api/article/{sku} — body: at least one of { name, unitamount, unitSi } */ + /** PATCH /api/article/{sku} — body: at least one of { name, unitamount, unitSi, track_stock } */ update: async (sku, body) => { const nameChange = body != null && Object.hasOwn(body, 'name'); if (nameChange) { @@ -400,6 +402,15 @@ export class ApiClient { /** PUT /api/article/{sku}/categories */ setCategories: (sku, body) => this.#json('PUT', `/api/article/${enc(sku)}/categories`, { body }), + /** PUT /api/article/{sku}/track_stock */ + setTrackStock: async (sku, body) => { + const payload = typeof body === 'boolean' ? { track_stock: body } : body; + const res = await this.#json('PUT', `/api/article/${enc(sku)}/track_stock`, { body: payload }); + if (res?.article) { + this.setArticle(res.article); + } + return res; + }, /** GET /api/article/{sku}/supplier */ getSuppliers: (sku) => this.#json('GET', `/api/article/${enc(sku)}/supplier`), /** POST /api/article/{sku}/supplier */ diff --git a/src/api/index.js b/src/api/index.js index 302bb9d..d64ddb5 100644 --- a/src/api/index.js +++ b/src/api/index.js @@ -216,16 +216,20 @@ export const article = { }, /** POST /api/article → 201 { article } */ - create({ parentId, name }) { + create({ parentId, name, track_stock }) { return http('/api/article', { method: 'POST', - body: { parentId, name }, + body: { + parentId, + name, + ...(track_stock !== undefined ? { track_stock } : {}), + }, }); }, /** * PATCH /api/article/:sku - * Body: at least one of { name, unitamount, unitSi } + * Body: at least one of { name, unitamount, unitSi, track_stock } * unitSi must exist for selected company → 404 Unit not found * → 200 { article } (same detail shape as GET) */ @@ -236,6 +240,19 @@ export const article = { }); }, + /** + * PUT /api/article/:sku/track_stock + * Body: { track_stock: boolean } + * → 200 { article } + */ + setTrackStock(sku, body) { + const payload = typeof body === 'boolean' ? { track_stock: body } : body; + return http(`/api/article/${encodeURIComponent(sku)}/track_stock`, { + method: 'PUT', + body: payload, + }); + }, + /** * DELETE /api/article/:sku → 204 * Errors: 400 Article has children, 401, 403, 404 Article not found @@ -404,6 +421,56 @@ export const article = { const qs = params.toString(); return httpGetBinary(`/api/article/export.zip${qs ? `?${qs}` : ''}`); }, + /** + * POST /api/article/:sku/print + * Body: { printerId, templateId, quantity } + * Prints the given template to the specified printer for this article. + */ + printLabel(sku, body) { + return http(`/api/article/${encodeURIComponent(sku)}/print`, { + method: 'POST', + body, + }); + }, +}; + +/** + * Company-scoped printers (selectedCompanyId from session). + * Shape: Printer = { id, address, type, model, serial, sort, desc } + */ +export const printer = { + /** GET /api/printer → { printers: Printer[] } */ + list() { + return http('/api/printer'); + }, + + /** GET /api/printer/:id → { printer: Printer } */ + getById(id) { + return http(`/api/printer/${id}`); + }, + + /** + * POST /api/printer + * Body: { address, type, model, serial, sort, desc } + * → 201 { printer: Printer } + */ + create(body) { + return http('/api/printer', { method: 'POST', body }); + }, + + /** + * PATCH /api/printer/:id + * Body: partial printer fields + * → 200 { printer: Printer } + */ + update(id, body) { + return http(`/api/printer/${id}`, { method: 'PATCH', body }); + }, + + /** DELETE /api/printer/:id → 204 */ + delete(id) { + return http(`/api/printer/${id}`, { method: 'DELETE' }); + }, }; /** @@ -679,7 +746,7 @@ export const warehouse = { /** * POST /api/warehouse - * Body: { name } — empty name ⇒ 400 Name required. + * Body: { name, sort? } — empty name ⇒ 400 Name required. * → 201 { warehouse: Warehouse } */ create(body) { @@ -688,13 +755,22 @@ export const warehouse = { /** * PATCH /api/warehouse/:id - * Body: { name } — empty name ⇒ 400 Name required. + * Body: { name?, sort? } * → 200 { warehouse: Warehouse } */ update(id, body) { return http(`/api/warehouse/${id}`, { method: 'PATCH', body }); }, + /** + * PUT /api/warehouse/order + * Body: { warehouseIds: number[] } + * → 200 { warehouseIds: number[] } + */ + order(body) { + return http('/api/warehouse/order', { method: 'PUT', body }); + }, + /** DELETE /api/warehouse/:id → 204 */ delete(id) { return http(`/api/warehouse/${id}`, { method: 'DELETE' }); @@ -1466,6 +1542,47 @@ export const auth = { }, }; +/** + * Company-scoped ZPL label templates (selectedCompanyId from session). + * Shape: LabelTemplate = { id, company_id, name, width, height, dpi, type, content, thumb } + */ +export const labeltemplate = { + /** GET /api/labeltemplate → { labeltemplates: LabelTemplate[] } */ + list() { + return http('/api/labeltemplate'); + }, + + /** GET /api/labeltemplate/:id → { labeltemplate: LabelTemplate } */ + get(id) { + return http(`/api/labeltemplate/${encodeURIComponent(id)}`); + }, + + /** + * POST /api/labeltemplate + * Body: { name, width, height, dpi, type, content } + * → 201 { labeltemplate: LabelTemplate } + */ + create(body) { + return http('/api/labeltemplate', { method: 'POST', body }); + }, + + /** + * PATCH /api/labeltemplate/:id + * Body: partial { name?, width?, height?, dpi?, type?, content? } + * → 200 { labeltemplate: LabelTemplate } + */ + update(id, body) { + return http(`/api/labeltemplate/${encodeURIComponent(id)}`, { method: 'PATCH', body }); + }, + + /** DELETE /api/labeltemplate/:id → 204 */ + delete(id) { + return http(`/api/labeltemplate/${encodeURIComponent(id)}`, { method: 'DELETE' }); + }, + + // thumb is returned inline as a base64 string in list/get responses +}; + export default { auth, article, @@ -1476,10 +1593,12 @@ export default { customergroup, delivery, entity, + labeltemplate, ledger, number, order, posterminal, + printer, quote, supplier, thumb, diff --git a/src/appRouter.jsx b/src/appRouter.jsx index 835b4cd..8823a39 100644 --- a/src/appRouter.jsx +++ b/src/appRouter.jsx @@ -8,6 +8,7 @@ const ArtikelKategorienPage = lazy(() => import('./pages/artikel/kategorien')); const RedirectArtikelKategorien = lazy(() => import('./pages/artikel/RedirectArtikelKategorien')); const ArtikelLagerPage = lazy(() => import('./pages/artikel/lager')); const ArtikelMarkenPage = lazy(() => import('./pages/artikel/marken')); +const ArtikelVorlagenPage = lazy(() => import('./pages/artikel/vorlagen')); const ArtikelSkuPage = lazy(() => import('./pages/artikel/sku')); const LieferungListePage = lazy(() => import('./pages/lieferung/index')); const LieferungNeuPage = lazy(() => import('./pages/lieferung/neu')); @@ -55,6 +56,7 @@ const routes = [ { path: 'kategorien/*', element: }, { path: 'lager', element: }, { path: 'marken', element: }, + { path: 'vorlagen', element: }, { path: ':sku/:tab?', element: }, ], }, diff --git a/src/automats/warehouseAutomat.js b/src/automats/warehouseAutomat.js index 488b16b..baf43f7 100644 --- a/src/automats/warehouseAutomat.js +++ b/src/automats/warehouseAutomat.js @@ -130,6 +130,17 @@ const actions = { await warehouseAutomat.actions.reload(); }, + /** + * Persists a new sort order for all warehouses. + * + * @param {Array} warehouseIds IDs in the desired order. + * @returns {Promise} + */ + async reorder(warehouseIds) { + await warehouseApi.order({ warehouseIds }); + await warehouseAutomat.actions.reload(); + }, + /** * Replaces the cached list without a round-trip. * diff --git a/src/components/article/ArticleStockAdjustDialog.jsx b/src/components/article/ArticleStockAdjustDialog.jsx index f1a18a0..a4505db 100644 --- a/src/components/article/ArticleStockAdjustDialog.jsx +++ b/src/components/article/ArticleStockAdjustDialog.jsx @@ -25,8 +25,10 @@ import WarehouseIcon from '@mui/icons-material/Warehouse'; import TrendingUpIcon from '@mui/icons-material/TrendingUp'; import TrendingDownIcon from '@mui/icons-material/TrendingDown'; import TuneIcon from '@mui/icons-material/Tune'; +import Switch from '@mui/material/Switch'; import { enqueueSnackbar } from 'notistack'; -import { stock } from '../../api'; +import { stock, article as articleApi } from '../../api'; +import { StorageManagerContext } from '../../api/storageManagerContext'; import { formatStock } from '../../pages/artikel/searchFormat'; import { notifyError } from '../../utils/notify'; import artikelAutomat from '../../automats/artikelAutomat'; @@ -41,9 +43,13 @@ const REASON_PRESETS = [ ]; export default class ArticleStockAdjustDialog extends PureComponent { + static contextType = StorageManagerContext; + constructor(props) { super(props); const initialWhId = this.resolveInitialWarehouseId(props); + const isTrackStock = + props.article?.track_stock !== false && props.article?.track_stock !== 0; this.state = { mode: 'diff', // 'diff' | 'target' warehouseId: initialWhId, @@ -53,6 +59,8 @@ export default class ArticleStockAdjustDialog extends PureComponent { submitting: false, error: null, warehouses: warehouseAutomat.state.warehouses || [], + trackStock: isTrackStock, + initialTrackStock: isTrackStock, }; this.handleWarehouseChange = this.handleWarehouseChange.bind(this); @@ -60,6 +68,7 @@ export default class ArticleStockAdjustDialog extends PureComponent { this.handleDiffChange = this.handleDiffChange.bind(this); this.handleTargetChange = this.handleTargetChange.bind(this); this.handleReasonChange = this.handleReasonChange.bind(this); + this.handleTrackStockToggle = this.handleTrackStockToggle.bind(this); this.handleSubmit = this.handleSubmit.bind(this); } @@ -82,6 +91,8 @@ export default class ArticleStockAdjustDialog extends PureComponent { if (this.props.open && !prevProps.open) { void warehouseAutomat.actions.load().catch(() => {}); const initialWhId = this.resolveInitialWarehouseId(this.props); + const isTrackStock = + this.props.article?.track_stock !== false && this.props.article?.track_stock !== 0; this.setState({ mode: 'diff', warehouseId: initialWhId, @@ -91,6 +102,8 @@ export default class ArticleStockAdjustDialog extends PureComponent { submitting: false, error: null, warehouses: warehouseAutomat.state.warehouses || [], + trackStock: isTrackStock, + initialTrackStock: isTrackStock, }); } } @@ -134,8 +147,15 @@ export default class ArticleStockAdjustDialog extends PureComponent { this.setState({ reason: event.target.value }); } + handleTrackStockToggle(event) { + this.setState({ trackStock: event.target.checked, error: null }); + } + calculateAdjustment() { - const { mode, warehouseId, diffValue, targetValue } = this.state; + const { mode, warehouseId, diffValue, targetValue, trackStock } = this.state; + if (!trackStock) { + return { valid: false, amount: 0, newStock: 0 }; + } const currentStock = this.getCurrentStock(warehouseId); if (mode === 'diff') { @@ -167,43 +187,77 @@ export default class ArticleStockAdjustDialog extends PureComponent { async handleSubmit(event) { event?.preventDefault(); - const { article, onClose, onAdjustSuccess } = this.props; - const { warehouseId, reason, submitting } = this.state; + const { article, onClose, onAdjustSuccess, onArticleUpdated } = this.props; + const { warehouseId, reason, submitting, trackStock, initialTrackStock } = this.state; if (submitting) return; - if (!warehouseId) { - this.setState({ error: 'Bitte wählen Sie ein Lager aus.' }); + const trackStockChanged = trackStock !== initialTrackStock; + const { valid, amount } = this.calculateAdjustment(); + const hasAdjustment = trackStock && valid && amount !== 0; + + if (!trackStockChanged && !hasAdjustment) { + if (trackStock && (!valid || amount === 0)) { + this.setState({ error: 'Bitte geben Sie eine gültige Bestandsänderung ein (ungleich 0).' }); + } return; } - const { valid, amount } = this.calculateAdjustment(); - if (!valid || amount === 0) { - this.setState({ error: 'Bitte geben Sie eine gültige Bestandsänderung ein (ungleich 0).' }); + if (hasAdjustment && !warehouseId) { + this.setState({ error: 'Bitte wählen Sie ein Lager aus.' }); return; } this.setState({ submitting: true, error: null }); try { - const payload = { - sku: article.sku, - warehouseId: Number(warehouseId), - amount, - text: reason.trim() || undefined, - }; + let updatedArticle = null; - const result = await stock.adjust(payload); + // 1. Update track_stock if changed + if (trackStockChanged) { + const store = this.context; + const setFn = store?.article?.setTrackStock ?? articleApi.setTrackStock; + const trackRes = await setFn(article.sku, { track_stock: trackStock }); + updatedArticle = trackRes?.article || null; + } - enqueueSnackbar( - `Bestand für „${article.name || article.sku}“ erfolgreich angepasst (${amount > 0 ? `+${amount}` : amount}).`, - { variant: 'success' } - ); + // 2. Adjust stock if an adjustment was entered and stock is tracked + let adjustResult = null; + if (hasAdjustment) { + const payload = { + sku: article.sku, + warehouseId: Number(warehouseId), + amount, + text: reason.trim() || undefined, + }; + adjustResult = await stock.adjust(payload); + } - // Reload article to update UI + // User feedback + if (trackStockChanged && hasAdjustment) { + enqueueSnackbar( + `Bestandsführung ${trackStock ? 'aktiviert' : 'deaktiviert'} und Bestand angepasst.`, + { variant: 'success' } + ); + } else if (trackStockChanged) { + enqueueSnackbar( + `Bestandsführung für „${article.name || article.sku}“ ${trackStock ? 'aktiviert' : 'deaktiviert'}.`, + { variant: 'success' } + ); + } else if (hasAdjustment) { + enqueueSnackbar( + `Bestand für „${article.name || article.sku}“ erfolgreich angepasst (${amount > 0 ? `+${amount}` : amount}).`, + { variant: 'success' } + ); + } + + // Reload article in automat cache void artikelAutomat.actions.reloadArticle(article.sku).catch(() => {}); - if (onAdjustSuccess) { - onAdjustSuccess(result); + if (updatedArticle) { + onArticleUpdated?.(updatedArticle); + } + if (adjustResult && onAdjustSuccess) { + onAdjustSuccess(adjustResult); } if (onClose) { onClose(); @@ -229,10 +283,16 @@ export default class ArticleStockAdjustDialog extends PureComponent { submitting, error, warehouses, + trackStock, + initialTrackStock, } = this.state; + const trackStockChanged = trackStock !== initialTrackStock; const currentStock = this.getCurrentStock(warehouseId); const { valid, amount, newStock, isZeroChange } = this.calculateAdjustment(); + const hasAdjustment = trackStock && valid && amount !== 0; + const canSubmit = + !submitting && (trackStockChanged || (hasAdjustment && Boolean(warehouseId))); const selectedWarehouse = warehouses.find((w) => Number(w.id) === Number(warehouseId)); const unit = @@ -247,6 +307,13 @@ export default class ArticleStockAdjustDialog extends PureComponent { maxWidth="sm" fullWidth aria-labelledby="stock-adjust-dialog-title" + slotProps={{ + paper: { + sx: { + minHeight: 560, + }, + }, + }} > - - + + {/* Article overview */} + {/* Track Stock Toggle Card */} + + + + Bestand verfolgen + + + {trackStock + ? 'Lagerbestand wird für diesen Artikel geführt und bei Buchungen aktualisiert.' + : 'Keine Bestandsführung. Artikel hat unbegrenzte Verfügbarkeit.'} + + + + + {warehouses.length === 0 ? ( Es sind keine Lager vorhanden. Bitte legen Sie zuerst unter „Artikel → Lager“ ein Lager an. ) : ( - <> + {/* Warehouse selection & Current stock display */} } @@ -358,7 +465,7 @@ export default class ArticleStockAdjustDialog extends PureComponent { onChange={this.handleModeChange} size="small" fullWidth - disabled={submitting} + disabled={submitting || !trackStock} > @@ -380,7 +487,7 @@ export default class ArticleStockAdjustDialog extends PureComponent { type="number" value={diffValue} onChange={this.handleDiffChange} - disabled={submitting} + disabled={submitting || !trackStock} placeholder="z.B. +5 oder -2" slotProps={{ input: { @@ -409,7 +516,7 @@ export default class ArticleStockAdjustDialog extends PureComponent { type="number" value={targetValue} onChange={this.handleTargetChange} - disabled={submitting} + disabled={submitting || !trackStock} placeholder="z.B. 10" helperText={ isZeroChange @@ -459,7 +566,7 @@ export default class ArticleStockAdjustDialog extends PureComponent { label="Grund / Buchungstext" value={reason} onChange={this.handleReasonChange} - disabled={submitting} + disabled={submitting || !trackStock} placeholder="z.B. Inventur, Bruch, Schwund" helperText="Wird im Journal / Ledger als Transaktionstext gespeichert" /> @@ -470,14 +577,14 @@ export default class ArticleStockAdjustDialog extends PureComponent { label={preset} size="small" clickable - disabled={submitting} + disabled={submitting || !trackStock} onClick={() => this.setState({ reason: preset })} sx={{ fontSize: '0.75rem' }} /> ))} - + )} {error && ( @@ -497,7 +604,7 @@ export default class ArticleStockAdjustDialog extends PureComponent { variant="contained" color="primary" onClick={this.handleSubmit} - disabled={submitting || !valid || amount === 0 || !warehouseId} + disabled={!canSubmit} startIcon={ submitting ? ( @@ -507,7 +614,11 @@ export default class ArticleStockAdjustDialog extends PureComponent { } sx={{ minWidth: 150, fontWeight: 600 }} > - {submitting ? 'Wird gebucht...' : 'Bestand anpassen'} + {submitting + ? 'Wird gespeichert...' + : hasAdjustment + ? 'Bestand anpassen' + : 'Speichern'} diff --git a/src/components/article/ArticleTileTab.jsx b/src/components/article/ArticleTileTab.jsx index 56078c3..076bc8d 100644 --- a/src/components/article/ArticleTileTab.jsx +++ b/src/components/article/ArticleTileTab.jsx @@ -159,7 +159,7 @@ class ArticleTileTab extends PureComponent { case ARTICLE_TAB.seo: return ; case ARTICLE_TAB.label: - return ; + return ; case ARTICLE_TAB.attributes: return ; case ARTICLE_TAB.compound: diff --git a/src/components/article/boxes/ArticleViewStock.jsx b/src/components/article/boxes/ArticleViewStock.jsx index 53e6e70..39d0ba4 100644 --- a/src/components/article/boxes/ArticleViewStock.jsx +++ b/src/components/article/boxes/ArticleViewStock.jsx @@ -3,6 +3,7 @@ import Box from '@mui/material/Box'; import Typography from '@mui/material/Typography'; import WarehouseIcon from '@mui/icons-material/Warehouse'; import EditOutlinedIcon from '@mui/icons-material/EditOutlined'; +import Tooltip from '@mui/material/Tooltip'; import { PanelTile } from 'dashgui/panels'; import { formatStock } from '../../../pages/artikel/searchFormat'; import ArticleStockAdjustDialog from '../ArticleStockAdjustDialog'; @@ -30,6 +31,9 @@ export default class ArticleViewStock extends PureComponent { render() { const { article: articleData } = this.props; const { adjustOpen } = this.state; + const isTrackStock = + articleData?.track_stock !== false && articleData?.track_stock !== 0; + const rawWarehouses = Array.isArray(articleData?.warehouses) ? articleData.warehouses : []; @@ -63,149 +67,196 @@ export default class ArticleViewStock extends PureComponent { onClick: this.handleOpenAdjust, }} > - - {/* Top section: Headline and Total Stock */} - - - Bestand - - - + + {/* Top section: Headline and Total Stock */} + 0 ? 'text.primary' : 'text.secondary', + textTransform: 'uppercase', + letterSpacing: 0.6, + fontWeight: 600, + display: 'block', }} > - {formatStock(totalStock)} + Bestand - {unit ? ( - - {unit} - - ) : null} - - - {/* Bottom section: Per-warehouse breakdown */} - {hasWarehouses ? ( - - - {warehouses.map((wh) => ( + {isTrackStock ? ( + + 0 ? 'text.primary' : 'text.secondary', + }} + > + {formatStock(totalStock)} + + {unit ? ( + + {unit} + + ) : null} + + + ) : ( + + + Keine Erfassung + + + Bestand wird nicht überwacht + + + )} + + + {/* Bottom section: Per-warehouse breakdown */} + {isTrackStock && hasWarehouses ? ( + + + {warehouses.map((wh) => ( - - - {wh.name} + + + {wh.name} + + + + 0 + ? 'text.primary' + : 'text.secondary', + }} + > + {formatStock(wh.stock)} - - 0 - ? 'text.primary' - : 'text.secondary', - }} - > - {formatStock(wh.stock)} - - - ))} + ))} + - - ) : null} - - + ) : null} + + - - - ); -} + + + ); + } } diff --git a/src/components/article/tabs/ArticleLabelTab.jsx b/src/components/article/tabs/ArticleLabelTab.jsx index d1da224..5a3e242 100644 --- a/src/components/article/tabs/ArticleLabelTab.jsx +++ b/src/components/article/tabs/ArticleLabelTab.jsx @@ -1,12 +1,256 @@ -import { Component } from 'react'; +import { PureComponent } from 'react'; +import Box from '@mui/material/Box'; import Typography from '@mui/material/Typography'; +import CircularProgress from '@mui/material/CircularProgress'; +import Button from '@mui/material/Button'; +import TextField from '@mui/material/TextField'; +import MenuItem from '@mui/material/MenuItem'; +import Grid from '@mui/material/Grid'; +import Paper from '@mui/material/Paper'; +import PrintIcon from '@mui/icons-material/Print'; +import CheckCircleIcon from '@mui/icons-material/CheckCircle'; +import { enqueueSnackbar } from 'notistack'; + +import { labeltemplate, printer, article } from '../../../api'; +import { notifyError } from '../../../utils/notify'; +import BackendError from '../../BackendError'; + +export default class ArticleLabelTab extends PureComponent { + constructor(props) { + super(props); + this.state = { + templates: null, + printers: null, + selectedTemplateId: '', + selectedPrinterId: '', + quantity: 1, + loading: true, + error: null, + }; + } + + componentDidMount() { + this.loadData(); + } + + async loadData() { + this.setState({ loading: true, error: null }); + try { + const [resTemplates, resPrinters] = await Promise.all([ + labeltemplate.list(), + printer.list(), + ]); + + const templates = resTemplates.labeltemplates || []; + const zplPrinters = (resPrinters.printers || []).filter((p) => p.type === 'zpl'); + + this.setState({ + templates, + printers: zplPrinters, + selectedTemplateId: templates.length > 0 ? templates[0].id : '', + selectedPrinterId: zplPrinters.length > 0 ? zplPrinters[0].id : '', + loading: false, + }); + } catch (error) { + this.setState({ error, loading: false }); + } + } + + handlePrint = async () => { + const { selectedTemplateId, selectedPrinterId, quantity } = this.state; + const { article: articleData } = this.props; + + if (!selectedTemplateId || !selectedPrinterId || quantity < 1) { + enqueueSnackbar('Bitte Vorlage, Drucker und Menge auswählen', { variant: 'warning' }); + return; + } + + try { + await article.printLabel(articleData.sku, { + templateId: selectedTemplateId, + printerId: selectedPrinterId, + quantity, + }); + enqueueSnackbar('Druckauftrag erfolgreich gesendet', { variant: 'success' }); + } catch (err) { + notifyError(err); + } + }; -export default class ArticleLabelTab extends Component { render() { + const { + templates, + printers, + selectedTemplateId, + selectedPrinterId, + quantity, + loading, + error, + } = this.state; + + if (loading) { + return ( + + + + ); + } + + if (error) { + return ( + + this.loadData()} /> + + ); + } + + if (templates.length === 0) { + return ( + + + Es sind keine ZPL-Etikettenvorlagen vorhanden. + + + ); + } + + if (printers.length === 0) { + return ( + + + Es sind keine ZPL-Drucker konfiguriert. + + + ); + } + return ( - - Label - + + + + {templates.map((t) => { + const isSelected = t.id === selectedTemplateId; + return ( + + this.setState({ selectedTemplateId: t.id })} + sx={{ + p: 2, + cursor: 'pointer', + border: '2px solid', + borderColor: isSelected ? 'primary.main' : 'divider', + bgcolor: isSelected ? 'action.selected' : 'background.paper', + boxShadow: isSelected ? 3 : 0, + transition: 'all 0.2s', + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + position: 'relative', + gap: 2, + '&:hover': { + borderColor: 'primary.main', + boxShadow: isSelected ? 3 : 1, + }, + }} + > + {isSelected && ( + + )} + + {t.thumb ? ( + {t.name} + ) : ( + + Keine Vorschau + + )} + + + + {t.name} + + + {t.width}x{t.height} ({t.dpi} dpi) + + + + + ); + })} + + + + + + this.setState({ selectedPrinterId: e.target.value })} + sx={{ minWidth: 200 }} + size="small" + > + {printers.map((p) => ( + + {p.desc ? `${p.desc} (${p.address})` : p.address} + + ))} + + + { + const val = parseInt(e.target.value, 10); + this.setState({ quantity: isNaN(val) ? 1 : Math.max(1, val) }); + }} + inputProps={{ min: 1, max: 9999 }} + sx={{ width: 100 }} + size="small" + /> + + + + + ); } } diff --git a/src/nav.js b/src/nav.js index af5063c..3664908 100644 --- a/src/nav.js +++ b/src/nav.js @@ -15,6 +15,7 @@ import AddBoxIcon from '@mui/icons-material/AddBox'; import StorefrontIcon from '@mui/icons-material/Storefront'; import RequestQuoteIcon from '@mui/icons-material/RequestQuote'; import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; +import LabelIcon from '@mui/icons-material/Label'; import { isKategorienPath } from './pages/artikel/categoryRoute'; import { deliveryEditorAutomat } from './automats/deliveryEditorAutomat'; @@ -105,6 +106,7 @@ export const SUB_NAV = { { segment: 'kategorien', label: 'Kategorieen', title: 'Kategorien', icon: CategoryIcon }, { segment: 'lager', label: 'Lager', icon: WarehouseIcon }, { segment: 'marken', label: 'Marken', icon: CopyrightIcon }, + { segment: 'vorlagen', label: 'Vorlagen', icon: LabelIcon }, ], '/lieferung': [ { segment: '', label: 'Liste', title: 'Lieferungen', icon: ListAltIcon }, diff --git a/src/pages/artikel/lager.jsx b/src/pages/artikel/lager.jsx index ce541ce..fae7fe5 100644 --- a/src/pages/artikel/lager.jsx +++ b/src/pages/artikel/lager.jsx @@ -1,4 +1,4 @@ -import { PureComponent } from 'react'; +import { PureComponent, createRef } from 'react'; import Alert from '@mui/material/Alert'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; @@ -9,7 +9,9 @@ import ListItem from '@mui/material/ListItem'; import Stack from '@mui/material/Stack'; import Typography from '@mui/material/Typography'; import DeleteOutlinedIcon from '@mui/icons-material/DeleteOutlined'; +import DragIndicatorIcon from '@mui/icons-material/DragIndicator'; import WarehouseIcon from '@mui/icons-material/Warehouse'; +import Sortable from 'sortablejs'; import { enqueueSnackbar } from 'notistack'; import BackendError from '../../components/BackendError'; import SingleLineTextEdit from 'dashgui/SingleLineTextEdit'; @@ -20,12 +22,6 @@ import { notifyError } from '../../utils/notify'; import { setLastArticleSku } from '../../automats'; import warehouseAutomat from '../../automats/warehouseAutomat'; -function sortWarehouses(warehouses) { - return [...warehouses].sort((a, b) => - String(a.name).localeCompare(String(b.name), 'de'), - ); -} - function draftsFrom(warehouses) { return Object.fromEntries(warehouses.map((row) => [row.id, row.name])); } @@ -50,7 +46,7 @@ class ArtikelLagerPage extends PureComponent { constructor(props) { super(props); const { prefill } = getInitialParams(props); - const initialWarehouses = sortWarehouses(warehouseAutomat.state.warehouses || []); + const initialWarehouses = warehouseAutomat.state.warehouses || []; this.state = { status: warehouseAutomat.state.status === 'ready' ? 'ready' : 'loading', error: warehouseAutomat.state.error ? backendErrorFrom(warehouseAutomat.state.error) : null, @@ -60,9 +56,14 @@ class ArtikelLagerPage extends PureComponent { busyKey: null, }; this._cancelled = false; + this.listRef = createRef(); + this._sortable = null; + this.handleCreate = this.handleCreate.bind(this); this.handleRetry = this.handleRetry.bind(this); this.loadWarehouses = this.loadWarehouses.bind(this); + this._initSortable = this._initSortable.bind(this); + this._destroySortable = this._destroySortable.bind(this); } componentDidMount() { @@ -85,27 +86,76 @@ class ArtikelLagerPage extends PureComponent { void this.loadWarehouses(); } - componentDidUpdate(prevProps) { + componentDidUpdate(prevProps, prevState) { if (prevProps.location !== this.props.location) { const { prefill } = getInitialParams(this.props); if (prefill && prefill !== this.state.newName) { this.setState({ newName: prefill }); } } + + // Re-initialise Sortable when warehouses change or list mounts + if (prevState.warehouses !== this.state.warehouses && this.listRef.current) { + this._initSortable(); + } } componentWillUnmount() { this._cancelled = true; this.unsub?.(); + this._destroySortable(); + } + + _initSortable() { + this._destroySortable(); + const el = this.listRef.current; + if (!el) return; + + this._sortable = Sortable.create(el, { + handle: '.drag-handle', + animation: 150, + ghostClass: 'sortable-ghost', + chosenClass: 'sortable-chosen', + onEnd: (evt) => { + const { oldIndex, newIndex } = evt; + if (oldIndex === newIndex) return; + + this.setState((prev) => { + const next = [...prev.warehouses]; + const [moved] = next.splice(oldIndex, 1); + next.splice(newIndex, 0, moved); + return { warehouses: next }; + }, () => { + const ids = this.state.warehouses.map((w) => w.id); + void this._persistOrder(ids); + }); + }, + }); + } + + _destroySortable() { + this._sortable?.destroy(); + this._sortable = null; + } + + async _persistOrder(warehouseIds) { + try { + await warehouseAutomat.actions.reorder(warehouseIds); + } catch (err) { + if (this._cancelled) return; + notifyError(err); + // Roll back optimistic reorder + void this.refreshFromServer(); + } } applyWarehouses(warehouses) { - const sorted = sortWarehouses(warehouses); + // Preserve order returned by the server (already sorted by sort/name from backend) this.setState((prev) => { const currentDrafts = prev.drafts || {}; - const nextDrafts = { ...draftsFrom(sorted) }; + const nextDrafts = { ...draftsFrom(warehouses) }; // Preserve unsaved in-progress edits for still-existing items if not busy - for (const wh of sorted) { + for (const wh of warehouses) { if (prev.busyKey !== wh.id && currentDrafts[wh.id] !== undefined) { nextDrafts[wh.id] = currentDrafts[wh.id]; } @@ -113,7 +163,7 @@ class ArtikelLagerPage extends PureComponent { return { status: 'ready', error: null, - warehouses: sorted, + warehouses, drafts: nextDrafts, }; }); @@ -155,7 +205,7 @@ class ArtikelLagerPage extends PureComponent { await this.refreshFromServer(); if (this._cancelled) return; this.setState({ newName: '', busyKey: null }); - enqueueSnackbar(`Lager „${newWarehouse.name || name}“ angelegt.`, { variant: 'success' }); + enqueueSnackbar(`Lager „${newWarehouse.name || name}" angelegt.`, { variant: 'success' }); if (returnTo && this.props.navigate) { this.props.navigate(returnTo); @@ -196,7 +246,7 @@ class ArtikelLagerPage extends PureComponent { async handleDelete(wh) { if (this.state.busyKey != null) return; - if (!window.confirm(`Lager „${wh.name}“ wirklich löschen?`)) { + if (!window.confirm(`Lager „${wh.name}" wirklich löschen?`)) { return; } @@ -233,113 +283,137 @@ class ArtikelLagerPage extends PureComponent { } return ( - - - - {returnTo ? ( - this.props.navigate?.(returnTo)} - > - Zurück - - } - > - {newName - ? `Lagername „${newName}“ übernommen.` - : 'Neues Lager anlegen.'} - - ) : null} + <> + {/* SortableJS ghost / chosen styling */} + - - Lager der ausgewählten Firma. - - - - {warehouses.length === 0 ? ( - - Noch keine Lager angelegt. - - ) : ( - warehouses.map((wh) => ( - - - + + + {returnTo ? ( + - this.setState((prev) => ({ - drafts: { ...prev.drafts, [wh.id]: next }, - })) - } - onBlur={() => void this.handleRename(wh)} - onKeyDown={(event) => { - if (event.key === 'Enter') { - event.preventDefault(); - event.target.blur(); - } - if (event.key === 'Escape') { - event.preventDefault(); - this.setState((prev) => ({ - drafts: { ...prev.drafts, [wh.id]: wh.name }, - })); - event.target.blur(); - } - }} - sx={{ flex: 1 }} - /> - void this.handleDelete(wh)} + onClick={() => this.props.navigate?.(returnTo)} > - - - - )) - )} - - - - this.setState({ newName: next })} - onKeyDown={(event) => { - if (event.key === 'Enter') { - event.preventDefault(); - void this.handleCreate(); + Zurück + } - }} - sx={{ flex: 1 }} - /> - - - - - + > + {newName + ? `Lagername „${newName}" übernommen.` + : 'Neues Lager anlegen.'} + + ) : null} + + + Reihenfolge per Drag & Drop anpassen. + + + + {warehouses.length === 0 ? ( + + Noch keine Lager angelegt. + + ) : ( + warehouses.map((wh) => ( + + + + + + + this.setState((prev) => ({ + drafts: { ...prev.drafts, [wh.id]: next }, + })) + } + onBlur={() => void this.handleRename(wh)} + onKeyDown={(event) => { + if (event.key === 'Enter') { + event.preventDefault(); + event.target.blur(); + } + if (event.key === 'Escape') { + event.preventDefault(); + this.setState((prev) => ({ + drafts: { ...prev.drafts, [wh.id]: wh.name }, + })); + event.target.blur(); + } + }} + sx={{ flex: 1 }} + /> + void this.handleDelete(wh)} + > + + + + )) + )} + + + + this.setState({ newName: next })} + onKeyDown={(event) => { + if (event.key === 'Enter') { + event.preventDefault(); + void this.handleCreate(); + } + }} + sx={{ flex: 1 }} + /> + + + + + + ); } } diff --git a/src/pages/artikel/marken.jsx b/src/pages/artikel/marken.jsx index 68fc3d4..8c0645e 100644 --- a/src/pages/artikel/marken.jsx +++ b/src/pages/artikel/marken.jsx @@ -181,10 +181,6 @@ class ArtikelMarkenPage extends PureComponent { return ( - - Marken der ausgewählten Firma. - - {brands.length === 0 ? ( diff --git a/src/pages/artikel/vorlagen.jsx b/src/pages/artikel/vorlagen.jsx new file mode 100644 index 0000000..355370c --- /dev/null +++ b/src/pages/artikel/vorlagen.jsx @@ -0,0 +1,594 @@ +import { PureComponent } from 'react'; +import Box from '@mui/material/Box'; +import Button from '@mui/material/Button'; +import CircularProgress from '@mui/material/CircularProgress'; +import Dialog from '@mui/material/Dialog'; +import DialogActions from '@mui/material/DialogActions'; +import DialogContent from '@mui/material/DialogContent'; +import DialogTitle from '@mui/material/DialogTitle'; +import Divider from '@mui/material/Divider'; +import IconButton from '@mui/material/IconButton'; +import InputAdornment from '@mui/material/InputAdornment'; +import TextField from '@mui/material/TextField'; +import ToggleButton from '@mui/material/ToggleButton'; +import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'; +import Tooltip from '@mui/material/Tooltip'; +import Typography from '@mui/material/Typography'; +import AddIcon from '@mui/icons-material/Add'; +import DeleteOutlinedIcon from '@mui/icons-material/DeleteOutlined'; +import EditIcon from '@mui/icons-material/Edit'; +import LabelIcon from '@mui/icons-material/Label'; +import { CanvasEditor } from 'react-canvas-label-editor'; +import 'react-canvas-label-editor/style.css'; +import BackendError from '../../components/BackendError'; +import { PanelTile, PanelTileGrid } from 'dashgui/panels'; +import { backendErrorFrom } from '../../utils/backendError'; +import { notifyError } from '../../utils/notify'; +import { setLastArticleSku } from '../../automats'; +import { labeltemplate } from '../../api'; +import { enqueueSnackbar } from 'notistack'; + +const MIN_HEIGHT_MM = 10; +const DEFAULT_HEIGHT_MM = 25; +const DEFAULT_DPI = 203; + +function getCanvasWidth(widthClass, dpi) { + if (widthClass === '4') { + return dpi === 300 ? 1248 : 832; + } + return dpi === 300 ? 640 : 448; +} + +function getMinHeightPx(dpi) { + return Math.max(80, Math.round((MIN_HEIGHT_MM * dpi) / 25.4)); +} + +function mmToPx(mm, dpi) { + return Math.round((Number(mm) * dpi) / 25.4); +} + +function pxToMm(px, dpi) { + return Number(((px / dpi) * 25.4).toFixed(1)); +} + +class ArtikelVorlagenPage extends PureComponent { + constructor(props) { + super(props); + const initialDpi = DEFAULT_DPI; + const initialWidthClass = '2'; + const initialHeightMm = DEFAULT_HEIGHT_MM; + + this.state = { + status: 'loading', + error: null, + templates: [], + // Editor dialog state + editorOpen: false, + editorLoading: false, + editorTemplate: null, // null = new, object = edit + editorName: '', + editorObjects: [], + editorDpi: initialDpi, + editorWidthClass: initialWidthClass, + editorWidth: getCanvasWidth(initialWidthClass, initialDpi), + editorHeightMm: initialHeightMm, + editorHeight: mmToPx(initialHeightMm, initialDpi), + editorClipboard: null, + saving: false, + // Delete busy + deletingId: null, + }; + this._cancelled = false; + this._currentEditId = null; + this.handleRetry = this.handleRetry.bind(this); + this.handleOpenNew = this.handleOpenNew.bind(this); + this.handleOpenEdit = this.handleOpenEdit.bind(this); + this.handleEditorClose = this.handleEditorClose.bind(this); + this.handleEditorSave = this.handleEditorSave.bind(this); + this.handleWidthClassChange = this.handleWidthClassChange.bind(this); + this.handleDpiChange = this.handleDpiChange.bind(this); + this.handleHeightMmChange = this.handleHeightMmChange.bind(this); + this.handleHeightMmBlur = this.handleHeightMmBlur.bind(this); + } + + componentDidMount() { + setLastArticleSku(null); + this._cancelled = false; + void this.loadTemplates(); + } + + componentWillUnmount() { + this._cancelled = true; + } + + async loadTemplates() { + this.setState({ status: 'loading', error: null }); + try { + const { labeltemplates } = await labeltemplate.list(); + if (this._cancelled) return; + this.setState({ status: 'ready', templates: labeltemplates || [] }); + } catch (err) { + if (this._cancelled) return; + this.setState({ status: 'failed', error: backendErrorFrom(err) }); + } + } + + handleRetry() { + void this.loadTemplates(); + } + + handleOpenNew() { + this._currentEditId = null; + const dpi = DEFAULT_DPI; + const widthClass = '2'; + const width = getCanvasWidth(widthClass, dpi); + const heightMm = DEFAULT_HEIGHT_MM; + const height = mmToPx(heightMm, dpi); + + this.setState({ + editorOpen: true, + editorLoading: false, + editorTemplate: null, + editorName: 'Neue Vorlage', + editorObjects: [], + editorDpi: dpi, + editorWidthClass: widthClass, + editorWidth: width, + editorHeightMm: heightMm, + editorHeight: height, + }); + } + + async handleOpenEdit(tmpl) { + const fetchId = tmpl.id; + this._currentEditId = fetchId; + const initialDpi = tmpl.dpi === 300 ? 300 : 203; + const initialWidthClass = (tmpl.width || 0) >= 800 ? '4' : '2'; + const initialWidth = tmpl.width || getCanvasWidth(initialWidthClass, initialDpi); + const initialHeight = tmpl.height || mmToPx(DEFAULT_HEIGHT_MM, initialDpi); + const initialHeightMm = pxToMm(initialHeight, initialDpi); + + this.setState({ + editorOpen: true, + editorLoading: true, + editorTemplate: tmpl, + editorName: tmpl.name, + editorObjects: [], + editorDpi: initialDpi, + editorWidthClass: initialWidthClass, + editorWidth: initialWidth, + editorHeightMm: initialHeightMm, + editorHeight: initialHeight, + }); + + try { + const { labeltemplate: full } = await labeltemplate.get(fetchId); + if (this._cancelled || this._currentEditId !== fetchId || !this.state.editorOpen) return; + const content = full?.content || {}; + const dpi = full?.dpi === 300 ? 300 : 203; + const widthClass = (full?.width || 0) >= 800 ? '4' : '2'; + const width = full?.width || getCanvasWidth(widthClass, dpi); + const height = full?.height || mmToPx(DEFAULT_HEIGHT_MM, dpi); + const heightMm = pxToMm(height, dpi); + + this.setState({ + editorLoading: false, + editorTemplate: full, + editorName: full.name ?? tmpl.name, + editorObjects: content.objects || [], + editorDpi: dpi, + editorWidthClass: widthClass, + editorWidth: width, + editorHeightMm: heightMm, + editorHeight: height, + }); + } catch (err) { + if (this._cancelled || this._currentEditId !== fetchId) return; + notifyError(err); + this.setState({ editorOpen: false, editorLoading: false, editorTemplate: null }); + } + } + + handleWidthClassChange(event, nextValue) { + if (!nextValue) return; + const width = getCanvasWidth(nextValue, this.state.editorDpi); + this.setState({ + editorWidthClass: nextValue, + editorWidth: width, + }); + } + + handleDpiChange(event, nextValue) { + if (!nextValue) return; + const dpi = Number(nextValue); + const width = getCanvasWidth(this.state.editorWidthClass, dpi); + const mm = parseFloat(this.state.editorHeightMm) || DEFAULT_HEIGHT_MM; + const minHeightPx = getMinHeightPx(dpi); + const height = Math.max(minHeightPx, mmToPx(mm, dpi)); + this.setState({ + editorDpi: dpi, + editorWidth: width, + editorHeight: height, + }); + } + + handleHeightMmChange(event) { + const val = event.target.value; + const dpi = this.state.editorDpi; + const num = parseFloat(val); + const minHeightPx = getMinHeightPx(dpi); + const height = !isNaN(num) && num > 0 + ? Math.max(minHeightPx, mmToPx(num, dpi)) + : this.state.editorHeight; + this.setState({ + editorHeightMm: val, + editorHeight: height, + }); + } + + handleHeightMmBlur() { + const dpi = this.state.editorDpi; + const num = parseFloat(this.state.editorHeightMm); + const safeMm = !isNaN(num) && num >= MIN_HEIGHT_MM ? num : MIN_HEIGHT_MM; + const minHeightPx = getMinHeightPx(dpi); + this.setState({ + editorHeightMm: safeMm, + editorHeight: Math.max(minHeightPx, mmToPx(safeMm, dpi)), + }); + } + + handleEditorClose() { + if (this.state.saving) return; + this._currentEditId = null; + this.setState({ editorOpen: false, editorLoading: false, editorTemplate: null }); + } + + async handleEditorSave() { + const { + editorTemplate, editorName, editorObjects, + editorHeight, editorWidth, editorDpi, + } = this.state; + const name = editorName.trim(); + if (!name) return; + + this.setState({ saving: true }); + const body = { + name, + width: editorWidth, + height: editorHeight, + dpi: editorDpi, + type: 'zpl', + content: { objects: editorObjects }, + }; + + try { + if (editorTemplate) { + const { labeltemplate: updated } = await labeltemplate.update(editorTemplate.id, body); + if (this._cancelled) return; + this.setState((prev) => ({ + saving: false, + editorOpen: false, + templates: prev.templates.map((t) => (t.id === updated.id ? updated : t)), + })); + enqueueSnackbar(`Vorlage „${updated.name}" gespeichert.`, { variant: 'success' }); + } else { + const { labeltemplate: created } = await labeltemplate.create(body); + if (this._cancelled) return; + this.setState((prev) => ({ + saving: false, + editorOpen: false, + templates: [...prev.templates, created], + })); + enqueueSnackbar(`Vorlage „${created.name}" angelegt.`, { variant: 'success' }); + } + } catch (err) { + if (this._cancelled) return; + notifyError(err); + this.setState({ saving: false }); + } + } + + async handleDelete(tmpl) { + if (this.state.deletingId != null) return; + if (!window.confirm(`Vorlage „${tmpl.name}" wirklich löschen?`)) return; + + this.setState({ deletingId: tmpl.id }); + try { + await labeltemplate.delete(tmpl.id); + if (this._cancelled) return; + this.setState((prev) => ({ + deletingId: null, + templates: prev.templates.filter((t) => t.id !== tmpl.id), + })); + enqueueSnackbar('Vorlage gelöscht.', { variant: 'success' }); + } catch (err) { + if (this._cancelled) return; + notifyError(err); + this.setState({ deletingId: null }); + } + } + + renderEditor() { + const { + editorOpen, editorLoading, editorTemplate, editorName, editorObjects, + editorHeight, editorWidth, editorDpi, editorWidthClass, editorHeightMm, + editorClipboard, saving, + } = this.state; + + const minHeightPx = getMinHeightPx(editorDpi); + + return ( + + + {editorTemplate ? `„${editorTemplate.name}" bearbeiten` : 'Neue Vorlage'} + + + {editorLoading ? ( + + + + Vorlage wird geladen… + + + ) : ( + <> + + this.setState({ editorName: e.target.value })} + disabled={saving} + sx={{ flex: 1, minWidth: 200 }} + /> + + + Breite: + + 2" + 4" + + + + + Auflösung: + + 203 DPI + 300 DPI + + + + mm, + }} + inputProps={{ + min: MIN_HEIGHT_MM, + max: 300, + step: 1, + }} + sx={{ width: 120 }} + /> + + + + this.setState({ editorObjects: objects })} + clipboard={editorClipboard} + onCopy={(obj) => this.setState({ editorClipboard: obj })} + /> + + + )} + + + + + + + ); + } + + render() { + const { status, error, templates, deletingId } = this.state; + + if (status === 'loading') { + return ( + + + + ); + } + + if (status === 'failed') { + return ; + } + + return ( + <> + + + + + + + {templates.length === 0 ? ( + + + Noch keine Vorlagen angelegt. + + ) : ( + + {templates.map((tmpl) => ( + + {/* Thumbnail */} + this.handleOpenEdit(tmpl)} + sx={{ + height: 100, + bgcolor: '#f8f8f8', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + borderBottom: '1px solid', + borderColor: 'divider', + overflow: 'hidden', + cursor: 'pointer', + }} + > + {tmpl.thumb ? ( + + ) : ( + + )} + + + {/* Footer */} + + + {tmpl.name} + + + + this.handleOpenEdit(tmpl)} + disabled={deletingId != null} + > + + + + + + + void this.handleDelete(tmpl)} + disabled={deletingId === tmpl.id} + > + {deletingId === tmpl.id + ? + : } + + + + + + {/* Dimensions chip */} + + + {Number(((tmpl.width / (tmpl.dpi || 203)) * 25.4).toFixed(0))} × {Number(((tmpl.height / (tmpl.dpi || 203)) * 25.4).toFixed(0))} mm ({tmpl.width} × {tmpl.height} px) · {tmpl.dpi || 203} DPI + + + ))} + + )} + + + + {this.renderEditor()} + + ); + } +} + +export default ArtikelVorlagenPage; diff --git a/src/pages/lieferung/lieferanten.jsx b/src/pages/lieferung/lieferanten.jsx index ccd73e6..ff08a54 100644 --- a/src/pages/lieferung/lieferanten.jsx +++ b/src/pages/lieferung/lieferanten.jsx @@ -246,10 +246,6 @@ class LieferungLieferantenPage extends PureComponent { ) : null} - - Lieferanten der ausgewählten Firma. - - {suppliers.length === 0 ? (