mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2025-06-07 08:56:58 +00:00
added theme manager
This commit is contained in:
parent
efc83c89aa
commit
ba9062dbcf
416
package-lock.json
generated
416
package-lock.json
generated
@ -41,6 +41,7 @@
|
|||||||
"@tiptap/starter-kit": "^2.5.9",
|
"@tiptap/starter-kit": "^2.5.9",
|
||||||
"@transistorsoft/capacitor-background-fetch": "^6.0.1",
|
"@transistorsoft/capacitor-background-fetch": "^6.0.1",
|
||||||
"@types/chrome": "^0.0.263",
|
"@types/chrome": "^0.0.263",
|
||||||
|
"@uiw/react-color": "^2.5.1",
|
||||||
"adm-zip": "^0.5.16",
|
"adm-zip": "^0.5.16",
|
||||||
"asmcrypto.js": "2.3.2",
|
"asmcrypto.js": "2.3.2",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
@ -5900,6 +5901,399 @@
|
|||||||
"url": "https://opencollective.com/typescript-eslint"
|
"url": "https://opencollective.com/typescript-eslint"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@uiw/color-convert": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/color-convert/-/color-convert-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-p+P8Ho0Z1AbUprES0hcLEDAaXbGH92TmjckkRQZ5S7HcyQ+9ZXlSsDFILjFbYu/okVjx5VG59T57Dx84lv9AWA==",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@uiw/react-color": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/react-color/-/react-color-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-u6Kj7rdhsMOls2KItpHLkG8WTghDS2jYBucLeOLLJXJDs25TuEBI9d1o939og8cUJtTwBrowWFFU63a1kGsciA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@uiw/color-convert": "2.5.1",
|
||||||
|
"@uiw/react-color-alpha": "2.5.1",
|
||||||
|
"@uiw/react-color-block": "2.5.1",
|
||||||
|
"@uiw/react-color-chrome": "2.5.1",
|
||||||
|
"@uiw/react-color-circle": "2.5.1",
|
||||||
|
"@uiw/react-color-colorful": "2.5.1",
|
||||||
|
"@uiw/react-color-compact": "2.5.1",
|
||||||
|
"@uiw/react-color-editable-input": "2.5.1",
|
||||||
|
"@uiw/react-color-editable-input-hsla": "2.5.1",
|
||||||
|
"@uiw/react-color-editable-input-rgba": "2.5.1",
|
||||||
|
"@uiw/react-color-github": "2.5.1",
|
||||||
|
"@uiw/react-color-hue": "2.5.1",
|
||||||
|
"@uiw/react-color-material": "2.5.1",
|
||||||
|
"@uiw/react-color-name": "2.5.1",
|
||||||
|
"@uiw/react-color-saturation": "2.5.1",
|
||||||
|
"@uiw/react-color-shade-slider": "2.5.1",
|
||||||
|
"@uiw/react-color-sketch": "2.5.1",
|
||||||
|
"@uiw/react-color-slider": "2.5.1",
|
||||||
|
"@uiw/react-color-swatch": "2.5.1",
|
||||||
|
"@uiw/react-color-wheel": "2.5.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0",
|
||||||
|
"react": ">=16.9.0",
|
||||||
|
"react-dom": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@uiw/react-color-alpha": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/react-color-alpha/-/react-color-alpha-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-hPsIgsnuOQrqinXt3Gt+87fHudbUvvPW+TpvRY0HS9v4ptFu5UsCc/7DPTVKTaL+p+0oaA6eTbziLzPLRLzgsQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@uiw/color-convert": "2.5.1",
|
||||||
|
"@uiw/react-drag-event-interactive": "2.5.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0",
|
||||||
|
"react": ">=16.9.0",
|
||||||
|
"react-dom": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@uiw/react-color-block": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/react-color-block/-/react-color-block-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-qvubiV0z0P3OxpNt6o1UQ3CVsjVBY1/n/oz6Gzzxx9YPqSClI04AtFjwOQxF7M17SYqXv+88y77gfEfPIqk5+A==",
|
||||||
|
"dependencies": {
|
||||||
|
"@uiw/color-convert": "2.5.1",
|
||||||
|
"@uiw/react-color-editable-input": "2.5.1",
|
||||||
|
"@uiw/react-color-swatch": "2.5.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0",
|
||||||
|
"react": ">=16.9.0",
|
||||||
|
"react-dom": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@uiw/react-color-chrome": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/react-color-chrome/-/react-color-chrome-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-m/CyRaWgmkW5aQTQ8AZwyvopYm+bhvX06uS+ezQjXDYDtjLvq7RbM0JLLNIOyMXke964R58fhoX4G06ZWd8ycA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@uiw/color-convert": "2.5.1",
|
||||||
|
"@uiw/react-color-alpha": "2.5.1",
|
||||||
|
"@uiw/react-color-editable-input": "2.5.1",
|
||||||
|
"@uiw/react-color-editable-input-hsla": "2.5.1",
|
||||||
|
"@uiw/react-color-editable-input-rgba": "2.5.1",
|
||||||
|
"@uiw/react-color-github": "2.5.1",
|
||||||
|
"@uiw/react-color-hue": "2.5.1",
|
||||||
|
"@uiw/react-color-saturation": "2.5.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0",
|
||||||
|
"react": ">=16.9.0",
|
||||||
|
"react-dom": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@uiw/react-color-circle": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/react-color-circle/-/react-color-circle-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-+8zb/Ork1Q5f2bq0jN+GF7OyqY+2ZDYGrdZovN3EBZLMmERbg6TM2+1gTweeFsdiEM/gpteupJpwKpO1aBCocg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@uiw/color-convert": "2.5.1",
|
||||||
|
"@uiw/react-color-swatch": "2.5.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0",
|
||||||
|
"react": ">=16.9.0",
|
||||||
|
"react-dom": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@uiw/react-color-colorful": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/react-color-colorful/-/react-color-colorful-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-Y/8Y2Kman6IZQpgs4tPTGPuTNr3fJIJxf4f13jll6xuaOsVZeDq9q+DlMErggL+5ICtaBr8gG+w68nCiY+QqKg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@uiw/color-convert": "2.5.1",
|
||||||
|
"@uiw/react-color-alpha": "2.5.1",
|
||||||
|
"@uiw/react-color-hue": "2.5.1",
|
||||||
|
"@uiw/react-color-saturation": "2.5.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0",
|
||||||
|
"react": ">=16.9.0",
|
||||||
|
"react-dom": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@uiw/react-color-compact": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/react-color-compact/-/react-color-compact-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-5jHJcXEkjMwcghzCgSBU2rPMVjuuaJ7B6IxypNkafRQ4FkW/6bP9WpPkzcNXCZ/gPvSJ1OMQ+Y600mdO78qG5Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"@uiw/color-convert": "2.5.1",
|
||||||
|
"@uiw/react-color-editable-input": "2.5.1",
|
||||||
|
"@uiw/react-color-editable-input-rgba": "2.5.1",
|
||||||
|
"@uiw/react-color-swatch": "2.5.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0",
|
||||||
|
"react": ">=16.9.0",
|
||||||
|
"react-dom": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@uiw/react-color-editable-input": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/react-color-editable-input/-/react-color-editable-input-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-0kr5vQJGPln8LObXwfI2YLiHFz2DW3Atgi51JXlrZUyyaVujXRgMTAc1fz/1RQR6cU2A4bweFaCQljcTsv+Cdg==",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0",
|
||||||
|
"react": ">=16.9.0",
|
||||||
|
"react-dom": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@uiw/react-color-editable-input-hsla": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/react-color-editable-input-hsla/-/react-color-editable-input-hsla-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-gmnXB6JrYFAd8VN/EfNDJaTdkFHAnUxjzcsQjQyOEr046jDjWgEc/5o2uE1LwIvoJNg9Lo6LYsr37LnFWwsiLw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@uiw/color-convert": "2.5.1",
|
||||||
|
"@uiw/react-color-editable-input-rgba": "2.5.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0",
|
||||||
|
"react": ">=16.9.0",
|
||||||
|
"react-dom": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@uiw/react-color-editable-input-rgba": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/react-color-editable-input-rgba/-/react-color-editable-input-rgba-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-rk6OxL9lTdRI45aNe3GbUghvaELk4knkEf0gvF/mPHxoeE+nNphSrO5gHm3HhoDOgaplp81VP3q4gUwcdjBzvw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@uiw/color-convert": "2.5.1",
|
||||||
|
"@uiw/react-color-editable-input": "2.5.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0",
|
||||||
|
"react": ">=16.9.0",
|
||||||
|
"react-dom": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@uiw/react-color-github": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/react-color-github/-/react-color-github-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-t05rIy2ifReiVnjv3x+IVlJH7wvwtZugMeouDa/1Y7jIGZswO0zw3zMxz7qfHrzf5NVYWjmEF8QCj85ngv9brg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@uiw/color-convert": "2.5.1",
|
||||||
|
"@uiw/react-color-swatch": "2.5.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0",
|
||||||
|
"react": ">=16.9.0",
|
||||||
|
"react-dom": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@uiw/react-color-hue": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/react-color-hue/-/react-color-hue-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-o7mjZhm+U4gHxaBXFxjPINeE3jWfiZAl7RUFqwn4PDZC8wvhU5hEKgJUvcXzErYro0ZYrE1fC/wUHRpI+vcEBg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@uiw/color-convert": "2.5.1",
|
||||||
|
"@uiw/react-color-alpha": "2.5.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0",
|
||||||
|
"react": ">=16.9.0",
|
||||||
|
"react-dom": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@uiw/react-color-material": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/react-color-material/-/react-color-material-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-iPB4YfKVTNO1lSIQ16DMdDurDKvGTjv6Qwi/nq47yE3nnhB0YbOFwb/IZbWBS1sCTPx1an7dM2IZ+hYoYcjrXg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@uiw/color-convert": "2.5.1",
|
||||||
|
"@uiw/react-color-editable-input": "2.5.1",
|
||||||
|
"@uiw/react-color-editable-input-rgba": "2.5.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0",
|
||||||
|
"react": ">=16.9.0",
|
||||||
|
"react-dom": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@uiw/react-color-name": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/react-color-name/-/react-color-name-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-JFb6DFz9kF2jI42MS/vtXZu1XzIrzcSIOqCwVkYWCQnSxOM9h+vd4pv2Yi1oy7IPgaadXUDkrGQSAvEkXU593Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"colors-named": "^1.0.1",
|
||||||
|
"colors-named-hex": "^1.0.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@uiw/react-color-saturation": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/react-color-saturation/-/react-color-saturation-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-mQ6eGmn6dUXfScQrb5tP0TBGCpZWzrQuYOAiwK9u31IJaxFwD1NNAzkiienWe4MQkA5zmgz7Ol6FEdLN8K+vGw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@uiw/color-convert": "2.5.1",
|
||||||
|
"@uiw/react-drag-event-interactive": "2.5.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0",
|
||||||
|
"react": ">=16.9.0",
|
||||||
|
"react-dom": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@uiw/react-color-shade-slider": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/react-color-shade-slider/-/react-color-shade-slider-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-hrscAmqmy/Od/usUPETaEuvsNRhUGvNArl73d7HK6e6FjbRFPDBq40LkvjETe8BJMbxrBXTMo6dK7DO08lYq9g==",
|
||||||
|
"dependencies": {
|
||||||
|
"@uiw/color-convert": "2.5.1",
|
||||||
|
"@uiw/react-color-alpha": "2.5.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0",
|
||||||
|
"react": ">=16.9.0",
|
||||||
|
"react-dom": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@uiw/react-color-sketch": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/react-color-sketch/-/react-color-sketch-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-eQgAnlSZvqoTt6frZa/j+tFdaIBEFneIdxEUfidD8hwvyu5OR/WLHnDy/4fYAxhehDp9Ej8eS3ZsCgPACBMOtA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@uiw/color-convert": "2.5.1",
|
||||||
|
"@uiw/react-color-alpha": "2.5.1",
|
||||||
|
"@uiw/react-color-editable-input": "2.5.1",
|
||||||
|
"@uiw/react-color-editable-input-rgba": "2.5.1",
|
||||||
|
"@uiw/react-color-hue": "2.5.1",
|
||||||
|
"@uiw/react-color-saturation": "2.5.1",
|
||||||
|
"@uiw/react-color-swatch": "2.5.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0",
|
||||||
|
"react": ">=16.9.0",
|
||||||
|
"react-dom": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@uiw/react-color-slider": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/react-color-slider/-/react-color-slider-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-2yluI0Akp6UMXTeAJ4CEjL8flhIFpn3xUPsFXbQmBSzMYJygleVFmwhMye8LSA2PCe3UdaqA2cWXxWsTL0FbIg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@uiw/color-convert": "2.5.1",
|
||||||
|
"@uiw/react-color-alpha": "2.5.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0",
|
||||||
|
"react": ">=16.9.0",
|
||||||
|
"react-dom": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@uiw/react-color-swatch": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/react-color-swatch/-/react-color-swatch-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-EQ7UEzxdohfsdpXmcEWNmK/uiznZovEKo6+j3OLrSU5pZGO7pxjR9sQMlscikvd8Mu1Mm3U0E6bJseo2acD4Lg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@uiw/color-convert": "2.5.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0",
|
||||||
|
"react": ">=16.9.0",
|
||||||
|
"react-dom": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@uiw/react-color-wheel": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/react-color-wheel/-/react-color-wheel-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-e3tDwDoC2T7zTapRRm/QxcOJ7IWJwNCoxZ/f97RL1Ib3gAN/k67H1bkR9TK7euRCUxGy031guxTgdKO9v19XFg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@uiw/color-convert": "2.5.1",
|
||||||
|
"@uiw/react-drag-event-interactive": "2.5.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0",
|
||||||
|
"react": ">=16.9.0",
|
||||||
|
"react-dom": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@uiw/react-drag-event-interactive": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@uiw/react-drag-event-interactive/-/react-drag-event-interactive-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-GNxhxk5L4O5Gpi20A/BG5sO0GNBNwtNWJidJsJu3pgHUBErN4rhqTDXXu3BQTz5C8yOG5D02Y6Zq/6yu6ckImw==",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@babel/runtime": ">=7.19.0",
|
||||||
|
"react": ">=16.9.0",
|
||||||
|
"react-dom": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@ungap/structured-clone": {
|
"node_modules/@ungap/structured-clone": {
|
||||||
"version": "1.2.0",
|
"version": "1.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
|
||||||
@ -7774,6 +8168,28 @@
|
|||||||
"color-support": "bin.js"
|
"color-support": "bin.js"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/colors-named": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/colors-named/-/colors-named-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-2ANq2r393PV9njYUD66UdfBcxR1slMqRA3QRTWgCx49JoCJ+kOhyfbQYxKJbPZQIhZUcNjVOs5AlyY1WwXec3w==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/colors-named-hex": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/colors-named-hex/-/colors-named-hex-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-k6kq1e1pUCQvSVwIaGFq2l0LrkAPQZWyeuZn1Z8nOiYSEZiKoFj4qx690h2Kd34DFl9Me0gKS6MUwAMBJj8nuA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://jaywcjlove.github.io/#/sponsor"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/combined-stream": {
|
"node_modules/combined-stream": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
|
@ -46,6 +46,7 @@
|
|||||||
"@tiptap/starter-kit": "^2.5.9",
|
"@tiptap/starter-kit": "^2.5.9",
|
||||||
"@transistorsoft/capacitor-background-fetch": "^6.0.1",
|
"@transistorsoft/capacitor-background-fetch": "^6.0.1",
|
||||||
"@types/chrome": "^0.0.263",
|
"@types/chrome": "^0.0.263",
|
||||||
|
"@uiw/react-color": "^2.5.1",
|
||||||
"adm-zip": "^0.5.16",
|
"adm-zip": "^0.5.16",
|
||||||
"asmcrypto.js": "2.3.2",
|
"asmcrypto.js": "2.3.2",
|
||||||
"axios": "^1.7.7",
|
"axios": "^1.7.7",
|
||||||
|
@ -48,7 +48,7 @@ export const Wallets = ({ setExtState, setRawWallet, rawWallet }) => {
|
|||||||
const [password, setPassword] = useState('');
|
const [password, setPassword] = useState('');
|
||||||
const [isOpenSeedModal, setIsOpenSeedModal] = useState(false);
|
const [isOpenSeedModal, setIsOpenSeedModal] = useState(false);
|
||||||
const [isLoadingEncryptSeed, setIsLoadingEncryptSeed] = useState(false);
|
const [isLoadingEncryptSeed, setIsLoadingEncryptSeed] = useState(false);
|
||||||
|
const theme = useTheme();
|
||||||
const { isShow, onCancel, onOk, show } = useModal();
|
const { isShow, onCancel, onOk, show } = useModal();
|
||||||
|
|
||||||
const { getRootProps, getInputProps } = useDropzone({
|
const { getRootProps, getInputProps } = useDropzone({
|
||||||
@ -216,7 +216,7 @@ export const Wallets = ({ setExtState, setRawWallet, rawWallet }) => {
|
|||||||
maxHeight: '60vh',
|
maxHeight: '60vh',
|
||||||
overflowY: 'auto',
|
overflowY: 'auto',
|
||||||
overflowX: 'hidden',
|
overflowX: 'hidden',
|
||||||
backgroundColor: 'rgb(30 30 32 / 70%)',
|
backgroundColor: theme.palette.background.paper,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{wallets?.map((wallet, idx) => {
|
{wallets?.map((wallet, idx) => {
|
||||||
@ -429,7 +429,7 @@ const WalletItem = ({ wallet, updateWalletItem, idx, setSelectedWallet }) => {
|
|||||||
bgcolor: theme.palette.background.default,
|
bgcolor: theme.palette.background.default,
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
backgroundColor: theme.palette.background.paper,
|
backgroundColor: theme.palette.action.hover,
|
||||||
transform: 'scale(1.01)',
|
transform: 'scale(1.01)',
|
||||||
},
|
},
|
||||||
transition: 'all 0.1s ease-in-out',
|
transition: 'all 0.1s ease-in-out',
|
||||||
|
@ -110,7 +110,6 @@ export const BuyQortInformation = ({ balance }) => {
|
|||||||
</Typography>
|
</Typography>
|
||||||
<List
|
<List
|
||||||
sx={{
|
sx={{
|
||||||
bgcolor: theme.palette.background.default,
|
|
||||||
maxWidth: 360,
|
maxWidth: 360,
|
||||||
width: '100%',
|
width: '100%',
|
||||||
}}
|
}}
|
||||||
@ -118,21 +117,13 @@ export const BuyQortInformation = ({ balance }) => {
|
|||||||
>
|
>
|
||||||
<ListItem disablePadding>
|
<ListItem disablePadding>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<RadioButtonCheckedIcon
|
<RadioButtonCheckedIcon />
|
||||||
sx={{
|
|
||||||
color: theme.palette.primary.dark,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText primary="Create transactions on the Qortal Blockchain" />
|
<ListItemText primary="Create transactions on the Qortal Blockchain" />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
<ListItem disablePadding>
|
<ListItem disablePadding>
|
||||||
<ListItemIcon>
|
<ListItemIcon>
|
||||||
<RadioButtonCheckedIcon
|
<RadioButtonCheckedIcon />
|
||||||
sx={{
|
|
||||||
color: theme.palette.primary.dark,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</ListItemIcon>
|
</ListItemIcon>
|
||||||
<ListItemText primary="Having at least 4 QORT in your balance allows you to send chat messages at near instant speed." />
|
<ListItemText primary="Having at least 4 QORT in your balance allows you to send chat messages at near instant speed." />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
|
@ -48,6 +48,7 @@ import { useVirtualizer } from '@tanstack/react-virtual';
|
|||||||
import ErrorBoundary from '../../common/ErrorBoundary';
|
import ErrorBoundary from '../../common/ErrorBoundary';
|
||||||
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
||||||
import ExpandLessIcon from '@mui/icons-material/ExpandLess';
|
import ExpandLessIcon from '@mui/icons-material/ExpandLess';
|
||||||
|
import { getFee } from '../../background';
|
||||||
export const requestQueuePromos = new RequestQueueWithPromise(20);
|
export const requestQueuePromos = new RequestQueueWithPromise(20);
|
||||||
|
|
||||||
export function utf8ToBase64(inputString: string): string {
|
export function utf8ToBase64(inputString: string): string {
|
||||||
|
@ -18,6 +18,7 @@ import { TransitionProps } from '@mui/material/transitions';
|
|||||||
import { Box, FormControlLabel, Switch, styled, useTheme } from '@mui/material';
|
import { Box, FormControlLabel, Switch, styled, useTheme } from '@mui/material';
|
||||||
import { enabledDevModeAtom } from '../../atoms/global';
|
import { enabledDevModeAtom } from '../../atoms/global';
|
||||||
import { useRecoilState } from 'recoil';
|
import { useRecoilState } from 'recoil';
|
||||||
|
import ThemeManager from '../Theme/ThemeManager';
|
||||||
|
|
||||||
const LocalNodeSwitch = styled(Switch)(({ theme }) => ({
|
const LocalNodeSwitch = styled(Switch)(({ theme }) => ({
|
||||||
padding: 8,
|
padding: 8,
|
||||||
@ -185,6 +186,7 @@ export const Settings = ({ address, open, setOpen }) => {
|
|||||||
label="Enable dev mode"
|
label="Enable dev mode"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
<ThemeManager />
|
||||||
</Box>
|
</Box>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</Fragment>
|
</Fragment>
|
||||||
|
@ -6,57 +6,129 @@ import {
|
|||||||
useEffect,
|
useEffect,
|
||||||
useCallback,
|
useCallback,
|
||||||
} from 'react';
|
} from 'react';
|
||||||
import { ThemeProvider as MuiThemeProvider } from '@mui/material/styles';
|
import {
|
||||||
import { darkTheme } from '../../styles/theme-dark';
|
ThemeProvider as MuiThemeProvider,
|
||||||
import { lightTheme } from '../../styles/theme-light';
|
createTheme,
|
||||||
|
} from '@mui/material/styles';
|
||||||
|
import { lightThemeOptions } from '../../styles/theme-light';
|
||||||
|
import { darkThemeOptions } from '../../styles/theme-dark';
|
||||||
|
|
||||||
|
const defaultTheme = {
|
||||||
|
id: 'default',
|
||||||
|
name: 'Default Theme',
|
||||||
|
light: lightThemeOptions.palette,
|
||||||
|
dark: darkThemeOptions.palette,
|
||||||
|
};
|
||||||
|
|
||||||
const ThemeContext = createContext({
|
const ThemeContext = createContext({
|
||||||
themeMode: 'light',
|
themeMode: 'light',
|
||||||
toggleTheme: () => {},
|
toggleTheme: () => {},
|
||||||
|
userThemes: [defaultTheme],
|
||||||
|
addUserTheme: (themes) => {},
|
||||||
|
setUserTheme: (theme) => {},
|
||||||
|
currentThemeId: 'default',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const ThemeProvider = ({ children }: { children: React.ReactNode }) => {
|
export const ThemeProvider = ({ children }) => {
|
||||||
const [themeMode, setThemeMode] = useState('light');
|
const [themeMode, setThemeMode] = useState('light');
|
||||||
|
const [userThemes, setUserThemes] = useState([defaultTheme]);
|
||||||
|
const [currentThemeId, setCurrentThemeId] = useState('default');
|
||||||
|
|
||||||
const theme = useMemo(
|
const currentTheme =
|
||||||
() => (themeMode === 'light' ? lightTheme : darkTheme),
|
userThemes.find((theme) => theme.id === currentThemeId) || defaultTheme;
|
||||||
[themeMode]
|
|
||||||
);
|
const muiTheme = useMemo(() => {
|
||||||
|
if (themeMode === 'light') {
|
||||||
|
return createTheme({
|
||||||
|
...lightThemeOptions,
|
||||||
|
palette: {
|
||||||
|
...currentTheme.light,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return createTheme({
|
||||||
|
...lightThemeOptions,
|
||||||
|
palette: {
|
||||||
|
...currentTheme.dark,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [themeMode, currentTheme]);
|
||||||
|
|
||||||
|
const saveSettings = (
|
||||||
|
themes = userThemes,
|
||||||
|
mode = themeMode,
|
||||||
|
themeId = currentThemeId
|
||||||
|
) => {
|
||||||
|
localStorage.setItem(
|
||||||
|
'saved_ui_theme',
|
||||||
|
JSON.stringify({
|
||||||
|
mode,
|
||||||
|
userThemes: themes,
|
||||||
|
currentThemeId: themeId,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const toggleTheme = () => {
|
const toggleTheme = () => {
|
||||||
setThemeMode((prevMode) => {
|
setThemeMode((prev) => {
|
||||||
const newMode = prevMode === 'light' ? 'dark' : 'light';
|
const newMode = prev === 'light' ? 'dark' : 'light';
|
||||||
|
saveSettings(userThemes, newMode, currentThemeId);
|
||||||
const themeProperties = {
|
|
||||||
mode: newMode,
|
|
||||||
};
|
|
||||||
|
|
||||||
localStorage.setItem('saved_ui_theme', JSON.stringify(themeProperties));
|
|
||||||
|
|
||||||
return newMode;
|
return newMode;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const getSavedTheme = useCallback(async () => {
|
const addUserTheme = (themes) => {
|
||||||
try {
|
setUserThemes(themes);
|
||||||
const themeProperties = JSON.parse(
|
saveSettings(themes);
|
||||||
localStorage.getItem(`saved_ui_theme`) || '{}'
|
};
|
||||||
);
|
|
||||||
|
|
||||||
const theme = themeProperties?.mode || 'light';
|
const setUserTheme = (theme) => {
|
||||||
setThemeMode(theme);
|
if (theme.id === 'default') {
|
||||||
} catch (error) {
|
setCurrentThemeId('default');
|
||||||
console.log('error', error);
|
saveSettings(userThemes, themeMode, 'default');
|
||||||
|
} else {
|
||||||
|
setCurrentThemeId(theme.id);
|
||||||
|
saveSettings(userThemes, themeMode, theme.id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const loadSettings = useCallback(() => {
|
||||||
|
const saved = localStorage.getItem('saved_ui_theme');
|
||||||
|
if (saved) {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(saved);
|
||||||
|
if (parsed.mode === 'light' || parsed.mode === 'dark')
|
||||||
|
setThemeMode(parsed.mode);
|
||||||
|
if (Array.isArray(parsed.userThemes)) {
|
||||||
|
const filteredThemes = parsed.userThemes.filter(
|
||||||
|
(theme) => theme.id !== 'default'
|
||||||
|
);
|
||||||
|
setUserThemes([defaultTheme, ...filteredThemes]);
|
||||||
|
}
|
||||||
|
if (parsed.currentThemeId) setCurrentThemeId(parsed.currentThemeId);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to parse saved_ui_theme:', error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
getSavedTheme();
|
loadSettings();
|
||||||
}, [getSavedTheme]);
|
}, [loadSettings]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ThemeContext.Provider value={{ themeMode, toggleTheme }}>
|
<ThemeContext.Provider
|
||||||
<MuiThemeProvider theme={theme}>{children}</MuiThemeProvider>
|
value={{
|
||||||
|
themeMode,
|
||||||
|
toggleTheme,
|
||||||
|
userThemes,
|
||||||
|
addUserTheme,
|
||||||
|
setUserTheme,
|
||||||
|
currentThemeId,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<MuiThemeProvider theme={muiTheme}>{children}</MuiThemeProvider>
|
||||||
</ThemeContext.Provider>
|
</ThemeContext.Provider>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
309
src/components/Theme/ThemeManager.tsx
Normal file
309
src/components/Theme/ThemeManager.tsx
Normal file
@ -0,0 +1,309 @@
|
|||||||
|
import React, { useState, useRef, useEffect } from 'react';
|
||||||
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
IconButton,
|
||||||
|
Typography,
|
||||||
|
Dialog,
|
||||||
|
DialogTitle,
|
||||||
|
DialogContent,
|
||||||
|
DialogActions,
|
||||||
|
List,
|
||||||
|
ListItemText,
|
||||||
|
ListItemSecondaryAction,
|
||||||
|
TextField,
|
||||||
|
Tabs,
|
||||||
|
Tab,
|
||||||
|
ListItemButton,
|
||||||
|
} from '@mui/material';
|
||||||
|
import { Sketch } from '@uiw/react-color';
|
||||||
|
import DeleteIcon from '@mui/icons-material/Delete';
|
||||||
|
import EditIcon from '@mui/icons-material/Edit';
|
||||||
|
import AddIcon from '@mui/icons-material/Add';
|
||||||
|
import CheckIcon from '@mui/icons-material/Check';
|
||||||
|
import { useThemeContext } from './ThemeContext';
|
||||||
|
import { darkThemeOptions } from '../../styles/theme-dark';
|
||||||
|
import { lightThemeOptions } from '../../styles/theme-light';
|
||||||
|
import ShortUniqueId from 'short-unique-id';
|
||||||
|
import { rgbStringToHsva, rgbaStringToHsva } from '@uiw/color-convert';
|
||||||
|
|
||||||
|
const uid = new ShortUniqueId({ length: 8 });
|
||||||
|
|
||||||
|
function detectColorFormat(color) {
|
||||||
|
if (typeof color !== 'string') return null;
|
||||||
|
if (color.startsWith('rgba')) return 'rgba';
|
||||||
|
if (color.startsWith('rgb')) return 'rgb';
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ThemeManager() {
|
||||||
|
const { userThemes, addUserTheme, setUserTheme, currentThemeId } =
|
||||||
|
useThemeContext();
|
||||||
|
const [openEditor, setOpenEditor] = useState(false);
|
||||||
|
const [themeDraft, setThemeDraft] = useState({
|
||||||
|
id: '',
|
||||||
|
name: '',
|
||||||
|
light: {},
|
||||||
|
dark: {},
|
||||||
|
});
|
||||||
|
const [currentTab, setCurrentTab] = useState('light');
|
||||||
|
const nameInputRef = useRef(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (openEditor && nameInputRef.current) {
|
||||||
|
nameInputRef.current.focus();
|
||||||
|
}
|
||||||
|
}, [openEditor]);
|
||||||
|
|
||||||
|
const handleAddTheme = () => {
|
||||||
|
setThemeDraft({
|
||||||
|
id: '',
|
||||||
|
name: '',
|
||||||
|
light: structuredClone(lightThemeOptions.palette),
|
||||||
|
dark: structuredClone(darkThemeOptions.palette),
|
||||||
|
});
|
||||||
|
setOpenEditor(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEditTheme = (themeId) => {
|
||||||
|
const themeToEdit = userThemes.find((theme) => theme.id === themeId);
|
||||||
|
if (themeToEdit) {
|
||||||
|
setThemeDraft({ ...themeToEdit });
|
||||||
|
setOpenEditor(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSaveTheme = () => {
|
||||||
|
if (themeDraft.id) {
|
||||||
|
const updatedThemes = [...userThemes];
|
||||||
|
const index = updatedThemes.findIndex(
|
||||||
|
(theme) => theme.id === themeDraft.id
|
||||||
|
);
|
||||||
|
if (index !== -1) {
|
||||||
|
updatedThemes[index] = themeDraft;
|
||||||
|
addUserTheme(updatedThemes);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const newTheme = { ...themeDraft, id: uid.rnd() };
|
||||||
|
const updatedThemes = [...userThemes, newTheme];
|
||||||
|
addUserTheme(updatedThemes);
|
||||||
|
setUserTheme(newTheme);
|
||||||
|
}
|
||||||
|
setOpenEditor(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDeleteTheme = (id) => {
|
||||||
|
const updatedThemes = userThemes.filter((theme) => theme.id !== id);
|
||||||
|
addUserTheme(updatedThemes);
|
||||||
|
|
||||||
|
if (id === currentThemeId) {
|
||||||
|
// Find the default theme object in the list
|
||||||
|
const defaultTheme = updatedThemes.find(
|
||||||
|
(theme) => theme.id === 'default'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (defaultTheme) {
|
||||||
|
setUserTheme(defaultTheme);
|
||||||
|
} else {
|
||||||
|
// Emergency fallback
|
||||||
|
setUserTheme({
|
||||||
|
light: lightThemeOptions,
|
||||||
|
dark: darkThemeOptions,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleApplyTheme = (theme) => {
|
||||||
|
setUserTheme(theme);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleColorChange = (mode, fieldPath, color) => {
|
||||||
|
setThemeDraft((prev) => {
|
||||||
|
const updated = { ...prev };
|
||||||
|
const paths = fieldPath.split('.');
|
||||||
|
updated[mode][paths[0]][paths[1]] = color.hex;
|
||||||
|
return updated;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderColorPicker = (mode, label, fieldPath, currentValue) => {
|
||||||
|
let color = currentValue || '#ffffff';
|
||||||
|
const format = detectColorFormat(currentValue);
|
||||||
|
if (format === 'rgba') {
|
||||||
|
color = rgbaStringToHsva(currentValue);
|
||||||
|
} else if (format === 'rgb') {
|
||||||
|
color = rgbStringToHsva(currentValue);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Box
|
||||||
|
mb={2}
|
||||||
|
{...{ 'data-color-mode': mode === 'dark' ? 'dark' : 'light' }}
|
||||||
|
>
|
||||||
|
<Typography variant="body2" mb={1}>
|
||||||
|
{label}
|
||||||
|
</Typography>
|
||||||
|
<Sketch
|
||||||
|
key={`${mode}-${fieldPath}`}
|
||||||
|
color={color}
|
||||||
|
onChange={(color) => handleColorChange(mode, fieldPath, color)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box p={2}>
|
||||||
|
<Typography variant="h5" gutterBottom>
|
||||||
|
Theme Manager
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
startIcon={<AddIcon />}
|
||||||
|
onClick={handleAddTheme}
|
||||||
|
>
|
||||||
|
Add Theme
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<List>
|
||||||
|
{userThemes?.map((theme, index) => (
|
||||||
|
<ListItemButton
|
||||||
|
key={theme?.id || index}
|
||||||
|
selected={theme?.id === currentThemeId}
|
||||||
|
>
|
||||||
|
<ListItemText
|
||||||
|
primary={`${theme?.name || `Theme ${index + 1}`} ${theme?.id === currentThemeId ? '(Current)' : ''}`}
|
||||||
|
/>
|
||||||
|
<ListItemSecondaryAction>
|
||||||
|
{theme.id !== 'default' && (
|
||||||
|
<>
|
||||||
|
<IconButton onClick={() => handleEditTheme(theme.id)}>
|
||||||
|
<EditIcon />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton onClick={() => handleDeleteTheme(theme.id)}>
|
||||||
|
<DeleteIcon />
|
||||||
|
</IconButton>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<IconButton onClick={() => handleApplyTheme(theme)}>
|
||||||
|
<CheckIcon />
|
||||||
|
</IconButton>
|
||||||
|
</ListItemSecondaryAction>
|
||||||
|
</ListItemButton>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
|
||||||
|
<Dialog
|
||||||
|
open={openEditor}
|
||||||
|
onClose={() => setOpenEditor(false)}
|
||||||
|
fullWidth
|
||||||
|
maxWidth="md"
|
||||||
|
>
|
||||||
|
<DialogTitle>
|
||||||
|
{themeDraft.id ? 'Edit Theme' : 'Add New Theme'}
|
||||||
|
</DialogTitle>
|
||||||
|
<DialogContent>
|
||||||
|
<TextField
|
||||||
|
inputRef={nameInputRef}
|
||||||
|
margin="dense"
|
||||||
|
label="Theme Name"
|
||||||
|
fullWidth
|
||||||
|
value={themeDraft.name}
|
||||||
|
onChange={(e) =>
|
||||||
|
setThemeDraft((prev) => ({ ...prev, name: e.target.value }))
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Tabs
|
||||||
|
value={currentTab}
|
||||||
|
onChange={(e, newValue) => setCurrentTab(newValue)}
|
||||||
|
sx={{ mt: 2, mb: 2 }}
|
||||||
|
>
|
||||||
|
<Tab label="Light" value="light" />
|
||||||
|
<Tab label="Dark" value="dark" />
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
|
<Box>
|
||||||
|
{renderColorPicker(
|
||||||
|
currentTab,
|
||||||
|
'Primary Main',
|
||||||
|
'primary.main',
|
||||||
|
themeDraft[currentTab]?.primary?.main
|
||||||
|
)}
|
||||||
|
{renderColorPicker(
|
||||||
|
currentTab,
|
||||||
|
'Primary Dark',
|
||||||
|
'primary.dark',
|
||||||
|
themeDraft[currentTab]?.primary?.dark
|
||||||
|
)}
|
||||||
|
{renderColorPicker(
|
||||||
|
currentTab,
|
||||||
|
'Primary Light',
|
||||||
|
'primary.light',
|
||||||
|
themeDraft[currentTab]?.primary?.light
|
||||||
|
)}
|
||||||
|
{renderColorPicker(
|
||||||
|
currentTab,
|
||||||
|
'Secondary Main',
|
||||||
|
'secondary.main',
|
||||||
|
themeDraft[currentTab]?.secondary?.main
|
||||||
|
)}
|
||||||
|
{renderColorPicker(
|
||||||
|
currentTab,
|
||||||
|
'Background Default',
|
||||||
|
'background.default',
|
||||||
|
themeDraft[currentTab]?.background?.default
|
||||||
|
)}
|
||||||
|
{renderColorPicker(
|
||||||
|
currentTab,
|
||||||
|
'Background Paper',
|
||||||
|
'background.paper',
|
||||||
|
themeDraft[currentTab]?.background?.paper
|
||||||
|
)}
|
||||||
|
{renderColorPicker(
|
||||||
|
currentTab,
|
||||||
|
'Background Surface',
|
||||||
|
'background.surface',
|
||||||
|
themeDraft[currentTab]?.background?.surface
|
||||||
|
)}
|
||||||
|
{renderColorPicker(
|
||||||
|
currentTab,
|
||||||
|
'Text Primary',
|
||||||
|
'text.primary',
|
||||||
|
themeDraft[currentTab]?.text?.primary
|
||||||
|
)}
|
||||||
|
{renderColorPicker(
|
||||||
|
currentTab,
|
||||||
|
'Text Secondary',
|
||||||
|
'text.secondary',
|
||||||
|
themeDraft[currentTab]?.text?.secondary
|
||||||
|
)}
|
||||||
|
{renderColorPicker(
|
||||||
|
currentTab,
|
||||||
|
'Border Main',
|
||||||
|
'border.main',
|
||||||
|
themeDraft[currentTab]?.border?.main
|
||||||
|
)}
|
||||||
|
{renderColorPicker(
|
||||||
|
currentTab,
|
||||||
|
'Border Subtle',
|
||||||
|
'border.subtle',
|
||||||
|
themeDraft[currentTab]?.border?.subtle
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button onClick={() => setOpenEditor(false)}>Cancel</Button>
|
||||||
|
<Button
|
||||||
|
disabled={!themeDraft.name}
|
||||||
|
onClick={handleSaveTheme}
|
||||||
|
variant="contained"
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Dialog>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
39
src/components/Theme/themeManager.css
Normal file
39
src/components/Theme/themeManager.css
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
[data-color-mode*='dark'] .w-color-sketch {
|
||||||
|
--sketch-background: #323232 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-color-mode*='dark'] .w-color-swatch {
|
||||||
|
--sketch-swatch-border-top: 1px solid #525252 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-color-mode*='dark'] .w-color-block {
|
||||||
|
--block-background-color: #323232 !important;
|
||||||
|
--block-box-shadow: rgb(0 0 0 / 10%) 0 1px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-color-mode*='dark'] .w-color-editable-input {
|
||||||
|
--editable-input-label-color: #757575 !important;
|
||||||
|
--editable-input-box-shadow: #616161 0px 0px 0px 1px inset !important;
|
||||||
|
--editable-input-color: #bbb !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-color-mode*='dark'] .w-color-github {
|
||||||
|
--github-border: 1px solid rgba(0, 0, 0, 0.2) !important;
|
||||||
|
--github-background-color: #323232 !important;
|
||||||
|
--github-box-shadow: rgb(0 0 0 / 15%) 0px 3px 12px !important;
|
||||||
|
--github-arrow-border-color: rgba(0, 0, 0, 0.15) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-color-mode*='dark'] .w-color-compact {
|
||||||
|
--compact-background-color: #323232 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-color-mode*='dark'] .w-color-material {
|
||||||
|
--material-background-color: #323232 !important;
|
||||||
|
--material-border-bottom-color: #707070 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-color-mode*='dark'] .w-color-alpha {
|
||||||
|
--alpha-pointer-background-color: #6a6a6a !important;
|
||||||
|
--alpha-pointer-box-shadow: rgb(0 0 0 / 37%) 0px 1px 4px 0px !important;
|
||||||
|
}
|
@ -1,14 +1,14 @@
|
|||||||
import { createTheme, ThemeOptions } from '@mui/material/styles';
|
import { createTheme, ThemeOptions } from '@mui/material/styles';
|
||||||
import { commonThemeOptions } from './theme-common';
|
import { commonThemeOptions } from './theme-common';
|
||||||
|
|
||||||
const darkThemeOptions: ThemeOptions = {
|
export const darkThemeOptions: ThemeOptions = {
|
||||||
...commonThemeOptions,
|
...commonThemeOptions,
|
||||||
palette: {
|
palette: {
|
||||||
mode: 'dark',
|
mode: 'dark',
|
||||||
primary: {
|
primary: {
|
||||||
main: 'rgb(46, 61, 96)',
|
main: 'rgb(100, 155, 240)',
|
||||||
dark: 'rgb(5, 20, 53)',
|
dark: 'rgb(45, 92, 201)',
|
||||||
light: 'rgb(45, 92, 201)',
|
light: 'rgb(130, 185, 255)',
|
||||||
},
|
},
|
||||||
secondary: {
|
secondary: {
|
||||||
main: 'rgb(69, 173, 255)',
|
main: 'rgb(69, 173, 255)',
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { createTheme, ThemeOptions } from '@mui/material/styles';
|
import { createTheme, ThemeOptions } from '@mui/material/styles';
|
||||||
import { commonThemeOptions } from './theme-common';
|
import { commonThemeOptions } from './theme-common';
|
||||||
|
|
||||||
const lightThemeOptions: ThemeOptions = {
|
export const lightThemeOptions: ThemeOptions = {
|
||||||
...commonThemeOptions,
|
...commonThemeOptions,
|
||||||
palette: {
|
palette: {
|
||||||
mode: 'light',
|
mode: 'light',
|
||||||
@ -26,10 +26,6 @@ const lightThemeOptions: ThemeOptions = {
|
|||||||
main: 'rgba(0, 0, 0, 0.12)',
|
main: 'rgba(0, 0, 0, 0.12)',
|
||||||
subtle: 'rgba(0, 0, 0, 0.08)',
|
subtle: 'rgba(0, 0, 0, 0.08)',
|
||||||
},
|
},
|
||||||
border: {
|
|
||||||
main: 'rgba(0, 0, 0, 0.12)',
|
|
||||||
subtle: 'rgba(0, 0, 0, 0.08)',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
MuiCard: {
|
MuiCard: {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user