Сделать функцию резолвер для размеров

нужно сделать функцию резолвер для размеров по аналогии с резолвером цветов

import React, { cloneElement, ReactElement, useMemo } from 'react';
import { ClassNameProps, component, overridable, useTheme } from '@spatium/styled-system';
import { Mode, ModifiersModifierProps, PaddingModifierProps, RadiusModifierProps, RowModifierProps, Theme, theme, ThemeColor, ThemeSpace, IconProps } from '@spatium/theme';
import type { ButtonPosition, ButtonState } from '../lib/button';
import { RectangleButton } from '../rectangle-button';

export const buttonSizeList = ['large', 'medium', 'small'] as const;
type ButtonSize = typeof buttonSizeList[number];

export const buttonVariantList = ['primary', 'secondary'] as const;
export type SquareButtonVariant = typeof buttonVariantList[number];

export const typeList = ['square', 'round'] as const;
export type SquareButtonType = typeof typeList[number];

export type SquareButtonProps = {
  /**
 * Child element of Square Button
 * @example <SquareButton ... children={<SomeReactElement />} />
 */
  children: ReactElement<IconProps>;
  /**
 * Sets state of Square Button
 *
 * @default state = 'normal'
 * @example <SquareButton ... state={isLoading ? 'loading' : 'normal'} />
 */
  state?: ButtonState;
  /**
 * Sets one of two positions of components: on background
 * or on a surface
 * @default position = 'background'
 * @example <SquareButton ... position='background' />
 */
  position?: ButtonPosition;
  /**
 * Sets one of the default sizes of Square Button
 * @default size = 'large'
 * @example <SquareButton ... size='large' />
 */
  size?: ButtonSize;
  /**
 * Sets one of two default variants of buttons: primary and secondary
 * @default variant = 'primary'
 * @example <SquareButton ... variant={isActive ? 'primary' : 'secondary'} />
 */
  variant?: SquareButtonVariant;
  /**
 * Sets one of two default types of Square Button: round and square
 * @default type = 'round'
 * @example <SquareButton ... children={<SomeReactElement />} />
 */
  type?: SquareButtonType;
  /**
 * Allows you to customize Square Button size
 *
 * @example <SquareButton ... themeSize={theme.space(100)} />
 */
  themeSize?: ThemeSpace;
  /**
 * Allows you to customize Square Button background color
 *
 * @example <SquareButton ... themeBackgroundColor={theme.colors.red} />
 */
  themeBackgroundColor?: ThemeColor;
  /**
 * Allows you to customize Square Button content color
 *
 * @example <SquareButton ... themeContentColor={theme.colors.blue} />
 */
  themeContentColor?: ThemeColor;
} & ModifiersModifierProps & RowModifierProps & PaddingModifierProps & RadiusModifierProps & ClassNameProps;

export const SquareButton = component<SquareButtonProps>(({
  state = 'normal',
  position = 'background',
  size = 'large',
  variant = 'primary',
  children,
  themeSize = sizeMap[size],
  type = 'round',
  themeRadius = type === 'square' ? theme.space(10) : themeSize.divided(2),
  themePadding,
  themeBackgroundColor,
  themeContentColor,
  ...rest
}) => {
  const { mode } = useTheme<Theme>();

  const { backgroundColor, contentColor } = useMemo(() => {
    const { background, content } = resolveSquareButtonColor(state, variant, mode, position);
    return {
      backgroundColor: themeBackgroundColor ?? background ?? undefined,
      contentColor: themeContentColor ?? content ?? undefined,
    };
  }, [themeBackgroundColor, state, variant, mode, position, themeContentColor]);

  const icon = useMemo(() => (
    cloneElement(children, {
      ...children.props,
      themeColor: contentColor,
      themeSize: iconSizeMap[size],
    })
  ), [contentColor, children, size]);

  return (
    <RectangleButton
      state={state}
      position={position}
      variant={variant}
      themeWidth={themeSize}
      themeHeight={themeSize}
      themeRadius={themeRadius}
      themeBackgroundColor={backgroundColor}
      themePadding={themePadding}
      {...rest}
    >
      {icon}
    </RectangleButton>
  );
});

const disabledBackground: Record<Mode, Node> = {
  light: theme.colors.surface.alt(1),
  dark: {
    background: theme.colors.surface.alt(1),
    surface: theme.colors.surface,
  },
};

const defaultBackgroundMap: Record<ButtonState, Node> = {
  normal: {
    primary: {
      light: theme.colors.primary,
      dark: {
        background: theme.colors.surface,
        surface: theme.colors.surface.alt(2),
      },
    },
    secondary: {
      light: theme.colors.surface,
      dark: {
        background: theme.colors.surface,
        surface: theme.colors.surface.alt(2),
      },
    },
  },
  pressed: {
    primary: {
      light: theme.colors.primary.alt(1),
      dark: {
        background: theme.colors.surface.alt(1),
        surface: theme.colors.surface,
      },
    },
    secondary: {
      light: theme.colors.surface.alt(2),
      dark: {
        background: theme.colors.surface.alt(1),
        surface: theme.colors.surface,
      },
    },
  },
  disabled: {
    primary: disabledBackground,
    secondary: disabledBackground,
  },
  active: {
    primary: theme.colors.surface.alt(3),
    secondary: theme.colors.surface.alt(3),
  },
  loading: {
    primary: disabledBackground,
    secondary: disabledBackground,
  },
  success: {
    primary: disabledBackground,
    secondary: disabledBackground,
  },
};

const defaultContentMap: Record<ButtonState, Node> = {
  normal: {
    light: theme.colors.foreground,
    dark: theme.colors.foreground,
  },
  pressed: {
    light: theme.colors.foreground,
    dark: theme.colors.foreground,
  },
  disabled: {
    light: theme.colors.foreground,
    dark: theme.colors.foreground,
  },
  active: {
    primary: theme.colors.foreground.alt(3),
    secondary: theme.colors.foreground.alt(3),
  },
  loading: theme.colors.foreground,
  success: theme.colors.success,
};

type StateNode = { [key in ButtonState]: Node };
type VariantNode = { [key in SquareButtonVariant]: Node };
type ModeNode = { [key in Mode]: Node };
type PositionNode = { [key in ButtonPosition]: Node };
type Node = null | ThemeColor | StateNode | VariantNode | ModeNode | PositionNode;

export const resolveSquareButtonColor = overridable((state: ButtonState, variant: SquareButtonVariant, mode: Mode, position: ButtonPosition) => {
  const resolveNode = (node: Node): ThemeColor | null => {
    if (node && 'normal' in node) {
      return resolveNode(node[state]);
    } else if (node && 'primary' in node) {
      return resolveNode(node[variant]);
    } else if (node && 'light' in node) {
      return resolveNode(node[mode]);
    } else if (node && 'background' in node) {
      return resolveNode(node[position]);
    } else {
      return node;
    }
  };
  return { background: resolveNode(defaultBackgroundMap), content: resolveNode(defaultContentMap) };
});

const sizeMap: Record<ButtonSize, ThemeSpace> = {
  large: theme.space(60),
  medium: theme.space(40),
  small: theme.space(36),
};

const iconSizeMap: Record<ButtonSize, ThemeSpace> = {
  large: theme.space(36),
  medium: theme.space(24),
  small: theme.space(24),
};


Ответы (0 шт):