UNPKG

@vitus-labs/rocketstyle

Version:

Rocketstyle is ultra powerful and extensible styling system for building React components blazingly fast, easily and make them easily extensible and reusable.

598 lines (597 loc) 22.9 kB
import { config, context, render } from "@vitus-labs/core"; import { ComponentType, FC, FocusEventHandler, MouseEventHandler, ReactNode } from "react"; //#region src/context/context.d.ts type Theme$1 = { rootSize: number; breakpoints?: Record<string, number>; __VITUS_LABS__?: never; } & Record<string, unknown>; type TProvider = { children: ReactNode; theme?: Theme$1; mode?: 'light' | 'dark'; inversed?: boolean; provider?: ComponentType<any>; }; /** * Top-level theme and mode provider for rocketstyle components. * Reads the parent context, merges incoming props, and resolves * the active mode (with optional inversion for nested dark/light switching). */ declare const Provider: FC<TProvider>; //#endregion //#region src/constants/defaultDimensions.d.ts /** * Default dimension configuration for rocketstyle components. * Defines four built-in dimensions: `states`, `sizes`, `variants`, * and `multiple` (a multi-select dimension). */ declare const DEFAULT_DIMENSIONS: { readonly states: "state"; readonly sizes: "size"; readonly variants: "variant"; readonly multiple: { readonly propName: "multiple"; readonly multi: true; }; readonly modifiers: { readonly propName: "modifier"; readonly multi: true; readonly transform: true; }; }; type DefaultDimensions = typeof DEFAULT_DIMENSIONS; //#endregion //#region src/types/pseudo.d.ts type PseudoActions = { onMouseEnter: MouseEventHandler; onMouseLeave: MouseEventHandler; onMouseDown: MouseEventHandler; onMouseUp: MouseEventHandler; onFocus: FocusEventHandler; onBlur: FocusEventHandler; }; type PseudoState = { active: boolean; hover: boolean; focus: boolean; pressed: boolean; disabled: boolean; readOnly: boolean; }; type PseudoProps = Partial<PseudoState & PseudoActions>; //#endregion //#region src/types/utils.d.ts type TObj = Record<string, unknown>; type TFn = (...args: any) => any; type CallBackParam = TObj | TFn; type ElementType<T extends TObj | unknown = any> = ComponentType<T> & Partial<{ [key: string]: any; }>; type ValueOf<T> = T[keyof T]; type ArrayOfValues<T> = T[keyof T][]; type ArrayOfKeys<T> = Array<keyof T>; type IsFalseOrNullable<T> = T extends null | undefined | false ? never : true; type NullableKeys<T> = { [K in keyof T]: IsFalseOrNullable<T[K]> }; type ReturnCbParam<P extends TFn | TObj> = P extends TFn ? ReturnType<P> : P; type Id<T> = T extends infer U ? { [K in keyof U]: U[K] } : never; type IsAny<T> = 0 extends 1 & T ? true : false; type ExtractNullableKeys<T> = { [P in keyof T as IsAny<T[P]> extends true ? P : [T[P]] extends [never] ? never : [T[P]] extends [null | undefined] ? never : P]: T[P] }; type SpreadTwo<L, R> = Id<Pick<L, Exclude<keyof L, keyof R>> & R>; type Spread<A extends readonly [...any]> = A extends [infer L, ...infer R] ? SpreadTwo<L, Spread<R>> : unknown; type MergeTypes<A extends readonly [...any]> = ExtractNullableKeys<Spread<A>>; type ExtractProps<TComponentOrTProps> = TComponentOrTProps extends { (props: infer P1, ...args: any): any; (props: infer P2, ...args: any): any; (props: infer P3, ...args: any): any; (props: infer P4, ...args: any): any; } ? P1 | P2 | P3 | P4 : TComponentOrTProps extends { (props: infer P1, ...args: any): any; (props: infer P2, ...args: any): any; (props: infer P3, ...args: any): any; } ? P1 | P2 | P3 : TComponentOrTProps extends { (props: infer P1, ...args: any): any; (props: infer P2, ...args: any): any; } ? P1 | P2 : TComponentOrTProps extends ComponentType<infer TProps> ? TProps : TComponentOrTProps; //#endregion //#region src/types/styles.d.ts interface StylesDefault {} type Styles<S = unknown> = StylesDefault; type Css = typeof config.css; type Style = ReturnType<Css>; /** * Props available inside `.styles()` interpolation functions. * * - `$rocketstyle` — computed theme (inferred from `.theme()` chain) * - `$rocketstate` — active dimension values + pseudo state */ type RocketStyleInterpolationProps<CSS extends TObj = TObj> = { $rocketstyle: CSS; $rocketstate: Record<string, string | string[]> & { pseudo: Partial<PseudoState>; }; } & Record<string, any>; /** * A tagged-template css function whose interpolation functions * receive typed props including `$rocketstyle` and `$rocketstate`. * * When used via `.styles()`, `CSS` is inferred from the chain's * accumulated `.theme()` calls, so both props are typed automatically. * * `Style` (= `ReturnType<typeof config.css>`) is included so that nested * css results — e.g. `${styles({ ... })}` from unistyle — interpolate * cleanly without casts. */ type RocketCss<CSS extends TObj = TObj> = (strings: TemplateStringsArray, ...values: Array<string | number | boolean | null | undefined | Style | ((props: RocketStyleInterpolationProps<CSS>) => any) | any[]>) => any; type StylesCb<CSS extends TObj = TObj> = (css: RocketCss<CSS>) => ReturnType<Css>; type StylesCbArray = StylesCb[]; //#endregion //#region src/constants/index.d.ts /** Supported theme mode flags. */ declare const THEME_MODES: { readonly light: true; readonly dark: true; }; //#endregion //#region src/types/theme.d.ts interface ThemeDefault {} type Theme<T> = T extends unknown ? ThemeDefault : MergeTypes<[ThemeDefault, T]>; type ThemeModeKeys = keyof typeof THEME_MODES; type ThemeModeCallback = <A = any, B = any>(light: A, dark: B) => (mode: 'light' | 'dark') => A | B; type ThemeMode = <A = any, B = any>(light: A, dark: B) => A | B; type ThemeCb<CSS, T> = (theme: T, mode: ThemeModeCallback, css: Css) => Partial<CSS>; //#endregion //#region src/types/dimensions.d.ts type ExtractNullableDimensionKeys<T> = { [P in keyof T as T[P] extends false ? never : P]: T[P] }; type ExtractDimensionKey<T extends DimensionValue> = T extends DimensionValueObj ? T['propName'] : T; type ExtractDimensionMulti<T extends DimensionValue> = T extends DimensionValueObj ? true : false; type DimensionValuePrimitive = string; type DimensionValueObj = { propName: string; multi?: boolean; /** When true, this dimension is evaluated last and its values receive the accumulated theme as argument. */ transform?: boolean; }; type DimensionValue = DimensionValuePrimitive | DimensionValueObj; type Dimensions = Record<string, DimensionValue>; type MultiKeys<T extends Dimensions = Dimensions> = Partial<Record<ExtractDimensionKey<T[keyof T]>, true>>; type DeepPartial<T> = { [K in keyof T]?: T[K] extends ((...args: any[]) => any) ? T[K] : NonNullable<T[K]> extends Record<string, any> ? DeepPartial<NonNullable<T[K]>> | Extract<T[K], null> : T[K] }; type DimensionResult<CT, T = any> = Record<string, boolean | null | DeepPartial<CT> | ((theme: CT, appTheme: T, mode: ThemeModeCallback, css: Css) => DeepPartial<CT>)>; type DimensionObj<CT, T = any> = DimensionResult<CT, T>; type DimensionCb<T, CT> = (theme: T, mode: ThemeModeCallback, css: Css) => DimensionResult<CT, T>; type DimensionCallbackParam<T, CT> = DimensionObj<CT, T> | DimensionCb<T, CT>; type TDKP = Record<ExtractDimensionKey<Dimensions[keyof Dimensions]>, Record<string, boolean | never | Record<string, boolean>> | unknown>; type DimensionProps<K extends DimensionValue, D extends Dimensions, P extends CallBackParam, DKP extends TDKP> = { [I in ExtractDimensionKey<D[keyof D]>]: I extends ExtractDimensionKey<K> ? ExtractNullableDimensionKeys<Spread<[DKP[I], NullableKeys<ReturnCbParam<P>>]>> : DKP[I] }; type DimensionTypesHelper<DKP extends TDKP> = { [I in keyof DKP]: keyof DKP[I] }; type DimensionObjAttrs<D extends Dimensions, DKP extends TDKP> = { [I in keyof DKP]: ExtractDimensionMulti<D[I]> extends true ? Array<keyof DKP[I]> : keyof DKP[I] }; type DimensionBooleanAttrs<DKP extends TDKP> = Partial<Record<ValueOf<DimensionTypesHelper<DKP>>, boolean>>; type ExtractDimensionProps<D extends Dimensions, DKP extends TDKP, UB extends boolean> = UB extends true ? Partial<ExtractNullableDimensionKeys<DimensionObjAttrs<D, DKP> & DimensionBooleanAttrs<DKP>>> : Partial<ExtractNullableDimensionKeys<DimensionObjAttrs<D, DKP>>>; type ExtractDimensions<D extends Dimensions, DKP extends TDKP> = ExtractNullableDimensionKeys<DimensionObjAttrs<D, DKP>>; //#endregion //#region src/types/config.d.ts type RocketComponentType = ElementType & { IS_ROCKETSTYLE: true; $$rocketstyle: Record<string, unknown>; }; type RocketProviderState<T extends RocketComponentType | TObj | unknown = unknown> = T extends RocketComponentType ? Partial<T['$$rocketstyle']> & { pseudo: PseudoState; } : T; type ConsumerCtxCBValue<T extends RocketComponentType, D extends Dimensions, DKP extends TDKP> = (attrs: RocketProviderState<T>) => DKP extends TDKP ? Partial<ExtractDimensions<D, DKP> & { pseudo: PseudoState; }> : TObj; type ConsumerCtxCb<D extends Dimensions, DKP extends TDKP = TDKP> = <T extends RocketComponentType>(attrs: ConsumerCtxCBValue<T, D, DKP>) => ReturnType<ConsumerCtxCBValue<T, D, DKP>>; type ConsumerCb<D extends Dimensions, DKP extends TDKP = TDKP> = (ctx: ConsumerCtxCb<D, DKP>) => ReturnType<ConsumerCtxCb<D, DKP>>; type ConfigAttrs<C extends ElementType | unknown, D extends Dimensions, DKP extends TDKP, UB extends boolean> = Partial<{ name: string; component: C; provider: boolean; consumer: ConsumerCb<D, DKP>; DEBUG: boolean; inversed: boolean; passProps: UB extends true ? keyof DimensionBooleanAttrs<DKP>[] : never; styled: boolean; }>; //#endregion //#region src/types/configuration.d.ts type OptionFunc = (...arg: unknown[]) => Record<string, unknown>; type InitConfiguration<C, D> = { name?: string; component: C; useBooleans: boolean; dimensions: D; dimensionKeys: ArrayOfKeys<D>; dimensionValues: ArrayOfValues<D>; multiKeys: MultiKeys; transformKeys: Partial<Record<string, true>>; }; type Configuration<C = ElementType | unknown, D extends Dimensions = Dimensions> = InitConfiguration<C, D> & { provider?: boolean; consumer?: ConsumerCb<D>; DEBUG?: boolean; inversed?: boolean; passProps?: string[]; styled?: boolean; attrs: OptionFunc[]; priorityAttrs: OptionFunc[]; filterAttrs: string[]; theme: OptionFunc[]; styles: StylesCbArray; compose: Record<string, TFn | null | undefined | false>; statics: Record<string, any>; } & Record<string, any>; type DefaultProps = Partial<PseudoProps>; //#endregion //#region src/types/attrs.d.ts type AttrsCb<A, T> = (props: Partial<A>, theme: T, helpers: { mode?: ThemeModeKeys; isDark?: boolean; isLight?: boolean; createElement: typeof render; }) => Partial<A>; //#endregion //#region src/types/hoc.d.ts type GenericHoc = (component: ElementType) => ElementType; type ComposeParam = Record<string, GenericHoc | null | undefined | false>; //#endregion //#region src/types/rocketstyle.d.ts type RocketStyleComponent<OA extends TObj = {}, EA extends TObj = {}, T extends TObj = {}, CSS extends TObj = {}, S extends TObj = {}, HOC extends TObj = {}, D extends Dimensions = Dimensions, UB extends boolean = boolean, DKP extends TDKP = TDKP> = IRocketStyleComponent<OA, EA, T, CSS, S, HOC, D, UB, DKP> & { [I in keyof D]: <K extends DimensionValue = D[I], P extends DimensionCallbackParam<Theme<T>, Styles<CSS>> = DimensionCallbackParam<Theme<T>, Styles<CSS>>>(param: P) => P extends DimensionCallbackParam<Theme<T>, Styles<CSS>> ? RocketStyleComponent<OA, EA, T, CSS, S, HOC, D, UB, DimensionProps<K, D, P, DKP>> : RocketStyleComponent<OA, EA, T, CSS, S, HOC, D, UB, DKP> }; /** * @param OA Origin component props params. * @param EA Extended prop types * @param T Theme passed via context. * @param CSS Custom theme accepted by styles. * @param S Defined statics * @param D Dimensions to be used for defining component states. * @param UB Use booleans value * @param DKP Dimensions key props. * @param DFP Calculated final component props */ interface IRocketStyleComponent<OA extends TObj = {}, EA extends TObj = {}, T extends TObj = {}, CSS extends TObj = {}, S extends TObj = {}, HOC extends TObj = {}, D extends Dimensions = Dimensions, UB extends boolean = boolean, DKP extends TDKP = TDKP, DFP = (OA extends infer O ? Omit<O, keyof EA & keyof O> & Partial<Pick<O, keyof EA & keyof O>> & MergeTypes<[Partial<Omit<EA, keyof O>>, DefaultProps, ExtractDimensionProps<D, DKP, UB>]> : never)> { (props: DFP & { ref?: any; }): ReactNode; /** * A chaining method to define default component theme * @param param _object_ * * ### Examples * * #### Component name / displayName * ```tsx * const base = rocketstyleComponent * .config({ * name: 'Component name' * }) * ``` * * #### Replace component by a new one * ```tsx * const base = rocketstyleComponent * .config({ * component: (props) => <div {...props} /> * }) * ``` * * #### Component as provider * ```tsx * const parent = rocketstyleComponent * .config({ * provider: true * }) * ``` * * #### Component as consumer * ```tsx * const base = rocketstyleComponent * .config({ * consumer: ctx => ctx<typeof parent>(({ pseudo, state, ...rest }) => ({ * pseudo, * state * })) * }) * ``` * * #### Inversed theme * A possibility to set individualy for each component to have `inversed` styles * when using dark / light theme modes * ```tsx * const base = rocketstyleComponent * .config({ * inversed: true * }) * ``` * * #### Pass props to original component * A possibility to set individualy for each component props names to be passed * to `origin` component * * ```tsx * const base = rocketstyleComponent * .config({ * passProps: ['disabled', 'readOnly'] * }) * ``` */ config: <NC extends ElementType | unknown = unknown>({ name, component: NC, provider, consumer, DEBUG, inversed, passProps }: ConfigAttrs<NC, D, DKP, UB>) => NC extends ElementType ? RocketStyleComponent<ExtractProps<NC>, EA, T, CSS, S, HOC, D, UB, DKP> : RocketStyleComponent<OA, EA, T, CSS, S, HOC, D, UB, DKP>; /** * A chaining method to define default component props * @param param Can be either _object_ or a _callback_ * * #### Examples * * ##### Object as a parameter * ```tsx * const base = rocketstyleComponent * const newElement = base.attrs({ * propA: 'value', * propB: 'value, * }) * ``` * * ##### Callback as a parameter * ```tsx * const base = rocketstyleComponent * const newElement = base.attrs((props, theme, helpers) => ({ * propA: props.disabled ? 'valueA' : 'valueB', * propB: 'value, * })) * ``` */ attrs: { <P extends TObj = {}>(param: AttrsCb<DFP & P, Theme<T>>, config?: Partial<{ priority: boolean; filter: (keyof MergeTypes<[EA, P]>)[]; }>): RocketStyleComponent<OA, MergeTypes<[EA, P]>, T, CSS, S, HOC, D, UB, DKP>; <P extends TObj = {}>(param: P & Partial<NoInfer<DFP>>, config?: Partial<{ priority: boolean; filter: (keyof MergeTypes<[EA, P]>)[]; }>): RocketStyleComponent<OA, MergeTypes<[EA, P]>, T, CSS, S, HOC, D, UB, DKP>; }; /** * A chaining method to define default component theme * @param param Can be either _object_ or a _callback_ * * ### Examples * * #### Object as a parameter * ```tsx * const base = rocketstyleComponent * const newElement = base.attrs({ * backgroundColor: 'black', * }) * ``` * * #### Callback as a parameter * ```tsx * const base = rocketstyleComponent * const newElement = base.theme((theme, css) => ({ * backgroundColor: t.color.black, // value from context * })) *``` * * #### Dark / light theme callback * ```tsx * const base = rocketstyleComponent * * const newElement = base.theme((theme, mode, css) => ({ * backgroundColor: mode(t.color.black, t.color.white), // theme from context * })) * ``` */ theme: <P extends TObj = {}>(param: Partial<P> | Partial<Styles<CSS>> | ThemeCb<P, Theme<T>>) => RocketStyleComponent<OA, EA, T, MergeTypes<[CSS, P]>, S, HOC, D, UB, DKP>; /** * A chaining method to define default rendered styles * @param param Callback of styled-components `css` function * * #### Examples * * ```tsx * const base = rocketstyleComponent * * const newElement = base.styles(css => css``) * ``` */ styles: (param: StylesCb<CSS>) => RocketStyleComponent<OA, EA, T, CSS, S, HOC, D, UB, DKP>; /** * A chaining method to define high-order components to wrap * the defined component * @param param object of key hoc function * * ### Examples * * #### Define new hoc component * Using the `{ key: hoc }` annotation allows to override or remove * the defined hoc(s) later on. See the examples below. * ```tsx * const hoc = (WrappedComponent) => (props) => <WrappedComponent {...props} /> * const base = rocketstyleComponent * * const newElement = base.compose({ hocName: hoc }) * ``` * * #### Remove previously defined hoc component * (1) Set value to be `false` * ```tsx * const newElement = base.compose({ hocName: false }) * ``` * (2) Set value to be `null` * ```tsx * const newElement = base.compose({ hocName: null }) * ``` * (3) Set value to be `undefined` * ```tsx * const newElement = base.compose({ hocName: undefined }) * ``` */ compose: <P extends ComposeParam>(param: P) => P extends TObj ? RocketStyleComponent<OA, EA, T, CSS, S, MergeTypes<[HOC, P]>, D, UB, DKP> : RocketStyleComponent<OA, EA, T, CSS, S, HOC, D, UB, DKP>; /** * A chaining method to define statics on the rocketstyle component. * All statics are accessible via `is` static key on the component. * @param param object of statics * * ### Examples * * #### Define new static * Using the `{ key: value }` annotation allows to override or remove * the defined static(s) later on. See the examples below. * ```tsx * const base = rocketstyleComponent * * const newElement = base.statics({ * isNewStatic: true, * arrayStatic: ['a', 'b'], * functionStatic: (param) => { ...do something } * }) * ``` * * #### Override previously defined hoc component * (1) Set value to be `false` * ```tsx * const newElement = base.statics({ isNewStatic: false }) * ``` * (2) Set value to be `null` * ```tsx * const newElement = base.statics({ isNewStatic: null }) * ``` * (3) Set value to be `undefined` * ```tsx * const newElement = base.statics({ isNewStatic: undefined }) * ``` */ statics: <P extends TObj | unknown = unknown>(param: P) => P extends TObj ? RocketStyleComponent<OA, EA, T, CSS, MergeTypes<[S, P]>, HOC, D, UB, DKP> : RocketStyleComponent<OA, EA, T, CSS, S, HOC, D, UB, DKP>; /** * An access to all defined statics on the component. * * ### Examples * * #### Access a static property * ```tsx * const element = rocketcomponent.statics({ * isNewStatic: true, * arrayStatic: ['a', 'b'], * functionStatic: (param) => { ...do something } * }) * * // staticValue = true * const staticValue = element.meta.isNewStatic * ``` */ meta: S; getStaticDimensions: (theme: TObj) => { dimensions: DKP; useBooleans: UB; multiKeys: MultiKeys<D>; }; getDefaultAttrs: (props: TObj, theme: TObj, mode: ThemeModeKeys) => TObj; /** * Accessible via types only! * * Provides defined rocketstyle dimensions and their options * * ### Examples * ```tsx * const element = rocketcomponent * * type Props = typeof element['$$rocketstyle'] * * ``` */ readonly $$rocketstyle: ExtractDimensions<D, DKP>; /** * Accessible via types only! * * Provides defined original props types (props of origin * component passed to _rocketstyle_) * * ### Examples * ```tsx * const element = rocketcomponent * * type Props = typeof element['$$originProps'] * * ``` */ readonly $$originTypes: OA; /** * Accessible via types only! * * Provides defined extended props types (props types defined * on `.attrs()` chaining method * component passed to _rocketstyle_) * * ### Examples * ```tsx * const element = rocketcomponent * .attrs<{ propName: string }>({}) * * type Props = typeof element['$$extendedProps'] * * ``` */ readonly $$extendedTypes: EA; /** * Accessible via types only! * * Provides all defined props types (including **origin** * props types, **extended** props types & **rocketstyle** * props types all together) * * ### Examples * ```tsx * const element = rocketcomponent * * type Props = typeof element['$$allProps'] * * ``` */ readonly $$types: DFP; /** * Static Rocketstyle component identificator */ IS_ROCKETSTYLE: true; /** * Component displayName defined in `.config()` chaining * method * * ```tsx * const element = rockestyleComponent * .config({ * name: 'ComponentName' * }) * ``` */ displayName: string; } //#endregion //#region src/types/rocketComponent.d.ts type RocketComponent<C extends ElementType = ElementType, T extends TObj = {}, CSS extends TObj = {}, D extends Dimensions = DefaultDimensions, UB extends boolean = boolean> = (props: Configuration<C, D>) => RocketStyleComponent<ExtractProps<C>, {}, T, CSS, {}, {}, D, UB, {}>; //#endregion //#region src/init.d.ts type Rocketstyle = <D extends Dimensions = DefaultDimensions, UB extends boolean = true>({ dimensions, useBooleans }?: { dimensions?: D; useBooleans?: UB; }) => <C extends ElementType>({ name, component }: { name: string; component: C; }) => ReturnType<RocketComponent<C, {}, {}, D, UB>>; declare const typedRocketstyle: Rocketstyle; //#endregion //#region src/isRocketComponent.d.ts type IsRocketComponent = <T>(component: T) => boolean; declare const isRocketComponent: IsRocketComponent; //#endregion export { type AttrsCb, type ComposeParam, type ConfigAttrs, type ConsumerCb, type ConsumerCtxCBValue, type ConsumerCtxCb, type DefaultProps, type DimensionCallbackParam, type DimensionProps, type DimensionValue, type Dimensions, type ElementType, type ExtractDimensionProps, type ExtractDimensions, type ExtractProps, type GenericHoc, type IRocketStyleComponent, type IsRocketComponent, type MergeTypes, Provider, type RocketComponentType, type RocketProviderState, type RocketStyleComponent, type RocketStyleInterpolationProps, type Rocketstyle, type StylesCb, type StylesDefault, type TDKP, type TObj, type TProvider, type ThemeCb, type ThemeDefault, type ThemeMode, type ThemeModeCallback, type ThemeModeKeys, context, typedRocketstyle as default, typedRocketstyle as rocketstyle, isRocketComponent }; //# sourceMappingURL=index2.d.ts.map