From 3316d13f54d85c1e46093beec5f23afce58cb0c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Denis=20=F0=9F=8E=83=20Khripkov?= Date: Sun, 15 Dec 2024 23:40:11 +0300 Subject: [PATCH] feat(status-badge): add StatusBadgeBlank; without preloadicons --- .changeset/honest-dryers-speak.md | 6 + packages/status-badge/package.json | 1 + packages/status-badge/src/Component.base.tsx | 86 ++++++++++ packages/status-badge/src/Component.blank.tsx | 8 + packages/status-badge/src/Component.test.tsx | 2 +- packages/status-badge/src/Component.tsx | 79 +-------- .../status-badge/src/consts/iconMap.blank.ts | 15 ++ packages/status-badge/src/consts/iconMap.ts | 162 ++++++++++++++---- .../status-badge/src/docs/development.mdx | 13 ++ .../src/hooks/useStatusBadgeIcon.ts | 51 ++++-- packages/status-badge/src/index.ts | 7 +- 11 files changed, 302 insertions(+), 128 deletions(-) create mode 100644 .changeset/honest-dryers-speak.md create mode 100644 packages/status-badge/src/Component.base.tsx create mode 100644 packages/status-badge/src/Component.blank.tsx create mode 100644 packages/status-badge/src/consts/iconMap.blank.ts diff --git a/.changeset/honest-dryers-speak.md b/.changeset/honest-dryers-speak.md new file mode 100644 index 0000000000..f80b6da3fb --- /dev/null +++ b/.changeset/honest-dryers-speak.md @@ -0,0 +1,6 @@ +--- +'@alfalab/core-components-status-badge': minor +--- + + - Добавлен StatusBadgeBlank, без предзагрузки иконок + - Расширен пропс customIcons, теперь он принимает не только структуру иконок, но и массив таких структур diff --git a/packages/status-badge/package.json b/packages/status-badge/package.json index 2d89b06965..a1efc9d016 100644 --- a/packages/status-badge/package.json +++ b/packages/status-badge/package.json @@ -10,6 +10,7 @@ "access": "public", "directory": "dist" }, + "sideEffects": false, "peerDependencies": { "react": ">=16.8.0" }, diff --git a/packages/status-badge/src/Component.base.tsx b/packages/status-badge/src/Component.base.tsx new file mode 100644 index 0000000000..991f15b6dd --- /dev/null +++ b/packages/status-badge/src/Component.base.tsx @@ -0,0 +1,86 @@ +import React from 'react'; +import cn from 'classnames'; + +import type { IconMap } from './consts/iconMap'; +import { useStatusBadgeIcon } from './hooks/useStatusBadgeIcon'; +import { + StatusBadgeCustomIcon, + StatusBadgeSizes, + StatusBadgeViews, +} from './types/statusBadgePropTypes'; + +import defaultColors from './default.module.css'; +import styles from './index.module.css'; +import invertedColors from './inverted.module.css'; + +const colorStyles = { + default: defaultColors, + inverted: invertedColors, +}; + +export type StatusBadgeProps = { + /** + * Дополнительный класс + */ + className?: string; + + /** + * Размер компонента + * @default 24 + */ + size?: StatusBadgeSizes; + + /** + * Набор цветов для компонента + */ + colors?: 'default' | 'inverted'; + + /** + * Вид бейджа. + */ + view: StatusBadgeViews; + + /** + * Идентификатор для систем автоматизированного тестирования + */ + dataTestId?: string; + + /** + * Кастомные иконки + */ + customIcons?: StatusBadgeCustomIcon | StatusBadgeCustomIcon[]; +}; + +type StatusBadgePrivateProps = { + /** + * Базовый набор иконок + */ + iconMap: IconMap; +}; + +export const StatusBadgeBase = ({ + className, + dataTestId, + size = 24, + view, + colors = 'default', + customIcons, + iconMap, +}: StatusBadgeProps & StatusBadgePrivateProps) => { + const { Icon } = useStatusBadgeIcon(view, size, iconMap, customIcons); + + return ( +
+ +
+ ); +}; diff --git a/packages/status-badge/src/Component.blank.tsx b/packages/status-badge/src/Component.blank.tsx new file mode 100644 index 0000000000..db9e83255d --- /dev/null +++ b/packages/status-badge/src/Component.blank.tsx @@ -0,0 +1,8 @@ +import React from 'react'; + +import { ICON_MAP_BLANK } from './consts/iconMap.blank'; +import { type StatusBadgeProps, StatusBadgeBase } from './Component.base'; + +export const StatusBadgeBlank = (props: StatusBadgeProps) => ( + +); diff --git a/packages/status-badge/src/Component.test.tsx b/packages/status-badge/src/Component.test.tsx index f43c0cee00..f59b73e82f 100644 --- a/packages/status-badge/src/Component.test.tsx +++ b/packages/status-badge/src/Component.test.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; -import { StatusBadge, StatusBadgeProps } from '.'; +import { StatusBadge, type StatusBadgeProps } from '.'; const viewOptions: StatusBadgeProps['view'][] = [ 'positive-checkmark', diff --git a/packages/status-badge/src/Component.tsx b/packages/status-badge/src/Component.tsx index cbe6d778e2..b81ea51fc6 100644 --- a/packages/status-badge/src/Component.tsx +++ b/packages/status-badge/src/Component.tsx @@ -1,77 +1,8 @@ import React from 'react'; -import cn from 'classnames'; -import { useStatusBadgeIcon } from './hooks/useStatusBadgeIcon'; -import { - StatusBadgeCustomIcon, - StatusBadgeSizes, - StatusBadgeViews, -} from './types/statusBadgePropTypes'; +import { ICON_MAP } from './consts/iconMap'; +import { type StatusBadgeProps, StatusBadgeBase } from './Component.base'; -import defaultColors from './default.module.css'; -import styles from './index.module.css'; -import invertedColors from './inverted.module.css'; - -const colorStyles = { - default: defaultColors, - inverted: invertedColors, -}; - -export type StatusBadgeProps = { - /** - * Дополнительный класс - */ - className?: string; - - /** - * Размер компонента - * @default 24 - */ - size?: StatusBadgeSizes; - - /** - * Набор цветов для компонента - */ - colors?: 'default' | 'inverted'; - - /** - * Вид бейджа. - */ - view: StatusBadgeViews; - - /** - * Идентификатор для систем автоматизированного тестирования - */ - dataTestId?: string; - - /** - * Кастомные иконки - */ - customIcons?: StatusBadgeCustomIcon; -}; - -export const StatusBadge = ({ - className, - dataTestId, - size = 24, - view, - colors = 'default', - customIcons, -}: StatusBadgeProps) => { - const { Icon } = useStatusBadgeIcon(view, size, customIcons); - - return ( -
- -
- ); -}; +export const StatusBadge = (props: StatusBadgeProps) => ( + +); diff --git a/packages/status-badge/src/consts/iconMap.blank.ts b/packages/status-badge/src/consts/iconMap.blank.ts new file mode 100644 index 0000000000..48fbc7fc8b --- /dev/null +++ b/packages/status-badge/src/consts/iconMap.blank.ts @@ -0,0 +1,15 @@ +import type { IconMap } from './iconMap'; + +/** + * Базовая структура, без иконок + */ +export const ICON_MAP_BLANK: IconMap = { + 'positive-checkmark': {}, + 'negative-cross': {}, + 'negative-alert': {}, + 'negative-block': {}, + 'attention-alert': {}, + 'neutral-information': {}, + 'neutral-operation': {}, + 'neutral-cross': {}, +} as IconMap; diff --git a/packages/status-badge/src/consts/iconMap.ts b/packages/status-badge/src/consts/iconMap.ts index 6cbb0394f6..22c0cde6e8 100644 --- a/packages/status-badge/src/consts/iconMap.ts +++ b/packages/status-badge/src/consts/iconMap.ts @@ -1,8 +1,3 @@ -import { - StatusBadgeIcon, - StatusBadgeSizes, - StatusBadgeViews, -} from '@alfalab/core-components-status-badge'; import { CheckmarkCompactMIcon } from '@alfalab/icons-glyph/CheckmarkCompactMIcon'; import { CheckmarkCompactSIcon } from '@alfalab/icons-glyph/CheckmarkCompactSIcon'; import { ClockHandsCompactMIcon } from '@alfalab/icons-glyph/ClockHandsCompactMIcon'; @@ -17,66 +12,165 @@ import { StopBrickCompactMIcon } from '@alfalab/icons-glyph/StopBrickCompactMIco import { StopBrickMIcon } from '@alfalab/icons-glyph/StopBrickMIcon'; import { StopBrickSIcon } from '@alfalab/icons-glyph/StopBrickSIcon'; +import type { + StatusBadgeCustomIcon, + StatusBadgeIcon, + StatusBadgeSizes, + StatusBadgeViews, +} from '..'; +import { combineIcons } from '../hooks/useStatusBadgeIcon'; + +import { ICON_MAP_BLANK } from './iconMap.blank'; + export type IconMap = Record< StatusBadgeViews, Record, StatusBadgeIcon> >; -export const ICON_MAP: IconMap = { +const ICON_MAP_16: StatusBadgeCustomIcon = { 'positive-checkmark': { 16: CheckmarkCompactSIcon, - 20: CheckmarkCompactSIcon, - 24: CheckmarkCompactMIcon, - 32: CheckmarkCompactMIcon, - 40: CheckmarkCompactMIcon, }, 'negative-cross': { 16: CrossCompactSIcon, - 20: CrossCompactSIcon, - 24: CrossCompactMIcon, - 32: CrossCompactMIcon, - 40: CrossCompactMIcon, }, 'negative-alert': { 16: ExclamationCompactSIcon, - 20: ExclamationCompactSIcon, - 24: ExclamationCompactMIcon, - 32: ExclamationCompactMIcon, - 40: ExclamationCompactMIcon, }, 'negative-block': { 16: StopBrickSIcon, - 20: StopBrickSIcon, - 24: StopBrickCompactMIcon, - 32: StopBrickMIcon, - 40: StopBrickMIcon, }, 'attention-alert': { 16: ExclamationCompactSIcon, - 20: ExclamationCompactSIcon, - 24: ExclamationCompactMIcon, - 32: ExclamationCompactMIcon, - 40: ExclamationCompactMIcon, }, 'neutral-information': { 16: InformationCompactSIcon, - 20: InformationCompactSIcon, - 24: InformationCompactMIcon, - 32: InformationCompactMIcon, - 40: InformationCompactMIcon, }, 'neutral-operation': { 16: ClockHandsCompactSIcon, - 20: ClockHandsCompactSIcon, - 24: ClockHandsCompactMIcon, - 32: ClockHandsCompactMIcon, - 40: ClockHandsCompactMIcon, }, 'neutral-cross': { 16: CrossCompactSIcon, + }, +}; + +const ICON_MAP_20: StatusBadgeCustomIcon = { + 'positive-checkmark': { + 20: CheckmarkCompactSIcon, + }, + 'negative-cross': { + 20: CrossCompactSIcon, + }, + 'negative-alert': { + 20: ExclamationCompactSIcon, + }, + 'negative-block': { + 20: StopBrickSIcon, + }, + 'attention-alert': { + 20: ExclamationCompactSIcon, + }, + 'neutral-information': { + 20: InformationCompactSIcon, + }, + 'neutral-operation': { + 20: ClockHandsCompactSIcon, + }, + 'neutral-cross': { 20: CrossCompactSIcon, + }, +}; + +const ICON_MAP_24: StatusBadgeCustomIcon = { + 'positive-checkmark': { + 24: CheckmarkCompactMIcon, + }, + 'negative-cross': { + 24: CrossCompactMIcon, + }, + 'negative-alert': { + 24: ExclamationCompactMIcon, + }, + 'negative-block': { + 24: StopBrickCompactMIcon, + }, + 'attention-alert': { + 24: ExclamationCompactMIcon, + }, + 'neutral-information': { + 24: InformationCompactMIcon, + }, + 'neutral-operation': { + 24: ClockHandsCompactMIcon, + }, + 'neutral-cross': { 24: CrossCompactMIcon, + }, +}; + +const ICON_MAP_32: StatusBadgeCustomIcon = { + 'positive-checkmark': { + 32: CheckmarkCompactMIcon, + }, + 'negative-cross': { 32: CrossCompactMIcon, + }, + 'negative-alert': { + 32: ExclamationCompactMIcon, + }, + 'negative-block': { + 32: StopBrickMIcon, + }, + 'attention-alert': { + 32: ExclamationCompactMIcon, + }, + 'neutral-information': { + 32: InformationCompactMIcon, + }, + 'neutral-operation': { + 32: ClockHandsCompactMIcon, + }, + 'neutral-cross': { + 32: CrossCompactMIcon, + }, +}; + +const ICON_MAP_40: StatusBadgeCustomIcon = { + 'positive-checkmark': { + 40: CheckmarkCompactMIcon, + }, + 'negative-cross': { + 40: CrossCompactMIcon, + }, + 'negative-alert': { + 40: ExclamationCompactMIcon, + }, + 'negative-block': { + 40: StopBrickMIcon, + }, + 'attention-alert': { + 40: ExclamationCompactMIcon, + }, + 'neutral-information': { + 40: InformationCompactMIcon, + }, + 'neutral-operation': { + 40: ClockHandsCompactMIcon, + }, + 'neutral-cross': { 40: CrossCompactMIcon, }, }; + +/** + * Все пред-загруженные иконки + */ +const ICON_MAP: IconMap = combineIcons(ICON_MAP_BLANK, [ + ICON_MAP_16, + ICON_MAP_20, + ICON_MAP_24, + ICON_MAP_32, + ICON_MAP_40, +]); + +export { ICON_MAP, ICON_MAP_16, ICON_MAP_20, ICON_MAP_24, ICON_MAP_32, ICON_MAP_40 }; diff --git a/packages/status-badge/src/docs/development.mdx b/packages/status-badge/src/docs/development.mdx index b7213ecd5d..686b190ac3 100644 --- a/packages/status-badge/src/docs/development.mdx +++ b/packages/status-badge/src/docs/development.mdx @@ -4,7 +4,20 @@ import { StatusBadge } from '../Component'; ## Подключение ```jsx +// Иконки всех размеров предзагружены import { StatusBadge } from '@alfalab/core-components/status-badge'; + +// Без предзагруженных иконок +import { StatusBadgeBlank } from '@alfalab/core-components/status-badge'; + +// Сеты иконок +import { + ICON_MAP_16, + ICON_MAP_20, + ICON_MAP_24, + ICON_MAP_32, + ICON_MAP_40, +} from '@alfalab/core-components/status-badge'; ``` ## Свойства diff --git a/packages/status-badge/src/hooks/useStatusBadgeIcon.ts b/packages/status-badge/src/hooks/useStatusBadgeIcon.ts index d1b9fc56a3..57f69f8661 100644 --- a/packages/status-badge/src/hooks/useStatusBadgeIcon.ts +++ b/packages/status-badge/src/hooks/useStatusBadgeIcon.ts @@ -1,33 +1,48 @@ -import { ICON_MAP, IconMap } from '../consts/iconMap'; -import { +import type { IconMap } from '../consts/iconMap'; +import type { StatusBadgeCustomIcon, StatusBadgeSizes, StatusBadgeViews, } from '../types/statusBadgePropTypes'; -export const useStatusBadgeIcon = ( - view: StatusBadgeViews, - size: StatusBadgeSizes, - customIcons?: StatusBadgeCustomIcon, +export const combineIcons = ( + iconMap: IconMap, + customIcons?: StatusBadgeCustomIcon | StatusBadgeCustomIcon[], ) => { - let iconsMap = ICON_MAP; + let iconsMap = iconMap; // transform initial icons map if (customIcons) { - iconsMap = Object.keys(ICON_MAP).reduce( - (acc, current) => ({ - ...acc, - ...{ - [current]: { - ...ICON_MAP[current as StatusBadgeViews], - ...customIcons[current as StatusBadgeViews], + const customIconsAll: StatusBadgeCustomIcon[] = Array.isArray(customIcons) + ? customIcons + : [customIcons]; + + customIconsAll.forEach((customIconsSet) => { + iconsMap = Object.keys(iconsMap).reduce( + (acc, current) => ({ + ...acc, + ...{ + [current]: { + ...iconsMap[current as StatusBadgeViews], + ...customIconsSet[current as StatusBadgeViews], + }, }, - }, - }), - {} as IconMap, - ); + }), + {} as IconMap, + ); + }); } + return iconsMap; +}; + +export const useStatusBadgeIcon = ( + view: StatusBadgeViews, + size: StatusBadgeSizes, + iconMap: IconMap, + customIcons?: StatusBadgeCustomIcon | StatusBadgeCustomIcon[], +) => { + const iconsMap = combineIcons(iconMap, customIcons); const Icon = iconsMap[view][size]; return { Icon }; diff --git a/packages/status-badge/src/index.ts b/packages/status-badge/src/index.ts index c8bd02708d..2fecee1b25 100644 --- a/packages/status-badge/src/index.ts +++ b/packages/status-badge/src/index.ts @@ -1,7 +1,12 @@ export * from './Component'; -export { +export type { StatusBadgeProps } from './Component.base'; +export { StatusBadgeBlank } from './Component.blank'; + +export type { StatusBadgeViews, StatusBadgeSizes, StatusBadgeIcon, StatusBadgeCustomIcon, } from './types/statusBadgePropTypes'; + +export { ICON_MAP_16, ICON_MAP_20, ICON_MAP_24, ICON_MAP_32, ICON_MAP_40 } from './consts/iconMap';