New color palette and support for icons

- The new color palette copies the one from Readeck, introducing the
  same color palettes.
- Dark mode support
- Added an esbuild plugin to build svg files and be able to import them
  in svelte components
This commit is contained in:
Olivier Meunier
2024-09-04 06:00:25 +02:00
parent 4454a631cd
commit 3b293ccfeb
8 changed files with 564 additions and 12 deletions

8
LICENSES/ISC.txt Normal file
View File

@@ -0,0 +1,8 @@
ISC License:
Copyright (c) 2004-2010 by Internet Systems Consortium, Inc. ("ISC")
Copyright (c) 1995-2003 by Internet Software Consortium
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

37
esbuild/esbuild-svg.js Normal file
View File

@@ -0,0 +1,37 @@
// SPDX-FileCopyrightText: Copyright (c) Antoine Boulanger (https://github.com/ABXlink)
//
// SPDX-License-Identifier: ISC
// Source: https://github.com/nativew/esbuild-plugin-svg
const fs = require("fs")
const path = require("path")
const pluginSvg = (options = {}) => ({
name: "svg",
setup(build) {
const {customElement = false, namespace = "icon"} = options
const loader = customElement ? "js" : "text"
build.onLoad({filter: /\.svg$/}, async (args) => {
const fileName = path.basename(args.path, ".svg")
let contents = await fs.promises.readFile(args.path, "utf8")
if (customElement) {
contents = `
class SvgIcon extends HTMLElement {
connectedCallback() {
this.innerHTML = \`${contents}\`;
}
}
window.customElements.define('${namespace ? `${namespace}-` : ""}${fileName}', SvgIcon);
export default SvgIcon;
`
}
return {contents, loader}
})
},
})
module.exports = pluginSvg

View File

