Skip to content

Commit

Permalink
Change from class-based to function-based design
Browse files Browse the repository at this point in the history
  • Loading branch information
Karibash committed Jul 22, 2021
1 parent b6327a5 commit d1662b8
Show file tree
Hide file tree
Showing 35 changed files with 1,123 additions and 495 deletions.
1 change: 0 additions & 1 deletion src/common/Converter.ts

This file was deleted.

18 changes: 0 additions & 18 deletions src/common/ConvertibleLengthUnit.ts

This file was deleted.

8 changes: 0 additions & 8 deletions src/common/ConvertibleMultiplicationUnit.ts

This file was deleted.

7 changes: 0 additions & 7 deletions src/common/Unit.ts

This file was deleted.

59 changes: 0 additions & 59 deletions src/common/helpers.ts

This file was deleted.

75 changes: 75 additions & 0 deletions src/defs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
const AbsoluteLengthUnitSuffix = {
Pixel: 'px',
Centimeter: 'cm',
Millimeter: 'mm',
Quarter: 'Q',
Inch: 'in',
Pica: 'pc',
Point: 'pt',
} as const;
export type AbsoluteLengthUnitSuffix = typeof AbsoluteLengthUnitSuffix[keyof typeof AbsoluteLengthUnitSuffix];

const RelativeLengthUnitSuffix = {
REM: 'rem',
EM: 'em',
ViewWidth: 'vw',
ViewHeight: 'vh',
ViewMin: 'vmin',
ViewMax: 'vmax',
} as const;
export type RelativeLengthUnitSuffix = typeof RelativeLengthUnitSuffix[keyof typeof RelativeLengthUnitSuffix];

const MultiplicationUnitSuffix = {
Percent: '%',
Magnification: '',
} as const;
export type MultiplicationUnitSuffix = typeof MultiplicationUnitSuffix[keyof typeof MultiplicationUnitSuffix];

const LengthUnitSuffix = {
...AbsoluteLengthUnitSuffix,
...RelativeLengthUnitSuffix,
};
export type LengthUnitSuffix = typeof LengthUnitSuffix[keyof typeof LengthUnitSuffix];

export const UnitSuffix = {
...LengthUnitSuffix,
...MultiplicationUnitSuffix,
};
export type UnitSuffix = typeof UnitSuffix[keyof typeof UnitSuffix];

export type Unit<Suffix extends UnitSuffix> = `${number}${Suffix}`;

export type ConvertLengthUnitArgsOptions = {
rem?: Element | Unit<'px'>;
em?: Element | Unit<'px'>;
viewWidth?: Unit<'px'>;
viewHeight?: Unit<'px'>;
};

export type ConvertLengthUnitArgs<
FromUnitValue extends Unit<LengthUnitSuffix>,
ToUnitSuffix extends LengthUnitSuffix,
> = [
fromUnitValue: FromUnitValue,
toUnitSuffix: ToUnitSuffix,
options?: ConvertLengthUnitArgsOptions,
];

export type ConvertMultiplicationUnitArgs<
FromUnitValue extends Unit<MultiplicationUnitSuffix>,
ToUnitSuffix extends MultiplicationUnitSuffix,
> = [
fromUnitValue: FromUnitValue,
toUnitSuffix: ToUnitSuffix,
];

export type ConvertArgs<FromUnitValue, ToUnitSuffix> =
FromUnitValue extends Unit<LengthUnitSuffix>
? ToUnitSuffix extends LengthUnitSuffix
? ConvertLengthUnitArgs<FromUnitValue, ToUnitSuffix>
: never
: FromUnitValue extends Unit<MultiplicationUnitSuffix>
? ToUnitSuffix extends MultiplicationUnitSuffix
? ConvertMultiplicationUnitArgs<FromUnitValue, ToUnitSuffix>
: never
: never
89 changes: 71 additions & 18 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,71 @@
export {
findRootFontSize,
tryFindRootFontSize,
findViewHeight,
tryFindViewHeight,
findViewWidth,
tryFindViewWidth,
} from 'common/helpers';
export { Unit } from 'common/Unit';
export { Centimeter } from 'units/Centimeter';
export { Magnification } from 'units/Magnification';
export { Percent } from 'units/Percent';
export { Pixel } from 'units/Pixel';
export { Rem } from 'units/Rem';
export { VH } from 'units/VH';
export { VMax } from 'units/VMax';
export { VMin } from 'units/VMin';
export { VW } from 'units/VW';
import { ConvertArgs, Unit, UnitSuffix } from 'defs';
import {
getFontSizePixelValue,
getViewWidthPixelValue,
getViewHeightPixelValue,
converterMap,
} from 'internal';

export * from 'defs';

const UNIT_SPLIT_REGEXP = /^((?:[1-9]\d*|0)(?:\.\d+)?)(px|cm|mm|Q|in|pc|pt|rem|em|vw|vh|vmin|vmax|%|)$/;
export const splitUnitValue = (value: Unit<UnitSuffix>): { value: number, unitSuffix: UnitSuffix } => {
const split = value.match(UNIT_SPLIT_REGEXP);
if (split === null || split.length < 3) {
throw new TypeError('Invalid value for value argument.');
}
return {
value: parseFloat(split[1]),
unitSuffix: split[2] as UnitSuffix,
};
};

