@crossed/styled
Version:
A universal & performant styling library for React Native, Next.js & React
104 lines (97 loc) • 3.3 kB
text/typescript
/**
* Copyright (c) Paymium.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root of this projects source tree.
*/
import type { CrossedstyleValues, Plugin } from '../types';
import { convertKeyToCss, normalizeUnitPixel } from './utils';
export let cacheBreakpoints: Partial<
Record<'xs' | 'sm' | 'md' | 'lg' | 'xl', number>
> = {};
export interface CrossedMediaQueriesPlugin {
media?: {
xs?: CrossedstyleValues;
sm?: CrossedstyleValues;
md?: CrossedstyleValues;
lg?: CrossedstyleValues;
xl?: CrossedstyleValues;
};
}
let Dimensions: any;
let Platform: any;
export const MediaQueriesPlugin = <
B extends Record<'xs' | 'sm' | 'md' | 'lg' | 'xl', number>,
>(
breakpoints: B
): Plugin<CrossedMediaQueriesPlugin> => {
cacheBreakpoints = breakpoints;
return {
name: 'MediaQueriesPlugin',
test: ['media'],
apply: function MediaQueriesApply({ styles, addClassname, props, isWeb }) {
// props only exists at runtime
// Hack for load react-native only at runtime, not buildtime
if (props && !Dimensions && !Platform) {
// eslint-disable-next-line @typescript-eslint/no-var-requires
Dimensions = require('react-native').Dimensions;
// eslint-disable-next-line @typescript-eslint/no-var-requires
Platform = require('react-native').Platform;
}
Object.entries(styles).forEach(
([key, values]: [
keyof CrossedMediaQueriesPlugin['media'],
CrossedstyleValues,
]) => {
const breakpointsValue = normalizeUnitPixel(
'width',
breakpoints[key],
isWeb
);
if (values) {
Object.entries(values).forEach(([keyProperty, valueProperty]) => {
if (Platform && Dimensions && Platform.OS !== 'web') {
// apply style for native
if (breakpoints[key] < Dimensions.get('window').width) {
addClassname({
body: {
[``]: {
[keyProperty]: valueProperty,
},
},
});
}
} else {
// apply style for web
const valueNormalized = normalizeUnitPixel(
keyProperty,
valueProperty,
isWeb
);
const body = {
[`${key}:${convertKeyToCss(keyProperty)}-[${
typeof valueNormalized === 'number'
? valueNormalized
: valueNormalized?.replace(/ /g, '-')
}]`]: {
[keyProperty]: valueNormalized,
},
};
addClassname({
wrapper: (str) =>
`@media (min-width: ${breakpointsValue}) { ${str} }`,
body,
});
if (props && typeof window !== 'undefined' && Dimensions) {
if (breakpoints[key] < Dimensions.get('window').width) {
addClassname({ body });
}
}
}
});
}
}
);
},
};
};