diff --git a/.circleci/config.yml b/.circleci/config.yml index 9aabb9a8..bc10353c 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -18,6 +18,7 @@ jobs: key: v2-npm-deps-{{ arch }}-{{ checksum "yarn.lock" }} paths: - node_modules + - run: yarn run type-check - run: yarn run build-ci - run: yarn run test - run: yarn run lint diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..31544016 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,4 @@ +node_modules +/dist +/dist-modern +/tmp diff --git a/.gitignore b/.gitignore index 7d228b2c..bf4d2b1b 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ node_modules # sewing-kit temporary folder tmp + +dist-modern diff --git a/.npmignore b/.npmignore index 718f1145..774b063f 100644 --- a/.npmignore +++ b/.npmignore @@ -1,8 +1,8 @@ **/* !dist/**/* +!dist-modern/**/* !index.js !LICENSE.md !README.md !package.json -!yarn.lock dist/colors.ase.json diff --git a/.prettierignore b/.prettierignore index ec6d3cdd..be3ca290 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1 +1,5 @@ +node_modules package.json +/.dev +/dist-modern +/tmp diff --git a/.vscode/settings.json b/.vscode/settings.json index 1ec65dfa..cf827981 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -5,5 +5,18 @@ "editor.formatOnSave": true, "editor.codeActionsOnSave": { "source.fixAll.eslint": true + }, + "files.exclude": { + "**/.DS_Store": true, + "**/.git": true, + "**/node_modules": true, + ".{bundle,dev,shadowenv.d}": true, + "{tmp,dist-modern}/": true + }, + "search.exclude": { + "**/.DS_Store": true, + "**/.git": true, + "**/node_modules": true, + "{tmp,dist-modern}/": true } } diff --git a/CHANGELOG.md b/CHANGELOG.md index 131499a7..ebaf4d12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. +- Added color factory and built modern tokens ([#105](https://github.com/Shopify/polaris-tokens/pull/105)) + - Added surface disabled variant and updated other variant configs ([#101](https://github.com/Shopify/polaris-tokens/pull/101)) + - Added TypeScript build for modern tokens, and shifted directory structures to differentiate between legacy and modern tokens ([#97](https://github.com/Shopify/polaris-tokens/pull/97)) + - Updated variant names and descriptions ([#96](https://github.com/Shopify/polaris-tokens/pull/96)) + - Added decorative icon variants ([#94](https://github.com/Shopify/polaris-tokens/pull/94)) + - Built changes from previous release, and added textOnInteractive variant ([#93](https://github.com/Shopify/polaris-tokens/pull/93)) + - Fixed an issue where legacy themes caused the color factory to throw ([#92](https://github.com/Shopify/polaris-tokens/pull/92)) + - Update color variants for consistency with changes in Polaris React ([#91](https://github.com/Shopify/polaris-tokens/pull/91)) + - Marked the config as optional and the colors as partial ([dd3d8fc](https://github.com/Shopify/polaris-tokens/commit/ + - Actually exporting the types would be helpful ([4998856](https://github.com/Shopify/polaris-tokens/commit/49988564d7048c73e53cd85eab89f5ff49d0e28b)) + - Added the Color Factory. Long live the Color Factory! ([#89](https://github.com/Shopify/polaris-tokens/pull/89)) + ## [2.7.0] - 2019-10-28 - Updated filter for the Blue color ([#64](https://github.com/Shopify/polaris-tokens/pull/64)) diff --git a/docs/index.css b/docs/index.css index 9af87b64..2ebbd1ed 100644 --- a/docs/index.css +++ b/docs/index.css @@ -6,8 +6,7 @@ body { text-transform: initial; letter-spacing: initial; color: #212b36; - font-family: -apple-system, BlinkMacSystemFont, 'San Francisco', Roboto, - 'Segoe UI', 'Helvetica Neue', sans-serif; + font-family: -apple-system, BlinkMacSystemFont, "San Francisco", Roboto, "Segoe UI", "Helvetica Neue", sans-serif; } @media (min-width: 40em) { @@ -121,7 +120,7 @@ thead th:first-child { } code { - font-family: Monaco, Consolas, 'Lucida Console', monospace; + font-family: Monaco, Consolas, "Lucida Console", monospace; } .metric-box, diff --git a/docs/index.css.map b/docs/index.css.map index 09337256..fcd0f0c7 100644 --- a/docs/index.css.map +++ b/docs/index.css.map @@ -1 +1 @@ -{"version":3,"file":"index.css","sources":["polaris-index.scss","../dist/index.scss"],"sourcesContent":["// stylelint-disable property-no-vendor-prefix, selector-max-type, selector-class-pattern\n\n@import '../dist/index';\n\nhtml,\nbody {\n font-size: 1.5rem;\n font-weight: 400;\n line-height: 2rem;\n text-transform: initial;\n letter-spacing: initial;\n color: $color-ink;\n font-family: $font-stack-base;\n}\n\n@media (min-width: 40em) {\n html,\n body {\n font-size: 1.4rem;\n }\n}\n\nhtml {\n position: relative;\n box-sizing: border-box;\n font-size: 62.5%;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n -webkit-text-size-adjust: 100%;\n -ms-text-size-adjust: 100%;\n text-size-adjust: 100%;\n text-rendering: optimizeLegibility;\n}\n\nbody {\n min-height: 100%;\n margin: 0;\n padding: 0;\n background-color: $color-sky-light;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\np {\n margin: 0;\n font-size: 1em;\n font-weight: 400;\n}\n\n.banner,\n.contentinfo {\n background: $color-sky-light;\n}\n\n.banner {\n padding: 1em 0;\n}\n\n.container {\n margin: 0 auto;\n padding: $spacing-base $spacing-extra-loose;\n max-width: 128rem;\n}\n\n.container--shadow {\n background: $color-white;\n border-radius: 6px;\n box-shadow: 0 1.2rem 3.6rem rgba(0, 0, 0, 0.2);\n margin-bottom: $spacing-extra-loose * 2;\n}\n\nh1 {\n margin: 0;\n font-size: 3rem;\n font-weight: 400;\n line-height: 2;\n padding-left: $spacing-loose;\n}\n\nsection + section {\n margin-top: $spacing-extra-loose * 2;\n}\n\ntable {\n table-layout: fixed;\n border-collapse: separate;\n border-spacing: 1rem;\n width: 100%;\n}\n\nth,\ntd {\n padding: 0 1rem;\n vertical-align: baseline;\n word-break: break-word;\n hyphens: auto;\n}\n\nth {\n font-weight: 400;\n text-align: left;\n}\n\nthead th {\n border-bottom: 1px solid $color-indigo-lighter;\n padding-top: 1rem;\n padding-bottom: 0.5rem;\n color: $color-ink-lighter;\n}\n\nthead th:first-child {\n font-size: 2rem;\n color: inherit;\n}\n\ncode {\n font-family: $font-stack-monospace;\n}\n\n.metric-box,\n.radius-box {\n display: inline-block;\n vertical-align: middle;\n background: $color-sky;\n}\n\n.radius-box {\n width: 100%;\n height: 3rem;\n}\n\n.radius-box.borderRadiusCircle {\n width: 3rem;\n}\n\n.line-height-example {\n border-bottom: 1px solid $color-sky;\n background-image: linear-gradient($color-sky 1px, transparent 1px);\n background-size: 100% 1rem;\n}\n","\n$color-purple-text: rgb(80, 73, 90);\n$color-purple-darker: rgb(35, 0, 81);\n$color-purple-dark: rgb(80, 36, 143);\n$color-purple: rgb(156, 106, 222);\n$color-purple-light: rgb(227, 208, 255);\n$color-purple-lighter: rgb(246, 240, 253);\n$color-indigo-text: rgb(62, 65, 85);\n$color-indigo-darker: rgb(0, 6, 57);\n$color-indigo-dark: rgb(32, 46, 120);\n$color-indigo: rgb(92, 106, 196);\n$color-indigo-light: rgb(179, 188, 245);\n$color-indigo-lighter: rgb(244, 245, 250);\n$color-blue-text: rgb(62, 78, 87);\n$color-blue-darker: rgb(0, 20, 41);\n$color-blue-dark: rgb(8, 78, 138);\n$color-blue: rgb(0, 111, 187);\n$color-blue-light: rgb(180, 225, 250);\n$color-blue-lighter: rgb(235, 245, 250);\n$color-teal-text: rgb(64, 83, 82);\n$color-teal-darker: rgb(0, 49, 53);\n$color-teal-dark: rgb(0, 132, 142);\n$color-teal: rgb(71, 193, 191);\n$color-teal-light: rgb(183, 236, 236);\n$color-teal-lighter: rgb(224, 245, 245);\n$color-green-text: rgb(65, 79, 62);\n$color-green-darker: rgb(23, 54, 48);\n$color-green-dark: rgb(16, 128, 67);\n$color-green: rgb(80, 184, 60);\n$color-green-light: rgb(187, 229, 179);\n$color-green-lighter: rgb(227, 241, 223);\n$color-yellow-text: rgb(89, 81, 48);\n$color-yellow-darker: rgb(87, 59, 0);\n$color-yellow-dark: rgb(138, 97, 22);\n$color-yellow: rgb(238, 194, 0);\n$color-yellow-light: rgb(255, 234, 138);\n$color-yellow-lighter: rgb(252, 241, 205);\n$color-orange-text: rgb(89, 68, 48);\n$color-orange-darker: rgb(74, 21, 4);\n$color-orange-dark: rgb(192, 87, 23);\n$color-orange: rgb(244, 147, 66);\n$color-orange-light: rgb(255, 197, 139);\n$color-orange-lighter: rgb(252, 235, 219);\n$color-red-text: rgb(88, 60, 53);\n$color-red-darker: rgb(51, 1, 1);\n$color-red-dark: rgb(191, 7, 17);\n$color-red: rgb(222, 54, 24);\n$color-red-light: rgb(254, 173, 154);\n$color-red-lighter: rgb(251, 234, 229);\n$color-ink: rgb(33, 43, 54);\n$color-ink-light: rgb(69, 79, 91);\n$color-ink-lighter: rgb(99, 115, 129);\n$color-ink-lightest: rgb(145, 158, 171);\n$color-sky-dark: rgb(196, 205, 213);\n$color-sky: rgb(223, 227, 232);\n$color-sky-light: rgb(244, 246, 248);\n$color-sky-lighter: rgb(249, 250, 251);\n$color-black: rgb(0, 0, 0);\n$color-white: rgb(255, 255, 255);\n$duration-none: 0;\n$duration-fast: 100ms;\n$duration-base: 200ms;\n$duration-slow: 300ms;\n$duration-slower: 400ms;\n$duration-slowest: 500ms;\n$spacing-none: 0;\n$spacing-extra-tight: 4px;\n$spacing-tight: 8px;\n$spacing-base-tight: 12px;\n$spacing-base: 16px;\n$spacing-loose: 20px;\n$spacing-extra-loose: 32px;\n$font-stack-base: -apple-system, BlinkMacSystemFont, 'San Francisco', Roboto, 'Segoe UI', 'Helvetica Neue', sans-serif;\n$font-stack-monospace: Monaco, Consolas, 'Lucida Console', monospace;\n"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"index.css","sources":["polaris-index.scss","../dist/index.scss"],"sourcesContent":["// stylelint-disable property-no-vendor-prefix, selector-max-type, selector-class-pattern\n\n@import '../dist/index';\n\nhtml,\nbody {\n font-size: 1.5rem;\n font-weight: 400;\n line-height: 2rem;\n text-transform: initial;\n letter-spacing: initial;\n color: $color-ink;\n font-family: $font-stack-base;\n}\n\n@media (min-width: 40em) {\n html,\n body {\n font-size: 1.4rem;\n }\n}\n\nhtml {\n position: relative;\n box-sizing: border-box;\n font-size: 62.5%;\n -webkit-font-smoothing: antialiased;\n -moz-osx-font-smoothing: grayscale;\n -webkit-text-size-adjust: 100%;\n -ms-text-size-adjust: 100%;\n text-size-adjust: 100%;\n text-rendering: optimizeLegibility;\n}\n\nbody {\n min-height: 100%;\n margin: 0;\n padding: 0;\n background-color: $color-sky-light;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\nh1,\nh2,\nh3,\nh4,\nh5,\nh6,\np {\n margin: 0;\n font-size: 1em;\n font-weight: 400;\n}\n\n.banner,\n.contentinfo {\n background: $color-sky-light;\n}\n\n.banner {\n padding: 1em 0;\n}\n\n.container {\n margin: 0 auto;\n padding: $spacing-base $spacing-extra-loose;\n max-width: 128rem;\n}\n\n.container--shadow {\n background: $color-white;\n border-radius: 6px;\n box-shadow: 0 1.2rem 3.6rem rgba(0, 0, 0, 0.2);\n margin-bottom: $spacing-extra-loose * 2;\n}\n\nh1 {\n margin: 0;\n font-size: 3rem;\n font-weight: 400;\n line-height: 2;\n padding-left: $spacing-loose;\n}\n\nsection + section {\n margin-top: $spacing-extra-loose * 2;\n}\n\ntable {\n table-layout: fixed;\n border-collapse: separate;\n border-spacing: 1rem;\n width: 100%;\n}\n\nth,\ntd {\n padding: 0 1rem;\n vertical-align: baseline;\n word-break: break-word;\n hyphens: auto;\n}\n\nth {\n font-weight: 400;\n text-align: left;\n}\n\nthead th {\n border-bottom: 1px solid $color-indigo-lighter;\n padding-top: 1rem;\n padding-bottom: 0.5rem;\n color: $color-ink-lighter;\n}\n\nthead th:first-child {\n font-size: 2rem;\n color: inherit;\n}\n\ncode {\n font-family: $font-stack-monospace;\n}\n\n.metric-box,\n.radius-box {\n display: inline-block;\n vertical-align: middle;\n background: $color-sky;\n}\n\n.radius-box {\n width: 100%;\n height: 3rem;\n}\n\n.radius-box.borderRadiusCircle {\n width: 3rem;\n}\n\n.line-height-example {\n border-bottom: 1px solid $color-sky;\n background-image: linear-gradient($color-sky 1px, transparent 1px);\n background-size: 100% 1rem;\n}\n","$color-purple-text: rgb(80, 73, 90);\n$color-purple-darker: rgb(35, 0, 81);\n$color-purple-dark: rgb(80, 36, 143);\n$color-purple: rgb(156, 106, 222);\n$color-purple-light: rgb(227, 208, 255);\n$color-purple-lighter: rgb(246, 240, 253);\n$color-indigo-text: rgb(62, 65, 85);\n$color-indigo-darker: rgb(0, 6, 57);\n$color-indigo-dark: rgb(32, 46, 120);\n$color-indigo: rgb(92, 106, 196);\n$color-indigo-light: rgb(179, 188, 245);\n$color-indigo-lighter: rgb(244, 245, 250);\n$color-blue-text: rgb(62, 78, 87);\n$color-blue-darker: rgb(0, 20, 41);\n$color-blue-dark: rgb(8, 78, 138);\n$color-blue: rgb(0, 111, 187);\n$color-blue-light: rgb(180, 225, 250);\n$color-blue-lighter: rgb(235, 245, 250);\n$color-teal-text: rgb(64, 83, 82);\n$color-teal-darker: rgb(0, 49, 53);\n$color-teal-dark: rgb(0, 132, 142);\n$color-teal: rgb(71, 193, 191);\n$color-teal-light: rgb(183, 236, 236);\n$color-teal-lighter: rgb(224, 245, 245);\n$color-green-text: rgb(65, 79, 62);\n$color-green-darker: rgb(23, 54, 48);\n$color-green-dark: rgb(16, 128, 67);\n$color-green: rgb(80, 184, 60);\n$color-green-light: rgb(187, 229, 179);\n$color-green-lighter: rgb(227, 241, 223);\n$color-yellow-text: rgb(89, 81, 48);\n$color-yellow-darker: rgb(87, 59, 0);\n$color-yellow-dark: rgb(138, 97, 22);\n$color-yellow: rgb(238, 194, 0);\n$color-yellow-light: rgb(255, 234, 138);\n$color-yellow-lighter: rgb(252, 241, 205);\n$color-orange-text: rgb(89, 68, 48);\n$color-orange-darker: rgb(74, 21, 4);\n$color-orange-dark: rgb(192, 87, 23);\n$color-orange: rgb(244, 147, 66);\n$color-orange-light: rgb(255, 197, 139);\n$color-orange-lighter: rgb(252, 235, 219);\n$color-red-text: rgb(88, 60, 53);\n$color-red-darker: rgb(51, 1, 1);\n$color-red-dark: rgb(191, 7, 17);\n$color-red: rgb(222, 54, 24);\n$color-red-light: rgb(254, 173, 154);\n$color-red-lighter: rgb(251, 234, 229);\n$color-ink: rgb(33, 43, 54);\n$color-ink-light: rgb(69, 79, 91);\n$color-ink-lighter: rgb(99, 115, 129);\n$color-ink-lightest: rgb(145, 158, 171);\n$color-sky-dark: rgb(196, 205, 213);\n$color-sky: rgb(223, 227, 232);\n$color-sky-light: rgb(244, 246, 248);\n$color-sky-lighter: rgb(249, 250, 251);\n$color-black: rgb(0, 0, 0);\n$color-white: rgb(255, 255, 255);\n$duration-none: 0;\n$duration-fast: 100ms;\n$duration-base: 200ms;\n$duration-slow: 300ms;\n$duration-slower: 400ms;\n$duration-slowest: 500ms;\n$spacing-none: 0;\n$spacing-extra-tight: 4px;\n$spacing-tight: 8px;\n$spacing-base-tight: 12px;\n$spacing-base: 16px;\n$spacing-loose: 20px;\n$spacing-extra-loose: 32px;\n$font-stack-base: -apple-system, BlinkMacSystemFont, 'San Francisco', Roboto,\n 'Segoe UI', 'Helvetica Neue', sans-serif;\n$font-stack-monospace: Monaco, Consolas, 'Lucida Console', monospace;\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/formats/tokens.js b/formats/tokens.js new file mode 100644 index 00000000..f1a006f7 --- /dev/null +++ b/formats/tokens.js @@ -0,0 +1,28 @@ +const path = require('path'); +const fs = require('fs'); + +const {colorFactory} = require('../dist-modern/color-factory.js'); +const {tokensToJson} = require('../dist-modern/utils'); + +function tokenify(scheme) { + return (result) => { + const configFile = path.basename(result.toJS().meta.file, '.yml'); + const config = `${__dirname}/../dist-modern/configs/${configFile}`; + let configArg; + + if (fs.existsSync(`${config}.js`)) { + configArg = require(`../dist-modern/configs/${configFile}`).config; + } + + const theme = tokensToJson(result); + const palette = colorFactory(theme, scheme, configArg); + + const yml = Object.entries(palette).reduce((accumulator, [key, value]) => { + return `${accumulator} - name: ${key}\n value: '${value}'\n`; + }, ''); + + return `props:\n${yml}global:\n type: color\n category: background-color\n`; + }; +} + +module.exports = {tokenify}; diff --git a/gulpfile.js b/gulpfile.js index 767f8c7d..2f10b3f3 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -75,6 +75,70 @@ const removePrefix = (gulpRenameOptions) => { return gulpRenameOptions; }; +const {tokenify} = require('./formats/tokens'); + +theo.registerTransform('theme', ['color/hex']); +theo.registerFormat('light.yml', tokenify('light')); +theo.registerFormat('dark.yml', tokenify('dark')); + +const colorSchemes = [ + {transformType: 'raw', formatType: 'light.yml'}, + {transformType: 'raw', formatType: 'dark.yml'}, +]; + +const colorSystemFormats = [ + {transformType: 'web/js', formatType: 'json'}, + {transformType: 'android', formatType: 'android.xml'}, + {transformType: 'ios', formatType: 'ios.json'}, +]; + +gulp.task('themes', (done) => { + gulp + .src('tokens/themes/*.yml') + .pipe($.rename(addPrefix)) + .pipe( + $.theo({ + transform: {type: 'theme'}, + format: {type: 'json'}, + }), + ) + .pipe($.rename(removePrefix)) + .on('error', (err) => { + throw new Error(err); + }) + .pipe(gulp.dest('dist-modern/theme')); + done(); +}); + +gulp.task('palettes', (done) => { + colorSchemes.map( + ({transformType: schemeTransform, formatType: schemeFormat}) => + colorSystemFormats.map(({transformType, formatType}) => + gulp + .src('tokens/themes/*.yml') + .pipe( + $.theo({ + transform: {type: schemeTransform}, + format: {type: schemeFormat}, + }), + ) + .pipe($.rename(addPrefix)) + .pipe( + $.theo({ + transform: {type: transformType}, + format: {type: formatType}, + }), + ) + .pipe($.rename(removePrefix)) + .on('error', (err) => { + throw new Error(err); + }) + .pipe(gulp.dest('dist-modern/palette')), + ), + ); + done(); +}); + gulp.task('web-formats', (done) => { webFormats.map(({transformType, formatType}) => gulp @@ -186,6 +250,7 @@ gulp.task('docs:styles', (done) => { $.sass .sync({ precision: 10, + outputStyle: 'expanded', }) .on('error', $.sass.logError), ) @@ -234,13 +299,15 @@ function reload(done) { function watch() { gulp.watch( - ['tokens/*.yml'], + ['tokens/*.yml', 'tokens/themes/*.yml'], gulp.series([ 'web-formats', 'typings', 'spacing-formats', 'color-formats', 'docs', + 'themes', + 'palettes', ]), ); gulp.watch('docs/**/*.scss', gulp.series('docs:styles')); @@ -251,13 +318,20 @@ function watch() { gulp.task( 'watch', gulp.series( - ['web-formats', 'spacing-formats', 'color-formats', 'docs'], + [ + 'web-formats', + 'spacing-formats', + 'color-formats', + 'docs', + 'themes', + 'palettes', + ], gulp.series(serve, watch), ), ); gulp.task( - 'default', + 'build-legacy', gulp.series([ 'web-formats', 'typings', @@ -266,3 +340,7 @@ gulp.task( 'color-formats', ]), ); + +gulp.task('build-modern', gulp.series(['themes', 'palettes'])); + +gulp.task('default', gulp.series(['build-modern', 'build-legacy'])); diff --git a/package.json b/package.json index 2f206ef1..6abb8a58 100644 --- a/package.json +++ b/package.json @@ -1,22 +1,28 @@ { "name": "@shopify/polaris-tokens", - "version": "2.7.0", + "version": "2.8.0-rc.0", "description": "Design Tokens for the Polaris Design System", "main": "index.js", "types": "dist/index.d.ts", "scripts": { "test": "sewing-kit test", "test-watch": "nodemon --exec 'yarn run build && yarn run test --no-watch' --watch ./tokens --watch ./formats --watch ./gulpfile.js --watch ./scripts --ext js,ts,json,yml", - "clean": "rimraf ./dist", + "clean": "rimraf ./dist-modern ./dist", "prebuild": "yarn run clean", - "build": "npm-run-all build:**", - "build-ci": "npm-run-all build:* build:*:*", - "build:gulp": "gulp", - "build:docs": "gulp docs", - "build:format": "prettier ./{dist,docs}/*.{js,json,css,scss,sketchpalette} --write", - "build:colors:ase": "node ./scripts/ase-encode.js", - "build:colors:clr:exclude-from-ci": "ase2clr ./dist/colors.ase ./dist/colors.clr", - "build:colors:rename-palettes:exclude-from-ci": "renamer --find colors --replace Polaris ./dist/colors.{ase,clr,sketchpalette}", + "build": "npm-run-all build-modern build-legacy build-docs", + "build-ci": "npm-run-all build-modern build-legacy-ci build-docs", + "build-legacy": "npm-run-all build-legacy:**", + "build-legacy-ci": "npm-run-all build-legacy:* build-legacy:*:*", + "build-legacy:gulp": "gulp build-legacy", + "build-legacy:format": "prettier ./dist/*.{js,json,css,scss,sketchpalette} --write", + "build-legacy:colors:ase": "node ./scripts/ase-encode.js", + "build-legacy:colors:clr:exclude-from-ci": "ase2clr ./dist/colors.ase ./dist/colors.clr", + "build-legacy:colors:rename-palettes:exclude-from-ci": "renamer --find colors --replace Polaris ./dist/colors.{ase,clr,sketchpalette}", + "build-modern": "npm-run-all build-modern:ts build-modern:gulp", + "build-modern:ts": "tsc -p tsconfig.build.json", + "build-modern:gulp": "gulp build-modern", + "build-docs": "gulp docs", + "type-check": "sewing-kit type-check", "lint": "sewing-kit lint", "watch": "gulp watch", "heroku-postbuild": "yarn run build-ci", @@ -41,7 +47,7 @@ }, "eslintConfig": { "extends": [ - "plugin:shopify/esnext", + "plugin:shopify/typescript", "plugin:shopify/node", "plugin:shopify/jest", "plugin:shopify/prettier" @@ -55,6 +61,8 @@ "homepage": "https://github.com/Shopify/polaris-tokens#readme", "devDependencies": { "@shopify/sewing-kit": "^0.116.0", + "@types/lodash": "^4.14.149", + "@types/theo": "^8.1.3", "ase-util": "^1.0.3", "ase-utils": "^0.1.1", "browser-sync": "^2.26.7", @@ -76,6 +84,11 @@ "rimraf": "^3.0.0", "theo": "8.1.4", "tinycolor2": "^1.4.1", + "typescript": "^3.7.5", "xml": "^1.0.1" + }, + "dependencies": { + "hsluv": "^0.1.0", + "tslib": "^1.10.0" } } diff --git a/polaris_tokens.gemspec b/polaris_tokens.gemspec index 0ab7237d..0cb16000 100644 --- a/polaris_tokens.gemspec +++ b/polaris_tokens.gemspec @@ -16,7 +16,7 @@ Gem::Specification.new do |s| s.summary = 'Design Tokens for the Polaris Design System' s.description = 'Design Tokens for the Polaris Design System' s.files = Dir[ - "{dist,lib}/**/*", + "{dist,dist-modern/palette,dist-modern/theme,lib}/**/*", 'README.md', 'LICENSE.md', 'package.json', diff --git a/sewing-kit.config.ts b/sewing-kit.config.ts new file mode 100644 index 00000000..9cc65c77 --- /dev/null +++ b/sewing-kit.config.ts @@ -0,0 +1,11 @@ +import {ConfigurationCallback} from '@shopify/sewing-kit'; + +const sewingKitConfig: ConfigurationCallback = () => { + return { + name: 'polaris-tokens', + library: true, + plugins: [], + }; +}; + +export default sewingKitConfig; diff --git a/shipit.yml b/shipit.yml index dad011f1..f84b60ab 100644 --- a/shipit.yml +++ b/shipit.yml @@ -4,6 +4,7 @@ dependencies: - bundle install deploy: pre: + - yarn run build-modern - bundle exec rake build # Use auto-dist-tag to still allow publishing beta, alpha, and rc versions - npx auto-dist-tag --write diff --git a/src/color-factory.test.ts b/src/color-factory.test.ts new file mode 100644 index 00000000..eb164293 --- /dev/null +++ b/src/color-factory.test.ts @@ -0,0 +1,45 @@ +import {colorFactory} from './color-factory'; + +describe('colorFactory()', () => { + const colors = { + surface: '#111213', + onSurface: '#111213', + interactive: '#2E72D2', + secondary: '#111213', + primary: '#008060', + critical: '#D82C0D', + warning: '#FFC453', + highlight: '#5BCDDA', + success: '#008060', + decorative: '#FFC96B', + }; + + it('outputs variants', () => { + const variants = colorFactory(colors, 'light'); + expect(Object.keys(variants)).toContain('text'); + }); + + it('does not throw when given a color role without a corresponding config', () => { + expect(() => { + colorFactory({blarp: 'notAColor'}, 'light'); + }).not.toThrow(); + }); + + it('does not throw when given a non-standard shape', () => { + expect(() => { + colorFactory( + { + // Silly casting needed to stop typescript helpfully pointing out that + // this is invalid as topBar should be a string, not an object + topBar: ({background: '#eeeeee'} as unknown) as string, + surface: '#ffffff', + }, + 'light', + ); + }).not.toThrow(); + }); + + it.todo('creates variants based on a theme'); + + it.todo('creates variants based on a custom config'); +}); diff --git a/src/color-factory.ts b/src/color-factory.ts new file mode 100644 index 00000000..ffbb5889 --- /dev/null +++ b/src/color-factory.ts @@ -0,0 +1,49 @@ +import {hexToHsluv, hsluvToRgb} from 'hsluv'; + +import {config as baseConfig} from './configs/base'; +import {Lambda} from './types'; + +type Scheme = 'light' | 'dark'; + +export function colorFactory( + theme: Partial>, + scheme: Scheme, + config = baseConfig, +) { + return Object.assign( + {}, + ...Object.entries(theme).map(([role, hex]) => { + if (typeof hex !== 'string') { + return null; + } + + const base = hexToHsluv(hex); + const variants = config[role] || []; + return { + ...variants.reduce((accumulator, {name, ...settings}) => { + const { + hue = base[0], + saturation = base[1], + lightness = base[2], + alpha = 1, + } = settings[scheme]; + + const resolve = (value: number | Lambda, baseToResolve: number) => { + return typeof value === 'number' ? value : value(baseToResolve); + }; + + const [red, green, blue] = hsluvToRgb([ + resolve(hue, base[0]), + resolve(saturation, base[1]), + resolve(lightness, base[2]), + ]).map((channel) => Math.round(channel * 255)); + + return { + ...accumulator, + [name]: `rgba(${red}, ${green}, ${blue}, ${alpha})`, + }; + }, {}), + }; + }), + ); +} diff --git a/src/configs/base.ts b/src/configs/base.ts new file mode 100644 index 00000000..6ec21840 --- /dev/null +++ b/src/configs/base.ts @@ -0,0 +1,806 @@ +import {saturationAdjustmentFn, hueRotationFn} from '../utils'; +import {Config} from '../types'; + +export const config: Config = { + surface: [ + { + name: 'background', + description: + 'For use as a background color, in components such as Page and Frame backgrounds.', + light: {lightness: 98.3}, + dark: {lightness: 3.3}, + }, + { + name: 'surface', + description: + 'For use as a background color, in components such as Card, Modal, and Popover.', + light: {lightness: 100}, + dark: {lightness: 12.7}, + }, + { + name: 'surfaceSubdued', + description: + 'For use as a subdued background color, in components such as Card, Modal, and Popover.', + light: {lightness: 98.3}, + dark: {lightness: 10}, + }, + { + name: 'surfaceDisabled', + description: + 'For use as a surface color on disabled interactive elements such as option list items and action list items when in a disabled state.', + light: {lightness: 98.3}, + dark: {lightness: 10}, + }, + { + name: 'surfaceHovered', + description: + 'For use as a surface color on interactive elements such as resource list items and action list items when in a hovered state.', + light: {lightness: 95}, + dark: {lightness: 20}, + }, + { + name: 'surfacePressed', + description: + 'For use as a surface color on interactive elements such as resource list items and action list items when in a pressed state.', + light: {lightness: 92}, + dark: {lightness: 27}, + }, + { + name: 'backdrop', + description: + 'For use as the background color of the backdrop component for navigation and modal. This color has an alpha of `0.5`.', + light: { + hue: 0, + saturation: 0, + lightness: 0, + alpha: 0.5, + }, + dark: { + hue: 0, + saturation: 0, + lightness: 0, + alpha: 0.5, + }, + }, + { + name: 'overlay', + description: + 'For use as the background color of elements which lay on top of surfaces to obscure their contents. This color has an alpha of `0.5`.', + light: { + hue: 0, + saturation: 0, + lightness: 100, + alpha: 0.5, + }, + dark: { + hue: 0, + saturation: 0, + lightness: 12.7, + alpha: 0.5, + }, + }, + { + name: 'shadowFromAmbientLight', + description: + 'For use in building shadows for popovers, cards, and modals. This color has an alpha of `0.05`.', + light: { + hue: 180, + saturation: 5, + lightness: 8, + alpha: 0.05, + }, + dark: { + hue: 180, + saturation: 5, + lightness: 8, + alpha: 0.05, + }, + }, + { + name: 'shadowFromDirectLight', + description: + 'For use in building shadows for popovers, cards, and modals. This color has an alpha of `0.15`.', + light: { + hue: 0, + saturation: 0, + lightness: 0, + alpha: 0.15, + }, + dark: { + hue: 0, + saturation: 0, + lightness: 100, + alpha: 0.15, + }, + }, + { + name: 'hintFromDirectLight', + description: 'For use in building shadows scrollables.', + light: { + hue: 0, + saturation: 0, + lightness: 0, + alpha: 0.15, + }, + dark: { + hue: 0, + saturation: 0, + lightness: 75, + alpha: 0.2, + }, + }, + ], + onSurface: [ + { + name: 'border', + description: 'For use as a border on non-interactive elements.', + light: {lightness: 75}, + dark: {lightness: 35}, + }, + { + name: 'borderSubdued', + description: 'For use as a subdued border on non-interactive elements.', + light: {lightness: 85}, + dark: {lightness: 32}, + }, + { + name: 'icon', + description: 'For use as the fill color of icons.', + light: {lightness: 40.1}, + dark: {lightness: 70.1}, + }, + { + name: 'iconHovered', + description: 'For use as the fill color of hovered icons.', + light: {lightness: 10}, + dark: {lightness: 90}, + }, + { + name: 'iconPressed', + description: 'For use as the fill color of pressed icons.', + light: {lightness: 30}, + dark: {lightness: 70}, + }, + { + name: 'iconDisabled', + description: 'For use as the fill color of disabled icons.', + light: {lightness: 76.9}, + dark: {lightness: 36.8}, + }, + { + name: 'iconSubdued', + description: 'For use as the fill color of subdued icons.', + light: {lightness: 59.8}, + dark: {lightness: 52.1}, + }, + { + name: 'text', + description: 'For use as a text color.', + light: {lightness: 13.1}, + dark: {lightness: 90.8}, + }, + { + name: 'textDisabled', + description: 'For use as a disabled text color.', + light: {lightness: 61.3}, + dark: {lightness: 48.2}, + }, + { + name: 'textSubdued', + description: 'For use as a subdued text color.', + light: {lightness: 47.4}, + dark: {lightness: 65.1}, + }, + ], + interactive: [ + { + name: 'interactive', + description: + 'Used for links, plain buttons, and as the fill color for selected checkboxes and radio buttons.', + light: {lightness: 48.6}, + dark: { + lightness: 65, + saturation: saturationAdjustmentFn(11.2), + hue: hueRotationFn(-7.1), + }, + }, + { + name: 'interactiveDisabled', + description: 'Used for disabled links and plain buttons.', + light: {lightness: 58}, + dark: { + lightness: 42, + }, + }, + { + name: 'interactiveHovered', + description: 'Used for hovered links and plain buttons.', + light: {lightness: 37}, + dark: { + lightness: 70, + saturation: saturationAdjustmentFn(11.2), + hue: hueRotationFn(-7.1), + }, + }, + { + name: 'interactivePressed', + description: 'Used for pressed links and plain buttons.', + light: {lightness: 31}, + dark: { + lightness: 75, + saturation: saturationAdjustmentFn(11.2), + hue: hueRotationFn(-7.1), + }, + }, + { + name: 'focused', + description: 'For use in the focus ring on interactive elements.', + light: {lightness: 58}, + dark: {lightness: 42}, + }, + { + name: 'surfaceSelected', + description: + 'For use as a surface color in selected interactive elements, in components such as action list and resource list.', + light: {lightness: 96}, + dark: {lightness: 4}, + }, + { + name: 'surfaceSelectedHovered', + description: + 'For use as a surface color in selected interactive elements that are hovered, in components such as action list and resource list.', + light: {lightness: 89}, + dark: {lightness: 11}, + }, + { + name: 'surfaceSelectedPressed', + description: + 'For use as a surface color in selected interactive elements that are pressed, in components such as action list and resource list.', + light: {lightness: 82}, + dark: {lightness: 18}, + }, + { + name: 'iconOnInteractive', + description: 'For use as a fill color for icons on interactive elements.', + light: {lightness: 100}, + dark: {lightness: 100}, + }, + { + name: 'textOnInteractive', + description: 'For use as a text color on interactive elements.', + light: {lightness: 100}, + dark: {lightness: 100}, + }, + ], + secondary: [ + { + name: 'actionSecondary', + description: + 'Used for secondary buttons and tertiary buttons, as well as in form elements as a background color and pontentially other secondary surfaces.', + light: {lightness: 93}, + dark: {lightness: 34}, + }, + { + name: 'actionSecondaryDisabled', + description: 'Used as a disabled state for secondary buttons', + light: {lightness: 95}, + dark: {lightness: 13}, + }, + { + name: 'actionSecondaryHovered', + description: 'Used as a hovered state for secondary buttons', + light: {lightness: 90}, + dark: {lightness: 37}, + }, + { + name: 'actionSecondaryPressed', + description: 'Used as a pressed state for secondary buttons', + light: {lightness: 87}, + dark: {lightness: 42}, + }, + { + name: 'borderSecondary', + description: 'Used for borders on form elements', + light: {lightness: 75}, + dark: {lightness: 35}, + }, + { + name: 'borderSecondaryHovered', + description: 'Used for borders on hovered form elements', + light: {lightness: 65}, + dark: {lightness: 35}, + }, + { + name: 'borderSecondaryDisabled', + description: 'Used for disabled borders on form elements', + light: {lightness: 85}, + dark: {lightness: 45}, + }, + ], + primary: [ + { + name: 'actionPrimary', + description: + 'Used as the background color for primary actions, and as the fill color for icons and the text color in navigation and tabs to communicate interaction states.', + light: {lightness: 47.3}, + dark: {lightness: 47.3}, + }, + { + name: 'actionPrimaryDisabled', + description: + 'Used as the background color for disabled primary actions, and as the fill color for icons and the text color in navigation and tabs to communicate interaction states.', + light: {lightness: 32}, + dark: {lightness: 32}, + }, + { + name: 'actionPrimaryHovered', + description: + 'Used as the background color for hovered primary actions, and as the fill color for icons and the text color in navigation and tabs to communicate interaction states.', + light: {lightness: 42.3}, + dark: {lightness: 55}, + }, + { + name: 'actionPrimaryPressed', + description: + 'Used as the background color for pressed primary actions, and as the fill color for icons and the text color in navigation and tabs to communicate interaction states.', + light: {lightness: 37.3}, + dark: {lightness: 60}, + }, + { + name: 'iconOnPrimary', + description: + 'For use as a fill color for icons on primary actions. Not for use in icons on navigation and tabs.', + light: {lightness: 98}, + dark: {lightness: 98}, + }, + { + name: 'textOnPrimary', + description: + 'For use as a text color on primary actions. Not for use in text on navigation and tabs.', + light: {lightness: 100}, + dark: {lightness: 100}, + }, + { + name: 'surfacePrimarySelected', + description: + 'Used as a surface color to indicate selected interactive states in navigation and tabs.', + light: {lightness: 95, saturation: 20}, + dark: {lightness: 5, saturation: 30}, + }, + { + name: 'surfacePrimarySelectedHovered', + description: + 'Used as a surface color to indicate selected interactive states that are hovered in navigation and tabs.', + light: {lightness: 81, saturation: 22}, + dark: {lightness: 19, saturation: 22}, + }, + { + name: 'surfacePrimarySelectedPressed', + description: + 'Used as a surface color to indicate selected interactive states that are pressed in navigation and tabs.', + light: {lightness: 74, saturation: 22}, + dark: {lightness: 26, saturation: 22}, + }, + ], + critical: [ + { + name: 'borderCritical', + description: + 'For use as a border on critical components such as banners, and as an outline on interactive elements in an error state.', + light: {lightness: 50}, + dark: {lightness: 50}, + }, + { + name: 'borderCriticalDisabled', + description: + 'For use as a disabled border on critical components such as banners, and as an outline on interactive elements in an error state.', + light: {lightness: 82}, + dark: {lightness: 28}, + }, + { + name: 'iconCritical', + description: 'For use as an icon fill color on top of critical elements.', + light: {lightness: 47.3}, + dark: {lightness: 48}, + }, + { + name: 'surfaceCritical', + description: + 'For use as a surface color on critical elements including badges.', + light: {lightness: 98.6}, + dark: {lightness: 12}, + }, + { + name: 'surfaceCriticalSubdued', + description: + 'For use as a subdued surface color on critical elements including banners.', + light: {lightness: 98}, + dark: {lightness: 12}, + }, + { + name: 'surfaceCriticalSubduedHovered', + description: + 'For use as a surface color on critical interactive elements including action list items in a hovered state.', + light: {lightness: 96}, + dark: {lightness: 15, saturation: 60}, + }, + { + name: 'surfaceCriticalSubduedPressed', + description: + 'For use as a surface color on critical interactive elements including action list items in a pressed state.', + light: {lightness: 88}, + dark: {lightness: 22}, + }, + { + name: 'textCritical', + description: + 'For use as a text color in inert critical elements such as exception list. Not for use as a text color on banners and badges.', + light: {lightness: 47.3}, + dark: {lightness: 65, saturation: 70}, + }, + { + name: 'actionCritical', + description: + 'For use as the background color for destructive buttons, and as the background color for error toast messages.', + light: {lightness: 47.5}, + dark: {lightness: 45}, + }, + { + name: 'actionCriticalDisabled', + description: + 'For use as the background color for disabled destructive buttons, and as the background color for error toast messages.', + light: {lightness: 59}, + dark: {lightness: 41}, + }, + { + name: 'actionCriticalHovered', + description: + 'For use as the background color for hovered destructive buttons, and as the background color for error toast messages.', + light: {lightness: 42.5}, + dark: {lightness: 50}, + }, + { + name: 'actionCriticalPressed', + description: + 'For use as the background color for pressed destructive buttons, and as the background color for error toast messages.', + light: {lightness: 37.5}, + dark: {lightness: 55}, + }, + { + name: 'iconOnCritical', + description: 'For use as a fill color for icons on critical actions.', + light: {lightness: 98}, + dark: {lightness: 98}, + }, + { + name: 'textOnCritical', + description: 'For use as a text color on critical actions.', + light: {lightness: 100}, + dark: {lightness: 100}, + }, + { + name: 'interactiveCritical', + description: + 'Used for destructive interactive elements: links, destructive plain buttons, error state of selected checkboxes and radio buttons, as well as a text color on destructive action list items. Not for use on critical banners and badges.', + light: {lightness: 48.5}, + dark: {lightness: 65}, + }, + { + name: 'interactiveCriticalDisabled', + description: + 'For use as a text color in disabled destructive plain buttons, as well as a text color on destructive action list items. Not for use on critical banners and badges.', + light: {lightness: 72}, + dark: {lightness: 78}, + }, + { + name: 'interactiveCriticalHovered', + description: + 'For use as a text color in hovered destructive plain buttons, as well as a text color on destructive action list items. Not for use on critical banners and badges.', + light: {lightness: 45}, + dark: {lightness: 70}, + }, + { + name: 'interactiveCriticalPressed', + description: + 'For use as a text color in pressed destructive plain buttons, as well as a text color on destructive action list items. Not for use on critical banners and badges.', + light: {lightness: 21}, + dark: {lightness: 75}, + }, + ], + warning: [ + { + name: 'borderWarning', + description: 'For use as a border on warning components such as banners.', + light: {lightness: 76.6}, + dark: {lightness: 50}, + }, + { + name: 'iconWarning', + description: 'For use as an icon fill color on top of warning elements.', + light: {lightness: 60}, + dark: {lightness: 34}, + }, + { + name: 'surfaceWarning', + description: + 'For use as a surface color on warning elements including badges.', + light: {lightness: 84.5}, + dark: {lightness: 50}, + }, + { + name: 'surfaceWarningSubdued', + description: + 'For use as a subdued surface color on warning elements including banners.', + light: {lightness: 96}, + dark: {lightness: 26, saturation: 71}, + }, + { + name: 'textWarning', + description: + 'For use as a text color in inert critical elements such as exception list. Not for use as a text color on banners and badges.', + light: {lightness: 47.4}, + dark: {lightness: 64.9}, + }, + ], + highlight: [ + { + name: 'borderHighlight', + description: + 'For use as a border on informational components such as banners.', + light: {lightness: 60}, + dark: {lightness: 60}, + }, + { + name: 'iconHighlight', + description: + 'For use as an icon fill color on top of informational elements.', + light: {lightness: 58}, + dark: {lightness: 42}, + }, + { + name: 'surfaceHighlight', + description: + 'For use as a surface color on information elements including badges.', + light: {lightness: 84.5, saturation: 60}, + dark: {lightness: 40, saturation: 100}, + }, + { + name: 'surfaceHighlightSubdued', + description: + 'For use as a surface color on information elements including banners.', + light: {lightness: 98.6}, + dark: {lightness: 20}, + }, + { + name: 'textHighlight', + description: + 'For use as a text color in inert informational elements. Not for use as a text color on banners and badges.', + light: {lightness: 10}, + dark: {lightness: 90}, + }, + ], + success: [ + { + name: 'borderSuccess', + description: 'For use as a border on success components such as banners.', + light: {lightness: 50}, + dark: {lightness: 50}, + }, + { + name: 'iconSuccess', + description: 'For use as an icon fill color on top of success elements.', + light: {lightness: 25}, + dark: {lightness: 35}, + }, + { + name: 'surfaceSuccess', + description: + 'For use as a surface color on success elements including badges.', + light: {lightness: 84.5, saturation: 60}, + dark: {lightness: 35}, + }, + { + name: 'surfaceSuccessSubdued', + description: + 'For use as a surface color on information elements including banners.', + light: {lightness: 99, saturation: 60}, + dark: {lightness: 20, saturation: 60}, + }, + { + name: 'textSuccess', + description: + 'For use as a text color in inert success elements. Not for use as a text color on banners and badges.', + light: {lightness: 47.3}, + dark: {lightness: 65, saturation: 70}, + }, + ], + decorative: [ + { + name: 'decorativeOneIcon', + description: + 'For use as a decorative icon color that is applied on a decorative surface.', + light: { + hue: hueRotationFn(-4.5), + lightness: 40, + }, + dark: { + hue: hueRotationFn(-4.5), + lightness: 80, + }, + }, + { + name: 'decorativeOneSurface', + description: 'For use as a decorative surface color.', + light: { + lightness: 84, + }, + dark: { + hue: hueRotationFn(-2.5), + saturation: saturationAdjustmentFn(-2), + lightness: 46, + }, + }, + { + name: 'decorativeOneText', + description: + 'For use as a decorative text color that is applied on a decorative surface.', + light: { + hue: hueRotationFn(-4.5), + lightness: 18, + }, + dark: {lightness: 100}, + }, + { + name: 'decorativeTwoIcon', + description: + 'For use as a decorative icon color that is applied on a decorative surface.', + light: { + hue: hueRotationFn(305.5), + saturation: saturationAdjustmentFn(-20), + lightness: 40, + }, + dark: { + hue: hueRotationFn(305.5), + saturation: saturationAdjustmentFn(-20), + lightness: 80, + }, + }, + { + name: 'decorativeTwoSurface', + description: 'For use as a decorative surface color.', + light: { + hue: hueRotationFn(-26.5), + lightness: 84, + }, + dark: { + hue: hueRotationFn(-32.5), + saturation: saturationAdjustmentFn(-4), + lightness: 52, + }, + }, + { + name: 'decorativeTwoText', + description: + 'For use as a decorative text color that is applied on a decorative surface.', + light: { + hue: hueRotationFn(305.5), + saturation: saturationAdjustmentFn(-20), + lightness: 14, + }, + dark: {lightness: 100}, + }, + { + name: 'decorativeThreeIcon', + description: + 'For use as a decorative icon color that is applied on a decorative surface.', + light: { + hue: hueRotationFn(87.5), + lightness: 40, + }, + dark: { + hue: hueRotationFn(87.5), + lightness: 80, + }, + }, + { + name: 'decorativeThreeSurface', + description: 'For use as a decorative surface color.', + light: { + hue: hueRotationFn(87.5), + saturation: saturationAdjustmentFn(-46), + lightness: 85, + }, + dark: { + hue: hueRotationFn(97.5), + lightness: 46, + }, + }, + { + name: 'decorativeThreeText', + description: + 'For use as a decorative text color that is applied on a decorative surface.', + light: { + hue: hueRotationFn(87.5), + lightness: 16, + }, + dark: {lightness: 100}, + }, + { + name: 'decorativeFourIcon', + description: + 'For use as a decorative icon color that is applied on a decorative surface.', + light: { + hue: hueRotationFn(133.5), + lightness: 40, + }, + dark: { + hue: hueRotationFn(133.5), + lightness: 80, + }, + }, + { + name: 'decorativeFourSurface', + description: 'For use as a decorative surface color.', + light: { + hue: hueRotationFn(123.5), + saturation: saturationAdjustmentFn(-44), + lightness: 84, + }, + dark: { + hue: hueRotationFn(131.5), + saturation: saturationAdjustmentFn(-5), + lightness: 47, + }, + }, + { + name: 'decorativeFourText', + description: + 'For use as a decorative text color that is applied on a decorative surface.', + light: { + hue: hueRotationFn(133.5), + lightness: 16, + }, + dark: {lightness: 100}, + }, + { + name: 'decorativeFiveIcon', + description: + 'For use as a decorative icon color that is applied on a decorative surface.', + light: { + hue: hueRotationFn(306.5), + saturation: saturationAdjustmentFn(-22), + lightness: 40, + }, + dark: { + hue: hueRotationFn(306.5), + saturation: saturationAdjustmentFn(-22), + lightness: 80, + }, + }, + { + name: 'decorativeFiveSurface', + description: 'For use as a decorative surface color.', + light: { + hue: hueRotationFn(-53.4), + saturation: saturationAdjustmentFn(-5.4), + lightness: 85.6, + }, + dark: { + hue: hueRotationFn(306.5), + saturation: saturationAdjustmentFn(-23), + lightness: 45, + }, + }, + { + name: 'decorativeFiveText', + description: + 'For use as a decorative text color that is applied on a decorative surface.', + light: { + hue: hueRotationFn(306.5), + saturation: saturationAdjustmentFn(-22), + lightness: 16, + }, + dark: {lightness: 100}, + }, + ], +}; diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 00000000..47cd276b --- /dev/null +++ b/src/index.ts @@ -0,0 +1 @@ +export {colorFactory} from './color-factory'; diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 00000000..bf8e5a12 --- /dev/null +++ b/src/types.ts @@ -0,0 +1,17 @@ +export type Lambda = (value: number) => number; + +interface HslaSetting { + hue?: number | Lambda; + saturation?: number | Lambda; + lightness?: number | Lambda; + alpha?: number; +} + +export interface Variant { + name: string; + description?: string; + light: HslaSetting; + dark: HslaSetting; +} + +export type Config = Record; diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 00000000..277c0271 --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,49 @@ +import {ImmutableStyleMap} from 'theo'; + +import {Config} from './types'; + +export function hueRotationFn(rotation: number) { + return (hue: number) => (360 + hue + rotation) % 360; +} + +export function saturationAdjustmentFn(adjustment: number) { + return (saturation: number) => + Math.min(Math.max(saturation + adjustment, 0), 100); +} + +export function tokensToJson(data: ImmutableStyleMap) { + return data.toJS().props.reduce( + (accumulator: any, prop: any) => ({ + ...accumulator, + [prop.name]: prop.originalValue, + }), + {}, + ); +} + +export function mergeConfigs(base: Config, extended: Config) { + return Object.entries(base).reduce((accumulator, [role, variants]) => { + const extendedVariants = extended[role]; + const mergedVariants = variants; + + if (extendedVariants != null) { + extendedVariants.forEach((variant) => { + const {name} = variant; + const indexToReplace = mergedVariants.findIndex( + (baseVariant) => baseVariant.name === name, + ); + + if (indexToReplace === -1) { + mergedVariants.push(variant); + } else { + mergedVariants.splice(indexToReplace, 1, variant); + } + }); + } + + return { + ...accumulator, + [role]: mergedVariants, + }; + }, {}); +} diff --git a/tests/__snapshots__/colors.test.js.snap b/tests/__snapshots__/colors.test.ts.snap similarity index 100% rename from tests/__snapshots__/colors.test.js.snap rename to tests/__snapshots__/colors.test.ts.snap diff --git a/tests/__snapshots__/duration.test.js.snap b/tests/__snapshots__/duration.test.ts.snap similarity index 100% rename from tests/__snapshots__/duration.test.js.snap rename to tests/__snapshots__/duration.test.ts.snap diff --git a/tests/colors.test.js b/tests/colors.test.ts similarity index 75% rename from tests/colors.test.js rename to tests/colors.test.ts index b11a048e..a550779d 100644 --- a/tests/colors.test.js +++ b/tests/colors.test.ts @@ -1,13 +1,15 @@ /* eslint-disable shopify/jest/no-snapshots */ -const fs = require('fs'); -const path = require('path'); +import fs from 'fs'; +import path from 'path'; -const _ = require('lodash'); +import lodash from 'lodash'; +/* eslint-disable @typescript-eslint/no-var-requires */ const colorsJSON = require('../dist/colors.json'); const colorsAseJSON = require('../dist/colors.ase.json'); const colorsRawJSON = require('../dist/colors.raw.json'); +/* eslint-enable @typescript-eslint/no-var-requires */ const colorFiles = [ 'colors.android.xml', @@ -35,7 +37,8 @@ describe('Compare files snapshots', () => { describe('JSON object representation', () => { it('renders similar JSON objects', () => { expect( - _(colorsJSON) + lodash + .chain(colorsJSON) .toPairs() .sortBy(0) .fromPairs() @@ -46,13 +49,14 @@ describe('JSON object representation', () => { it('renders similar ASE JSON objects', () => { expect(colorsAseJSON.version).toBe('1.0'); expect(colorsAseJSON.groups).toHaveLength(0); - expect(_(colorsAseJSON.colors).sortBy('name')).toMatchSnapshot(); + expect(lodash.sortBy(colorsAseJSON.colors, 'name')).toMatchSnapshot(); }); it('renders similar RAW JSON objects', () => { // Aliases expect( - _(colorsRawJSON.aliases) + lodash + .chain(colorsRawJSON.aliases) .toPairs() .sortBy(0) .fromPairs() @@ -60,6 +64,6 @@ describe('JSON object representation', () => { ).toMatchSnapshot(); // Props - expect(_(colorsRawJSON.props).sortBy('name')).toMatchSnapshot(); + expect(lodash.sortBy(colorsRawJSON.props, 'name')).toMatchSnapshot(); }); }); diff --git a/tests/duration.test.js b/tests/duration.test.ts similarity index 78% rename from tests/duration.test.js rename to tests/duration.test.ts index 7b51b1bc..0b113422 100644 --- a/tests/duration.test.js +++ b/tests/duration.test.ts @@ -1,12 +1,14 @@ /* eslint-disable shopify/jest/no-snapshots */ -const fs = require('fs'); -const path = require('path'); +import fs from 'fs'; +import path from 'path'; -const _ = require('lodash'); +import lodash from 'lodash'; +/* eslint-disable @typescript-eslint/no-var-requires */ const durationJSON = require('../dist/duration.json'); const durationRawJSON = require('../dist/duration.raw.json'); +/* eslint-enable @typescript-eslint/no-var-requires */ const durationFiles = [ 'duration.map.scss', @@ -34,7 +36,8 @@ describe('Compare files snapshots', () => { describe('JSON object representation', () => { it('renders similar JSON objects', () => { expect( - _(durationJSON) + lodash + .chain(durationJSON) .toPairs() .sortBy(0) .fromPairs() @@ -43,16 +46,17 @@ describe('JSON object representation', () => { }); it('outputs integers in JSON', () => { - const everyValueIsInteger = Object.values(durationJSON).every((value) => - Number.isInteger(value), - ); + const everyValueIsInteger = Object.values( + durationJSON, + ).every((value: any) => Number.isInteger(value)); expect(everyValueIsInteger).toBe(true); }); it('renders similar RAW JSON objects', () => { // Aliases expect( - _(durationRawJSON.aliases) + lodash + .chain(durationRawJSON.aliases) .toPairs() .sortBy(0) .fromPairs() @@ -60,7 +64,7 @@ describe('JSON object representation', () => { ).toMatchSnapshot(); // Props - expect(_(durationRawJSON.props).sortBy('name')).toMatchSnapshot(); + expect(lodash.sortBy(durationRawJSON.props, 'name')).toMatchSnapshot(); }); it('outputs `none` value as integer', () => { diff --git a/tests/package.json.test.js b/tests/package.json.test.js deleted file mode 100644 index 5e1f2201..00000000 --- a/tests/package.json.test.js +++ /dev/null @@ -1,5 +0,0 @@ -describe('package.json', () => { - it('doesn’t have any dependencies', () => { - expect(require('../package.json').dependencies).toBeUndefined(); - }); -}); diff --git a/tokens/themes/base.yml b/tokens/themes/base.yml new file mode 100644 index 00000000..a143f14f --- /dev/null +++ b/tokens/themes/base.yml @@ -0,0 +1,24 @@ +props: + - name: surface + value: '#111213' + - name: onSurface + value: '#111213' + - name: interactive + value: '#2E72D2' + - name: secondary + value: '#111213' + - name: primary + value: '#008060' + - name: critical + value: '#D82C0D' + - name: warning + value: '#FFC453' + - name: highlight + value: '#5BCDDA' + - name: success + value: '#008060' + - name: decorative + value: '#FFC96B' +global: + type: color + category: background-color diff --git a/tsconfig.build.json b/tsconfig.build.json new file mode 100644 index 00000000..2a4d6d3f --- /dev/null +++ b/tsconfig.build.json @@ -0,0 +1,5 @@ +{ + "extends": "./tsconfig.json", + "include": ["./src"], + "exclude": ["./src/**/*.test.ts"] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..13a48372 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@shopify/typescript-configs/library", + "compilerOptions": { + "outDir": "./dist-modern", + "module": "commonjs", + "declarationMap": false, + "importHelpers": true + }, + "include": ["./src", "./tests"] +} diff --git a/yarn.lock b/yarn.lock index 8f881cf2..1804f80e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1585,6 +1585,11 @@ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339" integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA== +"@types/lodash@^4.14.149": + version "4.14.149" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.149.tgz#1342d63d948c6062838fbf961012f74d4e638440" + integrity sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ== + "@types/minimatch@*": version "3.0.3" resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" @@ -1627,6 +1632,13 @@ resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.4.tgz#b4ffc7dc97b498c969b360a41eee247f82616370" integrity sha512-78AdXtlhpCHT0K3EytMpn4JNxaf5tbqbLcbIRoQIHzpTIyjpxLQKRoxU55ujBXAtg3Nl2h/XWvfDa9dsMOd0pQ== +"@types/theo@^8.1.3": + version "8.1.3" + resolved "https://registry.yarnpkg.com/@types/theo/-/theo-8.1.3.tgz#91915c34f4114fe0f8d3f8ffaf9263beefa64557" + integrity sha512-/TnoJulCbxdIO4C79H2Fdvx+UK+oBEUCXp3KlffthDMHYhwGsWyPD5rogWEIopGShYfOfk3gYqItArS4v4htdg== + dependencies: + immutable "3.8.2" + "@types/uglify-js@*": version "3.0.4" resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.0.4.tgz#96beae23df6f561862a830b4288a49e86baac082" @@ -5221,11 +5233,6 @@ detect-file@^1.0.0: resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" integrity sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc= -detect-libc@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" - integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= - detect-newline@2.X, detect-newline@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-2.1.0.tgz#f41f1c10be4b00e87b5f13da680759f2c5bfd3e2" @@ -6933,13 +6940,6 @@ fs-extra@^7.0.1: jsonfile "^4.0.0" universalify "^0.1.0" -fs-minipass@^1.2.5: - version "1.2.7" - resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" - integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== - dependencies: - minipass "^2.6.0" - fs-mkdirp-stream@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz#0b7815fc3201c6a69e14db98ce098c16935259eb" @@ -8044,6 +8044,11 @@ hsla-regex@^1.0.0: resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= +hsluv@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/hsluv/-/hsluv-0.1.0.tgz#29f40d49642bd56dd0c192122abcc723bb5c2d6c" + integrity sha512-ERcanKLAszD2XN3Vh5r5Szkrv9q0oSTudmP0rkiKAGM/3NMc9FLmMZBB7TSqTaXJfSDBOreYTfjezCOYbRKqlw== + html-comment-regex@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" @@ -8190,7 +8195,7 @@ https-browserify@^1.0.0: resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= -iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4, iconv-lite@~0.4.13: +iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@~0.4.13: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -8238,13 +8243,6 @@ ignore-by-default@^1.0.1: resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk= -ignore-walk@^3.0.1: - version "3.0.3" - resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" - integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== - dependencies: - minimatch "^3.0.4" - ignore@^3.3.5: version "3.3.10" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" @@ -10865,21 +10863,6 @@ minimist@~0.0.1: resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.10.tgz#de3f98543dbf96082be48ad1a0c7cda836301dcf" integrity sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8= -minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: - version "2.9.0" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" - integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== - dependencies: - safe-buffer "^5.1.2" - yallist "^3.0.0" - -minizlib@^1.2.1: - version "1.3.3" - resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" - integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== - dependencies: - minipass "^2.9.0" - mississippi@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" @@ -11032,15 +11015,6 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= -needle@^2.2.1: - version "2.4.0" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.4.0.tgz#6833e74975c444642590e15a750288c5f939b57c" - integrity sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg== - dependencies: - debug "^3.2.6" - iconv-lite "^0.4.4" - sax "^1.2.4" - negotiator@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" @@ -11164,22 +11138,6 @@ node-object-hash@^1.4.1: resolved "https://registry.yarnpkg.com/node-object-hash/-/node-object-hash-1.4.2.tgz#385833d85b229902b75826224f6077be969a9e94" integrity sha512-UdS4swXs85fCGWWf6t6DMGgpN/vnlKeSGEQ7hJcrs7PBFoxoKLmibc3QRb7fwiYsjdL7PX8iI/TMSlZ90dgHhQ== -node-pre-gyp@*: - version "0.14.0" - resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83" - integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA== - dependencies: - detect-libc "^1.0.2" - mkdirp "^0.5.1" - needle "^2.2.1" - nopt "^4.0.1" - npm-packlist "^1.1.6" - npmlog "^4.0.2" - rc "^1.2.7" - rimraf "^2.6.1" - semver "^5.3.0" - tar "^4.4.2" - node-releases@^1.0.0-alpha.11, node-releases@^1.1.44: version "1.1.45" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.45.tgz#4cf7e9175d71b1317f15ffd68ce63bce1d53e9f2" @@ -11245,14 +11203,6 @@ nodemon@^2.0.2: dependencies: abbrev "1" -nopt@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" - integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= - dependencies: - abbrev "1" - osenv "^0.1.4" - nopt@~1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" @@ -11313,13 +11263,6 @@ now-and-later@^2.0.0: dependencies: once "^1.3.2" -npm-bundled@^1.0.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b" - integrity sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA== - dependencies: - npm-normalize-package-bin "^1.0.1" - npm-conf@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9" @@ -11328,19 +11271,6 @@ npm-conf@^1.1.0: config-chain "^1.1.11" pify "^3.0.0" -npm-normalize-package-bin@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" - integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== - -npm-packlist@^1.1.6: - version "1.4.7" - resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.7.tgz#9e954365a06b80b18111ea900945af4f88ed4848" - integrity sha512-vAj7dIkp5NhieaGZxBJB8fF4R0078rqsmhJcAfXZ6O7JJhjhPK96n5Ry1oZcfLXgfun0GWTZPOxaEyqv8GBykQ== - dependencies: - ignore-walk "^3.0.1" - npm-bundled "^1.0.1" - npm-run-all@^4.1.5: version "4.1.5" resolved "https://registry.yarnpkg.com/npm-run-all/-/npm-run-all-4.1.5.tgz#04476202a15ee0e2e214080861bff12a51d98fba" @@ -11363,7 +11293,7 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" -"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0, npmlog@^4.0.2: +"npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.0: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== @@ -11729,7 +11659,7 @@ os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= -osenv@0, osenv@^0.1.4: +osenv@0: version "0.1.5" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== @@ -13068,7 +12998,7 @@ raw-body@^2.3.2: iconv-lite "0.4.24" unpipe "1.0.0" -rc@^1.0.1, rc@^1.1.2, rc@^1.1.6, rc@^1.2.7: +rc@^1.0.1, rc@^1.1.2, rc@^1.1.6: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== @@ -13829,7 +13759,7 @@ rgba-regex@^1.0.0: resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= -rimraf@2, rimraf@^2.2.6, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: +rimraf@2, rimraf@^2.2.6, rimraf@^2.5.4, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -15331,19 +15261,6 @@ tar@^2.0.0: fstream "^1.0.12" inherits "2" -tar@^4.4.2: - version "4.4.13" - resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" - integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== - dependencies: - chownr "^1.1.1" - fs-minipass "^1.2.5" - minipass "^2.8.6" - minizlib "^1.2.1" - mkdirp "^0.5.0" - safe-buffer "^5.1.2" - yallist "^3.0.3" - temp-dir@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" @@ -15845,6 +15762,11 @@ typeof-article@^0.1.1: dependencies: kind-of "^3.1.0" +typescript@^3.7.5: + version "3.7.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae" + integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw== + typical@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/typical/-/typical-4.0.0.tgz#cbeaff3b9d7ae1e2bbfaf5a4e6f11eccfde94fc4" @@ -16943,7 +16865,7 @@ yallist@^2.1.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= -yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: +yallist@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==