Skip to content

mj-studio-library/react-native-scaled-layout

Repository files navigation

react-native-scaled-layout

npm

ogimage-1260-630

Sorry to Api changes in 1.1.0 😢

Flexible, Scalable layout dimensions, font sizes for React Native

@mj-studio/react-native-scaled-layout is using monkey-patch feature in javascript(typescript) and augmentation syntax in typescript.

Contents 🏆

Install 💠

npm i @mj-studio/react-native-scaled-layout

or

yarn add @mj-studio/react-native-scaled-layout

Usage 📌

0. Configure your environment or wanted behavior

❕ If @mj-studio/react-native-scaled-layout is not imported for side-effect, then TypeError will be invoked.

index.js

import { initScaledSettings } from '@mj-studio/react-native-scaled-layout';
...
initScaledSettings(375, { min: 0.5, max: 1.5 }, { min: 0.75, max: 1.35 }, 14);
Params Type Default Required
designSpecWidth number 375 false
dimenScaleRange { min: number; max: number } [0.5, 1.5] false
fontScaleRange { min: number; max: number } [0.75, 1.3] false
defaultFontSize number 14 false

1. Number type Augmentation(Extension)

// calculated with width length of design spec
// clamped with dimenScaleRange min, max value
(36).scaled() /* or */ (36).d() 

// calculated with width length of design spec
// clamped with fontScaleRange min, max value
(24).fontScaled() /* or */ (24).f()

Example in ViewStyle

style={{
    width: (100).d(),
    height: (210).d() + safeAreaBottom,
    borderRadius: (16).d(),
    justifyContent: 'center',
    paddingBottom: safeAreaBottom + (24).d(),
}}

2. ScaledText Component

// automatically adjusted with (14).fontScaled()
<ScaledText style={{fontSize: 14}}>My Text</ScaledText> 

// ignore calculated font scale
// fixed with 28(14 * 2)
<ScaledText style={{fontSize: 14}} customFontScale={isTablet ? 2 : undefined}>My Text</ScaledText>

react-native-scaled-layout is also compatible with Styled Component

export const BoldText = styled(ScaledText)`
  font-family: ${fonts.NotoSansKRBold};
`;
...
const TutorialText = styled(BoldText)`
  left: ${(20).d()}px;
  right: ${(20).d()}px;
  position: absolute;
  font-size: 24px; // automatically adjust font size with (24).fontScaled()
  color: ${({ theme }): string => theme.white};
`;

Calculation 📐

The following is the implementation of initScaledSettings

/**
 * Set initial configuration for scaled layout behavior. If your height of design guideline spec is less than width, invert 1st, 2nd params.
 * @param designSpecWidth your design width viewport width(zeplin, pigma etc...). If your design viewport is 375 x 1000 then 375 is a right value.
 * @param dimenScaleRange dimension scale factor minimum & maximum range. default is [0.5, 1.5]..
 * @param fontScaleRange font scale factor minimum & maximum range. default is [0.75, 1.3].
 * @param defaultFontsize default `<Text>` fontSize. default is 12.
 *
 * @example
 * ```ts
 * initScaledSettings(375, 812, {min: 0.5, max: 1.5}, {min: 0.75, max: 1.3}, 12);
 * ```
 */
export function initScaledSettings(
  designSpecWidth = 375,
  dimenScaleRange: { min: number; max: number } = { min: 0.5, max: 1.5 },
  fontScaleRange: { min: number; max: number } = { min: 0.75, max: 1.3 },
  defaultFontsize = 12,
): void {
  dimenRatio = minLength / designSpecWidth;

  dimenScale = clamp(dimenRatio, dimenScaleRange.min, dimenScaleRange.max);

  fontScale =
    dimenScale >= 1 ? Math.min(dimenScale, fontScaleRange.max) : Math.max(dimenScale * dimenScale, fontScaleRange.min);
  _FONT_SCALE_ = fontScale;
  _defaultFontSize = defaultFontsize;

  /* eslint-disable no-extend-native */
  Number.prototype.scaled = function scaled(): number {
    return Math.round((this as number) * dimenScale);
  };
  Number.prototype.fontScaled = function fontScaled(): number {
    return Math.round((this as number) * fontScale);
  };
  Number.prototype.d = function d(): number {
    return (this as number).scaled();
  };
  Number.prototype.f = function f(): number {
    return (this as number).fontScaled();
  };
  /* eslint-enable no-extend-native */
}
initScaledSettings();

Trouble Shooting❗️

1. TypeError: 40.d is not a function

Please put import '@mj-studio/react-native-scaled-layout' to top of index.js or top of file which in setupFiles list of jest.config.js

Todo ✅

  • Create ScaledView, ScaledTextInput, ScaledTouchableXXX like ScaledText

Change Logs 🔧

  • 1.2.0
    • Change customFontScale logic in ScaledText
  • 1.1.7
    • Fix ScaledText font size scaling issue. Previously, the fontSize property is multiplied to float not integer.
  • 1.1.6
    • The values are calculated with ceil() instead of round().
  • 1.1.4
    • minimumFontSize prop is added in ScaledText
  • 1.1.2
    • dimenWidthScaled(), dimenHeightScaled(), w(), h() are removed
    • designSpecHeight parameter is removed from initScaledSettings
  • 1.1.1
    • FontScale is calculated with design spec width length not design spec diagonal length
  • 1.1.0 (Sorry to API changes)
    • dimenScaled() is renamed to scaled()
    • New number type augmentation dimenWidthScaled(), dimenHeightScaled()
    • Add simple alias for functions d(), f(), w(), h()
  • 1.0.6
    • Apply round for fixing showing weird line because of floating number dimension

feel free your fork or any PR! Thanks

About

Flexible, Scalable layout dimensions, font sizes for React Native

Resources

License

Stars

Watchers

Forks

Packages

No packages published