Skip to content

Commit

Permalink
Add smaller-than and larget-than mixins
Browse files Browse the repository at this point in the history
  • Loading branch information
rtivital committed Nov 11, 2023
1 parent a9d0d0f commit d097158
Show file tree
Hide file tree
Showing 6 changed files with 170 additions and 53 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "postcss-preset-mantine",
"version": "1.10.0",
"version": "1.11.0",
"description": "PostCSS preset for Mantine (7.0+) applications",
"main": "dist/preset.js",
"types": "dist/index.d.ts",
Expand Down
95 changes: 95 additions & 0 deletions src/converters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
function scaleRem(remValue: string) {
return `calc(${remValue} * var(--mantine-scale))`;
}

function createConverter(units: string, { shouldScale = false } = {}) {
function converter(value: unknown): string {
if (value === 0 || value === '0') {
return '0';
}

if (typeof value === 'number') {
const val = `${value / 16}${units}`;
return shouldScale ? scaleRem(val) : val;
}

if (typeof value === 'string') {
if (value.startsWith('calc(') || value.startsWith('var(')) {
return value;
}

if (value.includes(' ')) {
return value
.split(' ')
.map((val) => converter(val))
.join(' ');
}

if (value.includes(units)) {
return shouldScale ? scaleRem(value) : value;
}

const replaced = value.replace('px', '');
if (!Number.isNaN(Number(replaced))) {
const val = `${Number(replaced) / 16}${units}`;
return shouldScale ? scaleRem(val) : val;
}
}

return value as string;
}

return converter;
}

const rem = createConverter('rem', { shouldScale: true });
const remNoScale = createConverter('rem');
const em = createConverter('em');

function getTransformedScaledValue(value: unknown) {
if (typeof value !== 'string' || !value.includes('var(--mantine-scale)')) {
return value;
}

return value
.match(/^calc\((.*?)\)$/)?.[1]
.split('*')[0]
.trim();
}

function px(value: unknown) {
const transformedValue = getTransformedScaledValue(value);

if (typeof transformedValue === 'number') {
return transformedValue;
}

if (typeof transformedValue === 'string') {
if (transformedValue.includes('calc') || transformedValue.includes('var')) {
return transformedValue;
}

if (transformedValue.includes('px')) {
return Number(transformedValue.replace('px', ''));
}

if (transformedValue.includes('rem')) {
return Number(transformedValue.replace('rem', '')) * 16;
}

if (transformedValue.includes('em')) {
return Number(transformedValue.replace('em', '')) * 16;
}

return Number(transformedValue);
}

return NaN;
}

module.exports = {
px,
em,
rem,
remNoScale,
};
59 changes: 7 additions & 52 deletions src/postcss-rem-em.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,5 @@
import type { AtRule, Root } from 'postcss';

function scaleRem(remValue: string) {
return `calc(${remValue} * var(--mantine-scale))`;
}

function createConverter(units: string, { shouldScale = false } = {}) {
function converter(value: unknown): string {
if (value === 0 || value === '0') {
return '0';
}

if (typeof value === 'number') {
const val = `${value / 16}${units}`;
return shouldScale ? scaleRem(val) : val;
}

if (typeof value === 'string') {
if (value.startsWith('calc(') || value.startsWith('var(')) {
return value;
}

if (value.includes(' ')) {
return value
.split(' ')
.map((val) => converter(val))
.join(' ');
}

if (value.includes(units)) {
return shouldScale ? scaleRem(value) : value;
}

const replaced = value.replace('px', '');
if (!Number.isNaN(Number(replaced))) {
const val = `${Number(replaced) / 16}${units}`;
return shouldScale ? scaleRem(val) : val;
}
}

return value as string;
}

return converter;
}

const rem = createConverter('rem', { shouldScale: true });
const remNoScale = createConverter('rem');
const em = createConverter('em');
const converters = require('./converters');

const getRegExp = (units: 'rem' | 'em') => new RegExp('\\b' + units + '\\(([^()]+)\\)', 'g');
const emRegExp = getRegExp('em');
Expand All @@ -57,15 +10,17 @@ module.exports = () => {
postcssPlugin: 'postcss-rem-em',

Once(root: Root) {
root.replaceValues(remRegExp, { fast: `rem(` }, (_, values) => rem(values));
root.replaceValues(emRegExp, { fast: `em(` }, (_, values) => em(values));
root.replaceValues(remRegExp, { fast: `rem(` }, (_, values) => converters.rem(values));
root.replaceValues(emRegExp, { fast: `em(` }, (_, values) => converters.em(values));
},

AtRule: {
media: (atRule: AtRule) => {
atRule.params = atRule.params
.replace(remRegExp, (value) => remNoScale(value.replace(/rem\((.*?)\)/g, '$1')))
.replace(emRegExp, (value) => em(value.replace(/em\((.*?)\)/g, '$1')));
.replace(remRegExp, (value) =>
converters.remNoScale(value.replace(/rem\((.*?)\)/g, '$1'))
)
.replace(emRegExp, (value) => converters.em(value.replace(/em\((.*?)\)/g, '$1')));
},
},
};
Expand Down
15 changes: 15 additions & 0 deletions src/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ const nested = require('postcss-nested');
const mixins = require('postcss-mixins');
const remEm = require('./postcss-rem-em');
const lightDark = require('./postcss-light-dark');
const converters = require('./converters');

function colorSchemeMixin(colorScheme: 'light' | 'dark') {
return {
Expand Down Expand Up @@ -56,6 +57,18 @@ const notLtrMixin = {
},
};

const smallerThanMixin = (_mixin: string, breakpoint: string) => ({
[`@media (max-width: ${converters.em(converters.px(breakpoint) - 0.1)})`]: {
'@mixin-content': {},
},
});

const largerThanMixin = (_mixin: string, breakpoint: string) => ({
[`@media (min-width: ${converters.em(breakpoint)})`]: {
'@mixin-content': {},
},
});

module.exports = () => {
return {
postcssPlugin: 'postcss-preset-mantine',
Expand All @@ -74,6 +87,8 @@ module.exports = () => {
ltr: ltrMixin,
'not-rtl': notRtlMixin,
'not-ltr': notLtrMixin,
'smaller-than': smallerThanMixin,
'larger-than': largerThanMixin,
},
}),
],
Expand Down
21 changes: 21 additions & 0 deletions src/tests/__snapshots__/smaller-larget-than.test.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`larger-than it transforms larger-than mixin correctly 1`] = `
"
@media (min-width: 20em) {
.a {
background: red
}
}
"
`;

exports[`smaller-than it transforms smaller-than mixin correctly 1`] = `
"
@media (max-width: 19.99375em) {
.a {
background: red
}
}
"
`;
31 changes: 31 additions & 0 deletions src/tests/smaller-larget-than.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { testTransform } from './utils';

const smallerThanInput = `
.a {
@mixin smaller-than 320px {
background: red;
}
}
`;

const largerThanInput = `
.a {
@mixin larger-than 320px {
background: red;
}
}
`;

describe('smaller-than', () => {
it('it transforms smaller-than mixin correctly', async () => {
const res = await testTransform(smallerThanInput);
expect(res.css).toMatchSnapshot();
});
});

describe('larger-than', () => {
it('it transforms larger-than mixin correctly', async () => {
const res = await testTransform(largerThanInput);
expect(res.css).toMatchSnapshot();
});
});

0 comments on commit d097158

Please sign in to comment.