diff --git a/package-lock.json b/package-lock.json index 9042bf2..af855ae 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,6 +8,8 @@ "name": "portal-chart-builder", "version": "0.0.0", "dependencies": { + "@consta/icons": "^1.7.1", + "@consta/uikit": "^5.33.2", "@xyflow/react": "^12.11.2", "react": "^19.2.7", "react-dom": "^19.2.7" @@ -22,6 +24,71 @@ "vite": "^8.1.1" } }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/runtime-corejs3": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.29.7.tgz", + "integrity": "sha512-ppj9ouYku+RX0ljtgZd+KMO5mkM2bCqg8H2PYAFWnLsHEIKIdRojqbJ2i3eVHrisuxy7nOFCmngTDdWtUCdXUQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "core-js-pure": "^3.48.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bem-react/classname": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@bem-react/classname/-/classname-1.8.0.tgz", + "integrity": "sha512-uazGRFKTMNbGR8KLvEh5qT+aP0yuym+sB+YFFaAyCkFodtjI0SskV6BfkiZ9+E3FloIFYPkwqJ1owxp48WCS9g==", + "license": "MPL-2.0", + "peer": true + }, + "node_modules/@bem-react/classnames": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@bem-react/classnames/-/classnames-1.5.0.tgz", + "integrity": "sha512-kHa04vgeU0pJbqE/ZDzOn0bRkkVdbo0ZuV2h71h8PtopfDDGzfrgPIn+L6ohW3uF4cbdWUE49sQ0nyVT+O555g==", + "license": "MPL-2.0", + "peer": true + }, + "node_modules/@consta/icons": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@consta/icons/-/icons-1.7.1.tgz", + "integrity": "sha512-ZFngpjo9MlVyNnRU0SJqg2kbzHmh41ydqCYLOWokvhPjlgqUS7W+R38+dHSpIMyMe33wKBvF8LciSqhGwmuP9w==", + "peerDependencies": { + "@consta/uikit": "^5.0.0" + } + }, + "node_modules/@consta/uikit": { + "version": "5.33.2", + "resolved": "https://registry.npmjs.org/@consta/uikit/-/uikit-5.33.2.tgz", + "integrity": "sha512-akF8UkXkJuIg3RKEzorGOZ9/aIPC9v8t3ZDSC+jFbHobP4h0AhGF8NgltB4BW1aXBLkiVN3ee8uGid1edwGcMA==", + "peerDependencies": { + "@bem-react/classname": "^1.6.0", + "@bem-react/classnames": "^1.3.10", + "@consta/icons": "^1.7.1", + "@reatom/core": "^3.10.1", + "@reatom/npm-react": "^3.10.6", + "compute-scroll-into-view": "^3.1.1", + "date-fns": "^4.1.0", + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0", + "react-dropzone": "^14.2.3", + "react-imask": "^7.2.1", + "react-textarea-autosize": "^8.5.3", + "react-transition-group": "^4.4.5" + } + }, "node_modules/@emnapi/core": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", @@ -408,6 +475,85 @@ "node": "^20.19.0 || >=22.12.0" } }, + "node_modules/@reatom/core": { + "version": "3.10.3", + "resolved": "https://registry.npmjs.org/@reatom/core/-/core-3.10.3.tgz", + "integrity": "sha512-uctBfmL/ZNvHWRX92Y+VQZON37fXNja4FM1fzevX7RYOWy6R7evx42VM6K4kuOaIci7bVWPhPZzHWeAu0J2lHQ==", + "license": "MIT", + "peer": true + }, + "node_modules/@reatom/effects": { + "version": "3.11.3", + "resolved": "https://registry.npmjs.org/@reatom/effects/-/effects-3.11.3.tgz", + "integrity": "sha512-0qxr7m6e+GrOvt0pESONl4aRZxGjsU1HWXIsDR2Ghw0mNGjuStnEDUZnO+MVbKOArMIAvZ8ZoMrQWqXEBfOrVg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@reatom/core": "^3.2.0", + "@reatom/utils": "^3.5.0" + } + }, + "node_modules/@reatom/hooks": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@reatom/hooks/-/hooks-3.6.1.tgz", + "integrity": "sha512-1q8qXAOkQlDKc/Y94alPHWqMnXvJhCG4Rr9hQxPMPG1Qf3WpeKm7Zdxs4v3DC2Kcw6oG6djVk3i5duIjPygGWA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@reatom/core": "^3.2.0", + "@reatom/effects": "^3.7.0", + "@reatom/utils": "^3.3.0" + } + }, + "node_modules/@reatom/lens": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/@reatom/lens/-/lens-3.12.0.tgz", + "integrity": "sha512-YsEnYYHi58ePDscXomnbDPC9NSggfJQHvhcpqEAmvZuHH4nbsUpoQj2W69nSQyUDH/+X+TxURvsGUOHaXMl9pQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@reatom/core": "^3.4.0", + "@reatom/effects": "^3.2.0", + "@reatom/hooks": "^3.3.1", + "@reatom/primitives": "^3.6.0", + "@reatom/utils": "^3.1.0" + } + }, + "node_modules/@reatom/npm-react": { + "version": "3.10.6", + "resolved": "https://registry.npmjs.org/@reatom/npm-react/-/npm-react-3.10.6.tgz", + "integrity": "sha512-lyoJD+pF2/P6B5bzSYjUQCzUSa0zkUQNAm1Lj8VXmVbILuiWid+n/9o/fJa8eEyH+w6KaFRunz1WZcOg/NW91g==", + "license": "MIT", + "peer": true, + "dependencies": { + "@reatom/core": "^3.5.0", + "@reatom/effects": "^3.7.3", + "@reatom/lens": "^3.1.0", + "@reatom/utils": "^3.9.0", + "use-sync-external-store": "^1.2.0" + }, + "peerDependencies": { + "react": ">=16.8.0" + } + }, + "node_modules/@reatom/primitives": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@reatom/primitives/-/primitives-3.11.0.tgz", + "integrity": "sha512-b+jtK7qpQxSP83mYQXpPRMlFyg+C9WPv4sZDWSmm00mwmwetW0KbltftkWiwQjQM1TLwpDLZ6R7DX7fcTraIgg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@reatom/core": "^3.1.1", + "@reatom/utils": "^3.1.1" + } + }, + "node_modules/@reatom/utils": { + "version": "3.11.3", + "resolved": "https://registry.npmjs.org/@reatom/utils/-/utils-3.11.3.tgz", + "integrity": "sha512-H2FQf9xra7Twf0PxS6L0DtuRRC79NfHRB3V/YhnhPHyUE/UFscXrin/I2eGj3FEKcgOfC2BWnzCOrkXjKWgECQ==", + "license": "MIT", + "peer": true + }, "node_modules/@rolldown/binding-android-arm64": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz", @@ -830,17 +976,45 @@ "d3-zoom": "^3.0.0" } }, + "node_modules/attr-accept": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.5.tgz", + "integrity": "sha512-0bDNnY/u6pPwHDMoF0FieU354oBi0a8rD9FcsLwzcGWbc8KS8KPIi7y+s13OlVY+gMWc/9xEMUgNE6Qm8ZllYQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=4" + } + }, "node_modules/classcat": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/classcat/-/classcat-5.0.5.tgz", "integrity": "sha512-JhZUT7JFcQy/EzW605k/ktHtncoo9vnyW/2GspNYwFlN1C/WmjuV/xtS04e9SOkL2sTdw0VAZ2UGCcQ9lR6p6w==", "license": "MIT" }, + "node_modules/compute-scroll-into-view": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz", + "integrity": "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==", + "license": "MIT", + "peer": true + }, + "node_modules/core-js-pure": { + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.49.0.tgz", + "integrity": "sha512-XM4RFka59xATyJv/cS3O3Kml72hQXUeGRuuTmMYFxwzc9/7C8OYTaIR/Ji+Yt8DXzsFLNhat15cE/JP15HrCgw==", + "hasInstallScript": true, + "license": "MIT", + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/csstype": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "devOptional": true, "license": "MIT" }, "node_modules/d3-color": { @@ -948,6 +1122,17 @@ "node": ">=12" } }, + "node_modules/date-fns": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.4.0.tgz", + "integrity": "sha512-+1UMbeh68lH1SegH83CGWwpb6OHHbpSgr3+s5Eww5M4CAgswBpoWS0AjTOfEJ33HiYKz1hdj/KTFprzXHmq/6w==", + "license": "MIT", + "peer": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", @@ -958,6 +1143,17 @@ "node": ">=8" } }, + "node_modules/dom-helpers": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", + "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.8.7", + "csstype": "^3.0.2" + } + }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -976,6 +1172,19 @@ } } }, + "node_modules/file-selector": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/file-selector/-/file-selector-2.1.2.tgz", + "integrity": "sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig==", + "license": "MIT", + "peer": true, + "dependencies": { + "tslib": "^2.7.0" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -991,6 +1200,26 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "node_modules/imask": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/imask/-/imask-7.6.1.tgz", + "integrity": "sha512-sJlIFM7eathUEMChTh9Mrfw/IgiWgJqBKq2VNbyXvBZ7ev/IlO6/KQTKlV/Fm+viQMLrFLG/zCuudrLIwgK2dg==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime-corejs3": "^7.24.4" + }, + "engines": { + "npm": ">=4.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT", + "peer": true + }, "node_modules/lightningcss": { "version": "1.32.0", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", @@ -1252,6 +1481,19 @@ "url": "https://opencollective.com/parcel" } }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "peer": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/nanoid": { "version": "3.3.16", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", @@ -1271,6 +1513,16 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/oxlint": { "version": "1.73.0", "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.73.0.tgz", @@ -1369,6 +1621,18 @@ "node": "^10 || ^12 || >=14" } }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, "node_modules/react": { "version": "19.2.7", "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", @@ -1390,6 +1654,83 @@ "react": "^19.2.7" } }, + "node_modules/react-dropzone": { + "version": "14.4.1", + "resolved": "https://registry.npmjs.org/react-dropzone/-/react-dropzone-14.4.1.tgz", + "integrity": "sha512-QDuV76v3uKbHiH34SpwifZ+gOLi1+RdsCO1kl5vxMT4wW8R82+sthjvBw4th3NHF/XX6FBsqDYZVNN+pnhaw0g==", + "license": "MIT", + "peer": true, + "dependencies": { + "attr-accept": "^2.2.4", + "file-selector": "^2.1.0", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">= 10.13" + }, + "peerDependencies": { + "react": ">= 16.8 || 18.0.0" + } + }, + "node_modules/react-imask": { + "version": "7.6.1", + "resolved": "https://registry.npmjs.org/react-imask/-/react-imask-7.6.1.tgz", + "integrity": "sha512-vLNfzcCz62Yzx/GRGh5tiCph9Gbh2cZu+Tz8OiO5it2eNuuhpA0DWhhSlOtVtSJ80+Bx+vFK5De8eQ9AmbkXzA==", + "license": "MIT", + "peer": true, + "dependencies": { + "imask": "^7.6.1", + "prop-types": "^15.8.1" + }, + "engines": { + "npm": ">=4.0.0" + }, + "peerDependencies": { + "react": ">=0.14.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT", + "peer": true + }, + "node_modules/react-textarea-autosize": { + "version": "8.5.9", + "resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.9.tgz", + "integrity": "sha512-U1DGlIQN5AwgjTyOEnI1oCcMuEr1pv1qOtklB2l4nyMGbHzWrI0eFsYK0zos2YWqAolJyG0IWJaqWmWj5ETh0A==", + "license": "MIT", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.20.13", + "use-composed-ref": "^1.3.0", + "use-latest": "^1.2.1" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/react-transition-group": { + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", + "peer": true, + "dependencies": { + "@babel/runtime": "^7.5.5", + "dom-helpers": "^5.0.1", + "loose-envify": "^1.4.0", + "prop-types": "^15.6.2" + }, + "peerDependencies": { + "react": ">=16.6.0", + "react-dom": ">=16.6.0" + } + }, "node_modules/rolldown": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz", @@ -1461,9 +1802,7 @@ "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true, - "license": "0BSD", - "optional": true + "license": "0BSD" }, "node_modules/typescript": { "version": "6.0.3", @@ -1486,6 +1825,54 @@ "dev": true, "license": "MIT" }, + "node_modules/use-composed-ref": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.4.0.tgz", + "integrity": "sha512-djviaxuOOh7wkj0paeO1Q/4wMZ8Zrnag5H6yBvzN7AKKe8beOaED9SF5/ByLqsku8NP4zQqsvM2u3ew/tJK8/w==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-isomorphic-layout-effect": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.1.tgz", + "integrity": "sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==", + "license": "MIT", + "peer": true, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-latest": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/use-latest/-/use-latest-1.3.0.tgz", + "integrity": "sha512-mhg3xdm9NaM8q+gLT8KryJPnRFOz1/5XPBhmDEVZK1webPzDjrPk7f/mbpeLqTgB9msytYWANxgALOCJKnLvcQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "use-isomorphic-layout-effect": "^1.1.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/use-sync-external-store": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", diff --git a/package.json b/package.json index 2ed561c..b35ac5e 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,8 @@ "preview": "vite preview" }, "dependencies": { + "@consta/icons": "^1.7.1", + "@consta/uikit": "^5.33.2", "@xyflow/react": "^12.11.2", "react": "^19.2.7", "react-dom": "^19.2.7" diff --git a/palette.css b/palette.css new file mode 100644 index 0000000..52f85ce --- /dev/null +++ b/palette.css @@ -0,0 +1,109 @@ +/* + Извлечено со скриншотов брендбука/стайлгайда. + Угол градиента в источнике указан как «60%» — трактован как 60deg + (стандартная запись угла в CSS linear-gradient). Проверьте по оригиналу, + если это принципиально. +*/ + +:root { + /* ============================================================ + ОСНОВНЫЕ ГРАДИЕНТЫ (синие) — для инфоблоков, диаграмм, блок-схем + ============================================================ */ + --gradient-navy-start: rgb(0, 75, 158); + --gradient-navy-end: rgb(0, 164, 230); + --gradient-navy: linear-gradient(60deg, var(--gradient-navy-start), var(--gradient-navy-end)); + + --gradient-azure-start: rgb(36, 139, 224); + --gradient-azure-end: rgb(65, 205, 255); + --gradient-azure: linear-gradient(60deg, var(--gradient-azure-start), var(--gradient-azure-end)); + + --gradient-sky-start: rgb(94, 179, 236); + --gradient-sky-end: rgb(173, 214, 247); + --gradient-sky: linear-gradient(60deg, var(--gradient-sky-start), var(--gradient-sky-end)); + + --gradient-teal-dark-start: rgb(60, 129, 160); + --gradient-teal-dark-end: rgb(151, 195, 219); + --gradient-teal-dark: linear-gradient(60deg, var(--gradient-teal-dark-start), var(--gradient-teal-dark-end)); + + --gradient-teal-light-start: rgb(102, 190, 218); + --gradient-teal-light-end: rgb(161, 226, 233); + --gradient-teal-light: linear-gradient(60deg, var(--gradient-teal-light-start), var(--gradient-teal-light-end)); + + --gradient-navy-dark-start: rgb(0, 33, 92); + --gradient-navy-dark-end: rgb(0, 101, 170); + --gradient-navy-dark: linear-gradient(60deg, var(--gradient-navy-dark-start), var(--gradient-navy-dark-end)); + + --gradient-ice-start: rgb(206, 234, 255); + --gradient-ice-end: rgb(241, 249, 255); + --gradient-ice: linear-gradient(60deg, var(--gradient-ice-start), var(--gradient-ice-end)); + + --gradient-frost-start: rgb(215, 229, 237); + --gradient-frost-end: rgb(243, 245, 247); + --gradient-frost: linear-gradient(60deg, var(--gradient-frost-start), var(--gradient-frost-end)); + + /* ============================================================ + ОСНОВНАЯ ПАЛИТРА — для диаграмм, блок-схем, смысловых выделений + ============================================================ */ + --gradient-purple-start: rgb(161, 44, 126); + --gradient-purple-end: rgb(191, 51, 168); + --gradient-purple: linear-gradient(60deg, var(--gradient-purple-start), var(--gradient-purple-end)); + + --gradient-red-start: rgb(225, 48, 66); + --gradient-red-end: rgb(241, 103, 117); + --gradient-red: linear-gradient(60deg, var(--gradient-red-start), var(--gradient-red-end)); + + --gradient-orange-start: rgb(255, 142, 88); + --gradient-orange-end: rgb(254, 180, 106); + --gradient-orange: linear-gradient(60deg, var(--gradient-orange-start), var(--gradient-orange-end)); + + --gradient-olive-start: rgb(187, 189, 57); + --gradient-olive-end: rgb(197, 231, 103); + --gradient-olive: linear-gradient(60deg, var(--gradient-olive-start), var(--gradient-olive-end)); + + --gradient-green-start: rgb(44, 181, 135); + --gradient-green-end: rgb(57, 224, 137); + --gradient-green: linear-gradient(60deg, var(--gradient-green-start), var(--gradient-green-end)); + + --gradient-green-dark-start: rgb(25, 111, 82); + --gradient-green-dark-end: rgb(38, 160, 119); + --gradient-green-dark: linear-gradient(60deg, var(--gradient-green-dark-start), var(--gradient-green-dark-end)); + + --gradient-blue-start: rgb(7, 144, 203); + --gradient-blue-end: rgb(17, 203, 217); + --gradient-blue: linear-gradient(60deg, var(--gradient-blue-start), var(--gradient-blue-end)); + + --gradient-cyan-start: rgb(27, 211, 247); + --gradient-cyan-end: rgb(101, 240, 238); + --gradient-cyan: linear-gradient(60deg, var(--gradient-cyan-start), var(--gradient-cyan-end)); + + /* ============================================================ + ДОПОЛНИТЕЛЬНЫЕ ГРАДИЕНТЫ — для диаграмм, блок-схем, смысловых выделений + ============================================================ */ + --gradient-violet-start: rgb(138, 92, 231); + --gradient-violet-end: rgb(148, 57, 227); + --gradient-violet: linear-gradient(60deg, var(--gradient-violet-start), var(--gradient-violet-end)); + + --gradient-lavender-start: rgb(168, 143, 248); + --gradient-lavender-end: rgb(132, 159, 246); + --gradient-lavender: linear-gradient(60deg, var(--gradient-lavender-start), var(--gradient-lavender-end)); + + --gradient-pink-start: rgb(241, 141, 206); + --gradient-pink-end: rgb(222, 146, 232); + --gradient-pink: linear-gradient(60deg, var(--gradient-pink-start), var(--gradient-pink-end)); + + /* ============================================================ + ДОПОЛНИТЕЛЬНЫЕ ЦВЕТА — для мелкой графики, линий (одиночные акценты) + Соответствуют по цветовому тону основной палитре и доп. градиентам + ============================================================ */ + --accent-purple: rgb(181, 48, 154); + --accent-red: rgb(236, 86, 101); + --accent-orange: rgb(255, 171, 102); + --accent-olive: rgb(194, 220, 91); + --accent-green: rgb(50, 202, 136); + --accent-green-dark: rgb(34, 146, 109); + --accent-blue: rgb(14, 186, 213); + --accent-cyan: rgb(78, 231, 244); + --accent-violet: rgb(145, 82, 230); + --accent-lavender: rgb(157, 154, 247); + --accent-pink: rgb(232, 143, 219); +} diff --git a/src/App.tsx b/src/App.tsx index e852740..04ef689 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,4 +1,5 @@ import { useCallback, useEffect, useState } from 'react'; +import { Theme, presetGpnDefault } from '@consta/uikit/Theme'; import { DiagramEditor } from './DiagramEditor'; import { createDevAdapter } from './host/devAdapter'; import { createBitrixAdapter } from './host/bitrixAdapter'; @@ -83,7 +84,11 @@ function App() { return

