UNPKG

@razorpay/blade

Version:

The Design System that powers Razorpay

714 lines (681 loc) 19.3 kB
/// <reference types="react" /> import { Platform as Platform$1 } from 'react-native'; import * as React from 'react'; import { MutableRefObject } from 'react'; type BorderRadius = Readonly<{ /** none: 0(px/rem/pt) */ none: 0; /** xsmall: 1(px/rem/pt) */ xsmall: 1; /** small: 2(px/rem/pt) */ small: 2; /** medium: 4(px/rem/pt) */ medium: 4; /** large: 8(px/rem/pt) */ large: 8; /** xlarge: 12(px/rem/pt) */ xlarge: 12; /** 2xlarge: 16(px/rem/pt) */ '2xlarge': 16; /** max: 9999(px/rem/pt). This will round the left and right side of the box element */ max: 9999; /** round: 50%(pt). This will turn the box element into a circle */ round: '50%'; }>; type BorderWidth = Readonly<{ /** none: 0(px/rem/pt) */ none: 0; /** thinner: 0.5(px/rem/pt) */ thinner: 0.5; /** thin: 1(px/rem/pt) */ thin: 1; /** thick: 1.5(px/rem/pt) */ thick: 1.5; /** thicker: 2(px/rem/pt) */ thicker: 2; }>; type Border = Readonly<{ radius: BorderRadius; width: BorderWidth; }>; type Breakpoints = Readonly<{ /** * `base` is used for responsive styling following a **mobile first** approach. It starts from 0px till the next existing token * * Think of this as styles without any media query. * * ### Example * * This code will set margin as `spacing.2` on "m" size screens and above. And as `spacing.1` on less than "m" size screens * ```jsx * <Box margin={{ base: 'spacing.1', m: 'spacing.2' }} /> * ``` * * This roughly translates into - * * ``` * .Box { * margin: 'spacing.1'; * } * * @media screen and (min-width: 768px) { * .Box { * margin: 'spacing.2'; * } * } * ``` */ base: number; /** * `@media screen and (min-width: 320px)` * * Small Mobiles */ xs: number; /** * `@media screen and (min-width: 480px)` * * Mobiles and Small Tablets */ s: number; /** * `@media screen and (min-width: 768px)` * * Medium and Large Tablets. * * Dimensions with `m` and above can be treated as desktop in mobile-first approach (with min-width). * Hence this breakpoint can be used for desktop styling. * * E.g. next example will keep flexDirection `row` on mobiles and `column` on large tablets, desktop, and larger screens * * ```jsx * <Box display="flex" flexDirection={{ base: 'row', m: 'column' }} /> * ``` * */ m: number; /** * `@media screen and (min-width: 1024px)` * * Desktop */ l: number; /** * `@media screen and (min-width: 1200px)` * * HD Desktop */ xl: number; }>; type FontFamily = { /** Used for all type of textual content except code snippets, and headings */ text: string; /** Used for code snippets */ code: string; /** Used for headings */ heading: string; }; type FontWeight = { regular: 400; medium: 500; semibold: 600; bold: 700; }; /** * For font size and line-heights we can’t say from xl to 2xl the value will necessary increase. * it might decrease or remain same because these are alias tokens and we need aliases for cross platform. * so for example xl on mobile can be 32px and on desktop xl can be 34px, * similarly 2xl on mobile can be 34px but on desktop doesn’t necessarily mean 2xl will be more than xl(34px) it can be 32 as well since visually they make better hierarchy. */ type FontSize = { /** desktop: 10(px/rem/pt) * * mobile: 10(px/rem/pt) */ 25: number; /** desktop: 11(px/rem/pt) * * mobile: 11(px/rem/pt) */ 50: number; /** desktop: 12(px/rem/pt) * * mobile: 12(px/rem/pt) */ 75: number; /** desktop: 14(px/rem/pt) * * mobile: 14(px/rem/pt) */ 100: number; /** desktop: 16(px/rem/pt) * * mobile: 16(px/rem/pt) */ 200: number; /** desktop: 18(px/rem/pt) * * mobile: 16(px/rem/pt) */ 300: number; /** desktop: 20(px/rem/pt) * * mobile: 18(px/rem/pt) */ 400: number; /** desktop: 24(px/rem/pt) * * mobile: 20(px/rem/pt) */ 500: number; /** desktop: 32(px/rem/pt) * * mobile: 24(px/rem/pt) */ 600: number; /** desktop: 40(px/rem/pt) * * mobile: 32(px/rem/pt) */ 700: number; /** desktop: 48(px/rem/pt) * * mobile: 34(px/rem/pt) */ 800: number; /** desktop: 56(px/rem/pt) * * mobile: 36(px/rem/pt) */ 900: number; /** desktop: 64(px/rem/pt) * * mobile: 38(px/rem/pt) */ 1000: number; /** desktop: 72(px/rem/pt) * * mobile: 40(px/rem/pt) */ 1100: number; }; type Typography = { fonts: { family: FontFamily; size: FontSize; weight: FontWeight; }; lineHeights: { /** desktop: 0(px/rem/pt) * * mobile: 0(px/rem/pt) */ 0: number; /** desktop: 14(px/rem/pt) * * mobile: 14(px/rem/pt) */ 25: number; /** desktop: 16(px/rem/pt) * * mobile: 16(px/rem/pt) */ 50: number; /** desktop: 18(px/rem/pt) * * mobile: 18(px/rem/pt) */ 75: number; /** desktop: 20(px/rem/pt) * * mobile: 20(px/rem/pt) */ 100: number; /** desktop: 24(px/rem/pt) * * mobile: 24(px/rem/pt) */ 200: number; /** desktop: 24(px/rem/pt) * * mobile: 22(px/rem/pt) */ 300: number; /** desktop: 26(px/rem/pt) * * mobile: 24(px/rem/pt) */ 400: number; /** desktop: 32(px/rem/pt) * * mobile: 26(px/rem/pt) */ 500: number; /** desktop: 38(px/rem/pt) * * mobile: 32(px/rem/pt) */ 600: number; /** desktop: 46(px/rem/pt) * * mobile: 38(px/rem/pt) */ 700: number; /** desktop: 56(px/rem/pt) * * mobile: 40(px/rem/pt) */ 800: number; /** desktop: 64(px/rem/pt) * * mobile: 42(px/rem/pt) */ 900: number; /** desktop: 70(px/rem/pt) * * mobile: 46(px/rem/pt) */ 1000: number; /** desktop: 78(px/rem/pt) * * mobile: 48(px/rem/pt) */ 1100: number; }; letterSpacings: { /** -1% */ 50: number; /** 0% */ 100: number; }; }; type TypographyPlatforms = 'onDesktop' | 'onMobile'; type TypographyWithPlatforms = Record<TypographyPlatforms, Typography>; /** * When any of the values are changed here, do change the jsdoc comments in BaseBox/types/spacingTypes.ts as well * * {@link ../../components/Box/BaseBox/types/spacingTypes.ts} */ type Spacing = Readonly<{ /** 0: 0(px/rem/pt) */ 0: 0; /** 1: 2(px/rem/pt) */ 1: 2; /** 2: 4(px/rem/pt) */ 2: 4; /** 3: 8(px/rem/pt) */ 3: 8; /** 4: 12(px/rem/pt) */ 4: 12; /** 5: 16(px/rem/pt) */ 5: 16; /** 6: 20(px/rem/pt) */ 6: 20; /** 7: 24(px/rem/pt) */ 7: 24; /** 8: 32(px/rem/pt) */ 8: 32; /** 9: 40(px/rem/pt) */ 9: 40; /** 10: 48(px/rem/pt) */ 10: 48; /** 11: 56(px/rem/pt) */ 11: 56; }>; type Duration = { /** `80` milliseconds */ '2xquick': 80; /** `160` milliseconds */ xquick: 160; /** `200` milliseconds */ quick: 200; /** `280` milliseconds */ moderate: 280; /** `360` milliseconds */ xmoderate: 360; /** `480` milliseconds */ gentle: 480; /** `640` milliseconds */ xgentle: 640; /** `960` milliseconds */ '2xgentle': 960; }; type Delay = { /** `80` milliseconds */ '2xquick': 80; /** `160` milliseconds */ xquick: 160; /** `280` milliseconds */ moderate: 280; /** `480` milliseconds */ gentle: 480; /** `960` milliseconds */ xgentle: 960; /** `2000` milliseconds */ long: 2000; /** `3000` milliseconds */ xlong: 3000; /** `5000` milliseconds */ '2xlong': 5000; }; type EasingFactoryFn = { factory: () => (value: number) => number; }; type EasingType<Value extends string> = Platform.Select<{ web: Value; native: EasingFactoryFn; }>; type Easing = { /** * Linear Easing * * Use Case: Marquee, Progress Bar, etc * * Returns cubic-bezier string in web and EasingFactoryFn of react-native-reanimated in native */ linear: EasingType<'cubic-bezier(0, 0, 0, 0)'>; /** * Entrance Animation Easing * * Use Case: Entry of modals, drawer, dropdown, etc * * Returns cubic-bezier string in web and EasingFactoryFn of react-native-reanimated in native */ entrance: EasingType<'cubic-bezier(0, 0, 0.2, 1)'>; /** * Exit Animation Easing * * Use Case: Exit of modals, drawer, dropdown, etc * * Returns cubic-bezier string in web and EasingFactoryFn of react-native-reanimated in native */ exit: EasingType<'cubic-bezier(0.17, 0, 1, 1)'>; /** * Standard Easing * * Use Case: Morph * * Returns cubic-bezier string in web and EasingFactoryFn of react-native-reanimated in native */ standard: EasingType<'cubic-bezier(0.3, 0, 0.2, 1)'>; /** * Emphasized Easing * * Use Case: Hover states of interactive items * * Returns cubic-bezier string in web and EasingFactoryFn of react-native-reanimated in native */ emphasized: EasingType<'cubic-bezier(0.5, 0, 0, 1)'>; /** * Overshoot Easing * * Use Case: Toast notifications * * Returns cubic-bezier string in web and EasingFactoryFn of react-native-reanimated in native */ overshoot: EasingType<'cubic-bezier(0.5, 0, 0.3, 1.5)'>; /** * Error Easing * * Use Case: Error States * * Returns cubic-bezier string in web and EasingFactoryFn of react-native-reanimated in native */ shake: EasingType<'cubic-bezier(1, 0.5, 0, 0.5)'>; }; type Motion = Readonly<{ delay: Delay; duration: Duration; easing: Easing; }>; type ElevationLevels = 'none' | 'lowRaised' | 'midRaised' | 'highRaised'; type ElevationStyles = Readonly<{ elevation: number; shadowColor: string; shadowOpacity: number; shadowRadius: number; shadowOffset: { /** * x-axis */ width: number; /** * y-axis */ height: number; }; }>; type Elevation = Record<ElevationLevels, Platform.Select<{ web: string; native: ElevationStyles; }>>; type ElevationWithColorModes = Record<ColorSchemeModes, Elevation>; /** * * When combined with union, this type utility will give you autocomplete of union while still supporting any string value as input * * ### Usage * * ```ts * type ThemeName = 'themeOne' | 'themeTwo' | StringWithAutocomplete; * ``` * * This will show themeOne and themeTwo in autocomplete but also allow any other string as value. * * More details - https://github.com/razorpay/blade/pull/1031/commits/86b6ee0facf45e7556739efcbfa5396b11b1b3c9#r1121298293 * Related TS Issue - https://github.com/microsoft/TypeScript/issues/29729 * */ type StringWithAutocomplete = string & Record<never, never>; type ColorSchemeNames = 'dark' | 'light'; type ColorSchemeNamesInput = ColorSchemeNames | 'system'; type ColorSchemeModes = 'onDark' | 'onLight'; type FeedbackColors = 'information' | 'negative' | 'neutral' | 'notice' | 'positive'; type Emphasis = { subtle: string; moderate: string; intense: string; normal: string; muted: string; disabled: string; }; type SubtleOrIntenseEmphasis = Pick<Emphasis, 'subtle' | 'intense'>; type InteractiveStates = { default: string; highlighted: string; disabled: string; faded: string; }; type OnEmphasis = { onSubtle: string; onIntense: string; }; type ColorCategories = { staticBlack: Pick<Emphasis, 'normal' | 'subtle' | 'muted' | 'disabled'>; staticWhite: Pick<Emphasis, 'normal' | 'subtle' | 'muted' | 'disabled'>; gray: Pick<Emphasis, 'normal' | 'subtle' | 'muted' | 'disabled'>; onSea: Pick<OnEmphasis, 'onSubtle' | 'onIntense'>; onCloud: Pick<OnEmphasis, 'onSubtle' | 'onIntense'>; primary: Pick<Emphasis, 'normal'>; }; type InteractiveColorKeys = FeedbackColors | Exclude<keyof ColorCategories, 'onSea' | 'onCloud'>; type Colors = { interactive: { background: Record<InteractiveColorKeys, InteractiveStates & { fadedHighlighted: string; }>; border: Record<InteractiveColorKeys, InteractiveStates>; text: Record<InteractiveColorKeys | 'onPrimary', Pick<Emphasis, 'normal' | 'subtle' | 'muted' | 'disabled'>>; icon: Record<InteractiveColorKeys | 'onPrimary', Pick<Emphasis, 'normal' | 'subtle' | 'muted' | 'disabled'>>; }; feedback: { background: Record<FeedbackColors, SubtleOrIntenseEmphasis>; border: Record<FeedbackColors, SubtleOrIntenseEmphasis>; text: Record<FeedbackColors, SubtleOrIntenseEmphasis>; icon: Record<FeedbackColors, SubtleOrIntenseEmphasis>; }; surface: { background: { gray: Pick<Emphasis, 'subtle' | 'moderate' | 'intense'>; primary: SubtleOrIntenseEmphasis; sea: SubtleOrIntenseEmphasis; cloud: SubtleOrIntenseEmphasis; }; border: { gray: Pick<Emphasis, 'normal' | 'subtle' | 'muted'>; primary: Pick<Emphasis, 'normal' | 'muted'>; }; text: ColorCategories; icon: ColorCategories; }; overlay: { background: Pick<Emphasis, 'moderate' | 'subtle'>; }; popup: { background: SubtleOrIntenseEmphasis; border: SubtleOrIntenseEmphasis; }; transparent: string; }; type ColorsWithModes = Record<ColorSchemeModes, Colors>; type ThemeTokens = { name: 'bladeTheme' | StringWithAutocomplete; border: Border; breakpoints: Breakpoints; colors: ColorsWithModes; motion: Motion; elevation: ElevationWithColorModes; spacing: Spacing; typography: TypographyWithPlatforms; }; declare const getColorScheme: (colorScheme?: ColorSchemeNamesInput) => ColorSchemeNames; declare const getMediaQuery: ({ min, max }: { min: number; max?: number | undefined; }) => string; type PlatformTypes = 'browser' | 'node' | 'react-native' | 'unknown'; declare const getPlatformType: () => PlatformTypes; declare const deviceType: { readonly desktop: "desktop"; readonly mobile: "mobile"; }; type DeviceType = keyof typeof deviceType; type Breakpoint = keyof Breakpoints | undefined; type BreakpointAndDevice = { matchedBreakpoint: Breakpoint; matchedDeviceType: DeviceType; }; declare const useBreakpoint: ({ breakpoints, }: { breakpoints: Breakpoints; }) => BreakpointAndDevice; type UseColorScheme = { colorScheme: ColorSchemeNames; setColorScheme: (colorScheme: ColorSchemeNamesInput) => void; }; declare const useColorScheme: (initialColorScheme?: ColorSchemeNamesInput) => UseColorScheme; declare function useInterval(callback: () => void, { delay, enable }: { delay: number; enable?: boolean; }): void; declare const isReactNative: () => boolean; declare const isBrowser: () => boolean; declare const getOS: () => typeof Platform$1.OS; declare const isAndroid: () => boolean; /** * Brands a type making them act as nominal * @see https://medium.com/@KevinBGreene/surviving-the-typescript-ecosystem-branding-and-type-tagging-6cf6e516523d */ type Brand<Type, Name extends string> = Type & { __brand__?: Name; }; type NativeOrWebBrand = Brand<any, 'native' | 'web'>; declare namespace Platform { type Name = 'native'; /** * Right now, the module resolution is set to resolve `.native` files, * * Thus Platform.Select<> type will return the `native` type */ type Select<Options extends { web: unknown; native: unknown; }> = Brand<Options[Name], 'platform-native'>; type CastNative<T extends NativeOrWebBrand | undefined> = Extract<T, { __brand__?: 'platform-native' | 'platform-all'; }>; type CastWeb<T extends NativeOrWebBrand | undefined> = Extract<T, { __brand__?: 'platform-web' | 'platform-all'; }>; } /** * @description * * Casts a Platform.Select<> type to web type * * @example * * ```ts * type Example = Platform.Select<{ web: string; native: number }>; * * const extractedWebType = castWebType('' as Example); * // ^ string * ``` */ declare const castWebType: <T>(value: T) => Extract<T, { __brand__?: "platform-all" | "platform-web" | undefined; }>; /** * @description * * Casts a Platform.Select<> type to native type * * @example * * ```ts * type Example = Platform.Select<{ web: string; native: number }>; * * const extractedNativeType = castNativeType('' as Example); * // ^ number * ``` */ declare const castNativeType: <T>(value: T) => Extract<T, { __brand__?: "platform-native" | "platform-all" | undefined; }>; declare function makeBorderSize<T extends number>(size: T): `${T}px`; declare function makeBorderSize<T extends string>(size: T): T; type MakeMotionTime<Value extends number> = Platform.Select<{ native: number; web: `${Value}ms`; }>; declare const makeMotionTime: <T extends number>(time: T) => MakeMotionTime<T>; declare const makeSpace: <T extends number>(size: T) => `${T}px`; declare const makeTypographySize: <T extends number>(size: T) => `${T}px`; type MakeSize<T extends number> = `${T}px`; declare const makeSize: <T extends number>(size: T) => `${T}px`; /** * @deprecated This utility will be deprecated in subsequent version. */ declare const toTitleCase: (inputString: string) => string; /** * a type-safe version of the `usePrevious` hook described here: * @see {@link https://reactjs.org/docs/hooks-faq.html#how-to-get-the-previous-props-or-state} * @deprecated This utility will be deprecated in subsequent version. */ declare function usePrevious<T>(value: T): MutableRefObject<T | undefined>['current']; type Theme = { name: ThemeTokens['name']; border: Border; breakpoints: Breakpoints; colors: Colors; spacing: Spacing; motion: Motion; elevation: Elevation; typography: Typography; }; type ThemeContext = UseColorScheme & { theme: Theme; platform: TypographyPlatforms; }; declare const ThemeContext: React.Context<ThemeContext>; declare const useTheme: () => ThemeContext; export { DeviceType, MakeSize, Platform, PlatformTypes, ThemeContext, UseColorScheme, castNativeType, castWebType, getColorScheme, getMediaQuery, getOS, getPlatformType, isAndroid, isBrowser, isReactNative, makeBorderSize, makeMotionTime, makeSize, makeSpace, makeTypographySize, toTitleCase, useBreakpoint, useColorScheme, useInterval, usePrevious, useTheme };