export const convertUnits = <
FromUnitValue extends Unit<UnitSuffix>,
ToUnitSuffix extends UnitSuffix,
>(
...[
fromUnitValue,
toUnitSuffix,
options,
]: ConvertArgs<FromUnitValue, ToUnitSuffix>
): Unit<ToUnitSuffix> => {
const { value: fromValue, unitSuffix: fromUnitSuffix } = splitUnitValue(fromUnitValue) ?? {};

const converters = converterMap[fromUnitSuffix];
if (converters === undefined) {
throw new TypeError('Invalid value for fromUnitValue argument.');
}

const converter = converters[toUnitSuffix];
if (converter === undefined) {
throw new TypeError('Invalid value for toUnitSuffix argument');
}

const remPixel = typeof options?.rem === 'string' ? splitUnitValue(options?.rem) : undefined;
const remElement = options?.rem instanceof Element ? options?.rem : document.documentElement;
const remPixelValue = remPixel ? remPixel.value : getFontSizePixelValue(remElement);
if (!remPixelValue) {
throw new TypeError('Failed to get the font size of the root element. Please run it in the browser environment or specify the default size.');
}

const emPixel = typeof options?.em === 'string' ? splitUnitValue(options?.em) : undefined;
const emElement = options?.em instanceof Element ? options?.em : document.documentElement;
const emPixelValue = emPixel ? emPixel.value : getFontSizePixelValue(emElement);
if (!emPixelValue) {
throw new TypeError('Failed to get the font size of the element. Please run it in the browser environment or specify the default size.');
}

const viewWidthPixelValue = options?.viewWidth ?? getViewWidthPixelValue();
if (!viewWidthPixelValue) {
throw new TypeError('Failed to get the screen width size. Please run it in the browser environment or specify the default size.');
}

const viewHeightPixelValue = options?.viewHeight ?? getViewHeightPixelValue();
if (!viewHeightPixelValue) {
throw new TypeError('Failed to get the screen height size. Please run it in the browser environment or specify the default size.');
}

const toUnitValue = converter(fromValue, { remPixelValue, emPixelValue, viewWidthPixelValue, viewHeightPixelValue });
return `${toUnitValue}${toUnitSuffix}` as Unit<ToUnitSuffix>;
};
6 changes: 6 additions & 0 deletions src/internal/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const INCH_PIXEL_VALUE = 96;
export const CENTIMETER_PIXEL_VALUE = INCH_PIXEL_VALUE / 2.54;
export const MILLIMETER_PIXEL_VALUE = CENTIMETER_PIXEL_VALUE / 10;
export const QUARTER_PIXEL_VALUE = CENTIMETER_PIXEL_VALUE / 40;
export const PICA_PIXEL_VALUE = INCH_PIXEL_VALUE / 6;
export const POINT_PIXEL_VALUE = PICA_PIXEL_VALUE / 12;
68 changes: 68 additions & 0 deletions src/internal/converters/centimeter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { UnitSuffix } from 'defs';
import { CENTIMETER_PIXEL_VALUE } from 'internal/constants';
import { UnitConverterOptions, noConvert } from 'internal/converters';
import { pixel } from 'internal/converters/pixel';

const centimeterToPixel = (value: number): number => {
return value * CENTIMETER_PIXEL_VALUE;
};

const centimeterToMillimeter = (value: number): number => {
return pixel.mm(centimeterToPixel(value));
};

const centimeterToQuarter = (value: number): number => {
return pixel.Q(centimeterToPixel(value));
};

const centimeterToInch = (value: number): number => {
return pixel.in(centimeterToPixel(value));
};

const centimeterToPica = (value: number): number => {
return pixel.pc(centimeterToPixel(value));
};

const centimeterToPoint = (value: number): number => {
return pixel.pt(centimeterToPixel(value));
};

const centimeterToREM = (value: number, options: UnitConverterOptions): number => {
return pixel.rem(centimeterToPixel(value), options);
};

const centimeterToEM = (value: number, options: UnitConverterOptions): number => {
return pixel.em(centimeterToPixel(value), options);
};

const centimeterToViewWidth = (value: number, options: UnitConverterOptions): number => {
return pixel.vw(centimeterToPixel(value), options);
};

const centimeterToViewHeight = (value: number, options: UnitConverterOptions): number => {
return pixel.vh(centimeterToPixel(value), options);
};

const centimeterToViewMin = (value: number, options: UnitConverterOptions): number => {
return pixel.vmin(centimeterToPixel(value), options);
};

const centimeterToViewMax = (value: number, options: UnitConverterOptions): number => {
return pixel.vmax(centimeterToPixel(value), options);
};

export const centimeter = {
[UnitSuffix.Pixel]: centimeterToPixel,
[UnitSuffix.Centimeter]: noConvert,
[UnitSuffix.Millimeter]: centimeterToMillimeter,
[UnitSuffix.Quarter]: centimeterToQuarter,
[UnitSuffix.Inch]: centimeterToInch,
[UnitSuffix.Pica]: centimeterToPica,
[UnitSuffix.Point]: centimeterToPoint,
[UnitSuffix.REM]: centimeterToREM,
[UnitSuffix.EM]: centimeterToEM,
[UnitSuffix.ViewWidth]: centimeterToViewWidth,
[UnitSuffix.ViewHeight]: centimeterToViewHeight,
[UnitSuffix.ViewMin]: centimeterToViewMin,
[UnitSuffix.ViewMax]: centimeterToViewMax,
};
Loading

0 comments on commit d1662b8

Please sign in to comment.