Загрузка диаграммы…

; } - return ; + return ( + + + + ); } export default App; diff --git a/src/DiagramEditor.tsx b/src/DiagramEditor.tsx index 22f8829..cad2177 100644 --- a/src/DiagramEditor.tsx +++ b/src/DiagramEditor.tsx @@ -25,6 +25,9 @@ import { type EdgeMouseHandler, } from '@xyflow/react'; import '@xyflow/react/dist/style.css'; +import { Button } from '@consta/uikit/Button'; +import { ChoiceGroup } from '@consta/uikit/ChoiceGroup'; +import { Breadcrumbs } from '@consta/uikit/Breadcrumbs'; import { nodeTypes, NodesWithChildrenContext, ModeContext } from './nodes'; import { NodeInspector } from './NodeInspector'; import { EdgeInspector } from './EdgeInspector'; @@ -52,6 +55,13 @@ const NODE_KINDS: { kind: NodeKind; label: string }[] = [ { kind: 'inclusiveGateway', label: '+ Вкл. шлюз' }, ]; +// Stable references — ChoiceGroup's controlled `value` is compared against +// entries in `items` by identity, so this can't be recreated on every render. +const MODE_ITEMS: { label: string; mode: 'edit' | 'view' }[] = [ + { label: 'Просмотр', mode: 'view' }, + { label: 'Редактирование', mode: 'edit' }, +]; + const DEFAULT_NODE_SIZE: Record = { task: { width: 140, height: 50 }, startEvent: { width: 48, height: 48 }, @@ -634,38 +644,33 @@ function DiagramCanvas({ initialValue, onChange }: DiagramEditorProps) { {mode === 'edit' && } - - + item.mode === mode) ?? null} + onChange={(item) => setMode(item.mode)} + /> {mode === 'edit' && ( {NODE_KINDS.map(({ kind, label }) => ( - + - {breadcrumbPath.map((node, index) => ( - - {' / '} - - - ))} + goToLevel(null) : undefined }, + ...breadcrumbPath.map((node, index) => ({ + label: (node.data as DiagramNodeData).label, + onClick: index === breadcrumbPath.length - 1 ? undefined : () => goToLevel(node.id), + })), + ]} + getItemOnClick={(item) => item.onClick} + /> diff --git a/src/EdgeInspector.tsx b/src/EdgeInspector.tsx index c9f0ec3..0fa09e8 100644 --- a/src/EdgeInspector.tsx +++ b/src/EdgeInspector.tsx @@ -1,3 +1,7 @@ +import { Button } from '@consta/uikit/Button'; +import { TextField } from '@consta/uikit/TextField'; +import { Text } from '@consta/uikit/Text'; + interface EdgeInspectorProps { edgeId: string; label: string; @@ -18,29 +22,24 @@ export function EdgeInspector({ return (
- Связь - {edgeId} + + Связь + + + {edgeId} +
- +
- - +
- + onChange(value ?? '')} />
); } diff --git a/src/NodeInspector.tsx b/src/NodeInspector.tsx index be47d84..77dbb4d 100644 --- a/src/NodeInspector.tsx +++ b/src/NodeInspector.tsx @@ -1,6 +1,28 @@ +import { useRef, useState, type RefObject } from 'react'; +import { Button } from '@consta/uikit/Button'; +import { TextField } from '@consta/uikit/TextField'; +import { ColorControl, ColorPicker, hexModel } from '@consta/uikit/ColorPicker'; +import { Text } from '@consta/uikit/Text'; import { DEFAULT_NODE_COLOR } from './nodes'; import type { DiagramNodeData, NodeKind } from './types'; +// "Дополнительные цвета" from palette.css — the section the palette itself +// marks as meant for single-color accents (as opposed to the gradients used +// for shape defaults, which a flat-hex picker can't represent). +const NODE_COLOR_PRESETS = [ + '#B5309A', + '#EC5665', + '#FFAB66', + '#C2DC5B', + '#32CA88', + '#22926D', + '#0EBAD5', + '#4EE7F4', + '#9152E6', + '#9D9AF7', + '#E88FDB', +]; + const TYPE_LABELS: Record = { task: 'Задача', startEvent: 'Начальное событие', @@ -38,17 +60,29 @@ export function NodeInspector({ onBringToFront, onSendToBack, }: NodeInspectorProps) { + const [colorPickerOpen, setColorPickerOpen] = useState(false); + // Consta's ref props still use the pre-React-19 non-nullable RefObject shape. + const colorMarkerRef = useRef(null) as RefObject; + if (mode === 'view') { const hasMeta = Boolean(data.responsible || data.duration); return (
- {TYPE_LABELS[nodeType]} + + {TYPE_LABELS[nodeType]} +
-

{data.label}

+ + {data.label} + - {data.description &&

{data.description}

} + {data.description && ( + + {data.description} + + )} {hasMeta && (
@@ -68,9 +102,12 @@ export function NodeInspector({ )} {childCount > 0 && ( - +
); @@ -79,81 +116,88 @@ export function NodeInspector({ return (
- {TYPE_LABELS[nodeType]} - {nodeId} + + {TYPE_LABELS[nodeType]} + + + {nodeId} +
- - +
- - +
- + {colorPickerOpen && ( + onChange({ color: value })} + anchorRef={colorMarkerRef} + open={colorPickerOpen} + onOpen={setColorPickerOpen} + palette={NODE_COLOR_PRESETS} + paletteTitle="Пресеты" + /> + )} +
-