@@ -13,7 +13,7 @@ const gulpPostcss = require("gulp-postcss")
const gulpRename = require("gulp-rename")
const sveltePlugin = require("esbuild-svelte")
const svgPlugin = require("./esbuild/esbuild-svg")
const DEST = path.resolve("./addon")
// REUSE-IgnoreStart
@@ -46,7 +46,12 @@ function js_bundle(done) {
metafile: false,
minifyIdentifiers: process.env.NODE_ENV == "production",
minifyWhitespace: process.env.NODE_ENV == "production",
plugins: [sveltePlugin()],
plugins: [
sveltePlugin(),
svgPlugin({
customElement: true,
}),
],
}),
)
.pipe(gulpHeader("//" + LICENSE_HEADER.join("\n//") + "\n"))
@@ -59,6 +64,7 @@ function js_bundle(done) {
function css_bundle() {
const processors = [
//
require("./src/ui/palettes.js"),
require("postcss-import"),
require("tailwindcss"),
]

261
package-lock.json generated
View File

@@ -9,7 +9,9 @@
"version": "1.2.6",
"license": "GPL-3.0-only",
"devDependencies": {
"boxicons": "^2.1.4",
"cssnano": "^7.0.5",
"culori": "^4.0.1",
"esbuild-svelte": "^0.8.1",
"eslint": "^9.9.1",
"eslint-config-prettier": "^9.1.0",
@@ -1023,6 +1025,12 @@
"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
"dev": true
},
"node_modules/@webcomponents/webcomponentsjs": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/@webcomponents/webcomponentsjs/-/webcomponentsjs-2.8.0.tgz",
"integrity": "sha512-loGD63sacRzOzSJgQnB9ZAhaQGkN7wl2Zuw7tsphI5Isa0irijrRo6EnJii/GgjGefIFO8AIO7UivzRhFaEk9w==",
"dev": true
},
"node_modules/abort-controller": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
@@ -2039,6 +2047,20 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/boxicons": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/boxicons/-/boxicons-2.1.4.tgz",
"integrity": "sha512-BvJNfYfnE4g9WQ7GL91fftxMOTwAleWlPFwvQJPYb/Ju7aLjlQ/Eu55AH9JLNk/OR82z+ZSq4TbKzbV/e5Rr0A==",
"dev": true,
"dependencies": {
"@webcomponents/webcomponentsjs": "^2.0.2",
"prop-types": "^15.6.0",
"react": "^16.0.0",
"react-dom": "^16.0.0",
"react-interactive": "^0.8.1",
"react-router-dom": "^4.2.2"
}
},
"node_modules/bplist-parser": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz",
@@ -2816,6 +2838,15 @@
"integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==",
"dev": true
},
"node_modules/culori": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/culori/-/culori-4.0.1.tgz",
"integrity": "sha512-LSnjA6HuIUOlkfKVbzi2OlToZE8OjFi667JWN9qNymXVXzGDmvuP60SSgC+e92sd7B7158f7Fy3Mb6rXS5EDPw==",
"dev": true,
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
}
},
"node_modules/data-uri-to-buffer": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
@@ -2996,6 +3027,42 @@
"node": ">=0.10.0"
}
},
"node_modules/detect-hover": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/detect-hover/-/detect-hover-1.0.3.tgz",
"integrity": "sha512-HtLoY+tClgYucJNiovNICGWFp9nOGVmHY44s7L62iPqORXM9vujeWFaVcqtA7XRvp/2Y+4RBUfHbDKFGN+xxZQ==",
"dev": true
},
"node_modules/detect-it": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/detect-it/-/detect-it-3.0.7.tgz",
"integrity": "sha512-RxpgcdbatUX6epJE09K16iJqF7x6iEcEdoL18FR2zpBO4JhnL7aMOAUoUEyexdtbWOSfTmoDWmeD6mwRBQyRXg==",
"dev": true,
"dependencies": {
"detect-hover": "^1.0.3",
"detect-passive-events": "^1.0.5",
"detect-pointer": "^1.0.3",
"detect-touch-events": "^2.0.2"
}
},
"node_modules/detect-passive-events": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/detect-passive-events/-/detect-passive-events-1.0.5.tgz",
"integrity": "sha512-foW7Q35wwOCxVzW0xLf5XeB5Fhe7oyRgvkBYdiP9IWgLMzjqUqTvsJv9ymuEWGjY6AoDXD3OC294+Z9iuOw0QA==",
"dev": true
},
"node_modules/detect-pointer": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/detect-pointer/-/detect-pointer-1.0.3.tgz",
"integrity": "sha512-d0o/Puo3fiGSCXy6H039h9Kwz+mmYCGKZ/qtPFnpN3WfsumjC1C9b5KKvRu+aYnfdI8peqN/iAe7dPd85qIt2g==",
"dev": true
},
"node_modules/detect-touch-events": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/detect-touch-events/-/detect-touch-events-2.0.2.tgz",
"integrity": "sha512-g8GWBkJLiIDRJfRXEdrd1wMXpNyGId2DkbfuwFahSb4OCvn717hyRJtAcEDISfp3zkwEhZ4Y4woHPA6DeyB3Fw==",
"dev": true
},
"node_modules/didyoumean": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
@@ -4420,6 +4487,26 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/history": {
"version": "4.10.1",
"resolved": "https://registry.npmjs.org/history/-/history-4.10.1.tgz",
"integrity": "sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==",
"dev": true,
"dependencies": {
"@babel/runtime": "^7.1.2",
"loose-envify": "^1.2.0",
"resolve-pathname": "^3.0.0",
"tiny-invariant": "^1.0.2",
"tiny-warning": "^1.0.0",
"value-equal": "^1.0.1"
}
},
"node_modules/hoist-non-react-statics": {
"version": "2.5.5",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz",
"integrity": "sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw==",
"dev": true
},
"node_modules/homedir-polyfill": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz",
@@ -4619,6 +4706,15 @@
"node": ">=10.13.0"
}
},
"node_modules/invariant": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz",
"integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==",
"dev": true,
"dependencies": {
"loose-envify": "^1.0.0"
}
},
"node_modules/invert-kv": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-3.0.1.tgz",
@@ -5260,6 +5356,18 @@
"integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==",
"dev": true
},
"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==",
"dev": true,
"dependencies": {
"js-tokens": "^3.0.0 || ^4.0.0"
},
"bin": {
"loose-envify": "cli.js"
}
},
"node_modules/lowercase-keys": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz",
@@ -6231,6 +6339,21 @@
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/path-to-regexp": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
"integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
"dev": true,
"dependencies": {
"isarray": "0.0.1"
}
},
"node_modules/path-to-regexp/node_modules/isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==",
"dev": true
},
"node_modules/pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
@@ -6979,6 +7102,17 @@
"node": ">=6"
}
},
"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==",
"dev": true,
"dependencies": {
"loose-envify": "^1.4.0",
"object-assign": "^4.1.1",
"react-is": "^16.13.1"
}
},
"node_modules/proto-list": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
@@ -7096,6 +7230,90 @@
"node": ">=0.10.0"
}
},
"node_modules/react": {
"version": "16.14.0",
"resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz",
"integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==",
"dev": true,
"dependencies": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
"prop-types": "^15.6.2"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/react-dom": {
"version": "16.14.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz",
"integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==",
"dev": true,
"dependencies": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1",
"prop-types": "^15.6.2",
"scheduler": "^0.19.1"
},
"peerDependencies": {
"react": "^16.14.0"
}
},
"node_modules/react-interactive": {
"version": "0.8.3",
"resolved": "https://registry.npmjs.org/react-interactive/-/react-interactive-0.8.3.tgz",
"integrity": "sha512-mmRvA9aKP7zu9kVfP1AX1egX8tFlnE3DDXq92z0JTZezfOpmeQBzr77O1+mTV54OOmn+M2t6c5kFD5VnuFoM7A==",
"dev": true,
"dependencies": {
"detect-it": "^3.0.3",
"object-assign": "^4.1.1",
"prop-types": "^15.6.0"
},
"peerDependencies": {
"react": ">=15"
}
},
"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==",
"dev": true
},
"node_modules/react-router": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/react-router/-/react-router-4.3.1.tgz",
"integrity": "sha512-yrvL8AogDh2X42Dt9iknk4wF4V8bWREPirFfS9gLU1huk6qK41sg7Z/1S81jjTrGHxa3B8R3J6xIkDAA6CVarg==",
"dev": true,
"dependencies": {
"history": "^4.7.2",
"hoist-non-react-statics": "^2.5.0",
"invariant": "^2.2.4",
"loose-envify": "^1.3.1",
"path-to-regexp": "^1.7.0",
"prop-types": "^15.6.1",
"warning": "^4.0.1"
},
"peerDependencies": {
"react": ">=15"
}
},
"node_modules/react-router-dom": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-4.3.1.tgz",
"integrity": "sha512-c/MlywfxDdCp7EnB7YfPMOfMD3tOtIjrQlj/CKfNMBxdmpJP8xcz5P/UAFn3JbnQCNUxsHyVVqllF9LhgVyFCA==",
"dev": true,
"dependencies": {
"history": "^4.7.2",
"invariant": "^2.2.4",
"loose-envify": "^1.3.1",
"prop-types": "^15.6.1",
"react-router": "^4.3.1",
"warning": "^4.0.1"
},
"peerDependencies": {
"react": ">=15"
}
},
"node_modules/read-cache": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
@@ -7387,6 +7605,12 @@
"node": ">= 10.13.0"
}
},
"node_modules/resolve-pathname": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/resolve-pathname/-/resolve-pathname-3.0.0.tgz",
"integrity": "sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==",
"dev": true
},
"node_modules/responselike": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz",
@@ -7589,6 +7813,16 @@
"integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
"dev": true
},
"node_modules/scheduler": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz",
"integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==",
"dev": true,
"dependencies": {
"loose-envify": "^1.1.0",
"object-assign": "^4.1.1"
}
},
"node_modules/semver": {
"version": "7.6.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
@@ -8261,6 +8495,18 @@
"xtend": "~4.0.1"
}
},
"node_modules/tiny-invariant": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
"integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==",
"dev": true
},
"node_modules/tiny-warning": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz",
"integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==",
"dev": true
},
"node_modules/titleize": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz",
@@ -8562,6 +8808,12 @@
"node": ">= 10.13.0"
}
},
"node_modules/value-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz",
"integrity": "sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==",
"dev": true
},
"node_modules/value-or-function": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-4.0.0.tgz",
@@ -8657,6 +8909,15 @@
"source-map": "^0.5.1"
}
},
"node_modules/warning": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
"integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
"dev": true,
"dependencies": {
"loose-envify": "^1.0.0"
}
},
"node_modules/watchpack": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz",

