From 68b2a33f07151495169da2cdd49fcd0a91a0f97b Mon Sep 17 00:00:00 2001 From: Mark Striemer Date: Tue, 26 Mar 2024 16:56:06 +0000 Subject: [PATCH] Bug 1850611 - Create a JSON file source of truth for our design tokens. r=reusable-components-reviewers,desktop-theme-reviewers,hjones,dao * Add light-dark transformer for generating web CSS * Use value object in design-tokens.json * Add HCM media queries to built CSS * Add MPL license and how to edit file header * Strip '-default' from token names and values * Refactor generated media query placement within file. * generate multiple CSS files from a single JSON file. * add the :host(.anonymous-content-host) selector to the built CSS * Output tokens in pre-defined order * Generate CSS layer declarations and relevant selectors * Sort tokens by t-shirt size and state semantically not alphabetically * Add remaining tokens to design-tokens.json * Add design tokens JSON docs --------- Co-authored-by: Jules Simplicio Co-authored-by: Hanna Jones Co-authored-by: Mark Striemer Co-authored-by: Tim Giles Differential Revision: https://phabricator.services.mozilla.com/D204108 --- .gitignore | 3 + .hgignore | 3 + .../README.json-design-tokens.stories.md | 56 + .../shared/design-system/design-tokens.json | 944 +++++++++++ .../shared/design-system/package-lock.json | 1405 +++++++++++++++++ .../themes/shared/design-system/package.json | 12 + .../shared/design-system/tokens-brand.css | 16 +- .../shared/design-system/tokens-config.js | 428 +++++ .../shared/design-system/tokens-platform.css | 5 +- .../shared/design-system/tokens-shared.css | 17 +- toolkit/themes/shared/desktop-jar.inc.mn | 2 +- 11 files changed, 2875 insertions(+), 16 deletions(-) create mode 100644 toolkit/themes/shared/design-system/README.json-design-tokens.stories.md create mode 100644 toolkit/themes/shared/design-system/design-tokens.json create mode 100644 toolkit/themes/shared/design-system/package-lock.json create mode 100644 toolkit/themes/shared/design-system/package.json create mode 100644 toolkit/themes/shared/design-system/tokens-config.js diff --git a/.gitignore b/.gitignore index d684fcb90182..70c8f7992b1c 100644 --- a/.gitignore +++ b/.gitignore @@ -341,6 +341,9 @@ browser/components/storybook/storybook-static/ browser/components/storybook/.storybook/chrome-map.js browser/components/storybook/custom-elements.json +# Ignore design-system node_modules +toolkit/themes/shared/design-system/node_modules/ + # Ignore jscodeshift installed by mach esmify on windows tools/esmify/jscodeshift tools/esmify/jscodeshift.cmd diff --git a/.hgignore b/.hgignore index e1a360b07142..230fd78646c5 100644 --- a/.hgignore +++ b/.hgignore @@ -333,6 +333,9 @@ tps_result\.json$ ^browser/components/storybook/\.storybook/chrome-map\.js ^browser/components/storybook/custom-elements\.json +# Ignore design-system node_modules +toolkit/themes/shared/design-system/node_modules/ + # Ignore jscodeshift installed by mach esmify on windows ^tools/esmify/jscodeshift ^tools/esmify/jscodeshift\.cmd diff --git a/toolkit/themes/shared/design-system/README.json-design-tokens.stories.md b/toolkit/themes/shared/design-system/README.json-design-tokens.stories.md new file mode 100644 index 000000000000..1886c1c5c105 --- /dev/null +++ b/toolkit/themes/shared/design-system/README.json-design-tokens.stories.md @@ -0,0 +1,56 @@ +# JSON design tokens +## Background +The benefit of storing design tokens with a platform-agnostic format such as JSON is that it can be converted or translated into other languages or tools (e.g CSS, Swift, Kotlin, Figma). + +## Quick start +`design-tokens.json` holds our source of truth for design tokens in `mozilla-central` under the [design-system](https://searchfox.org/mozilla-central/source/toolkit/themes/shared/design-system) folder in `toolkit/themes/shared`. The CSS design token files in that folder come from the JSON file. If you need to modify a design token file, you should be editing the JSON. + +In order for us to be able to define design tokens in one place (the JSON file) and allow all platforms to consume design tokens in their specific format, we use a build system called [Style Dictionary](https://amzn.github.io/style-dictionary/#/). + +Here's how to build design tokens for desktop: + +```sh +$ ./mach npm run build --prefix=toolkit/themes/shared/design-system +``` + +If successful, you should see Style Dictionary building all of our tokens files within the `design-system` folder. Otherwise, Style Dictionary can also generate helpful errors to help you debug. + +At the end, we're capable of transforming JSON notation into CSS: + +```json +{ + "color": { + "blue": { + "05": { + "value": "#deeafc" + }, + "30": { + "value": "#73a7f3" + }, + "50": { + "value": "#0060df" + }, + "60": { + "value": "#0250bb" + }, + "70": { + "value": "#054096" + }, + "80": { + "value": "#003070" + } + }, + }, +} +``` + +```css +--color-blue-05: #deeafc; +--color-blue-30: #73a7f3; +--color-blue-50: #0060df; +--color-blue-60: #0250bb; +--color-blue-70: #054096; +--color-blue-80: #003070; +``` + +Neat! diff --git a/toolkit/themes/shared/design-system/design-tokens.json b/toolkit/themes/shared/design-system/design-tokens.json new file mode 100644 index 000000000000..c807335942d0 --- /dev/null +++ b/toolkit/themes/shared/design-system/design-tokens.json @@ -0,0 +1,944 @@ +{ + "attention": { + "dot": { + "color": { + "value": { + "platform": { + "default": "AccentColor" + }, + "brand": { + "light": "#2ac3a2", + "dark": "#54ffbd" + }, + "prefersContrast": "AccentColor" + } + } + } + }, + "background": { + "color": { + "box": { + "value": { + "light": "{color.white}", + "dark": "{color.gray.80}", + "prefersContrast": "{background.color.canvas}" + } + }, + "canvas": { + "value": { + "prefersContrast": "Canvas", + "brand": { + "light": "{color.white}", + "dark": "{color.gray.90}" + }, + "platform": { + "default": "Canvas" + } + } + }, + "critical": { + "value": { + "light": "{color.red.05}", + "dark": "{color.red.80}", + "prefersContrast": "{background.color.canvas}" + } + }, + "information": { + "value": { + "light": "{color.blue.05}", + "dark": "{color.blue.80}", + "prefersContrast": "{background.color.canvas}" + } + }, + "success": { + "value": { + "light": "{color.green.05}", + "dark": "{color.green.80}", + "prefersContrast": "{background.color.canvas}" + } + }, + "warning": { + "value": { + "light": "{color.yellow.05}", + "dark": "{color.yellow.80}", + "prefersContrast": "{background.color.canvas}" + } + } + } + }, + "border": { + "color": { + "@base": { + "value": { + "prefersContrast": "{text.color.@base}" + } + }, + "interactive": { + "@base": { + "value": { + "prefersContrast": "{text.color.@base}", + "forcedColors": "ButtonText", + "brand": { + "light": "{color.gray.60}", + "dark": "{color.gray.50}" + }, + "platform": { + "default": "color-mix(in srgb, currentColor 15%, {color.gray.60})" + } + } + }, + "hover": { + "value": { + "default": "{border.color.interactive.@base}", + "forcedColors": "SelectedItem" + } + }, + "active": { + "value": { + "default": "{border.color.interactive.@base}", + "forcedColors": "ButtonText" + } + }, + "disabled": { + "value": { + "default": "{border.color.interactive.@base}", + "forcedColors": "GrayText" + } + } + } + }, + "radius": { + "circle": { + "value": "9999px" + }, + "small": { + "value": "4px" + }, + "medium": { + "value": "8px" + } + }, + "width": { + "value": "1px" + } + }, + "box": { + "shadow": { + "10": { + "value": "0 1px 4px {color.black.a10}" + } + } + }, + "button": { + "background": { + "color": { + "@base": { + "comment": "TODO Bug 1821203 - Gray use needs to be consolidated", + "value": { + "forcedColors": "ButtonFace", + "brand": { + "default": "color-mix(in srgb, currentColor 7%, transparent)" + }, + "platform": { + "default": "var(--button-bgcolor)" + } + } + }, + "hover": { + "value": { + "forcedColors": "SelectedItemText", + "brand": { + "default": "color-mix(in srgb, currentColor 14%, transparent)" + }, + "platform": { + "default": "var(--button-hover-bgcolor)" + } + } + }, + "active": { + "value": { + "forcedColors": "SelectedItemText", + "brand": { + "default": "color-mix(in srgb, currentColor 21%, transparent)" + }, + "platform": { + "default": "var(--button-active-bgcolor)" + } + } + }, + "disabled": { + "value": { + "default": "{button.background.color.@base}", + "forcedColors": "ButtonFace" + } + }, + "primary": { + "@base": { + "value": "{color.accent.primary.@base}" + }, + "hover": { + "value": "{color.accent.primary.hover}" + }, + "active": { + "value": "{color.accent.primary.active}" + }, + "disabled": { + "value": { + "default": "{button.background.color.primary.@base}", + "forcedColors": "{button.text.color.disabled}" + } + } + }, + "destructive": { + "@base": { + "value": { + "light": "{color.red.50}", + "dark": "{color.red.30}", + "forcedColors": "{button.background.color.primary.@base}" + } + }, + "active": { + "value": { + "light": "{color.red.70}", + "dark": "{color.red.05}", + "forcedColors": "{button.background.color.primary.active}" + } + }, + "disabled": { + "value": { + "default": "{button.background.color.destructive.@base}", + "forcedColors": "{button.background.color.primary.disabled}" + } + }, + "hover": { + "value": { + "light": "{color.red.60}", + "dark": "{color.red.10}", + "forcedColors": "{button.background.color.primary.hover}" + } + } + }, + "ghost": { + "@base": { + "value": { + "default": "transparent", + "prefersContrast": "{button.background.color.@base}", + "forcedColors": "{button.background.color.@base}" + } + }, + "active": { + "value": "{button.background.color.active}" + }, + "disabled": { + "value": { + "default": "{button.background.color.ghost.@base}", + "forcedColors": "{button.background.color.disabled}" + } + }, + "hover": { + "value": "{button.background.color.hover}" + } + } + } + }, + "border": { + "@base": { + "value": "{border.width} solid {button.border.color.@base}" + }, + "color": { + "@base": { + "value": { + "default": "transparent", + "prefersContrast": "{button.text.color.@base}", + "forcedColors": "{border.color.interactive.@base}" + } + }, + "active": { + "value": { + "default": "{button.border.color.@base}", + "forcedColors": "{border.color.interactive.active}" + } + }, + "destructive": { + "@base": { + "value": { + "default": "transparent", + "forcedColors": "{button.border.color.primary.@base}" + } + }, + "active": { + "value": { + "default": "{button.border.color.destructive.@base}", + "forcedColors": "{button.border.color.primary.active}" + } + }, + "disabled": { + "value": { + "default": "{button.border.color.destructive.@base}", + "forcedColors": "{button.border.color.primary.disabled}" + } + }, + "hover": { + "value": { + "default": "{button.border.color.destructive.@base}", + "forcedColors": "{button.border.color.primary.hover}" + } + } + }, + "disabled": { + "value": { + "default": "{button.border.color.@base}", + "forcedColors": "{border.color.interactive.disabled}" + } + }, + "ghost": { + "@base": { + "value": { + "default": "{button.border.color.@base}" + } + }, + "active": { + "value": { + "default": "{button.border.color.active}" + } + }, + "disabled": { + "value": { + "default": "{button.border.color.disabled}" + } + }, + "hover": { + "value": { + "default": "{button.border.color.hover}" + } + } + }, + "hover": { + "value": { + "default": "{button.border.color.@base}", + "forcedColors": "{border.color.interactive.hover}" + } + }, + "primary": { + "@base": { + "value": { + "default": "transparent", + "forcedColors": "ButtonFace" + } + }, + "active": { + "value": { + "default": "{button.border.color.primary.@base}", + "forcedColors": "ButtonText" + } + }, + "disabled": { + "value": "{button.border.color.primary.@base}" + }, + "hover": { + "value": { + "default": "{button.border.color.primary.@base}", + "forcedColors": "SelectedItemText" + } + } + } + }, + "radius": { + "value": "{border.radius.small}" + } + }, + "font": { + "size": { + "@base": { + "value": "{font.size.root}" + }, + "small": { + "value": "{font.size.small}" + } + }, + "weight": { + "value": "{font.weight.bold}" + } + }, + "min": { + "height": { + "@base": { + "value": "{size.item.large}" + }, + "small": { + "value": "{size.item.medium}" + } + } + }, + "opacity": { + "disabled": { + "value": { + "default": 0.5, + "forcedColors": 1 + } + } + }, + "padding": { + "@base": { + "value": "{space.xsmall} {space.large}" + }, + "icon": { + "value": 0 + } + }, + "size": { + "icon": { + "@base": { + "value": "{button.min.height.@base}" + }, + "small": { + "value": "{button.min.height.small}" + } + } + }, + "text": { + "color": { + "@base": { + "value": { + "forcedColors": "ButtonText", + "brand": { + "light": "{color.gray.100}", + "dark": "{color.gray.05}" + }, + "platform": { + "default": "var(--button-color)" + } + } + }, + "active": { + "value": { + "default": "{button.text.color.@base}", + "forcedColors": "SelectedItem" + } + }, + "destructive": { + "@base": { + "value": { + "light": "{color.gray.05}", + "dark": "{color.gray.100}", + "forcedColors": "{button.text.color.primary.@base}" + } + }, + "active": { + "value": { + "default": "{button.text.color.destructive.@base}", + "forcedColors": "{button.text.color.primary.active}" + } + }, + "disabled": { + "value": { + "default": "{button.text.color.destructive.@base}", + "forcedColors": "{button.text.color.primary.disabled}" + } + }, + "hover": { + "value": { + "default": "{button.text.color.destructive.@base}", + "forcedColors": "{button.text.color.primary.hover}" + } + } + }, + "disabled": { + "value": { + "default": "{button.text.color.@base}", + "forcedColors": "GrayText" + } + }, + "ghost": { + "@base": { + "value": { + "default": "{button.text.color.@base}" + } + }, + "active": { + "value": { + "default": "{button.text.color.active}" + } + }, + "disabled": { + "value": { + "default": "{button.text.color.disabled}" + } + }, + "hover": { + "value": { + "default": "{button.text.color.hover}" + } + } + }, + "hover": { + "value": { + "default": "{button.text.color.@base}", + "forcedColors": "SelectedItem" + } + }, + "primary": { + "@base": { + "value": { + "forcedColors": "ButtonFace", + "brand": { + "light": "{color.gray.05}", + "dark": "{color.gray.100}" + }, + "platform": { + "default": "var(--button-primary-color)" + } + } + }, + "active": { + "value": "{button.text.color.primary.hover}" + }, + "disabled": { + "value": "{button.text.color.primary.@base}" + }, + "hover": { + "value": { + "default": "{button.text.color.primary.@base}", + "forcedColors": "SelectedItemText" + } + } + } + } + } + }, + "checkbox": { + "margin": { + "inline": { + "value": "{space.small}" + } + }, + "size": { + "comment": "TODO Bug 1876537: Make this em-based, probably?", + "value": "{size.item.small}" + } + }, + "color": { + "black": { + "a10": { + "value": "rgba(0, 0, 0, 0.1)" + } + }, + "blue": { + "05": { + "value": "#deeafc" + }, + "30": { + "value": "#73a7f3" + }, + "50": { + "value": "#0060df" + }, + "60": { + "value": "#0250bb" + }, + "70": { + "value": "#054096" + }, + "80": { + "value": "#003070" + } + }, + "cyan": { + "20": { + "value": "#aaf2ff" + }, + "30": { + "value": "#80ebff" + }, + "50": { + "value": "#00ddff" + } + }, + "gray": { + "05": { + "value": "#fbfbfe" + }, + "50": { + "value": "#bfbfc9" + }, + "60": { + "value": "#8f8f9d" + }, + "70": { + "value": "#5b5b66" + }, + "80": { + "value": "#23222b" + }, + "90": { + "value": "#1c1b22" + }, + "100": { + "value": "#15141a" + } + }, + "green": { + "05": { + "value": "#d8eedc" + }, + "30": { + "value": "#4dbc87" + }, + "50": { + "value": "#017a40" + }, + "80": { + "value": "#004725" + } + }, + "red": { + "05": { + "value": "#ffe8e8" + }, + "10": { + "value": "#ffbdc5" + }, + "20": { + "value": "#ff9aa2" + }, + "30": { + "value": "#f37f98" + }, + "50": { + "value": "#d7264c" + }, + "60": { + "value": "#ac1e3d" + }, + "70": { + "value": "#8a1831" + }, + "80": { + "value": "#690f22" + } + }, + "yellow": { + "05": { + "value": "#ffebcd" + }, + "30": { + "value": "#e49c49" + }, + "50": { + "value": "#cd411e" + }, + "80": { + "value": "#5a3100" + } + }, + "white": { + "value": "#ffffff" + }, + "accent": { + "primary": { + "@base": { + "value": { + "forcedColors": "ButtonText", + "brand": { + "light": "{color.blue.50}", + "dark": "{color.cyan.50}" + }, + "platform": { + "default": "var(--button-primary-bgcolor, AccentColor)" + } + } + }, + "hover": { + "value": { + "forcedColors": "SelectedItem", + "brand": { + "light": "{color.blue.60}", + "dark": "{color.cyan.30}" + }, + "platform": { + "default": "var(--button-primary-hover-bgcolor)" + } + } + }, + "active": { + "value": { + "forcedColors": "{color.accent.primary.hover}", + "brand": { + "light": "{color.blue.70}", + "dark": "{color.cyan.20}" + }, + "platform": { + "default": "var(--button-primary-active-bgcolor)" + } + } + } + } + } + }, + "focus": { + "outline": { + "@base": { + "value": "{focus.outline.width} solid {focus.outline.color}" + }, + "color": { + "value": "{color.accent.primary.@base}" + }, + "inset": { + "value": "calc(-1 * {focus.outline.width})" + }, + "offset": { + "value": "2px" + }, + "width": { + "value": "2px" + } + } + }, + "font": { + "size": { + "root": { + "value": { + "brand": { + "default": "15px" + }, + "platform": { + "default": "unset" + } + } + }, + "small": { + "value": { + "brand": { + "default": "0.867rem" + }, + "platform": { + "default": "unset" + } + } + }, + "large": { + "value": { + "brand": { + "default": "1.133rem" + }, + "platform": { + "default": "unset" + } + } + }, + "xlarge": { + "value": { + "brand": { + "default": "1.467rem" + }, + "platform": { + "default": "unset" + } + } + }, + "xxlarge": { + "value": { + "brand": { + "default": "1.6rem" + }, + "platform": { + "default": "unset" + } + } + } + }, + "weight": { + "@base": { + "value": "normal" + }, + "bold": { + "value": 600 + } + } + }, + "icon": { + "color": { + "@base": { + "value": { + "light": "{color.gray.70}", + "dark": "{color.gray.05}", + "prefersContrast": "{text.color.@base}" + } + }, + "information": { + "value": { + "light": "{color.blue.50}", + "dark": "{color.blue.30}", + "prefersContrast": "{icon.color.@base}" + } + }, + "success": { + "value": { + "light": "{color.green.50}", + "dark": "{color.green.30}", + "prefersContrast": "{icon.color.@base}" + } + }, + "warning": { + "value": { + "light": "{color.yellow.50}", + "dark": "{color.yellow.30}", + "prefersContrast": "{icon.color.@base}" + } + }, + "critical": { + "value": { + "light": "{color.red.50}", + "dark": "{color.red.30}", + "prefersContrast": "{icon.color.@base}" + } + } + }, + "size": { + "default": { + "value": "{size.item.small}" + } + } + }, + "input": { + "text": { + "min": { + "height": { + "value": "{button.min.height.@base}" + } + } + } + }, + "link": { + "color": { + "@base": { + "value": { + "prefersContrast": "LinkText", + "brand": { + "default": "{color.accent.primary.@base}" + }, + "platform": { + "default": "LinkText" + } + } + }, + "hover": { + "value": { + "prefersContrast": "LinkText", + "brand": { + "default": "{color.accent.primary.hover}" + }, + "platform": { + "default": "LinkText" + } + } + }, + "active": { + "value": { + "prefersContrast": "ActiveText", + "brand": { + "default": "{color.accent.primary.active}" + }, + "platform": { + "default": "ActiveText" + } + } + }, + "visited": { + "value": { + "prefersContrast": "{link.color.@base}", + "brand": { + "default": "{link.color.@base}" + }, + "platform": { + "default": "{link.color.@base}" + } + } + } + }, + "focus": { + "outline": { + "offset": { + "comment": "Not using --force-outline-offset for links because that's intended for\nelements with a background, and we only want a slight offset here while\nnot overlapping adjacent text", + "value": "1px" + } + } + } + }, + "outline": { + "color": { + "error": { + "value": { + "light": "{color.red.50}", + "dark": "{color.red.20}", + "prefersContrast": "{border.color.@base}" + } + } + } + }, + "size": { + "item": { + "small": { + "value": "16px" + }, + "medium": { + "value": "28px" + }, + "large": { + "value": "32px" + } + } + }, + "space": { + "xxsmall": { + "value": "calc(0.5 * {space.xsmall})" + }, + "xsmall": { + "value": "0.267rem" + }, + "small": { + "value": "calc(2 * {space.xsmall})" + }, + "medium": { + "value": "calc(3 * {space.xsmall})" + }, + "large": { + "value": "calc(4 * {space.xsmall})" + }, + "xlarge": { + "value": "calc(6 * {space.xsmall})" + }, + "xxlarge": { + "value": "calc(8 * {space.xsmall})" + } + }, + "text": { + "color": { + "@base": { + "value": { + "prefersContrast": "CanvasText", + "brand": { + "light": "{color.gray.100}", + "dark": "{color.gray.05}" + }, + "platform": { + "default": "currentColor" + } + } + }, + "deemphasized": { + "value": { + "default": "color-mix(in srgb, currentColor 69%, transparent)", + "prefersContrast": "inherit" + } + }, + "error": { + "value": { + "light": "{color.red.50}", + "dark": "{color.red.20}", + "prefersContrast": "inherit" + } + } + } + } +} diff --git a/toolkit/themes/shared/design-system/package-lock.json b/toolkit/themes/shared/design-system/package-lock.json new file mode 100644 index 000000000000..b45ca870947c --- /dev/null +++ b/toolkit/themes/shared/design-system/package-lock.json @@ -0,0 +1,1405 @@ +{ + "name": "design-system", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "design-system", + "version": "1.0.0", + "license": "MPL-2.0", + "devDependencies": { + "style-dictionary": "^3.9.2" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "dependencies": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "node_modules/capital-case": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", + "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/change-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", + "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", + "dev": true, + "dependencies": { + "camel-case": "^4.1.2", + "capital-case": "^1.0.4", + "constant-case": "^3.0.4", + "dot-case": "^3.0.4", + "header-case": "^2.0.4", + "no-case": "^3.0.4", + "param-case": "^3.0.4", + "pascal-case": "^3.1.2", + "path-case": "^3.0.4", + "sentence-case": "^3.0.4", + "snake-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/constant-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", + "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case": "^2.0.2" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/header-case": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", + "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", + "dev": true, + "dependencies": { + "capital-case": "^1.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/lru-cache": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", + "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "dev": true, + "engines": { + "node": "14 || >=16.14" + } + }, + "node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "dependencies": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "node_modules/param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", + "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sentence-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", + "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", + "dev": true, + "dependencies": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dev": true, + "dependencies": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/style-dictionary": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/style-dictionary/-/style-dictionary-3.9.2.tgz", + "integrity": "sha512-M2pcQ6hyRtqHOh+NyT6T05R3pD/gwNpuhREBKvxC1En0vyywx+9Wy9nXWT1SZ9ePzv1vAo65ItnpA16tT9ZUCg==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "change-case": "^4.1.2", + "commander": "^8.3.0", + "fs-extra": "^10.0.0", + "glob": "^10.3.10", + "json5": "^2.2.2", + "jsonc-parser": "^3.0.0", + "lodash": "^4.17.15", + "tinycolor2": "^1.4.1" + }, + "bin": { + "style-dictionary": "bin/style-dictionary" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", + "dev": true + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/upper-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", + "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/upper-case-first": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", + "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", + "dev": true, + "dependencies": { + "tslib": "^2.0.3" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + } + }, + "dependencies": { + "@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "requires": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + } + }, + "@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "camel-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", + "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", + "dev": true, + "requires": { + "pascal-case": "^3.1.2", + "tslib": "^2.0.3" + } + }, + "capital-case": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", + "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "change-case": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", + "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", + "dev": true, + "requires": { + "camel-case": "^4.1.2", + "capital-case": "^1.0.4", + "constant-case": "^3.0.4", + "dot-case": "^3.0.4", + "header-case": "^2.0.4", + "no-case": "^3.0.4", + "param-case": "^3.0.4", + "pascal-case": "^3.1.2", + "path-case": "^3.0.4", + "sentence-case": "^3.0.4", + "snake-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "dev": true + }, + "constant-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", + "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case": "^2.0.2" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "dot-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", + "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + } + }, + "fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, + "requires": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + } + }, + "graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "header-case": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", + "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", + "dev": true, + "requires": { + "capital-case": "^1.0.4", + "tslib": "^2.0.3" + } + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, + "requires": { + "@isaacs/cliui": "^8.0.2", + "@pkgjs/parseargs": "^0.11.0" + } + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true + }, + "jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lower-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", + "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", + "dev": true, + "requires": { + "tslib": "^2.0.3" + } + }, + "lru-cache": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", + "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "dev": true + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + }, + "minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "dev": true + }, + "no-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", + "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", + "dev": true, + "requires": { + "lower-case": "^2.0.2", + "tslib": "^2.0.3" + } + }, + "param-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", + "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", + "dev": true, + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "pascal-case": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", + "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "path-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", + "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", + "dev": true, + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dev": true, + "requires": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + } + }, + "sentence-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", + "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", + "dev": true, + "requires": { + "no-case": "^3.0.4", + "tslib": "^2.0.3", + "upper-case-first": "^2.0.2" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true + }, + "snake-case": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", + "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", + "dev": true, + "requires": { + "dot-case": "^3.0.4", + "tslib": "^2.0.3" + } + }, + "string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "requires": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + } + }, + "string-width-cjs": { + "version": "npm:string-width@4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + }, + "strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "requires": { + "ansi-regex": "^6.0.1" + } + }, + "strip-ansi-cjs": { + "version": "npm:strip-ansi@6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + } + } + }, + "style-dictionary": { + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/style-dictionary/-/style-dictionary-3.9.2.tgz", + "integrity": "sha512-M2pcQ6hyRtqHOh+NyT6T05R3pD/gwNpuhREBKvxC1En0vyywx+9Wy9nXWT1SZ9ePzv1vAo65ItnpA16tT9ZUCg==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "change-case": "^4.1.2", + "commander": "^8.3.0", + "fs-extra": "^10.0.0", + "glob": "^10.3.10", + "json5": "^2.2.2", + "jsonc-parser": "^3.0.0", + "lodash": "^4.17.15", + "tinycolor2": "^1.4.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "tinycolor2": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz", + "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==", + "dev": true + }, + "tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", + "dev": true + }, + "universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true + }, + "upper-case": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", + "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", + "dev": true, + "requires": { + "tslib": "^2.0.3" + } + }, + "upper-case-first": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", + "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", + "dev": true, + "requires": { + "tslib": "^2.0.3" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "requires": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true + } + } + }, + "wrap-ansi-cjs": { + "version": "npm:wrap-ansi@7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + } + } + } + } +} diff --git a/toolkit/themes/shared/design-system/package.json b/toolkit/themes/shared/design-system/package.json new file mode 100644 index 000000000000..e50a350383b5 --- /dev/null +++ b/toolkit/themes/shared/design-system/package.json @@ -0,0 +1,12 @@ +{ + "name": "design-system", + "version": "1.0.0", + "description": "Package file for node modules used to create our CSS tokens from a JSON source of truth.", + "license": "MPL-2.0", + "scripts": { + "build": "(npm ls || npm ci) && style-dictionary build --config ./tokens-config.js" + }, + "devDependencies": { + "style-dictionary": "^3.9.2" + } +} diff --git a/toolkit/themes/shared/design-system/tokens-brand.css b/toolkit/themes/shared/design-system/tokens-brand.css index 8e50294e0135..4574cf405aab 100644 --- a/toolkit/themes/shared/design-system/tokens-brand.css +++ b/toolkit/themes/shared/design-system/tokens-brand.css @@ -2,6 +2,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* DO NOT EDIT this file directly, instead modify design-tokens.json + * and run `npm run build` to see your changes. */ + @import url("chrome://global/skin/design-system/tokens-shared.css"); @layer tokens-foundation { @@ -17,8 +20,7 @@ --border-color-interactive: light-dark(var(--color-gray-60), var(--color-gray-50)); /** Button **/ - /* TODO Bug 1821203 - Gray use needs to be consolidated */ - --button-background-color: color-mix(in srgb, currentColor 7%, transparent); + --button-background-color: color-mix(in srgb, currentColor 7%, transparent); /* TODO Bug 1821203 - Gray use needs to be consolidated */ --button-background-color-hover: color-mix(in srgb, currentColor 14%, transparent); --button-background-color-active: color-mix(in srgb, currentColor 21%, transparent); --button-text-color: light-dark(var(--color-gray-100), var(--color-gray-05)); @@ -30,11 +32,11 @@ --color-accent-primary-active: light-dark(var(--color-blue-70), var(--color-cyan-20)); /** Font Size **/ - --font-size-root: 15px; /* Set at the `:root`. Do not use */ - --font-size-small: 0.867rem; /* 13px */ - --font-size-large: 1.133rem; /* 17px */ - --font-size-xlarge: 1.467rem; /* 22px */ - --font-size-xxlarge: 1.6rem; /* 24px */ + --font-size-root: 15px; + --font-size-small: 0.867rem; + --font-size-large: 1.133rem; + --font-size-xlarge: 1.467rem; + --font-size-xxlarge: 1.6rem; /** Link **/ --link-color: var(--color-accent-primary); diff --git a/toolkit/themes/shared/design-system/tokens-config.js b/toolkit/themes/shared/design-system/tokens-config.js new file mode 100644 index 000000000000..752c5705188c --- /dev/null +++ b/toolkit/themes/shared/design-system/tokens-config.js @@ -0,0 +1,428 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* eslint-env node */ + +const StyleDictionary = require("style-dictionary"); +const { createPropertyFormatter } = StyleDictionary.formatHelpers; +const TOKEN_SECTIONS = { + "Attention Dot": "attention-dot", + "Background Color": "background-color", + Border: "border", + "Box Shadow": "box-shadow", + Button: "button", + Checkbox: "checkbox", + Color: ["brand-color", "color", "platform-color"], + "Focus Outline": "focus-outline", + "Font Size": "font-size", + "Font Weight": "font-weight", + Icon: "icon", + "Input - Text": "input-text", + Link: "link", + "Outline Color": "outline-color", + Size: "size", + Space: "space", + Text: "text", + Unspecified: "", +}; +const TSHIRT_ORDER = [ + "circle", + "xxxsmall", + "xxsmall", + "xsmall", + "small", + "medium", + "large", + "xlarge", + "xxlarge", + "xxxlarge", +]; +const STATE_ORDER = [ + "base", + "default", + "root", + "hover", + "active", + "focus", + "disabled", +]; + +/** + * Adds the Mozilla Public License header in one comment and + * how to make changes in the generated output files via the + * design-tokens.json file in another comment. Also imports + * tokens-shared.css when applicable. + * + * @param {string} surface + * Desktop surface, either "brand" or "platform". Determines + * whether or not we need to import tokens-shared.css. + * @returns {string} Formatted comment header string + */ +let customFileHeader = surface => { + let licenseString = [ + "/* This Source Code Form is subject to the terms of the Mozilla Public", + " * License, v. 2.0. If a copy of the MPL was not distributed with this", + " * file, You can obtain one at http://mozilla.org/MPL/2.0/. */", + ].join("\n"); + + let commentString = [ + "/* DO NOT EDIT this file directly, instead modify design-tokens.json", + " * and run `npm run build` to see your changes. */", + ].join("\n"); + + let cssImport = surface + ? `@import url("chrome://global/skin/design-system/tokens-shared.css");\n\n` + : ""; + let layerString = !surface + ? `@layer tokens-foundation, tokens-prefers-contrast, tokens-forced-colors;\n\n` + : ""; + + return [ + licenseString + "\n\n" + commentString + "\n\n" + cssImport + layerString, + ]; +}; + +const NEST_MEDIA_QUERIES_COMMENT = `/* Bug 1879900: Can't nest media queries inside of :host, :root selector + until Bug 1879349 lands */`; + +const MEDIA_QUERY_PROPERTY_MAP = { + "forced-colors": "forcedColors", + "prefers-contrast": "prefersContrast", +}; + +function formatBaseTokenNames(str) { + return str.replaceAll(/(?\w+)-base(?=\b)/g, "$"); +} + +/** + * Creates a surface-specific formatter. The formatter is used to build + * our different CSS files, including "prefers-contrast" and "forced-colors" + * media queries. See more at + * https://amzn.github.io/style-dictionary/#/formats?id=formatter + * + * @param {string} surface + * Which desktop area we are generating CSS for. + * Either "brand" (i.e. in-content) or "platform" (i.e. chrome). + * @returns {Function} - Formatter function that returns a CSS string. + */ +const createDesktopFormat = surface => args => { + return formatBaseTokenNames( + customFileHeader(surface) + + formatTokens({ + surface, + args, + }) + + formatTokens({ + mediaQuery: "prefers-contrast", + surface, + args, + }) + + formatTokens({ + mediaQuery: "forced-colors", + surface, + args, + }) + ); +}; + +/** + * Formats a subset of tokens into CSS. Wraps token CSS in a media query when + * applicable. + * + * @param {object} tokenArgs + * @param {string} [tokenArgs.mediaQuery] + * Media query formatted CSS should be wrapped in. This is used + * to determine what property we are parsing from the token values. + * @param {string} [tokenArgs.surface] + * Specifies a desktop surface, either "brand" or "platform". + * @param {object} tokenArgs.args + * Formatter arguments provided by style-dictionary. See more at + * https://amzn.github.io/style-dictionary/#/formats?id=formatter + * @returns {string} Tokens formatted into a CSS string. + */ +function formatTokens({ mediaQuery, surface, args }) { + let prop = MEDIA_QUERY_PROPERTY_MAP[mediaQuery] ?? "default"; + let dictionary = Object.assign({}, args.dictionary); + let tokens = []; + + dictionary.allTokens.forEach(token => { + let originalVal = getOriginalTokenValue(token, prop, surface); + if (originalVal != undefined) { + let formattedToken = transformTokenValue(token, originalVal, dictionary); + tokens.push(formattedToken); + } + }); + + if (!tokens.length) { + return ""; + } + + dictionary.allTokens = dictionary.allProperties = tokens; + + let formattedVars = formatVariables({ + format: "css", + dictionary, + outputReferences: args.options.outputReferences, + formatting: { + indentation: mediaQuery ? " " : " ", + }, + }); + + let layer = `tokens-${mediaQuery ?? "foundation"}`; + // Weird spacing below is unfortunately necessary for formatting the built CSS. + if (mediaQuery) { + return ` +${NEST_MEDIA_QUERIES_COMMENT} +@layer ${layer} { + @media (${mediaQuery}) { + :root, + :host(.anonymous-content-host) { +${formattedVars} + } + } +} +`; + } + + return `@layer ${layer} { + :root, + :host(.anonymous-content-host) { +${formattedVars} + } +} +`; +} + +/** + * Finds the original value of a token for a given media query and surface. + * + * @param {object} token - Token object parsed by style-dictionary. + * @param {string} prop - Name of the property we're querying for. + * @param {string} surface + * The desktop surface we're generating CSS for, either "brand" or "platform". + * @returns {string} The original token value based on our parameters. + */ +function getOriginalTokenValue(token, prop, surface) { + if (surface) { + return token.original.value[surface]?.[prop]; + } else if (prop == "default" && typeof token.original.value != "object") { + return token.original.value; + } + return token.original.value?.[prop]; +} + +/** + * Updates a token's value to the relevant original value after resolving + * variable references. + * + * @param {object} token - Token object parsed from JSON by style-dictionary. + * @param {string} originalVal + * Original value of the token for the combination of surface and media query. + * @param {object} dictionary + * Object of transformed tokens and helper fns provided by style-dictionary. + * @returns {object} Token object with an updated value. + */ +function transformTokenValue(token, originalVal, dictionary) { + let value = originalVal; + if (dictionary.usesReference(value)) { + dictionary.getReferences(value).forEach(ref => { + value = value.replace(`{${ref.path.join(".")}}`, `var(--${ref.name})`); + }); + } + return { ...token, value }; +} + +/** + * Creates a light-dark transform that works for a given surface. Registers + * the transform with style-dictionary and returns the transform's name. + * + * @param {string} surface + * The desktop surface we're generating CSS for, either "brand", "platform", + * or "shared". + * @returns {string} Name of the transform that was registered. + */ +const createLightDarkTransform = surface => { + let name = `lightDarkTransform/${surface}`; + + // Matcher function for determining if a token's value needs to undergo + // a light-dark transform. + let matcher = token => { + if (surface != "shared") { + return ( + token.original.value[surface]?.light && + token.original.value[surface]?.dark + ); + } + return token.original.value.light && token.original.value.dark; + }; + + // Function that uses the token's original value to create a new "default" + // light-dark value and updates the original value object. + let transformer = token => { + if (surface != "shared") { + let lightDarkVal = `light-dark(${token.original.value[surface].light}, ${token.original.value[surface].dark})`; + token.original.value[surface].default = lightDarkVal; + return token.value; + } + let value = `light-dark(${token.original.value.light}, ${token.original.value.dark})`; + token.original.value.default = value; + return value; + }; + + StyleDictionary.registerTransform({ + type: "value", + transitive: true, + name, + matcher, + transformer, + }); + + return name; +}; + +/** + * Format the tokens dictionary to a string. This mostly defers to + * StyleDictionary.createPropertyFormatter but first it sorts the tokens based + * on the groupings in TOKEN_SECTIONS and adds comment headers to CSS output. + * + * @param {object} options + * Options for tokens to format. + * @param {string} options.format + * The format to output. Supported: "css" + * @param {object} options.dictionary + * The tokens dictionary. + * @param {string} options.outputReferences + * Whether to output variable references. + * @param {object} options.formatting + * The formatting settings to be passed to createPropertyFormatter. + * @returns {string} The formatted tokens. + */ +function formatVariables({ format, dictionary, outputReferences, formatting }) { + let lastSection = []; + let propertyFormatter = createPropertyFormatter({ + outputReferences, + dictionary, + format, + formatting, + }); + + let outputParts = []; + let remainingTokens = [...dictionary.allTokens]; + let isFirst = true; + + function tokenParts(name) { + let lastDash = name.lastIndexOf("-"); + let suffix = name.substring(lastDash + 1); + if (TSHIRT_ORDER.includes(suffix) || STATE_ORDER.includes(suffix)) { + return [name.substring(0, lastDash), suffix]; + } + return [name, ""]; + } + + for (let [label, selector] of Object.entries(TOKEN_SECTIONS)) { + let sectionMatchers = Array.isArray(selector) ? selector : [selector]; + let sectionParts = []; + + remainingTokens = remainingTokens.filter(token => { + if ( + sectionMatchers.some(m => + m.test ? m.test(token.name) : token.name.startsWith(m) + ) + ) { + sectionParts.push(token); + return false; + } + return true; + }); + + if (sectionParts.length) { + sectionParts.sort((a, b) => { + let aName = formatBaseTokenNames(a.name); + let bName = formatBaseTokenNames(b.name); + let [aToken, aSuffix] = tokenParts(aName); + let [bToken, bSuffix] = tokenParts(bName); + if (aSuffix || bSuffix) { + if (aToken == bToken) { + let aSize = TSHIRT_ORDER.indexOf(aSuffix); + let bSize = TSHIRT_ORDER.indexOf(bSuffix); + if (aSize != -1 && bSize != -1) { + return aSize - bSize; + } + let aState = STATE_ORDER.indexOf(aSuffix); + let bState = STATE_ORDER.indexOf(bSuffix); + if (aState != -1 && bState != -1) { + return aState - bState; + } + } + } + return aToken.localeCompare(bToken, undefined, { numeric: true }); + }); + + let headingParts = []; + if (!isFirst) { + headingParts.push(""); + } + isFirst = false; + + let sectionLevel = "**"; + let labelParts = label.split("/"); + for (let i = 0; i < labelParts.length; i++) { + if (labelParts[i] != lastSection[i]) { + headingParts.push( + `${formatting.indentation}/${sectionLevel} ${labelParts[i]} ${sectionLevel}/` + ); + } + sectionLevel += "*"; + } + lastSection = labelParts; + + outputParts = outputParts.concat( + headingParts.concat(sectionParts.map(propertyFormatter)) + ); + } + } + + return outputParts.join("\n"); +} + +module.exports = { + source: ["design-tokens.json"], + format: { + "css/variables/shared": createDesktopFormat(), + "css/variables/brand": createDesktopFormat("brand"), + "css/variables/platform": createDesktopFormat("platform"), + }, + platforms: { + css: { + options: { + outputReferences: true, + showFileHeader: false, + }, + transforms: [ + ...StyleDictionary.transformGroup.css, + ...["shared", "platform", "brand"].map(createLightDarkTransform), + ], + files: [ + { + destination: "tokens-shared.css", + format: "css/variables/shared", + }, + { + destination: "tokens-brand.css", + format: "css/variables/brand", + filter: token => + typeof token.original.value == "object" && + token.original.value.brand, + }, + { + destination: "tokens-platform.css", + format: "css/variables/platform", + filter: token => + typeof token.original.value == "object" && + token.original.value.platform, + }, + ], + }, + }, +}; diff --git a/toolkit/themes/shared/design-system/tokens-platform.css b/toolkit/themes/shared/design-system/tokens-platform.css index 93b6dc2dfd87..d3a48f804787 100644 --- a/toolkit/themes/shared/design-system/tokens-platform.css +++ b/toolkit/themes/shared/design-system/tokens-platform.css @@ -2,6 +2,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* DO NOT EDIT this file directly, instead modify design-tokens.json + * and run `npm run build` to see your changes. */ + @import url("chrome://global/skin/design-system/tokens-shared.css"); @layer tokens-foundation { @@ -17,7 +20,7 @@ --border-color-interactive: color-mix(in srgb, currentColor 15%, var(--color-gray-60)); /** Button **/ - --button-background-color: var(--button-bgcolor); + --button-background-color: var(--button-bgcolor); /* TODO Bug 1821203 - Gray use needs to be consolidated */ --button-background-color-hover: var(--button-hover-bgcolor); --button-background-color-active: var(--button-active-bgcolor); --button-text-color: var(--button-color); diff --git a/toolkit/themes/shared/design-system/tokens-shared.css b/toolkit/themes/shared/design-system/tokens-shared.css index 93ca1f687a09..42b33f5e0d9a 100644 --- a/toolkit/themes/shared/design-system/tokens-shared.css +++ b/toolkit/themes/shared/design-system/tokens-shared.css @@ -2,6 +2,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +/* DO NOT EDIT this file directly, instead modify design-tokens.json + * and run `npm run build` to see your changes. */ + @layer tokens-foundation, tokens-prefers-contrast, tokens-forced-colors; @layer tokens-foundation { @@ -85,8 +88,7 @@ /** Checkbox **/ --checkbox-margin-inline: var(--space-small); - /* TODO Bug 1876537: Make this em-based, probably? */ - --checkbox-size: var(--size-item-small); + --checkbox-size: var(--size-item-small); /* TODO Bug 1876537: Make this em-based, probably? */ /** Color **/ --color-black-a10: rgba(0, 0, 0, 0.1); @@ -147,9 +149,11 @@ --input-text-min-height: var(--button-min-height); /** Link **/ - /* Not using --focus-outline-offset for links because that's intended for - elements with a background, and we only want a slight offset here while not - overlapping adjacent text. */ + /** + * Not using --force-outline-offset for links because that's intended for + * elements with a background, and we only want a slight offset here while + * not overlapping adjacent text + */ --link-focus-outline-offset: 1px; /** Outline Color **/ @@ -226,7 +230,6 @@ /* Bug 1879900: Can't nest media queries inside of :host, :root selector until Bug 1879349 lands */ -/* NOTE: These do not apply in the browser chrome (bug 1878919). */ @layer tokens-forced-colors { @media (forced-colors) { :root, @@ -238,7 +241,7 @@ --border-color-interactive-disabled: GrayText; /** Button **/ - --button-background-color: ButtonFace; + --button-background-color: ButtonFace; /* TODO Bug 1821203 - Gray use needs to be consolidated */ --button-background-color-hover: SelectedItemText; --button-background-color-active: SelectedItemText; --button-background-color-disabled: ButtonFace; diff --git a/toolkit/themes/shared/desktop-jar.inc.mn b/toolkit/themes/shared/desktop-jar.inc.mn index cd08f7d5d93d..07a50b40c8e1 100644 --- a/toolkit/themes/shared/desktop-jar.inc.mn +++ b/toolkit/themes/shared/desktop-jar.inc.mn @@ -32,8 +32,8 @@ skin/classic/global/datetimeinputpickers.css (../../shared/datetimeinputpickers.css) skin/classic/global/design-system/text-and-typography.css(../../shared/design-system/text-and-typography.css) skin/classic/global/design-system/tokens-brand.css (../../shared/design-system/tokens-brand.css) - skin/classic/global/design-system/tokens-shared.css (../../shared/design-system/tokens-shared.css) skin/classic/global/design-system/tokens-platform.css (../../shared/design-system/tokens-platform.css) + skin/classic/global/design-system/tokens-shared.css (../../shared/design-system/tokens-shared.css) skin/classic/global/error-pages.css (../../shared/error-pages.css) skin/classic/global/findbar.css (../../shared/findbar.css) skin/classic/global/global-shared.css (../../shared/global-shared.css)