diff --git a/src/css-variables.ts b/src/css-variables.ts new file mode 100644 index 0000000..efd0b22 --- /dev/null +++ b/src/css-variables.ts @@ -0,0 +1,99 @@ +export const CSS_VARIABLES: Record = { + scale: 'var(--mantine-scale)', + 'cursor-type': 'var(--mantine-cursor-type)', + 'webkit-font-smoothing': 'var(--mantine-webkit-font-smoothing)', + 'moz-font-smoothing': 'var(--mantine-moz-font-smoothing)', + 'color-scheme': 'var(--mantine-color-scheme)', + white: 'var(--mantine-color-white)', + black: 'var(--mantine-color-black)', + 'line-height': 'var(--mantine-line-height)', + 'font-family': 'var(--mantine-font-family)', + 'font-family-monospace': 'var(--mantine-font-family-monospace)', + 'font-family-headings': 'var(--mantine-font-family-headings)', + ff: 'var(--mantine-font-family)', + 'ff-monospace': 'var(--mantine-font-family-monospace)', + 'ff-headings': 'var(--mantine-font-family-headings)', + 'heading-font-weight': 'var(--mantine-heading-font-weight)', + 'radius-default': 'var(--mantine-radius-default)', + 'primary-color-filled': 'var(--mantine-primary-color-filled)', + 'primary-color-filled-hover': 'var(--mantine-primary-color-filled-hover)', + 'primary-color-light': 'var(--mantine-primary-color-light)', + 'primary-color-light-hover': 'var(--mantine-primary-color-light-hover)', + 'primary-color-light-color': 'var(--mantine-primary-color-light-color)', + 'primary-color-0': 'var(--mantine-primary-color-0)', + 'primary-color-1': 'var(--mantine-primary-color-1)', + 'primary-color-2': 'var(--mantine-primary-color-2)', + 'primary-color-3': 'var(--mantine-primary-color-3)', + 'primary-color-4': 'var(--mantine-primary-color-4)', + 'primary-color-5': 'var(--mantine-primary-color-5)', + 'primary-color-6': 'var(--mantine-primary-color-6)', + 'primary-color-7': 'var(--mantine-primary-color-7)', + 'primary-color-8': 'var(--mantine-primary-color-8)', + 'primary-color-9': 'var(--mantine-primary-color-9)', + 'h1-font-size': 'var(--mantine-h1-font-size)', + 'h1-fz': 'var(--mantine-h1-font-size)', + 'h1-line-height': 'var(--mantine-h1-line-height)', + 'h1-lh': 'var(--mantine-h1-line-height)', + 'h2-font-size': 'var(--mantine-h2-font-size)', + 'h2-fz': 'var(--mantine-h2-font-size)', + 'h2-line-height': 'var(--mantine-h2-line-height)', + 'h2-lh': 'var(--mantine-h2-line-height)', + 'h3-font-size': 'var(--mantine-h3-font-size)', + 'h3-fz': 'var(--mantine-h3-font-size)', + 'h3-line-height': 'var(--mantine-h3-line-height)', + 'h3-lh': 'var(--mantine-h3-line-height)', + 'h4-font-size': 'var(--mantine-h4-font-size)', + 'h4-fz': 'var(--mantine-h4-font-size)', + 'h4-line-height': 'var(--mantine-h4-line-height)', + 'h4-lh': 'var(--mantine-h4-line-height)', + 'h5-font-size': 'var(--mantine-h5-font-size)', + 'h5-fz': 'var(--mantine-h5-font-size)', + 'h5-line-height': 'var(--mantine-h5-line-height)', + 'h5-lh': 'var(--mantine-h5-line-height)', + 'h6-font-size': 'var(--mantine-h6-font-size)', + 'h6-fz': 'var(--mantine-h6-font-size)', + 'h6-line-height': 'var(--mantine-h6-line-height)', + 'h6-lh': 'var(--mantine-h6-line-height)', +}; + +module.exports = function getVariable(input: string) { + const normalizedInput = input.trim().toLowerCase(); + + if (CSS_VARIABLES[normalizedInput]) { + return CSS_VARIABLES[normalizedInput]; + } + + if (normalizedInput.startsWith('spacing-')) { + return `var(--mantine-spacing-${normalizedInput.replace('spacing-', '')})`; + } + + if (normalizedInput.startsWith('font-size-') || normalizedInput.startsWith('fz-')) { + return `var(--mantine-font-size-${normalizedInput + .replace('font-size-', '') + .replace('fz-', '')})`; + } + + if (normalizedInput.startsWith('breakpoint-')) { + return `var(--mantine-breakpoint-${normalizedInput.replace('breakpoint-', '')})`; + } + + if (normalizedInput.startsWith('shadow-')) { + return `var(--mantine-shadow-${normalizedInput.replace('shadow-', '')})`; + } + + if (normalizedInput.startsWith('line-height-') || normalizedInput.startsWith('lh-')) { + return `var(--mantine-line-height-${normalizedInput + .replace('line-height-', '') + .replace('lh-', '')})`; + } + + if (normalizedInput.startsWith('radius-')) { + return `var(--mantine-radius-${normalizedInput.replace('radius-', '')})`; + } + + if (normalizedInput.startsWith('color-')) { + return `var(--mantine-color-${normalizedInput.replace('color-', '')})`; + } + + return input; +}; diff --git a/src/postcss-mantine-theme.ts b/src/postcss-mantine-theme.ts new file mode 100644 index 0000000..855f54f --- /dev/null +++ b/src/postcss-mantine-theme.ts @@ -0,0 +1,16 @@ +import type { Root } from 'postcss'; +const getVariable = require('./css-variables'); + +const regexp = new RegExp('\\b' + 'theme' + '\\(([^()]+)\\)', 'g'); + +module.exports = () => { + return { + postcssPlugin: 'postcss-mantine-theme', + + Once(root: Root) { + root.replaceValues(regexp, { fast: `theme(` }, (_, values) => getVariable(values)); + }, + }; +}; + +module.exports.postcss = true; diff --git a/src/preset.ts b/src/preset.ts index da7406f..1a1e75b 100644 --- a/src/preset.ts +++ b/src/preset.ts @@ -4,6 +4,7 @@ const remEm = require('./postcss-rem-em'); const colorMixAlpha = require('./postcss-color-mix'); const lightDark = require('./postcss-light-dark'); const converters = require('./converters'); +const theme = require('./postcss-mantine-theme'); function colorSchemeMixin(colorScheme: 'light' | 'dark') { return { @@ -75,6 +76,7 @@ module.exports = () => { postcssPlugin: 'postcss-preset-mantine', plugins: [ lightDark(), + theme(), nested(), colorMixAlpha(), remEm(), diff --git a/src/tests/__snapshots__/theme.test.ts.snap b/src/tests/__snapshots__/theme.test.ts.snap new file mode 100644 index 0000000..edd29a3 --- /dev/null +++ b/src/tests/__snapshots__/theme.test.ts.snap @@ -0,0 +1,22 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`theme correctly replaces theme function 1`] = ` +" +.demo { + background: var(--mantine-color-orange-4); + border: calc(0.0625rem * var(--mantine-scale)) solid var(--mantine-color-gray-filled); + padding: var(--mantine-spacing-md) var(--mantine-spacing-sm); +} +" +`; + +exports[`theme correctly replaces theme with light-dark function 1`] = ` +" +.demo { + background: var(--mantine-color-red-5); +} + [data-mantine-color-scheme='dark'] .demo { + background: var(--mantine-color-blue-5); +} +" +`; diff --git a/src/tests/theme.test.ts b/src/tests/theme.test.ts new file mode 100644 index 0000000..3c229aa --- /dev/null +++ b/src/tests/theme.test.ts @@ -0,0 +1,27 @@ +import { testTransform } from './utils'; + +const baseInput = ` +.demo { + background: theme(color-orange-4); + border: rem(1px) solid theme(color-gray-filled); + padding: theme(spacing-md) theme(spacing-sm); +} +`; + +const lightDarkInput = ` +.demo { + background: light-dark(theme(color-red-5), theme(color-blue-5)); +} +`; + +describe('theme', () => { + it('correctly replaces theme function', async () => { + const res = await testTransform(baseInput); + expect(res.css).toMatchSnapshot(); + }); + + it('correctly replaces theme with light-dark function', async () => { + const res = await testTransform(lightDarkInput); + expect(res.css).toMatchSnapshot(); + }); +});