View File

@@ -9,7 +9,9 @@
},
"license": "GPL-3.0-only",
"devDependencies": {
"boxicons": "^2.1.4",
"cssnano": "^7.0.5",
"culori": "^4.0.1",
"esbuild-svelte": "^0.8.1",
"eslint": "^9.9.1",
"eslint-config-prettier": "^9.1.0",

View File

@@ -13,6 +13,84 @@ body {
font-size: 16px;
}
@layer base {
:root {
--color-white: rgb-values(#fff);
--color-black: rgb-values(#000);
--color-gray-light: rgb-values(#fff);
--color-gray-dark: rgb-values(#000);
--color-gray: color-scale(#968273 inoutsine gamma 1.5);
--color-blue: color-scale(#0da6c9 inoutsine gamma 1.2);
--color-red: color-scale(#ef4444 inoutsine gamma 1.6);
--color-green: color-scale(#84cc16 inoutsine);
--color-yellow: color-scale(#f9b807 inoutsine gamma 1.7);
--color-app-bg: var(--color-gray-50);
--color-app-fg: var(--color-gray-900);
--color-primary: var(--color-blue-600);
--color-primary-light: var(--color-blue-400);
--color-primary-dark: var(--color-blue-700);
--color-shadow: var(--color-gray-700);
--default-shadow: rgb(var(--color-shadow) / 0.2);
--color-btn-default: var(--color-gray-700);
--color-btn-default-hover: var(--color-gray-800);
--color-btn-default-text: var(--color-white);
--color-btn-primary: var(--color-primary);
--color-btn-primary-hover: var(--color-primary-dark);
--color-btn-primary-text: var(--color-white);
--color-btn-danger: var(--color-red-600);
--color-btn-danger-hover: var(--color-red-800);
--color-btn-danger-text: var(--color-white);
--color-hl-yellow: var(--color-yellow-200);
--color-hl-yellow-dark: var(--color-yellow-500);
}
@media (prefers-color-scheme: dark) {
:root {
--color-app-bg: var(--color-gray-50);
--color-app-fg: var(--color-gray-950);
--color-gray-light: rgb-values(#000);
--color-gray-dark: rgb-values(#fff);
--color-gray: color-scale(
#6a7e84 reversed inoutsine to #161a1b gamma 1.2
);
--color-blue: color-scale(#0cabcf reversed inoutsine gamma 1.6);
--color-red: color-scale(#ef4444 reversed inoutsine gamma 1.1);
--color-green: color-scale(#84cc16 reversed inoutsine gamma 1.1);
--color-yellow: color-scale(#f9b807 reversed inoutsine gamma 1.1);
--color-primary: var(--color-blue-600);
--color-primary-light: var(--color-blue-400);
--color-primary-dark: var(--color-blue-700);
--color-shadow: var(--color-black);
--default-shadow: rgb(var(--color-shadow) / 0.6);
--color-btn-default: var(--color-gray-400);
--color-btn-default-hover: var(--color-gray-300);
--color-btn-primary: var(--color-blue-400);
--color-btn-primary-hover: var(--color-blue-300);
--color-btn-danger: var(--color-red-400);
--color-btn-danger-hover: var(--color-red-300);
--color-hl-yellow: var(--color-yellow-200);
--color-hl-yellow-dark: var(--color-yellow-300);
}
}
}
@layer components {
:focus-visible {
@apply outline-none;

131
src/ui/palettes.js Normal file
View File

@@ -0,0 +1,131 @@
// SPDX-FileCopyrightText: © 2023 Olivier Meunier <olivier@neokraft.net>
//
// SPDX-License-Identifier: GPL-3.0-only
"use strict"
const {
parse,
okhsl,
interpolate,
easingGamma,
easingInOutSine,
easingSmoothstep,
} = require("culori")
const {Declaration} = require("postcss")
const valueParser = require("postcss-value-parser")
const twScale = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950]
const clamp = (value) => Math.max(0, Math.min(1, value || 0))
const fixup = (value) => Math.round(clamp(value) * 255)
function getScale(
options = {base, from, to, gamma, inoutsine, smoothstep, reversed},
) {
options = {
gamma: null,
inoutsine: false,
smoothstep: false,
reversed: false,
...options,
}
const base = okhsl(options.base)
let from = okhsl(options.from || "#fff")
let to = okhsl(options.to || "#000")
const helpers = []
if (!!options.inoutsine) {
helpers.push(easingInOutSine)
}
if (!!options.smoothstep) {
helpers.push(easingSmoothstep)
}
if (options.gamma !== null) {
helpers.push(easingGamma(options.gamma))
}
const inpterpolator = interpolate([...helpers, from, base, to])
let res = twScale.map((x) => x / 1000).map(inpterpolator)
if (!!options.reversed) {
res.reverse()
}
return res
}
function setRGBValues(decl) {
const nodes = valueParser(decl.value).nodes[0].nodes.filter(
(n) => n.type == "word",
)
const c = parse(nodes[0].value)
decl.value = `${fixup(c.r)} ${fixup(c.g)} ${fixup(c.b)}`
}
function setColorScale(decl) {
const nodes = valueParser(decl.value).nodes[0].nodes.filter(
(n) => n.type == "word",
)
const params = {}
for (let i = 0; i < nodes.length; i++) {
if (i == 0) {
params.base = nodes[i].value
continue
}
switch (nodes[i].value) {
case "reversed":
params.reversed = true
break
case "inoutsine":
params.inoutsine = true
break
case "smoothstep":
params.smoothstep = true
break
case "from":
i++
params.from = nodes[i].value
break
case "to":
i++
params.to = nodes[i].value
break
case "gamma":
i++
params.gamma = nodes[i].value
break
}
}
decl.replaceWith(
...getScale(params).map((c, i) => {
return new Declaration({
prop: `${decl.prop}-${twScale[i]}`,
value: `${fixup(c.r)} ${fixup(c.g)} ${fixup(c.b)}`,
})
}),
)
}
const plugin = () => {
return {
postcssPlugin: "palette",
Declaration(decl) {
if (!decl.prop.startsWith("--")) {
return
}
if (decl.value.startsWith("color-scale(")) {
setColorScale(decl)
}
if (decl.value.startsWith("rgb-values(")) {
setRGBValues(decl)
}
},
}
}
plugin.postcss = true
module.exports = plugin

View File

@@ -59,23 +59,52 @@ const palette = {
},
}
const colorVar = (name) => {
return ({opacityValue}) => {
if (opacityValue) {
return `rgb(var(--color-${name}) / ${opacityValue})`
}
return `rgb(var(--color-${name}))`
}
}
const varPalette = (name) => {
return [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950].reduce(
(acc, cur) => {
acc[cur] = colorVar(`${name}-${cur}`)
return acc
},
{},
)
}
module.exports = {
content: ["addon/action/index.html", "src/**/*"],
theme: {
colors: {
inherit: "inherit",
transparent: "transparent",
current: "currentColor",
black: colors.black,
white: colors.white,
gray: palette.gray,
red: palette.red,
green: colors.lime,
blue: palette.blue,
yellow: palette.orange,
black: colorVar("black"),
white: colorVar("white"),
app: {
bg: colorVar("app-bg"),
fg: colorVar("app-fg"),
},
gray: {
...varPalette("gray"),
light: colorVar("gray-light"),
dark: colorVar("gray-dark"),
},
red: varPalette("red"),
green: varPalette("green"),
blue: varPalette("blue"),
yellow: varPalette("yellow"),
primary: {
light: palette.blue[300],
DEFAULT: palette.blue[600],
dark: palette.blue[800],
...varPalette("blue"),
DEFAULT: colorVar("primary"),
light: colorVar("primary-light"),
dark: colorVar("primary-dark"),
},
},
},