Skip to content

Instantly share code, notes, and snippets.

@antoniopresto
Last active November 4, 2022 14:07
Show Gist options
  • Save antoniopresto/dc27637b340a0e39bfac9d7032f2dd7d to your computer and use it in GitHub Desktop.
Save antoniopresto/dc27637b340a0e39bfac9d7032f2dd7d to your computer and use it in GitHub Desktop.
import cx from 'classnames';
import { createType, Infer, tuple, tupleNum } from 'backland';
export const ViewportSizeEnum = tuple('xs', 'sm', 'md', 'lg', 'xl');
export const ViewportSizes = Object.values(ViewportSizeEnum);
export type ViewportSize = typeof ViewportSizes[number];
export const ViewportSizeType = createType('ViewportSize', {
enum: ViewportSizes,
optional: true,
});
v
export const ColumnSizeUnionType = createType('ColumnSizesUnion', () => {
const str = tuple(
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'10',
'11',
'12'
);
const num = tupleNum(
//
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12
);
return {
optional: true,
union: [...num, ...str].map((el) => ({
literal: el,
})),
};
});
export const ColumnSizesType = createType('ColumnSizes', {
description:
'Sizes of a Column in different ' + //
'screens. See: http://flexboxgrid.com/',
object: {
_kind: {
defaultValue: names.ColumnSizes,
literal: names.ColumnSizes,
optional: true,
},
first: ViewportSizeType,
fluid: 'boolean?',
last: ViewportSizeType,
lg: ColumnSizeUnionType,
lgOffset: 'int?',
md: ColumnSizeUnionType,
mdOffset: 'int?',
sm: ColumnSizeUnionType,
smOffset: 'int?',
xl: ColumnSizeUnionType,
xlOffset: 'int?',
xs: ColumnSizeUnionType,
xsOffset: 'int?',
},
});
export type ColumnSizes = Infer<typeof ColumnSizesType> extends infer R
? { [K in keyof R as K extends '_kind' ? never : K]: R[K] } & {}
: never;
export const RowSizesType = createType('RowSizes', {
object: {
around: ViewportSizeType,
between: ViewportSizeType,
bottom: ViewportSizeType,
center: ViewportSizeType,
end: ViewportSizeType,
middle: ViewportSizeType,
reverse: 'boolean?',
start: ViewportSizeType,
top: ViewportSizeType,
},
});
export type RowSizes = Infer<typeof RowSizesType> extends infer R
? { [K in keyof R as K extends '_kind' ? never : K]: R[K] } & {}
: never;
export function sizeToClass(
kind: 'col',
sizes: ColumnSizes,
className?: string
): string;
export function sizeToClass(
kind: 'row',
sizes: RowSizes,
className?: string
): string;
export function sizeToClass(
...args:
| [kind: 'row', sizes: RowSizes, className?: string]
| [kind: 'col', sizes: ColumnSizes, className?: string]
) {
const [kind, sizes, className] = args;
if (!sizes) return '';
if (kind === 'row') {
return cx(
Object.entries(sizes).map(([k, v]) => {
if (k === 'reverse') return '';
return `${k}-${v}`;
}),
{ row: !sizes.reverse, 'row-reverse': sizes.reverse },
className
);
}
const {
sm,
lg,
md,
lgOffset,
smOffset,
mdOffset,
xsOffset,
xs,
xlOffset,
xl,
last,
first,
} = sizes;
return cx(
{
[`${numberLike.test(`${xs}`) ? `col-xs-${xs}` : ''}`]: xs,
[`${numberLike.test(`${sm}`) ? `col-sm-${sm}` : ''}`]: sm,
[`${numberLike.test(`${md}`) ? `col-md-${md}` : ''}`]: md,
[`${numberLike.test(`${lg}`) ? `col-lg-${lg}` : ''}`]: lg,
[`${numberLike.test(`${xl}`) ? `col-xl-${xl}` : ''}`]: xl,
[`${last ? `last-${last}` : ''}`]: last,
[`${first ? `first-${first}` : ''}`]: first,
[`col-xs-offset-${xsOffset}`]: xsOffset,
[`col-sm-offset-${smOffset}`]: smOffset,
[`col-md-offset-${mdOffset}`]: mdOffset,
[`col-lg-offset-${lgOffset}`]: lgOffset,
[`col-xl-offset-${xlOffset}`]: xlOffset,
},
className
);
}
const numberLike = /^\d*$/;
import { sizeToClass } from '../sizeToClass';
describe('sizesToClass', () => {
test('col', async () => {
const sut = sizeToClass('col', {
sm: '1',
lgOffset: 2,
last: 'xl',
first: 'sm',
});
expect(sut).toBe('col-sm-1 last-xl first-sm col-lg-offset-2');
});
test('row', () => {
const sut = sizeToClass('row', { top: 'xs', start: 'xs', reverse: true });
expect(sut).toBe('top-xs start-xs row-reverse');
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment