diff --git a/jest.config.mjs b/jest.config.mjs index 1851966fd4..fcfd62f029 100644 --- a/jest.config.mjs +++ b/jest.config.mjs @@ -56,6 +56,8 @@ const [initialProjectOptions] = [ moduleNameMapper: { ...pathsToModuleNameMapper(tsconfig.compilerOptions.paths, { prefix: '/' }), '^.+\\.css$': 'identity-obj-proxy', + // TODO remove test + 'postcss-each': path.join(import.meta.dirname, 'tools/postcss/postcss-each.cjs'), }, testPathIgnorePatterns: IGNORED_PACKAGES.map((pkg) => { const relativeDir = path.relative(import.meta.dirname, resolveInternal(pkg)); diff --git a/package.json b/package.json index a49a95cc43..1794900989 100644 --- a/package.json +++ b/package.json @@ -146,7 +146,6 @@ "postcss-color-mod-function": "^4.1.1", "postcss-custom-media": "^8.0.2", "postcss-custom-properties": "^12.1.10", - "postcss-each": "^1.1.0", "postcss-export-custom-variables": "^1.0.0", "postcss-for": "^2.1.1", "postcss-import": "^16.1.1", @@ -154,6 +153,7 @@ "postcss-mixins": "^7.0.3", "postcss-modules": "^6.0.1", "postcss-preset-env": "^7.8.3", + "postcss-simple-vars": "^7.0.1", "prettier": "~3.6.2", "querystring-es3": "^0.2.1", "raw-loader": "^4.0.1", diff --git a/packages/action-button/package.json b/packages/action-button/package.json index ebf3acf9f7..b3644f8c0c 100644 --- a/packages/action-button/package.json +++ b/packages/action-button/package.json @@ -10,9 +10,8 @@ "main": "index.js", "module": "./esm/index.js", "dependencies": { + "@alfalab/core-components-button": "^13.1.0", "@alfalab/core-components-shared": "^2.1.0", - "@alfalab/core-components-spinner": "^6.0.2", - "@alfalab/hooks": "^1.13.1", "classnames": "^2.5.1", "react-merge-refs": "^1.1.0", "tslib": "^2.4.0" diff --git a/packages/action-button/src/Component.screenshots.test.tsx b/packages/action-button/src/Component.screenshots.test.tsx index 94d9f070fe..5d7080deee 100644 --- a/packages/action-button/src/Component.screenshots.test.tsx +++ b/packages/action-button/src/Component.screenshots.test.tsx @@ -87,8 +87,10 @@ describe( }, }), screenshotOpts: { clip }, - evaluate: (page: Page) => - page.hover('button[class^=component]').then(() => page.waitForTimeout(500)), + evaluate: async (page) => { + await page.hover('button[class*=component]'); + await page.waitForTimeout(500); + }, matchImageSnapshotOptions: { customSnapshotIdentifier: (...args) => `hover-${customSnapshotIdentifier(...args)}`, }, @@ -106,10 +108,10 @@ describe( }, }), screenshotOpts: { clip }, - evaluate: (page: Page) => { - return page.mouse - .move(30, 30) - .then(() => page.mouse.down().then(() => page.waitForTimeout(500))); + evaluate: async (page) => { + await page.mouse.move(30, 30); + await page.mouse.down(); + await page.waitForTimeout(500); }, matchImageSnapshotOptions: { customSnapshotIdentifier: (...args) => `pressed-${customSnapshotIdentifier(...args)}`, diff --git a/packages/action-button/src/Component.test.tsx b/packages/action-button/src/Component.test.tsx index 14d86bbb1f..9ebe913bc3 100644 --- a/packages/action-button/src/Component.test.tsx +++ b/packages/action-button/src/Component.test.tsx @@ -20,20 +20,16 @@ describe('ActionButton', () => { it('should use "size" prop', () => { const size = 48; - render(); + render(); - expect(screen.getByRole('button')).toHaveClass('size-48'); - }); - - it('should use "size" prop "s" by default', () => { - render(); - - expect(screen.getByRole('button')).toHaveClass('size-48'); + expect(screen.getByRole('button')).toHaveClass('size48'); }); it('should use "iconWrapperClassName" prop', () => { const iconClassName = 'test-class'; - const { container } = render(); + const { container } = render( + , + ); expect(container.querySelector(`.${iconClassName}`)).toBeInTheDocument(); }); @@ -41,57 +37,65 @@ describe('ActionButton', () => { it('should use "href" prop and become a link', () => { const href = 'http://127.0.0.1'; - render(); + render(); - expect(screen.getByRole('button')).toHaveAttribute('href', href); + expect(screen.getByTestId(dti)).toHaveAttribute('href', href); }); it('should use "disabled" prop (button)', () => { - const { rerender } = render(); + const { rerender } = render(); expect(screen.getByRole('button')).not.toBeDisabled(); - rerender(); + rerender(); expect(screen.getByRole('button')).toBeDisabled(); }); it('should use "disabled" prop (link)', () => { - const { rerender } = render(); + const { rerender } = render( + , + ); - expect(screen.getByRole('button')).not.toHaveAttribute('aria-disabled', 'true'); + expect(screen.getByTestId(dti)).not.toHaveAttribute('aria-disabled', 'true'); - rerender(); + rerender( + , + ); - expect(screen.getByRole('button')).toHaveAttribute('aria-disabled', 'true'); + expect(screen.getByTestId(dti)).toHaveAttribute('aria-disabled', 'true'); }); it('should use "loading" prop (button)', () => { - const { rerender } = render(); + const { rerender } = render(); expect(screen.getByRole('button')).not.toBeDisabled(); expect(screen.queryByTestId(loaderDti)).toBeNull(); - rerender(); + rerender(); expect(screen.getByRole('button')).toBeDisabled(); expect(screen.getByTestId(loaderDti)).toBeInTheDocument(); }); it('should use "loading" prop (link)', () => { - const { rerender } = render(); + const { rerender } = render( + , + ); - expect(screen.getByRole('button')).not.toHaveAttribute('aria-disabled', 'true'); + expect(screen.getByTestId(dti)).not.toHaveAttribute('aria-disabled', 'true'); expect(screen.queryByTestId(loaderDti)).toBeNull(); - rerender(); + rerender( + , + ); - expect(screen.getByRole('button')).toHaveAttribute('aria-disabled', 'true'); + expect(screen.getByTestId(dti)).toHaveAttribute('aria-disabled', 'true'); expect(screen.getByTestId(loaderDti)).toBeInTheDocument(); }); it('should use "dataTestId" prop', () => { - render(); + render(); expect(screen.getByRole('button')).toHaveAttribute('data-test-id', dti); }); @@ -99,7 +103,7 @@ describe('ActionButton', () => { it('should use "children" prop', () => { const label = 'Action Button'; - render({label}); + render({label}); expect(screen.getByRole('button')).toHaveTextContent(label); }); @@ -107,7 +111,7 @@ describe('ActionButton', () => { it('should use "className" prop', () => { const className = 'test-class'; - render(); + render(); expect(screen.getByRole('button')).toHaveClass(className); }); @@ -115,7 +119,7 @@ describe('ActionButton', () => { it('should call "onClick" prop', async () => { const cb = jest.fn(); - render(); + render(); await userEvent.click(screen.getByRole('button')); @@ -124,11 +128,28 @@ describe('ActionButton', () => { it('should have data-test-id', () => { const dti = 'action-button-dti'; - const { getByTestId } = render(); + const { getByTestId } = render(); const testIds = getActionButtonTestIds(dti); expect(getByTestId(testIds.actionButton)).toBeInTheDocument(); expect(getByTestId(testIds.spinner)).toBeInTheDocument(); }); + + it('should pass "loaderClassName"', () => { + const dti = 'action-button-dti'; + const loaderClassName = 'foo'; + const { getByTestId } = render( + , + ); + + const testIds = getActionButtonTestIds(dti); + + expect(getByTestId(testIds.spinner)).toHaveClass(loaderClassName); + }); }); diff --git a/packages/action-button/src/Component.tsx b/packages/action-button/src/Component.tsx index 4bce3faceb..623e0dd918 100644 --- a/packages/action-button/src/Component.tsx +++ b/packages/action-button/src/Component.tsx @@ -1,19 +1,14 @@ -import React, { - type AnchorHTMLAttributes, - type ButtonHTMLAttributes, - forwardRef, - Fragment, - useRef, -} from 'react'; +import React, { forwardRef, type ReactNode } from 'react'; import mergeRefs from 'react-merge-refs'; import cn from 'classnames'; -import { getDataTestId } from '@alfalab/core-components-shared'; -import { Spinner } from '@alfalab/core-components-spinner'; -import { useFocus } from '@alfalab/hooks'; - -import { LOADER_MIN_DISPLAY_INTERVAL } from './constants/loader-min-display-interval'; -import { useLoader } from './hooks'; +import { + BaseButtonCandidate, + type BaseButtonOwnProps, + type ButtonPropsFactory, +} from '@alfalab/core-components-button/components/base-button-candidate'; +import { ButtonContent } from '@alfalab/core-components-button/components/button-content'; +import { useLoading } from '@alfalab/core-components-button/shared'; import defaultColors from './default.module.css'; import styles from './index.module.css'; @@ -24,15 +19,14 @@ const colorStyles = { default: defaultColors, inverted: invertedColors, static: staticColors, -}; - -type Colors = 'default' | 'inverted' | 'static'; +} as const; -type ComponentProps = { +interface ComponentProps + extends Omit { /** * Иконка кнопки */ - icon: React.ReactNode; + icon: ReactNode; /** * Размер кнопки @@ -44,142 +38,79 @@ type ComponentProps = { */ view?: 'primary' | 'secondary'; - /** - * Дополнительный класс - */ - className?: string; - /** * Дополнительный класс для обертки иконки */ iconWrapperClassName?: string; - /** - * Значение href для ссылки - */ - href?: string; - - /** - * Заблокировать кнопку - */ - disabled?: boolean; - - /** - * Показать лоадер - */ - loading?: boolean; - - /** - * Идентификатор для систем автоматизированного тестирования. - * Для спиннера используется модификатор -loader - */ - dataTestId?: string; - /** * Палитра, в контексте которой используется кнопка */ - colors?: Colors; -}; + colors?: 'default' | 'inverted' | 'static'; +} -type AnchorProps = ComponentProps & AnchorHTMLAttributes; -type ButtonProps = ComponentProps & ButtonHTMLAttributes; -export type ActionButtonProps = Partial; +export type ActionButtonProps = ButtonPropsFactory; export const ActionButton = forwardRef( ( { - className, + className: classNameFromProps, icon, children, - href, size = 48, view = 'primary', - type = 'button', iconWrapperClassName, disabled, - loading, - dataTestId, + loading: loadingFromProps, colors = 'default', - ...rest + dataTestId, + loaderClassName, + ...restProps }, ref, ) => { - const componentRef = useRef(null); - - const [focused] = useFocus(componentRef, 'keyboard'); - - const { showLoader } = useLoader(!!loading, LOADER_MIN_DISPLAY_INTERVAL); - - const styleSize = `size-${size}`; - - const componentProps = { - className: cn( - styles.component, - colorStyles[colors][view], - styles[styleSize], - { - [styles.focused]: focused, - [styles.disabled]: disabled, - [colorStyles[colors].disabled]: disabled, - [styles.loading]: showLoader, - }, - className, - ), - 'data-test-id': dataTestId, - }; + const loading = useLoading(loadingFromProps); + const className = cn( + styles.component, + colorStyles[colors].component, + colorStyles[colors][view], + styles[`size${size}`], + loading && [colorStyles[colors].loading, styles.loading], + classNameFromProps, + ); - const buttonChildren = ( - - +
- {showLoader ? ( - - ) : ( - icon - )} - + + {icon} + +
{children} -
- ); - - if (href) { - return ( - )} - > - {buttonChildren} - - ); - } - - return ( - + ); }, ); diff --git a/packages/action-button/src/__image_snapshots__/action-button-disabled-loading-sprite-snap.png b/packages/action-button/src/__image_snapshots__/action-button-disabled-loading-sprite-snap.png index 8b7f8858d5..7d012b7441 100644 --- a/packages/action-button/src/__image_snapshots__/action-button-disabled-loading-sprite-snap.png +++ b/packages/action-button/src/__image_snapshots__/action-button-disabled-loading-sprite-snap.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a48ee688b03ea661724b4b1a80dd1a2a0b2fda4bf6b42e31857dc79c167537bd -size 23117 +oid sha256:9c2b984531f5d9128efe25f6231c9e3c28cdec3691c19ad4778237fb0db00015 +size 22921 diff --git a/packages/action-button/src/default.module.css b/packages/action-button/src/default.module.css index 1180709089..01623ce266 100644 --- a/packages/action-button/src/default.module.css +++ b/packages/action-button/src/default.module.css @@ -25,57 +25,65 @@ --action-button-disabled-bg-color: var(--color-light-neutral-100); } -.primary { - color: var(--action-button-primary-base-color); +.component { + &.primary { + color: var(--action-button-primary-base-color); - & .iconWrapper { - color: var(--action-button-primary-base-icon-color); - background-color: var(--action-button-primary-base-bg-color); - } + .iconWrapper { + color: var(--action-button-primary-base-icon-color); + background-color: var(--action-button-primary-base-bg-color); + } - @media (hover: hover) { - &:hover .iconWrapper { - background-color: var(--action-button-primary-hover-color); + @mixin not-disabled { + @mixin hover { + .iconWrapper { + background-color: var(--action-button-primary-hover-color); + } + } + + &:active .iconWrapper { + background-color: var(--action-button-primary-active-color); + } } - } - &:active .iconWrapper { - background-color: var(--action-button-primary-active-color); + .loader { + color: var(--action-button-spinner-primary-color); + } } - & .loader { - color: var(--action-button-spinner-primary-color); - } -} + &.secondary { + color: var(--action-button-secondary-base-color); -.secondary { - color: var(--action-button-secondary-base-color); + .iconWrapper { + color: var(--action-button-secondary-base-icon-color); + background-color: var(--action-button-secondary-base-bg-color); + } - & .iconWrapper { - color: var(--action-button-secondary-base-icon-color); - background-color: var(--action-button-secondary-base-bg-color); - } + @mixin not-disabled { + @mixin hover { + .iconWrapper { + background-color: var(--action-button-secondary-hover-color); + } + } - @media (hover: hover) { - &:hover .iconWrapper { - background-color: var(--action-button-secondary-hover-color); + &:active .iconWrapper { + background-color: var(--action-button-secondary-active-color); + } } - } - - &:active .iconWrapper { - background-color: var(--action-button-secondary-active-color); - } - & .loader { - color: var(--action-button-spinner-default-color); + .loader { + color: var(--action-button-spinner-default-color); + } } -} -.disabled { - color: var(--action-button-disabled-color); + @mixin disabled { + &:not(.loading) { + color: var(--action-button-disabled-color); - & .iconWrapper { - color: var(--action-button-disabled-icon-color); - background-color: var(--action-button-disabled-bg-color); + .iconWrapper { + color: var(--action-button-disabled-icon-color); + background-color: var(--action-button-disabled-bg-color); + } + } } } diff --git a/packages/action-button/src/docs/description.mdx b/packages/action-button/src/docs/description.mdx index 2314427a33..97afd239d0 100644 --- a/packages/action-button/src/docs/description.mdx +++ b/packages/action-button/src/docs/description.mdx @@ -29,7 +29,7 @@ render(() => { Лейбл кнопки ограничен двумя строками. ```jsx live - } view='primary'> + } view='primary'> Пример переноса текста ``` diff --git a/packages/action-button/src/index.module.css b/packages/action-button/src/index.module.css index 6415dfe952..6b1493cc3e 100644 --- a/packages/action-button/src/index.module.css +++ b/packages/action-button/src/index.module.css @@ -1,77 +1,44 @@ @import '@alfalab/core-components-vars/src/no-typography-index.css'; .component { - position: relative; - display: inline-flex; - flex-flow: column nowrap; - align-items: center; - vertical-align: top; + flex-direction: column; + flex-wrap: nowrap; width: 80px; min-height: 80px; max-height: 100px; - padding: var(--gap-0); - margin: var(--gap-0); - background: none; - border: none; - cursor: pointer; - outline: none; - text-align: center; - text-decoration: none; - text-transform: none; - transition: - color 0.2s ease, - opacity 0.2s ease; - user-select: none; - font-family: inherit; - appearance: none; - -webkit-tap-highlight-color: transparent; - - &.size-48 { - @mixin action_primary_small; + transition: color 0.2s ease; + + /* prettier-ignore */ + @each $size, $mixin in (48, action_primary_small) { + &.size$(size) { + @mixin $(mixin); + + .iconWrapper { + width: $(size)px; + height: $(size)px; + } + } } } -.disabled { - cursor: not-allowed; - pointer-events: none; -} - -.loading { - cursor: auto; - pointer-events: none; -} - .iconWrapper { + position: relative; display: flex; align-items: center; justify-content: center; flex-shrink: 0; margin-bottom: var(--gap-12); border-radius: var(--border-radius-circle); - transition: background-color 0.2s ease; + transition: + opacity 0.2s ease, + background 0.2s ease; line-height: 0; - &.size-48 { - width: 48px; - height: 48px; + .loading & > *:not(.loader) { + opacity: 0; } } .label { - display: -webkit-box; - overflow: hidden; - text-overflow: ellipsis; - -webkit-line-clamp: 2; - -webkit-box-orient: vertical; -} - -.loader { - position: absolute; - left: var(--gap-0); - right: var(--gap-0); - margin: var(--gap-0) auto; -} - -.focused { - @mixin focus-outline; + @mixin row_limit 2; } diff --git a/packages/action-button/src/inverted.module.css b/packages/action-button/src/inverted.module.css index 95c703a389..55e83737a5 100644 --- a/packages/action-button/src/inverted.module.css +++ b/packages/action-button/src/inverted.module.css @@ -33,57 +33,65 @@ --action-button-inverted-disabled-bg-color: var(--color-light-neutral-100-inverted); } -.primary { - color: var(--action-button-inverted-primary-base-color); +.component { + &.primary { + color: var(--action-button-inverted-primary-base-color); - & .iconWrapper { - color: var(--action-button-inverted-primary-base-icon-color); - background-color: var(--action-button-inverted-primary-base-bg-color); - } + .iconWrapper { + color: var(--action-button-inverted-primary-base-icon-color); + background-color: var(--action-button-inverted-primary-base-bg-color); + } - @media (hover: hover) { - &:hover .iconWrapper { - background-color: var(--action-button-inverted-primary-hover-color); + @mixin not-disabled { + @mixin hover { + .iconWrapper { + background-color: var(--action-button-inverted-primary-hover-color); + } + } + + &:active .iconWrapper { + background-color: var(--action-button-inverted-primary-active-color); + } } - } - &:active .iconWrapper { - background-color: var(--action-button-inverted-primary-active-color); + .loader { + color: var(--action-button-spinner-inverted-primary-color); + } } - & .loader { - color: var(--action-button-spinner-inverted-primary-color); - } -} + &.secondary { + color: var(--action-button-inverted-secondary-base-color); -.secondary { - color: var(--action-button-inverted-secondary-base-color); + .iconWrapper { + color: var(--action-button-inverted-secondary-base-icon-color); + background-color: var(--action-button-inverted-secondary-base-bg-color); + } - & .iconWrapper { - color: var(--action-button-inverted-secondary-base-icon-color); - background-color: var(--action-button-inverted-secondary-base-bg-color); - } + @mixin not-disabled { + @mixin hover { + .iconWrapper { + background-color: var(--action-button-inverted-secondary-hover-color); + } + } - @media (hover: hover) { - &:hover .iconWrapper { - background-color: var(--action-button-inverted-secondary-hover-color); + &:active .iconWrapper { + background-color: var(--action-button-inverted-secondary-active-color); + } } - } - - &:active .iconWrapper { - background-color: var(--action-button-inverted-secondary-active-color); - } - & .loader { - color: var(--action-button-spinner-inverted-default-color); + .loader { + color: var(--action-button-spinner-inverted-default-color); + } } -} -.disabled { - color: var(--action-button-inverted-disabled-color); + @mixin disabled { + &:not(.loading) { + color: var(--action-button-inverted-disabled-color); - & .iconWrapper { - color: var(--action-button-inverted-disabled-icon-color); - background-color: var(--action-button-inverted-disabled-bg-color); + .iconWrapper { + color: var(--action-button-inverted-disabled-icon-color); + background-color: var(--action-button-inverted-disabled-bg-color); + } + } } } diff --git a/packages/action-button/src/static.module.css b/packages/action-button/src/static.module.css index 9936c2819f..2432e4e721 100644 --- a/packages/action-button/src/static.module.css +++ b/packages/action-button/src/static.module.css @@ -25,37 +25,41 @@ --action-button-static-disabled-bg-color: var(--color-static-neutral-100); } -.primary { - color: var(--action-button-static-primary-base-color); +.component { + &.primary { + color: var(--action-button-static-primary-base-color); - & .iconWrapper { - color: var(--action-button-static-primary-base-icon-color); - background-color: var(--action-button-static-primary-base-bg-color); - } + .iconWrapper { + color: var(--action-button-static-primary-base-icon-color); + background-color: var(--action-button-static-primary-base-bg-color); + } - & .loader { - color: var(--action-button-spinner-static-primary-color); + .loader { + color: var(--action-button-spinner-static-primary-color); + } } -} -.secondary { - color: var(--action-button-static-secondary-base-color); + &.secondary { + color: var(--action-button-static-secondary-base-color); - & .iconWrapper { - color: var(--action-button-static-secondary-base-icon-color); - background-color: var(--action-button-static-secondary-base-bg-color); - } + .iconWrapper { + color: var(--action-button-static-secondary-base-icon-color); + background-color: var(--action-button-static-secondary-base-bg-color); + } - & .loader { - color: var(--action-button-spinner-static-secondary-color); + .loader { + color: var(--action-button-spinner-static-secondary-color); + } } -} -.disabled { - color: var(--action-button-static-disabled-color); + @mixin disabled { + &:not(.loading) { + color: var(--action-button-static-disabled-color); - & .iconWrapper { - color: var(--action-button-static-disabled-icon-color); - background-color: var(--action-button-static-disabled-bg-color); + .iconWrapper { + color: var(--action-button-static-disabled-icon-color); + background-color: var(--action-button-static-disabled-bg-color); + } + } } } diff --git a/packages/action-button/tsconfig.build.json b/packages/action-button/tsconfig.build.json index d90f28397c..1c107e5ddd 100644 --- a/packages/action-button/tsconfig.build.json +++ b/packages/action-button/tsconfig.build.json @@ -9,14 +9,14 @@ "paths": { "@alfalab/core-components-action-button": ["./src"], "@alfalab/core-components-action-button/*": ["./src/*"], + "@alfalab/core-components-button": ["../button/src"], + "@alfalab/core-components-button/*": ["../button/src/*"], "@alfalab/core-components-shared": ["../shared/src"], - "@alfalab/core-components-shared/*": ["../shared/src/*"], - "@alfalab/core-components-spinner": ["../spinner/src"], - "@alfalab/core-components-spinner/*": ["../spinner/src/*"] + "@alfalab/core-components-shared/*": ["../shared/src/*"] } }, "references": [ - { "path": "../shared/tsconfig.build.json" }, - { "path": "../spinner/tsconfig.build.json" } + { "path": "../button/tsconfig.build.json" }, + { "path": "../shared/tsconfig.build.json" } ] } diff --git a/packages/action-button/tsconfig.json b/packages/action-button/tsconfig.json index d35aee6188..e4ad5083c7 100644 --- a/packages/action-button/tsconfig.json +++ b/packages/action-button/tsconfig.json @@ -8,20 +8,20 @@ "paths": { "@alfalab/core-components-action-button": ["./src"], "@alfalab/core-components-action-button/*": ["./src/*"], + "@alfalab/core-components-button": ["../button/src"], + "@alfalab/core-components-button/*": ["../button/src/*"], "@alfalab/core-components-screenshot-utils": ["../screenshot-utils/src"], "@alfalab/core-components-screenshot-utils/*": ["../screenshot-utils/src/*"], "@alfalab/core-components-shared": ["../shared/src"], "@alfalab/core-components-shared/*": ["../shared/src/*"], - "@alfalab/core-components-spinner": ["../spinner/src"], - "@alfalab/core-components-spinner/*": ["../spinner/src/*"], "@alfalab/core-components-test-utils": ["../test-utils/src"], "@alfalab/core-components-test-utils/*": ["../test-utils/src/*"] } }, "references": [ + { "path": "../button/tsconfig.build.json" }, { "path": "../screenshot-utils/tsconfig.build.json" }, { "path": "../shared/tsconfig.build.json" }, - { "path": "../spinner/tsconfig.build.json" }, { "path": "../test-utils/tsconfig.build.json" } ] } diff --git a/packages/attach/src/__snapshots__/Component.test.tsx.snap b/packages/attach/src/__snapshots__/Component.test.tsx.snap index e6274801c6..a5234bedee 100644 --- a/packages/attach/src/__snapshots__/Component.test.tsx.snap +++ b/packages/attach/src/__snapshots__/Component.test.tsx.snap @@ -6,11 +6,11 @@ exports[`Attach Snapshots tests should match snapshot 1`] = ` class="component size-48" > @@ -169,11 +161,11 @@ exports[`CalendarRange Display tests should match snapshot 1`] = ` tabindex="0" > @@ -1090,11 +1074,11 @@ exports[`CalendarRange Display tests should match snapshot 1`] = ` tabindex="0" > @@ -3508,11 +3500,11 @@ exports[`Calendar Display tests should match selectorView="month-only" snapshot tabindex="-1" > @@ -83,31 +75,27 @@ exports[`PeriodSlider empty PeriodSlider empty PeriodSlider specific title snaps > diff --git a/packages/confirmation-v1/src/__snapshots__/Component.test.tsx.snap b/packages/confirmation-v1/src/__snapshots__/Component.test.tsx.snap index 17ec893ba2..172a6f570b 100644 --- a/packages/confirmation-v1/src/__snapshots__/Component.test.tsx.snap +++ b/packages/confirmation-v1/src/__snapshots__/Component.test.tsx.snap @@ -136,11 +136,11 @@ exports[`Confirmation Snapshot tests should match snapshot with fatal error 1`] Выполните операцию с самого начала @@ -151,58 +144,51 @@ exports[`FileUploadItemV1 Snapshots tests should match snapshot 1`] = ` - - - - - + + diff --git a/packages/icon-button/src/__image_snapshots__/icon-button-screenshots-disabled-view-2-colors-0-snap.png b/packages/icon-button/src/__image_snapshots__/icon-button-screenshots-disabled-view-2-colors-0-snap.png index 55c90c17e8..33ff2c237a 100644 --- a/packages/icon-button/src/__image_snapshots__/icon-button-screenshots-disabled-view-2-colors-0-snap.png +++ b/packages/icon-button/src/__image_snapshots__/icon-button-screenshots-disabled-view-2-colors-0-snap.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8e53491bfb3fc6f57e699eb2c415dbcb9f83afb4df39ca93933ba24df1fe97ac -size 746 +oid sha256:62097e0415d97675a2f7450354d02030659f8f27758cf13087b9c659efd39b6c +size 666 diff --git a/packages/icon-button/src/__image_snapshots__/icon-button-screenshots-disabled-view-2-colors-1-snap.png b/packages/icon-button/src/__image_snapshots__/icon-button-screenshots-disabled-view-2-colors-1-snap.png index b6e213019c..47efd91ae2 100644 --- a/packages/icon-button/src/__image_snapshots__/icon-button-screenshots-disabled-view-2-colors-1-snap.png +++ b/packages/icon-button/src/__image_snapshots__/icon-button-screenshots-disabled-view-2-colors-1-snap.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:67d0e1565e1e3c8b6453dfbe05895aee84aae9c28dd30fbc55eab831ab0a6d0b -size 623 +oid sha256:0fc8bbcebdb89d7e81c629a0d947c3fe8892af7bdc60225f8d0fd5a200ceae17 +size 711 diff --git a/packages/icon-button/src/__snapshots__/Component.test.tsx.snap b/packages/icon-button/src/__snapshots__/Component.test.tsx.snap index 1c39fc51df..f61acf4182 100644 --- a/packages/icon-button/src/__snapshots__/Component.test.tsx.snap +++ b/packages/icon-button/src/__snapshots__/Component.test.tsx.snap @@ -6,42 +6,10 @@ exports[`IconButton Href tests should set \`href\` attribute and be link 1`] = ` "baseElement": - , - "container":
- - + +
+ , + "container": , @@ -123,40 +117,8 @@ exports[`IconButton Snapshots tests should match snapshot 1`] = ` "baseElement":
-
- , - "container":
- +
+ , + "container":
+
, diff --git a/packages/icon-button/src/components/base-icon-button/Component.tsx b/packages/icon-button/src/components/base-icon-button/Component.tsx index f1e7ae525a..6c73587751 100644 --- a/packages/icon-button/src/components/base-icon-button/Component.tsx +++ b/packages/icon-button/src/components/base-icon-button/Component.tsx @@ -1,8 +1,9 @@ import React, { forwardRef, type ReactElement } from 'react'; import cn from 'classnames'; -import { ButtonDesktop } from '@alfalab/core-components-button/desktop'; -import { ButtonMobile } from '@alfalab/core-components-button/mobile'; +import { BaseButtonCandidate } from '@alfalab/core-components-button/components/base-button-candidate'; +import { ButtonContent } from '@alfalab/core-components-button/components/button-content'; +import { useLoading } from '@alfalab/core-components-button/shared'; import { type IconButtonProps } from '../../types/icon-button-props'; @@ -13,14 +14,14 @@ import invertedColors from './inverted.module.css'; const colorStyles = { default: defaultColors, inverted: invertedColors, -}; +} as const; -type BaseIconButtonProps = { - client: 'desktop' | 'mobile'; - clientStyles: Record; -}; - -export const BaseIconButton = forwardRef( +export const BaseIconButton = forwardRef< + HTMLButtonElement, + IconButtonProps & { + clientStyles: Record; + } +>( ( { className, @@ -30,36 +31,40 @@ export const BaseIconButton = forwardRef { - const Component = client === 'desktop' ? ButtonDesktop : ButtonMobile; + const loading = useLoading(loadingFromProps); return ( - {React.isValidElement(Icon) ? ( - React.cloneElement(Icon as ReactElement<{ className?: string }>, { + React.cloneElement(Icon, { className: cn( styles.icon, (Icon as ReactElement<{ className?: string }>).props.className, @@ -69,7 +74,7 @@ export const BaseIconButton = forwardRef )} - + ); }, ); diff --git a/packages/icon-button/src/components/base-icon-button/default.module.css b/packages/icon-button/src/components/base-icon-button/default.module.css index 231494d1f5..3620310b2c 100644 --- a/packages/icon-button/src/components/base-icon-button/default.module.css +++ b/packages/icon-button/src/components/base-icon-button/default.module.css @@ -36,60 +36,70 @@ &.primary { color: var(--icon-button-primary-base-color); - @mixin hover { - color: var(--icon-button-primary-hover-color); - } + @mixin not-disabled { + @mixin hover { + color: var(--icon-button-primary-hover-color); + } - &:active { - color: var(--icon-button-primary-active-color); + &:active { + color: var(--icon-button-primary-active-color); + } } } &.secondary { color: var(--icon-button-secondary-base-color); - @mixin hover { - color: var(--icon-button-secondary-hover-color); - } + @mixin not-disabled { + @mixin hover { + color: var(--icon-button-secondary-hover-color); + } - &:active { - color: var(--icon-button-secondary-active-color); + &:active { + color: var(--icon-button-secondary-active-color); + } } } &.transparent { color: var(--icon-button-transparent-base-color); - @mixin hover { - color: var(--icon-button-transparent-hover-color); - } + @mixin not-disabled { + @mixin hover { + color: var(--icon-button-transparent-hover-color); + } - &:active { - color: var(--icon-button-transparent-active-color); + &:active { + color: var(--icon-button-transparent-active-color); + } } } &.negative { color: var(--icon-button-negative-base-color); - @mixin hover { - color: var(--icon-button-negative-hover-color); - } + @mixin not-disabled { + @mixin hover { + color: var(--icon-button-negative-hover-color); + } - &:active { - color: var(--icon-button-negative-active-color); + &:active { + color: var(--icon-button-negative-active-color); + } } } &.tertiary { color: var(--icon-button-tertiary-base-color); - @mixin hover { - color: var(--icon-button-tertiary-hover-color); - } + @mixin not-disabled { + @mixin hover { + color: var(--icon-button-tertiary-hover-color); + } - &:active { - color: var(--icon-button-tertiary-active-color); + &:active { + color: var(--icon-button-tertiary-active-color); + } } } @@ -97,87 +107,105 @@ &.primary { color: var(--color-light-text-primary); - @mixin hover { - background: var(--color-light-transparent-default-hover); - } + @mixin not-disabled { + @mixin hover { + background: var(--color-light-transparent-default-hover); + } - &:active { - background: var(--color-light-transparent-default-press); + &:active { + background: var(--color-light-transparent-default-press); + } } } &.secondary { color: var(--color-light-text-secondary); - @mixin hover { - background: var(--color-light-transparent-default-hover); - } + @mixin not-disabled { + @mixin hover { + background: var(--color-light-transparent-default-hover); + } - &:active { - background: var(--color-light-transparent-default-press); + &:active { + background: var(--color-light-transparent-default-press); + } } } &.negative { color: var(--color-light-text-negative); - @mixin hover { - background: var(--color-light-transparent-default-hover); - } + @mixin not-disabled { + @mixin hover { + background: var(--color-light-transparent-default-hover); + } - &:active { - background: var(--color-light-transparent-default-press); + &:active { + background: var(--color-light-transparent-default-press); + } } } &.tertiary { color: var(--color-light-text-tertiary); - @mixin hover { - background: var(--color-light-transparent-default-hover); - } + @mixin not-disabled { + @mixin hover { + background: var(--color-light-transparent-default-hover); + } - &:active { - background: var(--color-light-transparent-default-press); + &:active { + background: var(--color-light-transparent-default-press); + } } } } - &.component:disabled { - &.primary { - color: var(--icon-button-primary-disabled-color); + &.component { + @mixin disabled { + &.primary { + color: var(--icon-button-primary-disabled-color); - &.loader { - color: var(--icon-button-primary-base-color); + &.loader { + color: var(--icon-button-primary-base-color); + } } - } - &.secondary { - color: var(--icon-button-secondary-disabled-color); + &.secondary { + color: var(--icon-button-secondary-disabled-color); - &.loader { - color: var(--icon-button-secondary-base-color); + &.loader { + color: var(--icon-button-secondary-base-color); + } } - } - &.negative { - color: var(--icon-button-negative-disabled-color); + &.transparent { + color: var(--icon-button-transparent-disabled-color); - &.loader { - color: var(--icon-button-negative-base-color); + &.loader { + color: var(--icon-button-transparent-base-color); + } } - } - &.tertiary { - color: var(--icon-button-tertiary-disabled-color); + &.negative { + color: var(--icon-button-negative-disabled-color); - &.loader { - color: var(--icon-button-tertiary-base-color); + &.loader { + color: var(--icon-button-negative-base-color); + } } - } - &.transparentBg { - background: transparent; + &.tertiary { + color: var(--icon-button-tertiary-disabled-color); + + &.loader { + color: var(--icon-button-tertiary-base-color); + } + } + + &.transparentBg { + background: transparent; + } } } } diff --git a/packages/icon-button/src/components/base-icon-button/index.module.css b/packages/icon-button/src/components/base-icon-button/index.module.css index 4b997d4782..222e9b6081 100644 --- a/packages/icon-button/src/components/base-icon-button/index.module.css +++ b/packages/icon-button/src/components/base-icon-button/index.module.css @@ -1,6 +1,16 @@ @import '@alfalab/core-components-vars/src/no-typography-index.css'; @import '../../vars.css'; +.component { + position: relative; + + /* Loading */ + + &.loading > *:not(.loader) { + opacity: 0; + } +} + .size-24 { width: var(--icon-button-xxs-size); height: var(--icon-button-xxs-size); diff --git a/packages/icon-button/src/components/base-icon-button/inverted.module.css b/packages/icon-button/src/components/base-icon-button/inverted.module.css index 0b6f20d65e..81727ecd37 100644 --- a/packages/icon-button/src/components/base-icon-button/inverted.module.css +++ b/packages/icon-button/src/components/base-icon-button/inverted.module.css @@ -66,60 +66,70 @@ &.primary { color: var(--icon-button-inverted-primary-base-color); - @mixin hover { - color: var(--icon-button-inverted-primary-hover-color); - } + @mixin not-disabled { + @mixin hover { + color: var(--icon-button-inverted-primary-hover-color); + } - &:active { - color: var(--icon-button-inverted-primary-active-color); + &:active { + color: var(--icon-button-inverted-primary-active-color); + } } } &.secondary { color: var(--icon-button-inverted-secondary-base-color); - @mixin hover { - color: var(--icon-button-inverted-secondary-hover-color); - } + @mixin not-disabled { + @mixin hover { + color: var(--icon-button-inverted-secondary-hover-color); + } - &:active { - color: var(--icon-button-inverted-secondary-active-color); + &:active { + color: var(--icon-button-inverted-secondary-active-color); + } } } &.transparent { color: var(--icon-button-inverted-transparent-base-color); - @mixin hover { - color: var(--icon-button-inverted-transparent-hover-color); - } + @mixin not-disabled { + @mixin hover { + color: var(--icon-button-inverted-transparent-hover-color); + } - &:active { - color: var(--icon-button-inverted-transparent-active-color); + &:active { + color: var(--icon-button-inverted-transparent-active-color); + } } } &.negative { color: var(--icon-button-inverted-negative-base-color); - @mixin hover { - color: var(--icon-button-inverted-negative-hover-color); - } + @mixin not-disabled { + @mixin hover { + color: var(--icon-button-inverted-negative-hover-color); + } - &:active { - color: var(--icon-button-inverted-negative-active-color); + &:active { + color: var(--icon-button-inverted-negative-active-color); + } } } &.tertiary { color: var(--icon-button-inverted-tertiary-base-color); - @mixin hover { - color: var(--icon-button-inverted-tertiary-hover-color); - } + @mixin not-disabled { + @mixin hover { + color: var(--icon-button-inverted-tertiary-hover-color); + } - &:active { - color: var(--icon-button-inverted-tertiary-active-color); + &:active { + color: var(--icon-button-inverted-tertiary-active-color); + } } } @@ -127,87 +137,105 @@ &.primary { color: var(--color-light-text-primary-inverted); - @mixin hover { - background: var(--color-light-transparent-default-inverted-hover); - } + @mixin not-disabled { + @mixin hover { + background: var(--color-light-transparent-default-inverted-hover); + } - &:active { - background: var(--color-light-transparent-default-inverted-press); + &:active { + background: var(--color-light-transparent-default-inverted-press); + } } } &.secondary { color: var(--color-light-text-secondary-inverted); - @mixin hover { - background: var(--color-light-transparent-default-inverted-hover); - } + @mixin not-disabled { + @mixin hover { + background: var(--color-light-transparent-default-inverted-hover); + } - &:active { - background: var(--color-light-transparent-default-inverted-press); + &:active { + background: var(--color-light-transparent-default-inverted-press); + } } } &.negative { color: var(--color-light-text-negative-inverted); - @mixin hover { - background: var(--color-light-transparent-default-inverted-hover); - } + @mixin not-disabled { + @mixin hover { + background: var(--color-light-transparent-default-inverted-hover); + } - &:active { - background: var(--color-light-transparent-default-inverted-press); + &:active { + background: var(--color-light-transparent-default-inverted-press); + } } } &.tertiary { color: var(--color-light-text-tertiary-inverted); - @mixin hover { - background: var(--color-light-transparent-default-inverted-hover); - } + @mixin not-disabled { + @mixin hover { + background: var(--color-light-transparent-default-inverted-hover); + } - &:active { - background: var(--color-light-transparent-default-inverted-press); + &:active { + background: var(--color-light-transparent-default-inverted-press); + } } } } - &.component:disabled { - &.primary { - color: var(--icon-button-inverted-primary-disabled-color); + &.component { + @mixin disabled { + &.primary { + color: var(--icon-button-inverted-primary-disabled-color); - &.loader { - color: var(--icon-button-inverted-primary-base-color); + &.loader { + color: var(--icon-button-inverted-primary-base-color); + } } - } - &.secondary { - color: var(--icon-button-inverted-secondary-disabled-color); + &.secondary { + color: var(--icon-button-inverted-secondary-disabled-color); - &.loader { - color: var(--icon-button-inverted-secondary-base-color); + &.loader { + color: var(--icon-button-inverted-secondary-base-color); + } } - } - &.negative { - color: var(--icon-button-inverted-negative-disabled-color); + &.transparent { + color: var(--icon-button-inverted-transparent-disabled-color); - &.loader { - color: var(--icon-button-inverted-negative-base-color); + &.loader { + color: var(--icon-button-inverted-transparent-base-color); + } } - } - &.tertiary { - color: var(--icon-button-inverted-tertiary-disabled-color); + &.negative { + color: var(--icon-button-inverted-negative-disabled-color); - &.loader { - color: var(--icon-button-inverted-tertiary-base-color); + &.loader { + color: var(--icon-button-inverted-negative-base-color); + } } - } - &.transparentBg { - background: transparent; + &.tertiary { + color: var(--icon-button-inverted-tertiary-disabled-color); + + &.loader { + color: var(--icon-button-inverted-tertiary-base-color); + } + } + + &.transparentBg { + background: transparent; + } } } } diff --git a/packages/icon-button/src/desktop/Component.desktop.tsx b/packages/icon-button/src/desktop/Component.desktop.tsx index 0a3a29e900..a30cef0621 100644 --- a/packages/icon-button/src/desktop/Component.desktop.tsx +++ b/packages/icon-button/src/desktop/Component.desktop.tsx @@ -8,9 +8,7 @@ import clientStyles from './desktop.module.css'; export type IconButtonDesktopProps = IconButtonProps; export const IconButtonDesktop = forwardRef( - (props, ref) => ( - - ), + (props, ref) => , ); IconButtonDesktop.displayName = 'IconButtonDesktop'; diff --git a/packages/icon-button/src/mobile/Component.mobile.tsx b/packages/icon-button/src/mobile/Component.mobile.tsx index eee2df61c5..9dcb03211c 100644 --- a/packages/icon-button/src/mobile/Component.mobile.tsx +++ b/packages/icon-button/src/mobile/Component.mobile.tsx @@ -8,9 +8,7 @@ import clientStyles from './mobile.module.css'; export type IconButtonMobileProps = IconButtonProps; export const IconButtonMobile = forwardRef( - (props, ref) => ( - - ), + (props, ref) => , ); IconButtonMobile.displayName = 'IconButtonMobile'; diff --git a/packages/input-autocomplete/src/__snapshots__/Component.test.tsx.snap b/packages/input-autocomplete/src/__snapshots__/Component.test.tsx.snap index 4eb0d91878..baeda5d718 100644 --- a/packages/input-autocomplete/src/__snapshots__/Component.test.tsx.snap +++ b/packages/input-autocomplete/src/__snapshots__/Component.test.tsx.snap @@ -145,29 +145,25 @@ exports[`InputAutocompleteMobile Snapshots tests should match snapshot in open s > @@ -293,21 +289,21 @@ exports[`InputAutocompleteMobile Snapshots tests should match snapshot in open s tabindex="0" > @@ -165,11 +161,11 @@ exports[`ModalMobile snapshots tests should match snapshot 1`] = ` > diff --git a/packages/navigation-bar-private/src/__snapshots__/Component.test.tsx.snap b/packages/navigation-bar-private/src/__snapshots__/Component.test.tsx.snap index 4367b86fee..f129d7594b 100644 --- a/packages/navigation-bar-private/src/__snapshots__/Component.test.tsx.snap +++ b/packages/navigation-bar-private/src/__snapshots__/Component.test.tsx.snap @@ -18,12 +18,12 @@ exports[`Navigation Bar Snapshots tests should match snapshot 1`] = ` > diff --git a/packages/notification-manager/src/__snapshots__/component.test.tsx.snap b/packages/notification-manager/src/__snapshots__/component.test.tsx.snap index 9e58de515f..a0232741ef 100644 --- a/packages/notification-manager/src/__snapshots__/component.test.tsx.snap +++ b/packages/notification-manager/src/__snapshots__/component.test.tsx.snap @@ -57,29 +57,25 @@ exports[`NotificationManager Snapshots tests should match snapshot 1`] = ` > @@ -120,29 +116,25 @@ exports[`NotificationManager Snapshots tests should match snapshot 1`] = ` > @@ -183,29 +175,25 @@ exports[`NotificationManager Snapshots tests should match snapshot 1`] = ` > diff --git a/packages/notification/src/__snapshots__/Component.test.tsx.snap b/packages/notification/src/__snapshots__/Component.test.tsx.snap index 5e4d2859a7..35ee8baeab 100644 --- a/packages/notification/src/__snapshots__/Component.test.tsx.snap +++ b/packages/notification/src/__snapshots__/Component.test.tsx.snap @@ -67,29 +67,25 @@ exports[`Notification Snapshots tests should match snapshot 1`] = ` > diff --git a/packages/pass-code-v1/src/__snapshots__/component.test.tsx.snap b/packages/pass-code-v1/src/__snapshots__/component.test.tsx.snap index f2b2194062..eccff4798d 100644 --- a/packages/pass-code-v1/src/__snapshots__/component.test.tsx.snap +++ b/packages/pass-code-v1/src/__snapshots__/component.test.tsx.snap @@ -35,143 +35,67 @@ exports[`PassCodeV1 Snapshot tests should match snapshot with code length 1`] =
-
- -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
+ 9 +
-
- -
+ 0 +
@@ -202,173 +126,89 @@ exports[`PassCodeV1 Snapshot tests should match snapshot with error prop 1`] = `
-
- -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
+ 9 +
-
- -
-
+ -
+ + + +
@@ -396,143 +236,67 @@ exports[`PassCodeV1 Snapshot tests should match snapshot with unknown code lengt
-
- -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
-
+ -
+ 9 +
-
- -
+ 0 +
diff --git a/packages/pass-code-v1/src/component.test.tsx b/packages/pass-code-v1/src/component.test.tsx index 697ce3c939..ce3f89adc7 100644 --- a/packages/pass-code-v1/src/component.test.tsx +++ b/packages/pass-code-v1/src/component.test.tsx @@ -39,7 +39,7 @@ describe('PassCodeV1', () => { const { getByText } = render(); - const button = getByText(pressedDigit).parentNode as HTMLButtonElement; + const button = getByText(pressedDigit) as HTMLButtonElement; fireEvent.click(button); diff --git a/packages/pass-code-v1/src/components/KeyPad/Component.tsx b/packages/pass-code-v1/src/components/KeyPad/Component.tsx index 3f0a5c6c3b..cbd8c5f5a5 100644 --- a/packages/pass-code-v1/src/components/KeyPad/Component.tsx +++ b/packages/pass-code-v1/src/components/KeyPad/Component.tsx @@ -81,10 +81,14 @@ export const KeyPad: React.FC = ({ return
; } + const handleDigitClick = () => { + onClick(digit); + }; + return ( = { +export type KeyPadButtonProps = { /** * Вид кнопки. */ - view: ButtonMobileProps['view']; + view: 'secondary' | 'text'; /** * Значение. */ - children: T; + children?: ReactNode; /** * Дополнительный класс. @@ -29,7 +29,7 @@ export type KeyPadButtonProps = { /** * Коллбэк нажатия на кнопку. */ - onClick?: (payload: T) => void; + onClick?: () => void; /** * Идентификатор для систем автоматизированного тестирования. @@ -37,24 +37,18 @@ export type KeyPadButtonProps = { dataTestId?: string; }; -export function KeyPadButton({ - children, - onClick, - className, +export const KeyPadButton: FC = ({ view = 'secondary', buttonClassName, + children, dataTestId, -}: KeyPadButtonProps) { - return ( -
- onClick?.(children)} - dataTestId={dataTestId} - > - {children} - -
- ); -} + onClick, +}) => ( + + {children} + +); diff --git a/packages/pass-code-v1/src/components/KeyPadButton/index.module.css b/packages/pass-code-v1/src/components/KeyPadButton/index.module.css index 60277952b2..57c7c16ea9 100644 --- a/packages/pass-code-v1/src/components/KeyPadButton/index.module.css +++ b/packages/pass-code-v1/src/components/KeyPadButton/index.module.css @@ -2,67 +2,40 @@ @import '../../vars.css'; .component { - display: flex; - justify-content: center; - align-items: center; - padding: var(--gap-0); -} - -.button.button { @mixin action_component_secondary; border-radius: var(--border-radius-circle); - padding: var(--gap-0); - min-width: 64px; width: 64px; height: 64px; - text-align: center; - - & > span { - vertical-align: middle; - & > * { - vertical-align: middle; - } - } -} - -.secondary.secondary { + justify-content: center; + align-items: center; color: var(--color-light-text-primary); - background: var(--button-bg-color); - &:hover { - color: var(--color-light-text-primary); - } + &.secondary { + background: var(--button-bg-color); - &:active { - background: var(--button-bg-color-active); + &:active { + background: var(--button-bg-color-active); + } } -} - -.ghost.ghost { - color: var(--color-light-text-primary); - &:hover { - color: var(--color-light-text-primary); - } + &.text { + @mixin hover { + color: var(--color-light-text-primary-hover); + } - &:active { - background: var(--button-bg-color-active); + &:active { + color: var(--color-light-text-primary-press); + } } -} -@media screen and (min-width: 360px) { - .button.button { - min-width: 76px; + @media screen and (min-width: 360px) { height: 76px; width: 76px; } -} -@media screen and (min-width: 390px) { - .button.button { - min-width: 86px; + @media screen and (min-width: 390px) { width: 86px; height: 86px; } diff --git a/packages/pass-code/src/__snapshots__/component.test.tsx.snap b/packages/pass-code/src/__snapshots__/component.test.tsx.snap index 0fdc1d4e03..800ae4abd7 100644 --- a/packages/pass-code/src/__snapshots__/component.test.tsx.snap +++ b/packages/pass-code/src/__snapshots__/component.test.tsx.snap @@ -53,98 +53,62 @@ exports[`PassCode Snapshot tests should match snapshot with code length 1`] = ` class="component" >
diff --git a/packages/pattern-lock-v1/src/__snapshots__/component.test.tsx.snap b/packages/pattern-lock-v1/src/__snapshots__/component.test.tsx.snap index 630991db6c..d92d76a7ad 100644 --- a/packages/pattern-lock-v1/src/__snapshots__/component.test.tsx.snap +++ b/packages/pattern-lock-v1/src/__snapshots__/component.test.tsx.snap @@ -9,7 +9,7 @@ exports[`PatternLockV1 test Snapshot tests should match snapshot 1`] = ` class="message" />
@@ -26,7 +26,7 @@ exports[`PatternLockV1 test Snapshot tests should match snapshot with error prop Error message
diff --git a/packages/pattern-lock-v1/src/components/base-pattern-lock/Component.tsx b/packages/pattern-lock-v1/src/components/base-pattern-lock/Component.tsx index ca07026e6e..b7830a5299 100644 --- a/packages/pattern-lock-v1/src/components/base-pattern-lock/Component.tsx +++ b/packages/pattern-lock-v1/src/components/base-pattern-lock/Component.tsx @@ -126,23 +126,24 @@ export const BasePatternLock = forwardRef< extraBounds={extraBounds} hover={hover} /> - - {showForgotCodeBtn ? ( - - {forgotCodeBtnText} - - ) : ( -
- )} +
+ {showForgotCodeBtn && ( + + {forgotCodeBtnText} + + )} +
); }, diff --git a/packages/pattern-lock-v1/src/components/base-pattern-lock/index.module.css b/packages/pattern-lock-v1/src/components/base-pattern-lock/index.module.css index a9b297ba41..e02b49b74d 100644 --- a/packages/pattern-lock-v1/src/components/base-pattern-lock/index.module.css +++ b/packages/pattern-lock-v1/src/components/base-pattern-lock/index.module.css @@ -28,7 +28,12 @@ color: var(--color-light-text-negative); } -.forgotBtn { - display: block; +.forgotBtnContainer { + display: flex; + justify-content: center; +} + +.forgotBtnContainer, +.forgotBtn.forgotBtn.forgotBtn { min-height: var(--size-xs-height); } diff --git a/packages/pattern-lock-v1/src/desktop/desktop.module.css b/packages/pattern-lock-v1/src/desktop/desktop.module.css index f9a14de1e5..d580c66f7e 100644 --- a/packages/pattern-lock-v1/src/desktop/desktop.module.css +++ b/packages/pattern-lock-v1/src/desktop/desktop.module.css @@ -6,7 +6,7 @@ margin: var(--gap-8) var(--gap-0) var(--gap-24) var(--gap-0); } -.forgotBtn { +.forgotBtnContainer { margin: var(--gap-24) auto var(--gap-0); } diff --git a/packages/pattern-lock-v1/src/mobile/mobile.module.css b/packages/pattern-lock-v1/src/mobile/mobile.module.css index 771c91fc56..9caaaa80e1 100644 --- a/packages/pattern-lock-v1/src/mobile/mobile.module.css +++ b/packages/pattern-lock-v1/src/mobile/mobile.module.css @@ -6,13 +6,16 @@ margin: var(--gap-8) var(--gap-0) var(--gap-24) var(--gap-0); } -.forgotBtn { +.forgotBtnContainer { margin: var(--gap-24) auto var(--gap-0); } @media screen and (min-width: 360px) { - .forgotBtn { + .forgotBtnContainer { margin-top: var(--gap-32); + } + .forgotBtnContainer, + .forgotBtn.forgotBtn.forgotBtn { min-height: var(--size-s-height); } @@ -22,7 +25,8 @@ } @media screen and (min-width: 390px) { - .forgotBtn { + .forgotBtnContainer, + .forgotBtn.forgotBtn.forgotBtn { min-height: var(--size-m-height); } diff --git a/packages/pattern-lock/src/__image_snapshots__/pattern-lock-screenshots-default-with-forgot-code-button-snap.png b/packages/pattern-lock/src/__image_snapshots__/pattern-lock-screenshots-default-with-forgot-code-button-snap.png index 678ec1c6d2..dc230a1366 100644 --- a/packages/pattern-lock/src/__image_snapshots__/pattern-lock-screenshots-default-with-forgot-code-button-snap.png +++ b/packages/pattern-lock/src/__image_snapshots__/pattern-lock-screenshots-default-with-forgot-code-button-snap.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a8cc30205a0fdb528b64a54dbbd964a50b854d6a090b50cea8d2386e56df0d0 -size 9019 +oid sha256:bc7add260dd67f0f0bc65e793dec0b4f5bc8d617ee1624f013d3cab03f07de79 +size 8754 diff --git a/packages/pattern-lock/src/__snapshots__/component.test.tsx.snap b/packages/pattern-lock/src/__snapshots__/component.test.tsx.snap index 575242d8d9..bf276cc7fa 100644 --- a/packages/pattern-lock/src/__snapshots__/component.test.tsx.snap +++ b/packages/pattern-lock/src/__snapshots__/component.test.tsx.snap @@ -3,7 +3,7 @@ exports[`PatternLock test Snapshot tests should match snapshot 1`] = `
{showForgotCodeBtn && ( - - {forgotCodeBtnText} - +
+ + {forgotCodeBtnText} + +
)}
); diff --git a/packages/pattern-lock/src/components/base-pattern-lock/index.module.css b/packages/pattern-lock/src/components/base-pattern-lock/index.module.css index 8afcb3af9c..38ff009988 100644 --- a/packages/pattern-lock/src/components/base-pattern-lock/index.module.css +++ b/packages/pattern-lock/src/components/base-pattern-lock/index.module.css @@ -35,7 +35,8 @@ min-height: var(--pattern-lock-with-forgot-btn-min-height); } -.forgotBtn { - display: block; - min-height: var(--size-xs-height); +.forgotBtnContainer { + display: flex; + justify-content: center; + margin: var(--gap-8) auto var(--gap-0); } diff --git a/packages/pattern-lock/src/desktop/Component.desktop.tsx b/packages/pattern-lock/src/desktop/Component.desktop.tsx index be765912c1..880305a092 100644 --- a/packages/pattern-lock/src/desktop/Component.desktop.tsx +++ b/packages/pattern-lock/src/desktop/Component.desktop.tsx @@ -5,10 +5,8 @@ import { type TPatternLockInstance } from '@alfalab/react-canvas-pattern-lock'; import { BasePatternLock } from '../components/base-pattern-lock'; import { type CommonPatternLockProps } from '../typings'; -import styles from './desktop.module.css'; - export const PatternLockDesktop = forwardRef( - (restProps, ref) => , + (restProps, ref) => , ); PatternLockDesktop.displayName = 'PatternLockDesktop'; diff --git a/packages/pattern-lock/src/desktop/desktop.module.css b/packages/pattern-lock/src/desktop/desktop.module.css deleted file mode 100644 index 6c6b96266e..0000000000 --- a/packages/pattern-lock/src/desktop/desktop.module.css +++ /dev/null @@ -1,15 +0,0 @@ -@import '@alfalab/core-components-vars/src/no-typography-index.css'; -@import '../vars.css'; - -.component { - margin: var(--gap-0) auto; - min-width: var(--pattern-lock-min-width); -} - -.forgotBtn { - margin: var(--gap-8) auto var(--gap-0); -} - -.hiddenBtn { - display: none; -} diff --git a/packages/pattern-lock/src/mobile/Component.mobile.tsx b/packages/pattern-lock/src/mobile/Component.mobile.tsx index 98efd99c02..36735aab1d 100644 --- a/packages/pattern-lock/src/mobile/Component.mobile.tsx +++ b/packages/pattern-lock/src/mobile/Component.mobile.tsx @@ -5,10 +5,8 @@ import { type TPatternLockInstance } from '@alfalab/react-canvas-pattern-lock'; import { BasePatternLock } from '../components/base-pattern-lock'; import { type CommonPatternLockProps } from '../typings'; -import styles from './mobile.module.css'; - export const PatternLockMobile = forwardRef( - (restProps, ref) => , + (restProps, ref) => , ); PatternLockMobile.displayName = 'PatternLockMobile'; diff --git a/packages/pattern-lock/src/mobile/mobile.module.css b/packages/pattern-lock/src/mobile/mobile.module.css deleted file mode 100644 index 57d3ff2840..0000000000 --- a/packages/pattern-lock/src/mobile/mobile.module.css +++ /dev/null @@ -1,11 +0,0 @@ -@import '@alfalab/core-components-vars/src/no-typography-index.css'; -@import '../vars.css'; - -.component { - margin: var(--gap-0) auto; - min-width: var(--pattern-lock-min-width); -} - -.forgotBtn { - margin: var(--gap-8) auto var(--gap-0); -} diff --git a/packages/pattern-lock/src/typings.ts b/packages/pattern-lock/src/typings.ts index e17ec2e02b..e8d6b1d102 100644 --- a/packages/pattern-lock/src/typings.ts +++ b/packages/pattern-lock/src/typings.ts @@ -75,10 +75,6 @@ export type PrivatePatternLockProps = { * Включает ховер-эффект */ hover?: boolean; - /** - * Стили компонента - */ - styles: { [key: string]: string }; }; export type PatternLockProps = CommonPatternLockProps & { diff --git a/packages/picker-button/src/Component.test.tsx b/packages/picker-button/src/Component.test.tsx index 4898347365..2200de719a 100644 --- a/packages/picker-button/src/Component.test.tsx +++ b/packages/picker-button/src/Component.test.tsx @@ -118,7 +118,7 @@ describe('Render tests', () => { const button = document.querySelector('button'); const icon = getByTestId('picker-button-icon'); - expect(button).toHaveClass('size-56'); + expect(button).toHaveClass('size56'); expect(button).toHaveClass('secondary'); expect(icon.getAttribute('width')).toBe(iconSize); expect(icon.getAttribute('height')).toBe(iconSize); @@ -133,7 +133,7 @@ describe('Render tests', () => { const button = document.querySelector('button'); const icon = getByTestId('picker-button-icon'); - expect(button).toHaveClass(`size-${size}`); + expect(button).toHaveClass(`size${size}`); expect(icon.getAttribute('width')).toBe(iconSize); expect(icon.getAttribute('height')).toBe(iconSize); }); diff --git a/packages/picker-button/src/__snapshots__/Component.test.tsx.snap b/packages/picker-button/src/__snapshots__/Component.test.tsx.snap index 460fc2d468..1f7fd85328 100644 --- a/packages/picker-button/src/__snapshots__/Component.test.tsx.snap +++ b/packages/picker-button/src/__snapshots__/Component.test.tsx.snap @@ -13,7 +13,7 @@ exports[`Snapshots tests should display correctly 1`] = `
@@ -759,13 +755,13 @@ exports[`Snapshots tests should display opened correctly 5`] = ` diff --git a/packages/plate/src/Component.test.tsx b/packages/plate/src/Component.test.tsx index f97b347b9a..f84e552a8d 100644 --- a/packages/plate/src/Component.test.tsx +++ b/packages/plate/src/Component.test.tsx @@ -69,9 +69,9 @@ describe('Plate', () => { expect(queryByTestId('button-2')).toBeInTheDocument(); expect(queryByTestId('button-3')).toBeInTheDocument(); - expect(queryByTestId('button-1')).toHaveClass(`size-${size}`); - expect(queryByTestId('button-2')).toHaveClass(`size-${size}`); - expect(queryByTestId('button-3')).toHaveClass(`size-${size}`); + expect(queryByTestId('button-1')).toHaveClass(`size${size}`); + expect(queryByTestId('button-2')).toHaveClass(`size${size}`); + expect(queryByTestId('button-3')).toHaveClass(`size${size}`); expect(queryByTestId('button-1')).toHaveClass('secondary'); expect(queryByTestId('button-2')).toHaveClass('transparent'); diff --git a/packages/side-panel/src/__snapshots__/Component.test.tsx.snap b/packages/side-panel/src/__snapshots__/Component.test.tsx.snap index a9f447f373..a12755235c 100644 --- a/packages/side-panel/src/__snapshots__/Component.test.tsx.snap +++ b/packages/side-panel/src/__snapshots__/Component.test.tsx.snap @@ -30,11 +30,11 @@ exports[`SidePanelDesktop snapshots tests should match snapshot 1`] = ` > @@ -172,11 +168,11 @@ exports[`SidePanelMobile snapshots tests should match snapshot 1`] = ` > diff --git a/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-13-snap.png b/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-13-snap.png index 08611e4447..e3478b185e 100644 --- a/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-13-snap.png +++ b/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-13-snap.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c572698e7a2e6b6aeb77c40a9ca443c03e0931b5790e58a383bd02cb3094af18 -size 7987 +oid sha256:699e84b4e35ad13f7201dbc5f96010d60011b7c08c69a45e5a85b747ea152ee8 +size 8080 diff --git a/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-2-snap.png b/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-2-snap.png index 294994425a..b1f440a8dd 100644 --- a/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-2-snap.png +++ b/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-2-snap.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9750825ae110dd40bde417cf16122bc38db622435a9513925873b1123ad7c325 -size 7351 +oid sha256:af7c24f6602e818ae138537b17ef602e8dd26971de8ddec945caa782aa013c9b +size 7369 diff --git a/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-5-snap.png b/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-5-snap.png index d66f0440fa..c82d9fc6cc 100644 --- a/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-5-snap.png +++ b/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-5-snap.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ac058c0ff04f565cd6208bd5ede546cbaea78c1f85d3bb508c3efbf6ad827c56 -size 7610 +oid sha256:cd1cb94c931408904930ae306883ef68861a3553993c4ede7e576b57ec7928b8 +size 7738 diff --git a/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-8-snap.png b/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-8-snap.png index a98d0227ee..d2efdd3305 100644 --- a/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-8-snap.png +++ b/packages/tabs/src/__image_snapshots__/tabs-text-style-prop-text-style-8-snap.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5a4f1bf6046223e353ac71e2ab94df0d05c05d51d770f03317d24a65fc5f2250 -size 7824 +oid sha256:008ac7a1272a95c5c3dc345d30e81705d9ba1fb98911da94418ce0f004870c8a +size 7837 diff --git a/packages/toast-plate/src/__image_snapshots__/click-toast-plate-action-button-2-snap.png b/packages/toast-plate/src/__image_snapshots__/click-toast-plate-action-button-2-snap.png index 94414b101d..6ed6644efb 100644 --- a/packages/toast-plate/src/__image_snapshots__/click-toast-plate-action-button-2-snap.png +++ b/packages/toast-plate/src/__image_snapshots__/click-toast-plate-action-button-2-snap.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bb8a7a4914c0da52cce4e63438175e19b66ab1bafaab4cff36c044499491bb0d -size 8366 +oid sha256:f573d006f58e13148821d3e1db35ce2e16046574e1f517b73f5d799e0a3fd80f +size 8620 diff --git a/packages/toast-plate/src/__image_snapshots__/click-toast-plate-inverted-views-2-snap.png b/packages/toast-plate/src/__image_snapshots__/click-toast-plate-inverted-views-2-snap.png index aadc46fd73..eeede83270 100644 --- a/packages/toast-plate/src/__image_snapshots__/click-toast-plate-inverted-views-2-snap.png +++ b/packages/toast-plate/src/__image_snapshots__/click-toast-plate-inverted-views-2-snap.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7feb7bee476ec0ef0f8adb3b164ac067c576f8811846ac903f164295b3944836 -size 8410 +oid sha256:b9310a20e865debea20542198c0592f26af7c7a07e1148fcde2f741d94e0b36c +size 8659 diff --git a/packages/vars/src/mixins.css b/packages/vars/src/mixins.css index 88b145fbe3..ff406eafc6 100644 --- a/packages/vars/src/mixins.css +++ b/packages/vars/src/mixins.css @@ -119,3 +119,16 @@ -webkit-box-orient: vertical; overflow: hidden; } + +@define-mixin disabled { + &:disabled, + &.disabled { + @mixin-content; + } +} + +@define-mixin not-disabled { + &:not(:disabled):not(.disabled) { + @mixin-content; + } +} diff --git a/postcss.config.js b/postcss.config.js index f951a5af51..42925dcdb3 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -8,7 +8,7 @@ module.exports = { plugins: [ require('postcss-import')({}), require('postcss-for')({}), - require('postcss-each')({}), + require('./tools/postcss/postcss-each.cjs')({}), require('./tools/postcss/postcss-subtract-mixin.cjs')({}), require('postcss-mixins')({ mixinsFiles: globSync('src/*.css', { diff --git a/tools/postcss/postcss-each.cjs b/tools/postcss/postcss-each.cjs new file mode 100644 index 0000000000..da719e101c --- /dev/null +++ b/tools/postcss/postcss-each.cjs @@ -0,0 +1,78 @@ +const assert = require('node:assert/strict'); +const postcssSimpleVars = require('postcss-simple-vars'); + +/** + * @type {import('postcss').PluginCreator} + */ +const postcssEach = () => { + const separator = /\s+in\s+/; + + return { + postcssPlugin: 'postcss-each', + AtRule: { + each: async (rule, { list, postcss }) => { + assert(separator.test(rule.params), 'Missed "in" keyword in @each'); + + const [variablesPart, valuesPart] = rule.params + .split(/\s+in\s+/) + .map((s) => s.trim()); + + assert(variablesPart.length > 0, 'Missed variable in @each'); + assert(valuesPart.length > 0, 'Missed values list in @each'); + + const [variables, valuesList] = [variablesPart, valuesPart].map((s) => + list.comma(s), + ); + + assert( + variables.every((variable) => variable.startsWith('$')), + 'Every variable name must start with "$"', + ); + + const values = valuesList.map((value, i) => { + const match = /^\((.*)\)$/.exec(value); + + return (match ? list.comma(match[1]) : [value]).concat(`${i}`); + }); + + const valueSize = Math.max(...values.map((value) => value.length)); + + assert( + values.every((value) => value.length === valueSize), + 'Every value in list must have the same size', + ); + + assert(variables.length <= valueSize, 'Defined more variables than value in list'); + + if (variables.length === valueSize - 1) { + variables.push('$i'); + } + + await Promise.all( + values.map(async (value) => { + const context = Object.fromEntries( + variables.map((variable, i) => [variable.replace(/^\$/, ''), value[i]]), + ); + + const { + root: { + nodes: [proxy], + }, + } = await postcss(postcssSimpleVars({ only: context })).process( + rule.clone(), + { from: undefined }, + ); + + rule.parent.insertBefore(rule, proxy.nodes); + }), + ); + + rule.remove(); + }, + }, + }; +}; + +postcssEach.postcss = true; + +module.exports = postcssEach; diff --git a/yarn.lock b/yarn.lock index ce4813d858..c46629b924 100644 --- a/yarn.lock +++ b/yarn.lock @@ -110,9 +110,8 @@ __metadata: version: 0.0.0-use.local resolution: "@alfalab/core-components-action-button@workspace:packages/action-button" dependencies: + "@alfalab/core-components-button": "npm:^13.1.0" "@alfalab/core-components-shared": "npm:^2.1.0" - "@alfalab/core-components-spinner": "npm:^6.0.2" - "@alfalab/hooks": "npm:^1.13.1" classnames: "npm:^2.5.1" react-merge-refs: "npm:^1.1.0" tslib: "npm:^2.4.0" @@ -577,6 +576,7 @@ __metadata: resolution: "@alfalab/core-components-custom-button@workspace:packages/custom-button" dependencies: "@alfalab/core-components-button": "npm:^13.1.0" + "@alfalab/core-components-mq": "npm:^6.0.2" classnames: "npm:^2.5.1" tslib: "npm:^2.4.0" peerDependencies: @@ -1586,7 +1586,6 @@ __metadata: postcss-color-mod-function: "npm:^4.1.1" postcss-custom-media: "npm:^8.0.2" postcss-custom-properties: "npm:^12.1.10" - postcss-each: "npm:^1.1.0" postcss-export-custom-variables: "npm:^1.0.0" postcss-for: "npm:^2.1.1" postcss-import: "npm:^16.1.1" @@ -1594,6 +1593,7 @@ __metadata: postcss-mixins: "npm:^7.0.3" postcss-modules: "npm:^6.0.1" postcss-preset-env: "npm:^7.8.3" + postcss-simple-vars: "npm:^7.0.1" prettier: "npm:~3.6.2" querystring-es3: "npm:^0.2.1" raw-loader: "npm:^4.0.1" @@ -26464,17 +26464,6 @@ __metadata: languageName: node linkType: hard -"postcss-each@npm:^1.1.0": - version: 1.1.0 - resolution: "postcss-each@npm:1.1.0" - dependencies: - postcss-simple-vars: "npm:^6.0.0" - peerDependencies: - postcss: ^8.0.0 - checksum: 10c0/92a1e4a31f7f933920215104f055e2d2d6c40334ba6fd4d7aee76cc21ba034528aa1ab16316bb1d84f1f14b1d6b923f1c3541099ef7cf103b160bcc33676e009 - languageName: node - linkType: hard - "postcss-env-function@npm:^4.0.6": version: 4.0.6 resolution: "postcss-env-function@npm:4.0.6" @@ -27450,7 +27439,7 @@ __metadata: languageName: node linkType: hard -"postcss-simple-vars@npm:^6.0.0, postcss-simple-vars@npm:^6.0.3": +"postcss-simple-vars@npm:^6.0.3": version: 6.0.3 resolution: "postcss-simple-vars@npm:6.0.3" peerDependencies: @@ -27459,6 +27448,15 @@ __metadata: languageName: node linkType: hard +"postcss-simple-vars@npm:^7.0.1": + version: 7.0.1 + resolution: "postcss-simple-vars@npm:7.0.1" + peerDependencies: + postcss: ^8.2.1 + checksum: 10c0/b59c750b2f406a18b133184144b5ffefbd21a2179c5bf5d54651269c0b6bb0110c2bbed33a9161d8b93f8a11cf7725da0a65653e7c2786c8a59f937591115a33 + languageName: node + linkType: hard + "postcss-svgo@npm:^5.1.0": version: 5.1.0 resolution: "postcss-svgo@npm:5.1.0"