diff --git a/components/Head.tsx b/components/Head.tsx new file mode 100644 index 0000000..a83d975 --- /dev/null +++ b/components/Head.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import NextHead from 'next/head'; + +export default function Head({ host, categories }) { + const categoryLabels = categories.filter(c => c.tag && c.tag !== 'ALL').map(c => c.label.toLowerCase()); + + return ( + + Discover {host.name} + + encodeURIComponent(label)).join(',')}`} + /> + + ); +} diff --git a/lib/hosts.ts b/lib/hosts.ts index 3540a45..9743841 100644 --- a/lib/hosts.ts +++ b/lib/hosts.ts @@ -27,8 +27,15 @@ export const hosts: { currency: string; startYear: number; logoSrc: string; - color: string; - styles: { text: string; groupHoverText: string; button: string; brandBox: string; box: string; border: string }; + color: { closestPaletteColor: string; brand: string }; + styles: { + text: string; + groupHoverText: string; + button: string; + brandBox: string; + box: string; + border: string; + }; website?: string; cta?: { text: string; textLonger: string; href: string; buttonLabel: string }; groupTags: { [key: string]: string[] }; @@ -58,7 +65,7 @@ export const hosts: { currency: 'USD', startYear: 2016, logoSrc: '/oc-logo.svg', - color: 'blue', + color: { closestPaletteColor: 'blue', brand: '#0C2D66' }, website: 'https://opencollective.com', styles: { text: 'text-[#0C2D66]', @@ -82,7 +89,7 @@ export const hosts: { currency: 'USD', startYear: 2018, logoSrc: '/ocf-logo.svg', - color: 'teal', + color: { closestPaletteColor: 'teal', brand: '#0C5559' }, styles: { text: 'text-[#0C5559]', groupHoverText: 'group-hover:text-[#0C5559]', @@ -110,7 +117,7 @@ export const hosts: { startYear: 2016, logoSrc: '/osc-logo.svg', website: 'https://opencollective.com/opensource', - color: 'purple', + color: { closestPaletteColor: 'purple', brand: '#4B3084' }, styles: { text: 'text-[#4B3084]', groupHoverText: 'group-hover:text-[#4B3084]', @@ -132,7 +139,7 @@ export const hosts: { startYear: 2019, logoSrc: '/oce-logo.svg', website: 'https://opencollective.com/europe', - color: 'blue', + color: { closestPaletteColor: 'blue', brand: '#0C2D66' }, styles: { text: 'text-[#0C2D66]', groupHoverText: 'group-hover:text-[#0C2D66]', diff --git a/package-lock.json b/package-lock.json index 2b3e9dd..3af1191 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,6 +13,7 @@ "@opencollective/frontend-components": "0.3.8", "@styled-icons/fa-solid": "^10.46.0", "@styled-system/prop-types": "^5.1.5", + "@vercel/og": "^0.0.21", "apexcharts": "^3.36.3", "babel-plugin-formatjs": "^10.3.31", "babel-plugin-react-remove-properties": "^0.3.0", @@ -2930,6 +2931,14 @@ "url": "https://opencollective.com/popperjs" } }, + "node_modules/@resvg/resvg-wasm": { + "version": "2.0.0-alpha.4", + "resolved": "https://registry.npmjs.org/@resvg/resvg-wasm/-/resvg-wasm-2.0.0-alpha.4.tgz", + "integrity": "sha512-pWIG9a/x1ky8gXKRhPH1OPKpHFoMN1ISLbJ+O+gPXQHIAKhNd5I28RlWf7q576hAOQA9JZTlo3p/M2uyLzJmmw==", + "engines": { + "node": ">= 10" + } + }, "node_modules/@rushstack/eslint-patch": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz", @@ -2955,6 +2964,21 @@ "node": "^14.17.0 || >=16.0.0" } }, + "node_modules/@shuding/opentype.js": { + "version": "1.4.0-beta.0", + "resolved": "https://registry.npmjs.org/@shuding/opentype.js/-/opentype.js-1.4.0-beta.0.tgz", + "integrity": "sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA==", + "dependencies": { + "fflate": "^0.7.3", + "string.prototype.codepointat": "^0.2.1" + }, + "bin": { + "ot": "bin/ot" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/@styled-icons/boxicons-regular": { "version": "10.46.0", "resolved": "https://registry.npmjs.org/@styled-icons/boxicons-regular/-/boxicons-regular-10.46.0.tgz", @@ -3448,6 +3472,11 @@ "@types/node": "*" } }, + "node_modules/@types/yoga-layout": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@types/yoga-layout/-/yoga-layout-1.9.2.tgz", + "integrity": "sha512-S9q47ByT2pPvD65IvrWp7qppVMpk9WGMbVq9wbWZOHg6tnXSD4vyhao6nOSBwwfDdV2p3Kx9evA9vI+XWTfDvw==" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "5.40.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.40.1.tgz", @@ -3688,6 +3717,19 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@vercel/og": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/@vercel/og/-/og-0.0.21.tgz", + "integrity": "sha512-WgMahG5c8UM7xtn/mT+ljUpDMSDnSlu8AXL52JtTwxb1odrd0GWqZg2N1X38wulPj+sCccNpDdFmmAuw0GLc+Q==", + "dependencies": { + "@resvg/resvg-wasm": "2.0.0-alpha.4", + "satori": "0.0.44", + "yoga-wasm-web": "0.1.2" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@whatwg-node/fetch": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.3.2.tgz", @@ -4875,6 +4917,16 @@ "node": ">= 8" } }, + "node_modules/css-background-parser": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/css-background-parser/-/css-background-parser-0.1.0.tgz", + "integrity": "sha512-2EZLisiZQ+7m4wwur/qiYJRniHX4K5Tc9w93MT3AS0WS1u5kaZ4FKXlOTBhOjc+CgEgPiGY+fX1yWD8UwpEqUA==" + }, + "node_modules/css-box-shadow": { + "version": "1.0.0-3", + "resolved": "https://registry.npmjs.org/css-box-shadow/-/css-box-shadow-1.0.0-3.tgz", + "integrity": "sha512-9jaqR6e7Ohds+aWwmhe6wILJ99xYQbfmK9QQB9CcMjDbTxPZjwEmUQpU91OG05Xgm8BahT5fW+svbsQGjS/zPg==" + }, "node_modules/css-color-keywords": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", @@ -5264,8 +5316,7 @@ "node_modules/emoji-regex": { "version": "10.2.1", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.2.1.tgz", - "integrity": "sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==", - "dev": true + "integrity": "sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==" }, "node_modules/enhanced-resolve": { "version": "5.10.0", @@ -6865,6 +6916,11 @@ "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" }, + "node_modules/fflate": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.4.tgz", + "integrity": "sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==" + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -11085,6 +11141,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/satori": { + "version": "0.0.44", + "resolved": "https://registry.npmjs.org/satori/-/satori-0.0.44.tgz", + "integrity": "sha512-WKUxXC2qeyno6J3ucwwLozPL6j1HXOZiN5wIUf7iqAhlx1RUC/6ePIKHi7iPc3Cy6DYuZcJriZXxXkSdo2FQHg==", + "dependencies": { + "@shuding/opentype.js": "1.4.0-beta.0", + "css-background-parser": "^0.1.0", + "css-box-shadow": "1.0.0-3", + "css-to-react-native": "^3.0.0", + "emoji-regex": "^10.2.1", + "postcss-value-parser": "^4.2.0", + "yoga-layout-prebuilt": "^1.10.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/scheduler": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", @@ -11357,6 +11430,11 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "node_modules/string.prototype.codepointat": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz", + "integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==" + }, "node_modules/string.prototype.matchall": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", @@ -12720,6 +12798,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/yoga-layout-prebuilt": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/yoga-layout-prebuilt/-/yoga-layout-prebuilt-1.10.0.tgz", + "integrity": "sha512-YnOmtSbv4MTf7RGJMK0FvZ+KD8OEe/J5BNnR0GHhD8J/XcG/Qvxgszm0Un6FTHWW4uHlTgP0IztiXQnGyIR45g==", + "dependencies": { + "@types/yoga-layout": "1.9.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yoga-wasm-web": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yoga-wasm-web/-/yoga-wasm-web-0.1.2.tgz", + "integrity": "sha512-8SkgawHcA0RUbMrnhxbaQkZDBi8rMed8pQHixkFF9w32zGhAwZ9/cOHWlpYfr6RCx42Yp3siV45/jPEkJxsk6w==" + }, "node_modules/zen-observable": { "version": "0.8.15", "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", @@ -14828,6 +14922,11 @@ "integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==", "peer": true }, + "@resvg/resvg-wasm": { + "version": "2.0.0-alpha.4", + "resolved": "https://registry.npmjs.org/@resvg/resvg-wasm/-/resvg-wasm-2.0.0-alpha.4.tgz", + "integrity": "sha512-pWIG9a/x1ky8gXKRhPH1OPKpHFoMN1ISLbJ+O+gPXQHIAKhNd5I28RlWf7q576hAOQA9JZTlo3p/M2uyLzJmmw==" + }, "@rushstack/eslint-patch": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz", @@ -14847,6 +14946,15 @@ "resolved": "https://registry.npmjs.org/@shopify/address-consts/-/address-consts-4.1.2.tgz", "integrity": "sha512-OVbuVX1SqRYyI6afY67lIAIFUGtd8XLvsTanNG3fKsvM/aPDHjyB42GYSEiM1nUI9Ja0CKveEOdIO8K7Yn9GQw==" }, + "@shuding/opentype.js": { + "version": "1.4.0-beta.0", + "resolved": "https://registry.npmjs.org/@shuding/opentype.js/-/opentype.js-1.4.0-beta.0.tgz", + "integrity": "sha512-3NgmNyH3l/Hv6EvsWJbsvpcpUba6R8IREQ83nH83cyakCw7uM1arZKNfHwv1Wz6jgqrF/j4x5ELvR6PnK9nTcA==", + "requires": { + "fflate": "^0.7.3", + "string.prototype.codepointat": "^0.2.1" + } + }, "@styled-icons/boxicons-regular": { "version": "10.46.0", "resolved": "https://registry.npmjs.org/@styled-icons/boxicons-regular/-/boxicons-regular-10.46.0.tgz", @@ -15286,6 +15394,11 @@ "@types/node": "*" } }, + "@types/yoga-layout": { + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/@types/yoga-layout/-/yoga-layout-1.9.2.tgz", + "integrity": "sha512-S9q47ByT2pPvD65IvrWp7qppVMpk9WGMbVq9wbWZOHg6tnXSD4vyhao6nOSBwwfDdV2p3Kx9evA9vI+XWTfDvw==" + }, "@typescript-eslint/eslint-plugin": { "version": "5.40.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.40.1.tgz", @@ -15424,6 +15537,16 @@ } } }, + "@vercel/og": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/@vercel/og/-/og-0.0.21.tgz", + "integrity": "sha512-WgMahG5c8UM7xtn/mT+ljUpDMSDnSlu8AXL52JtTwxb1odrd0GWqZg2N1X38wulPj+sCccNpDdFmmAuw0GLc+Q==", + "requires": { + "@resvg/resvg-wasm": "2.0.0-alpha.4", + "satori": "0.0.44", + "yoga-wasm-web": "0.1.2" + } + }, "@whatwg-node/fetch": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.3.2.tgz", @@ -16298,6 +16421,16 @@ "which": "^2.0.1" } }, + "css-background-parser": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/css-background-parser/-/css-background-parser-0.1.0.tgz", + "integrity": "sha512-2EZLisiZQ+7m4wwur/qiYJRniHX4K5Tc9w93MT3AS0WS1u5kaZ4FKXlOTBhOjc+CgEgPiGY+fX1yWD8UwpEqUA==" + }, + "css-box-shadow": { + "version": "1.0.0-3", + "resolved": "https://registry.npmjs.org/css-box-shadow/-/css-box-shadow-1.0.0-3.tgz", + "integrity": "sha512-9jaqR6e7Ohds+aWwmhe6wILJ99xYQbfmK9QQB9CcMjDbTxPZjwEmUQpU91OG05Xgm8BahT5fW+svbsQGjS/zPg==" + }, "css-color-keywords": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", @@ -16595,8 +16728,7 @@ "emoji-regex": { "version": "10.2.1", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.2.1.tgz", - "integrity": "sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==", - "dev": true + "integrity": "sha512-97g6QgOk8zlDRdgq1WxwgTMgEWGVAQvB5Fdpgc1MkNy56la5SKP9GsMXKDOdqwn90/41a8yPwIGk1Y6WVbeMQA==" }, "enhanced-resolve": { "version": "5.10.0", @@ -17819,6 +17951,11 @@ "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==" }, + "fflate": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.7.4.tgz", + "integrity": "sha512-5u2V/CDW15QM1XbbgS+0DfPxVB+jUKhWEKuuFuHncbk3tEEqzmoXL+2KyOFuKGqOnmdIy0/davWF1CkuwtibCw==" + }, "figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -20735,6 +20872,20 @@ } } }, + "satori": { + "version": "0.0.44", + "resolved": "https://registry.npmjs.org/satori/-/satori-0.0.44.tgz", + "integrity": "sha512-WKUxXC2qeyno6J3ucwwLozPL6j1HXOZiN5wIUf7iqAhlx1RUC/6ePIKHi7iPc3Cy6DYuZcJriZXxXkSdo2FQHg==", + "requires": { + "@shuding/opentype.js": "1.4.0-beta.0", + "css-background-parser": "^0.1.0", + "css-box-shadow": "1.0.0-3", + "css-to-react-native": "^3.0.0", + "emoji-regex": "^10.2.1", + "postcss-value-parser": "^4.2.0", + "yoga-layout-prebuilt": "^1.10.0" + } + }, "scheduler": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", @@ -20962,6 +21113,11 @@ } } }, + "string.prototype.codepointat": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz", + "integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==" + }, "string.prototype.matchall": { "version": "4.0.7", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.7.tgz", @@ -21952,6 +22108,19 @@ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true }, + "yoga-layout-prebuilt": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/yoga-layout-prebuilt/-/yoga-layout-prebuilt-1.10.0.tgz", + "integrity": "sha512-YnOmtSbv4MTf7RGJMK0FvZ+KD8OEe/J5BNnR0GHhD8J/XcG/Qvxgszm0Un6FTHWW4uHlTgP0IztiXQnGyIR45g==", + "requires": { + "@types/yoga-layout": "1.9.2" + } + }, + "yoga-wasm-web": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/yoga-wasm-web/-/yoga-wasm-web-0.1.2.tgz", + "integrity": "sha512-8SkgawHcA0RUbMrnhxbaQkZDBi8rMed8pQHixkFF9w32zGhAwZ9/cOHWlpYfr6RCx42Yp3siV45/jPEkJxsk6w==" + }, "zen-observable": { "version": "0.8.15", "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", diff --git a/package.json b/package.json index 9dff40f..1a636c6 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "@opencollective/frontend-components": "0.3.8", "@styled-icons/fa-solid": "^10.46.0", "@styled-system/prop-types": "^5.1.5", + "@vercel/og": "^0.0.21", "apexcharts": "^3.36.3", "babel-plugin-formatjs": "^10.3.31", "babel-plugin-react-remove-properties": "^0.3.0", diff --git a/pages/[slug].tsx b/pages/[slug].tsx index 8633edb..617178c 100644 --- a/pages/[slug].tsx +++ b/pages/[slug].tsx @@ -1,10 +1,10 @@ import React from 'react'; import type { GetStaticProps } from 'next'; -import Head from 'next/head'; import { hosts as _hosts } from '../lib/hosts'; import Dashboard from '../components/Dashboard'; +import Head from '../components/Head'; import Layout from '../components/Layout'; import { createCategories } from '../utils/categories'; @@ -90,9 +90,7 @@ export default function Page({ const locale = 'en'; return ( - - Discover {host.name} - + res.arrayBuffer()); + +export const config = { + runtime: 'experimental-edge', +}; + +export default async function OG(req: NextRequest) { + const fontData = await font; + const { searchParams } = new URL(req.url); + const hasHost = searchParams.has('hostSlug'); + const hostSlug = hasHost ? searchParams.get('hostSlug') : ''; + const host = hosts.find(h => h.slug === hostSlug || (!hostSlug && h.root)) || hosts[0]; + + const hasTags = searchParams.has('tags'); + const tagsParams = hasTags ? searchParams.get('tags') : ''; + const hasCount = searchParams.has('count'); + const count = hasCount ? searchParams.get('count') : ''; + const tags = tagsParams?.split(',').map(tag => tag.replace('and', '&').trim()) || []; + const spanStyle = { + display: 'flex', + flexShrink: 0, + marginRight: 12, + fontWeight: 'bolder', + letterSpacing: '-0.025em', + }; + const tagStyles = tags.map((tag, i) => { + // to get same colors, we need to add 1 to the index and add 2 to the total length since we start without the "All" tag and without the More.. category + const color = pickColorForCategory(host.color.closestPaletteColor, i + 1, tags.length + 2); + return { + ...spanStyle, + textDecoration: 'underline', + textDecorationColor: color.hex, + textDecorationSkip: 'ink', + marginRight: 0, + }; + }); + return new ImageResponse( + ( +
+
+ Discover {count?.toLocaleString()}{' '} + collectives {host.root ? 'on' : 'hosted by'}{' '} + {host.name.split(' ').map(word => { + return ( + + {word} + + ); + })} + making an impact{' '} + in + {tags.map((tag, i, arr) => { + return ( + + {tag} + {arr.length - 1 === i ? ' ' : ', '} + + ); + })} + and more. +
+
+ ), + { + width: 1200, + height: 600, + fonts: [ + { + name: 'Inter', + data: fontData, + style: 'normal', + }, + ], + }, + ); +} diff --git a/tsconfig.json b/tsconfig.json index 79e68c0..cbecb61 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,7 +8,7 @@ "forceConsistentCasingInFileNames": true, "noEmit": true, "esModuleInterop": true, - "module": "commonjs", + "module": "esnext", "moduleResolution": "node", "resolveJsonModule": true, "isolatedModules": true, diff --git a/utils/categories.ts b/utils/categories.ts index 84d299a..40e5cc0 100644 --- a/utils/categories.ts +++ b/utils/categories.ts @@ -78,6 +78,6 @@ export const createCategories = ({ return categories.map((category, i, arr) => ({ ...category, - color: pickColorForCategory('blue', i, arr.length), + color: pickColorForCategory(host.color.closestPaletteColor, i, arr.length), })); }; diff --git a/utils/colors.ts b/utils/colors.ts index 49e20ff..c393376 100644 --- a/utils/colors.ts +++ b/utils/colors.ts @@ -20,6 +20,6 @@ const colors = [ export const pickColorForCategory = (startColor: string, i: number, numOfCategories: number) => { const startColorIndex = colors.findIndex(c => c.name === startColor); - const step = Math.floor(colors.length / numOfCategories); - return colors[(startColorIndex + i * step) % colors.length]; + const step = colors.length / numOfCategories; + return colors[(startColorIndex + Math.round(i * step)) % colors.length]; };