From 00084bcca881d388fc00f5e05d0c3f9b9beb384c Mon Sep 17 00:00:00 2001 From: mauroerta Date: Wed, 28 Jul 2021 23:52:03 +0200 Subject: [PATCH] feat: improved build command --- apps/cli/.gitignore | 2 +- apps/cli/README.md | 16 +- apps/cli/src/commands/build.ts | 28 ++- apps/cli/src/constants/maps.ts | 2 +- apps/cli/src/index.ts | 1 + apps/cli/src/types/config.ts | 24 +++ apps/cli/src/types/index.ts | 1 + apps/cli/src/utils/buildTheme.ts | 66 +++++++ .../{makeClasses.ts => getCSSClasses.ts} | 26 ++- apps/cli/src/utils/getConfiguration.ts | 29 +++ apps/cli/src/utils/index.ts | 2 +- apps/cli/src/utils/parseSlice.ts | 7 +- apps/cli/src/utils/parseTheme.ts | 37 ---- apps/cli/test/commands/build.test.ts | 71 +++++-- apps/cli/test/utils/.morfeorc.ts | 3 + apps/cli/test/utils/.morfeorcjson.json | 3 + apps/cli/test/utils/themejson.json | 178 ++++++++++++++++++ apps/cli/tokens/default.json | 174 ----------------- 18 files changed, 407 insertions(+), 263 deletions(-) create mode 100644 apps/cli/src/types/config.ts create mode 100644 apps/cli/src/types/index.ts create mode 100644 apps/cli/src/utils/buildTheme.ts rename apps/cli/src/utils/{makeClasses.ts => getCSSClasses.ts} (50%) create mode 100644 apps/cli/src/utils/getConfiguration.ts delete mode 100644 apps/cli/src/utils/parseTheme.ts create mode 100644 apps/cli/test/utils/.morfeorc.ts create mode 100644 apps/cli/test/utils/.morfeorcjson.json create mode 100644 apps/cli/test/utils/themejson.json delete mode 100644 apps/cli/tokens/default.json diff --git a/apps/cli/.gitignore b/apps/cli/.gitignore index e7bac7c8..728a1484 100644 --- a/apps/cli/.gitignore +++ b/apps/cli/.gitignore @@ -3,7 +3,7 @@ /.nyc_output /dist /lib -/morfeo +/test/builds /tmp /yarn.lock node_modules diff --git a/apps/cli/README.md b/apps/cli/README.md index 44668677..bf7ee245 100644 --- a/apps/cli/README.md +++ b/apps/cli/README.md @@ -33,23 +33,25 @@ USAGE # Commands -* [`morfeo build path/to/theme.(ts|js|json) [--name="theme name"]`](#morfeo-build-pathtothemetsjsjson---nametheme-name) +* [`morfeo build path/to/theme`](#morfeo-build-pathtotheme) * [`morfeo help [COMMAND]`](#morfeo-help-command) -## `morfeo build path/to/theme.(ts|js|json) [--name="theme name"]` +## `morfeo build path/to/theme` -build design tokens based on your theme +build css styles based on your themes ``` USAGE - $ morfeo build path/to/theme.(ts|js|json) [--name="theme name"] + $ morfeo build path/to/theme OPTIONS - -h, --help show CLI help - -n, --name=name [default: default] an identifier for the passed theme, for example "light", "dark" + -b, --build=build the path where the generated css files will be placed + -c, --config=config [default: .morfeorc] the path to the configuration file + -h, --help build css styles based on your themes + -n, --name=name [default: default] an identifier for the passed theme, for example "light", "dark" EXAMPLE - $ morfeo build path/to/theme.ts + $ morfeo build path/to/theme.ts --name="light" ``` _See code: [src/commands/build.ts](https://github.com/VLK-STUDIO/morfeo/blob/v0.0.0/src/commands/build.ts)_ diff --git a/apps/cli/src/commands/build.ts b/apps/cli/src/commands/build.ts index 32131050..ec1ef2b5 100644 --- a/apps/cli/src/commands/build.ts +++ b/apps/cli/src/commands/build.ts @@ -1,23 +1,34 @@ import * as path from 'path'; import { Command, flags } from '@oclif/command'; -import { parseTheme } from '../utils'; +import { buildTheme } from '../utils'; import { theme } from '@morfeo/web'; export default class Build extends Command { - static description = 'build design tokens based on your theme'; + static description = 'build css styles based on your themes'; - static examples = [`$ morfeo build path/to/theme.ts`]; + static examples = [`$ morfeo build path/to/theme.ts --name="light"`]; - static usage = 'build path/to/theme.(ts|js|json) [--name="theme name"]'; + static usage = 'build path/to/theme'; static flags = { - help: flags.help({ char: 'h' }), + help: flags.help({ char: 'h', description: Build.description }), name: flags.string({ char: 'n', description: 'an identifier for the passed theme, for example "light", "dark"', default: 'default', }), + build: flags.string({ + char: 'b', + description: 'the path where the generated css files will be placed', + required: false, + }), + config: flags.string({ + char: 'c', + description: 'the path to the configuration file', + default: '.morfeorc', + required: false, + }), }; static args = [{ name: 'theme' }]; @@ -32,16 +43,17 @@ export default class Build extends Command { async run() { const { args, flags } = this.parse(Build); + const { name, build, config } = flags; const themePath = args.theme; if (!themePath) { this.printMissingThemeError(); } - const localTheme = require(path.resolve(themePath)); + const localTheme = require(path.join(process.cwd(), themePath)); - theme.set(localTheme.default); + theme.set(localTheme.default ? localTheme.default : localTheme); - parseTheme(flags.name); + buildTheme({ name, buildPath: build, configPath: config }); } } diff --git a/apps/cli/src/constants/maps.ts b/apps/cli/src/constants/maps.ts index a1cbb105..a5134587 100644 --- a/apps/cli/src/constants/maps.ts +++ b/apps/cli/src/constants/maps.ts @@ -7,7 +7,7 @@ type SliceToBeParsed = { }; /** - * The values of these slices can't be represent as css variables + * The values of these slices can't be represented as css variables */ export const SLICES_TO_BE_EXCLUDED: ThemeKey[] = ['components', 'mediaQueries']; diff --git a/apps/cli/src/index.ts b/apps/cli/src/index.ts index 63a56fdf..e2bb9b34 100644 --- a/apps/cli/src/index.ts +++ b/apps/cli/src/index.ts @@ -1 +1,2 @@ export { run } from '@oclif/command'; +export * from './types'; diff --git a/apps/cli/src/types/config.ts b/apps/cli/src/types/config.ts new file mode 100644 index 00000000..396256bb --- /dev/null +++ b/apps/cli/src/types/config.ts @@ -0,0 +1,24 @@ +export type BuildConfig = { + /** + * an identifier for the passed theme, for example "light", "dark" + */ + name: string; + /** + * the path where the generated css files will be placed + * @default `morfeo` + */ + buildPath?: string; + /** + * the path to the configuration file. + * valid extensions are `js`, `ts`, `json` or `no extension` + * @default `./.morfeorc` + */ + configPath?: string; +}; + +export type MorfeoConfig = { + /** + * the path where the generated css files will be placed + */ + buildPath: string; +}; diff --git a/apps/cli/src/types/index.ts b/apps/cli/src/types/index.ts new file mode 100644 index 00000000..f03c2281 --- /dev/null +++ b/apps/cli/src/types/index.ts @@ -0,0 +1 @@ +export * from './config'; diff --git a/apps/cli/src/utils/buildTheme.ts b/apps/cli/src/utils/buildTheme.ts new file mode 100644 index 00000000..cdc43e87 --- /dev/null +++ b/apps/cli/src/utils/buildTheme.ts @@ -0,0 +1,66 @@ +import { theme, ThemeKey } from '@morfeo/web'; +import * as path from 'path'; +import { SLICES_TO_BE_EXCLUDED } from '../constants'; +import { getCSSClasses } from './getCSSClasses'; +import { safeWrite } from './safeWrite'; +import { parseSlice } from './parseSlice'; +import { BuildConfig } from '../types'; +import { getConfiguration } from './getConfiguration'; + +function getStylePaths(buildPath: string) { + const variablesPath = path.join(process.cwd(), buildPath, 'variables.css'); + const stylePath = path.join(process.cwd(), buildPath, 'style.css'); + + return { + variablesPath, + stylePath, + }; +} + +function wrapWithScope(name: string, css: string) { + const parsedCss = css.replace(/\n/g, '\n\t'); + return `:root, html[data-morfeo-theme="${name}"] {\n\t${parsedCss}\n}\n`; +} + +export function buildTheme(config: BuildConfig) { + const { name, buildPath } = getConfiguration(config); + + const currentTheme = theme.get(); + const slices = Object.keys(currentTheme) as ThemeKey[]; + const filtered = slices.filter( + slice => !SLICES_TO_BE_EXCLUDED.includes(slice), + ); + let cssText = ''; + + // `breakpoints` excluded since is not possible to have variables in media queries + const { breakpoints, ...newTheme } = filtered.reduce((acc, curr) => { + const { css, object } = parseSlice(curr); + cssText += css; + return { + ...acc, + [curr]: object, + }; + }, currentTheme); + + const { stylePath, variablesPath } = getStylePaths(buildPath as string); + + safeWrite(variablesPath, wrapWithScope(name, cssText)); + + /** + * Setting the new theme where values of slices are css variables + */ + theme.set(newTheme); + + /** + * getCSSClasses will return a css class for each component and foreach variant using + * the new theme with css variables as values + */ + const componentStyle = getCSSClasses(); + + safeWrite(stylePath, componentStyle); + + /** + * restored the old theme + */ + theme.set(currentTheme); +} diff --git a/apps/cli/src/utils/makeClasses.ts b/apps/cli/src/utils/getCSSClasses.ts similarity index 50% rename from apps/cli/src/utils/makeClasses.ts rename to apps/cli/src/utils/getCSSClasses.ts index f9e86135..d8dc6b1d 100644 --- a/apps/cli/src/utils/makeClasses.ts +++ b/apps/cli/src/utils/getCSSClasses.ts @@ -1,13 +1,11 @@ import { theme, getStyles, Component } from '@morfeo/web'; -import * as fs from 'fs'; -import * as path from 'path'; -const CSS_PATH = path.join(__dirname, '../../morfeo/style.css'); +function getComponentCSS(componentName: Component, variant?: string) { + let componentId = `morfeo-${componentName.toLowerCase()}`; -function appendCss(componentName: Component, variant?: string) { - const componentId = `morfeo-${componentName.toLowerCase()}${ - variant ? `-${variant.toLowerCase()}` : '' - }`; + if (variant) { + componentId += `-${variant.toLowerCase()}`; + } const { sheet } = getStyles( { [componentName]: { componentName, variant } }, @@ -18,24 +16,24 @@ function appendCss(componentName: Component, variant?: string) { const componentCss = sheet.toString(); - fs.appendFileSync(CSS_PATH, `\n${componentCss}\n`); + return `\n${componentCss}\n`; } -export function makeClasses() { +export function getCSSClasses() { const { components } = theme.get(); const componentNames = Object.keys(components) as Component[]; - const importLine = `@import "./variables.css";\n`; - - fs.writeFileSync(CSS_PATH, importLine); + let css = `@import "./variables.css";\n`; componentNames.forEach(componentName => { const { variants } = components[componentName]; const variantKeys = Object.keys(variants || {}); - appendCss(componentName); + css += getComponentCSS(componentName); variantKeys.forEach(variant => { - appendCss(componentName, variant); + css += getComponentCSS(componentName, variant); }); }); + + return css; } diff --git a/apps/cli/src/utils/getConfiguration.ts b/apps/cli/src/utils/getConfiguration.ts new file mode 100644 index 00000000..845f30c3 --- /dev/null +++ b/apps/cli/src/utils/getConfiguration.ts @@ -0,0 +1,29 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import { BuildConfig, MorfeoConfig } from '../types'; + +const MORFEO_CONFIG_FILE_EXTENSIONS = ['.js', '.ts', '.json', '']; + +export function getConfiguration({ + configPath, + ...rest +}: Partial): BuildConfig { + const morfeoConfigPath = path.join(process.cwd(), configPath as string); + let morfeoConfig: MorfeoConfig = {} as any; + const configExists = MORFEO_CONFIG_FILE_EXTENSIONS.some(extension => { + return fs.existsSync(`${morfeoConfigPath}${extension}`); + }); + + if (configExists) { + const imported = require(morfeoConfigPath); + morfeoConfig = imported.default ? imported.default : imported; + } + + const { buildPath } = morfeoConfig; + + return { + ...rest, + buildPath: rest.buildPath || buildPath, + configPath, + } as BuildConfig; +} diff --git a/apps/cli/src/utils/index.ts b/apps/cli/src/utils/index.ts index 8625c6e4..2b3a869c 100644 --- a/apps/cli/src/utils/index.ts +++ b/apps/cli/src/utils/index.ts @@ -1 +1 @@ -export * from './parseTheme'; +export * from './buildTheme'; diff --git a/apps/cli/src/utils/parseSlice.ts b/apps/cli/src/utils/parseSlice.ts index e37dbbf6..4352b876 100644 --- a/apps/cli/src/utils/parseSlice.ts +++ b/apps/cli/src/utils/parseSlice.ts @@ -44,7 +44,7 @@ function getValue( export function parseSlice(sliceName: Key) { const slice = theme.getSlice(sliceName); const aliases = Object.keys(slice) as (keyof Theme[Key])[]; - let css = ``; + let css: string[] = []; let object = {}; aliases.forEach(curr => { @@ -56,8 +56,9 @@ export function parseSlice(sliceName: Key) { ...object, [curr]: value, }; - css += `\n\t${variableName}: ${cssValue};`; + + css.push(`${variableName}: ${cssValue};`); }, object); - return { css, object }; + return { css: css.join('\n'), object }; } diff --git a/apps/cli/src/utils/parseTheme.ts b/apps/cli/src/utils/parseTheme.ts deleted file mode 100644 index fc0ab68e..00000000 --- a/apps/cli/src/utils/parseTheme.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { theme, ThemeKey } from '@morfeo/web'; -import { SLICES_TO_BE_EXCLUDED } from '../constants'; -import * as path from 'path'; -import { makeClasses } from './makeClasses'; -import { safeWrite } from './safeWrite'; -import { parseSlice } from './parseSlice'; - -const BUILD_PATH = path.join(__dirname, '../../morfeo'); -const CSS_VARIABLES_PATH = path.join(BUILD_PATH, 'variables.css'); - -export function parseTheme(themeName: string) { - const currentTheme = theme.get(); - const slices = Object.keys(currentTheme) as ThemeKey[]; - const filtered = slices.filter( - slice => !SLICES_TO_BE_EXCLUDED.includes(slice), - ); - let cssText = `:root, html[data-morfeo-theme="${themeName}"] {`; - - // `breakpoints` excluded since is not possible to have variables in media queries - const { breakpoints, ...newTheme } = filtered.reduce((acc, curr) => { - const { css, object } = parseSlice(curr); - cssText += css; - return { - ...acc, - [curr]: object, - }; - }, currentTheme); - - cssText += '\n}\n'; - - theme.set(newTheme); - - safeWrite(CSS_VARIABLES_PATH, cssText); - makeClasses(); - - theme.set(currentTheme); -} diff --git a/apps/cli/test/commands/build.test.ts b/apps/cli/test/commands/build.test.ts index 4edd38fd..07f34f1a 100644 --- a/apps/cli/test/commands/build.test.ts +++ b/apps/cli/test/commands/build.test.ts @@ -3,30 +3,67 @@ import * as path from 'path'; import * as fs from 'fs'; import { rmdir } from '../utils/rmdir'; -const THEME_PATH = path.join(__dirname, '../utils/theme.ts'); -const BUILD_PATH = path.join(__dirname, '../../morfeo'); +const THEME_PATH = 'test/utils/theme'; +const THEME_JSON_PATH = 'test/utils/themejson'; +const BUILD_PATH = 'test/builds'; +const CONFIG_PATH = 'test/utils/.morfeorc'; +const CONFIG_JSON_PATH = 'test/utils/.morfeorcjson'; const THEME_NAME = 'light'; function fileExists(fileName: string) { const filePath = path.join(BUILD_PATH, `${fileName}`); + return fs.existsSync(filePath); } -describe('should create a folder called `morfeo` is it does not exists', () => { - beforeEach(() => { - rmdir(BUILD_PATH); - }); +describe('build command', () => { + describe(`if the build folder does not exists"`, () => { + beforeEach(() => { + rmdir(BUILD_PATH); + }); - test - .command(['build', THEME_PATH]) - .it(`should create a file called style.css`, () => { - const exists = fileExists(''); + test + .command(['build', THEME_PATH, '--build', BUILD_PATH]) + .it( + `should create the build folder in the path passed from the CLI`, + () => { + const exists = fileExists(''); - expect(exists).to.be.true; - }); -}); + expect(exists).to.be.true; + }, + ); + + test + .command(['build', THEME_JSON_PATH, '--build', BUILD_PATH]) + .it(`should work from a theme inside a json file`, () => { + const exists = fileExists(''); + + expect(exists).to.be.true; + }); + + test + .command(['build', THEME_PATH, '--config', CONFIG_PATH]) + .it( + `should create the build folder from the typescript configuration file`, + () => { + const exists = fileExists(''); + + expect(exists).to.be.true; + }, + ); + + test + .command(['build', THEME_PATH, '--config', CONFIG_JSON_PATH]) + .it( + `should create the build folder from the json configuration file`, + () => { + const exists = fileExists(''); + + expect(exists).to.be.true; + }, + ); + }); -describe('build command', () => { test .stderr() .command(['build']) @@ -38,7 +75,7 @@ describe('build command', () => { .it(`should fail if no theme is passed`); test - .command(['build', THEME_PATH]) + .command(['build', THEME_PATH, '--build', BUILD_PATH]) .it(`should create a file called variables.css`, () => { const exists = fileExists('variables.css'); @@ -46,7 +83,7 @@ describe('build command', () => { }); test - .command(['build', THEME_PATH]) + .command(['build', THEME_PATH, '--build', BUILD_PATH]) .it(`should create a file called style.css`, () => { const exists = fileExists('style.css'); @@ -54,7 +91,7 @@ describe('build command', () => { }); test - .command(['build', THEME_PATH, '--name', THEME_NAME]) + .command(['build', THEME_PATH, '--name', THEME_NAME, '--build', BUILD_PATH]) .it( `should exist a scoped block with css variables inside the file "variables.css"`, () => { diff --git a/apps/cli/test/utils/.morfeorc.ts b/apps/cli/test/utils/.morfeorc.ts new file mode 100644 index 00000000..f2b7b62a --- /dev/null +++ b/apps/cli/test/utils/.morfeorc.ts @@ -0,0 +1,3 @@ +export default { + buildPath: 'test/builds', +}; diff --git a/apps/cli/test/utils/.morfeorcjson.json b/apps/cli/test/utils/.morfeorcjson.json new file mode 100644 index 00000000..2a81295f --- /dev/null +++ b/apps/cli/test/utils/.morfeorcjson.json @@ -0,0 +1,3 @@ +{ + "buildPath": "test/builds" +} diff --git a/apps/cli/test/utils/themejson.json b/apps/cli/test/utils/themejson.json new file mode 100644 index 00000000..4c214f7d --- /dev/null +++ b/apps/cli/test/utils/themejson.json @@ -0,0 +1,178 @@ +{ + "colors": { + "grey": "#bdc3c7", + "primary": "white", + "danger": "#e74c3c", + "secondary": "black", + "success": "#2ecc71", + "accent": "#3498db", + "warning": "#f39c12", + "transparent": "transparent" + }, + "fonts": { + "regular": "Roboto" + }, + "gradients": { + "primary": { + "start": 0, + "angle": 90, + "end": 100, + "colors": ["success", "accent"], + "kind": "linear" + }, + "secondary": { + "start": 0, + "end": 100, + "angle": 0, + "colors": ["accent", "success"], + "kind": "linear" + }, + "loading": { + "start": 0, + "end": 100, + "angle": 90, + "colors": ["transparent", "grey", "transparent"], + "kind": "linear" + } + }, + "radii": { + "m": "10px", + "round": "50%" + }, + "spacings": { + "s": "40px", + "m": "100px" + }, + "lineHeights": { + "s": 1.7 + }, + "letterSpacings": { + "s": 1.6 + }, + "fontSizes": { + "s": "14px" + }, + "sizes": { + "s": "10px", + "m": "100px", + "xl": "200px" + }, + "borderWidths": { + "s": "2px" + }, + "shadows": { + "none": { + "color": "transparent", + "offset": { "width": 0, "height": 0 }, + "opacity": 0, + "elevation": 0 + }, + "soft": { + "color": "accent", + "offset": { "width": 0, "height": 2 }, + "opacity": 0.2, + "radius": 4, + "elevation": 2 + }, + "medium": { + "color": "black", + "offset": { "width": 0, "height": 3 }, + "opacity": 0.3, + "radius": 4, + "elevation": 3 + }, + "strong": { + "color": "black", + "offset": { "width": 0, "height": 4 }, + "opacity": 0.4, + "radius": 4, + "elevation": 4 + } + }, + "breakpoints": { + "xs": "300px", + "sm": "600px", + "md": "900px", + "lg": "1300px" + }, + "transitions": { + "light": "all 0.5s" + }, + "components": { + "Box": { + "tag": "div", + "style": {} + }, + "Button": { + "tag": "button", + "style": { + "transition": "light", + "height": "m", + "width": "m", + "bg": { + "md": "danger", + "lg": "primary" + }, + "color": "secondary", + "borderRadius": "m", + "borderWidth": "s", + "borderStyle": "solid", + "borderColor": "primary", + "&:hover": { + "gradient": "secondary", + "color": "primary" + } + }, + "props": { + "aria-label": "button", + "type": "button" + }, + "variants": { + "primary": { + "props": { + "aria-label": "primary button" + }, + "style": { + "bg": "secondary", + "borderColor": "primary", + "color": "primary", + "&:hover": { + "bg": "primary", + "color": "secondary" + } + } + }, + "round": { + "style": { "borderRadius": "round" } + } + } + }, + "Typography": { + "tag": "p", + "style": { + "fontFamily": "regular", + "fontSize": "s", + "lineHeight": "s", + "letterSpacing": "s" + }, + "variants": { + "h1": { + "tag": "h1", + "style": { "color": "red" } + }, + "h2": { + "tag": "h1", + "style": { "color": "green" } + }, + "h3": { + "tag": "h3", + "style": { "color": "blue" } + }, + "code": { + "tag": "pre", + "style": { "color": "primary" } + } + } + } + } +} diff --git a/apps/cli/tokens/default.json b/apps/cli/tokens/default.json deleted file mode 100644 index f9c7d91a..00000000 --- a/apps/cli/tokens/default.json +++ /dev/null @@ -1,174 +0,0 @@ -{ - "colors": { - "grey": { - "value": "#bdc3c7", - "comment": "value referred to morfeo's `colors` theme slice" - }, - "primary": { - "value": "white", - "comment": "value referred to morfeo's `colors` theme slice" - }, - "danger": { - "value": "#e74c3c", - "comment": "value referred to morfeo's `colors` theme slice" - }, - "secondary": { - "value": "black", - "comment": "value referred to morfeo's `colors` theme slice" - }, - "success": { - "value": "#2ecc71", - "comment": "value referred to morfeo's `colors` theme slice" - }, - "accent": { - "value": "#3498db", - "comment": "value referred to morfeo's `colors` theme slice" - }, - "warning": { - "value": "#f39c12", - "comment": "value referred to morfeo's `colors` theme slice" - }, - "transparent": { - "value": "transparent", - "comment": "value referred to morfeo's `colors` theme slice" - } - }, - "mediaQueries": { - "xs": { - "value": "\"@media (min-width: 300px)\"", - "comment": "value referred to morfeo's `mediaQueries` theme slice" - }, - "sm": { - "value": "\"@media (min-width: 600px)\"", - "comment": "value referred to morfeo's `mediaQueries` theme slice" - }, - "md": { - "value": "\"@media (min-width: 900px)\"", - "comment": "value referred to morfeo's `mediaQueries` theme slice" - }, - "lg": { - "value": "\"@media (min-width: 1300px)\"", - "comment": "value referred to morfeo's `mediaQueries` theme slice" - } - }, - "fonts": { - "regular": { - "value": "Roboto", - "comment": "value referred to morfeo's `fonts` theme slice" - } - }, - "gradients": { - "primary": { - "value": "linear-gradient(90deg, #2ecc71 0%, #3498db 100%)", - "comment": "value referred to morfeo's `gradients` theme slice" - }, - "secondary": { - "value": "linear-gradient(0deg, #3498db 0%, #2ecc71 100%)", - "comment": "value referred to morfeo's `gradients` theme slice" - }, - "loading": { - "value": "linear-gradient(90deg, transparent 0%, #bdc3c7 50%, transparent 100%)", - "comment": "value referred to morfeo's `gradients` theme slice" - } - }, - "radii": { - "m": { - "value": "10px", - "comment": "value referred to morfeo's `radii` theme slice" - }, - "round": { - "value": "50%", - "comment": "value referred to morfeo's `radii` theme slice" - } - }, - "spacings": { - "s": { - "value": "40px", - "comment": "value referred to morfeo's `spacings` theme slice" - }, - "m": { - "value": "100px", - "comment": "value referred to morfeo's `spacings` theme slice" - } - }, - "lineHeights": { - "s": { - "value": 1.7, - "comment": "value referred to morfeo's `lineHeights` theme slice" - } - }, - "letterSpacings": { - "s": { - "value": 1.6, - "comment": "value referred to morfeo's `letterSpacings` theme slice" - } - }, - "fontSizes": { - "s": { - "value": "14px", - "comment": "value referred to morfeo's `fontSizes` theme slice" - } - }, - "sizes": { - "s": { - "value": "10px", - "comment": "value referred to morfeo's `sizes` theme slice" - }, - "m": { - "value": "100px", - "comment": "value referred to morfeo's `sizes` theme slice" - }, - "xl": { - "value": "200px", - "comment": "value referred to morfeo's `sizes` theme slice" - } - }, - "borderWidths": { - "s": { - "value": "2px", - "comment": "value referred to morfeo's `borderWidths` theme slice" - } - }, - "shadows": { - "none": { - "value": "0px 0px 0px transparent", - "comment": "value referred to morfeo's `shadows` theme slice" - }, - "soft": { - "value": "0px 2px 4px #3498db", - "comment": "value referred to morfeo's `shadows` theme slice" - }, - "medium": { - "value": "0px 3px 4px black", - "comment": "value referred to morfeo's `shadows` theme slice" - }, - "strong": { - "value": "0px 4px 4px black", - "comment": "value referred to morfeo's `shadows` theme slice" - } - }, - "breakpoints": { - "xs": { - "value": "300px", - "comment": "value referred to morfeo's `breakpoints` theme slice" - }, - "sm": { - "value": "600px", - "comment": "value referred to morfeo's `breakpoints` theme slice" - }, - "md": { - "value": "900px", - "comment": "value referred to morfeo's `breakpoints` theme slice" - }, - "lg": { - "value": "1300px", - "comment": "value referred to morfeo's `breakpoints` theme slice" - } - }, - "transitions": { - "light": { - "value": "all 0.5s", - "comment": "value referred to morfeo's `transitions` theme slice" - } - } -} \ No newline at end of file