1- import React , {
2- type AnchorHTMLAttributes ,
3- type ButtonHTMLAttributes ,
4- forwardRef ,
5- Fragment ,
6- useRef ,
7- } from 'react' ;
1+ import React , { type AnchorHTMLAttributes , type ButtonHTMLAttributes , forwardRef } from 'react' ;
82import mergeRefs from 'react-merge-refs' ;
93import cn from 'classnames' ;
104
5+ import {
6+ BaseButtonCandidate ,
7+ type BaseButtonOwnProps ,
8+ type MaybeAnchorAttributes ,
9+ } from '@alfalab/core-components-button/components/base-button-candidate' ;
10+ import { ButtonContent } from '@alfalab/core-components-button/components/button-content' ;
11+ import { useLoading } from '@alfalab/core-components-button/shared' ;
1112import { getDataTestId } from '@alfalab/core-components-shared' ;
12- import { Spinner } from '@alfalab/core-components-spinner' ;
13- import { useFocus } from '@alfalab/hooks' ;
14-
15- import { LOADER_MIN_DISPLAY_INTERVAL } from './constants/loader-min-display-interval' ;
16- import { useLoader } from './hooks' ;
1713
1814import defaultColors from './default.module.css' ;
1915import styles from './index.module.css' ;
@@ -24,11 +20,12 @@ const colorStyles = {
2420 default : defaultColors ,
2521 inverted : invertedColors ,
2622 static : staticColors ,
27- } ;
23+ } as const ;
2824
2925type Colors = 'default' | 'inverted' | 'static' ;
3026
31- type ComponentProps = {
27+ interface ComponentProps
28+ extends Omit < BaseButtonOwnProps , 'disabledClassName' | 'Content' | 'block' > {
3229 /**
3330 * Иконка кнопки
3431 */
@@ -44,92 +41,69 @@ type ComponentProps = {
4441 */
4542 view ?: 'primary' | 'secondary' ;
4643
47- /**
48- * Дополнительный класс
49- */
50- className ?: string ;
51-
5244 /**
5345 * Дополнительный класс для обертки иконки
5446 */
5547 iconWrapperClassName ?: string ;
5648
57- /**
58- * Значение href для ссылки
59- */
60- href ?: string ;
61-
62- /**
63- * Заблокировать кнопку
64- */
65- disabled ?: boolean ;
66-
67- /**
68- * Показать лоадер
69- */
70- loading ?: boolean ;
71-
72- /**
73- * Идентификатор для систем автоматизированного тестирования.
74- * Для спиннера используется модификатор -loader
75- */
76- dataTestId ?: string ;
77-
7849 /**
7950 * Палитра, в контексте которой используется кнопка
8051 */
8152 colors ?: Colors ;
82- } ;
53+ }
54+
55+ interface AnchorLikeProps
56+ extends MaybeAnchorAttributes < string > ,
57+ ComponentProps ,
58+ Omit < AnchorHTMLAttributes < HTMLElement > , keyof ComponentProps > { }
8359
84- type AnchorProps = ComponentProps & AnchorHTMLAttributes < HTMLAnchorElement > ;
85- type ButtonProps = ComponentProps & ButtonHTMLAttributes < HTMLButtonElement > ;
86- export type ActionButtonProps = Partial < AnchorProps | ButtonProps > ;
60+ interface ButtonLikeProps
61+ extends MaybeAnchorAttributes < undefined > ,
62+ ComponentProps ,
63+ Omit < ButtonHTMLAttributes < HTMLElement > , keyof ComponentProps > { }
64+
65+ export type ActionButtonProps = AnchorLikeProps | ButtonLikeProps ;
8766
8867export const ActionButton = forwardRef < HTMLAnchorElement | HTMLButtonElement , ActionButtonProps > (
8968 (
9069 {
91- className,
70+ className : classNameFromProps ,
9271 icon,
9372 children,
94- href,
9573 size = 48 ,
9674 view = 'primary' ,
97- type = 'button' ,
9875 iconWrapperClassName,
9976 disabled,
100- loading,
101- dataTestId,
77+ loading : loadingFromProps ,
10278 colors = 'default' ,
79+ dataTestId,
10380 ...rest
10481 } ,
10582 ref ,
10683 ) => {
107- const componentRef = useRef < HTMLElement > ( null ) ;
108-
109- const [ focused ] = useFocus ( componentRef , 'keyboard' ) ;
110-
111- const { showLoader } = useLoader ( ! ! loading , LOADER_MIN_DISPLAY_INTERVAL ) ;
84+ const loading = useLoading ( loadingFromProps ) ;
11285
11386 const styleSize = `size-${ size } ` ;
11487
115- const componentProps = {
116- className : cn (
117- styles . component ,
118- colorStyles [ colors ] [ view ] ,
119- styles [ styleSize ] ,
120- {
121- [ styles . focused ] : focused ,
122- [ styles . disabled ] : disabled ,
123- [ colorStyles [ colors ] . disabled ] : disabled ,
124- [ styles . loading ] : showLoader ,
125- } ,
126- className ,
127- ) ,
128- 'data-test-id' : dataTestId ,
129- } ;
130-
131- const buttonChildren = (
132- < Fragment >
88+ const className = cn (
89+ styles . component ,
90+ colorStyles [ colors ] . component ,
91+ colorStyles [ colors ] [ view ] ,
92+ styles [ styleSize ] ,
93+ loading && [ colorStyles [ colors ] . loading , styles . loading ] ,
94+ classNameFromProps ,
95+ ) ;
96+
97+ return (
98+ < BaseButtonCandidate
99+ { ...rest }
100+ dataTestId = { dataTestId }
101+ ref = { mergeRefs ( [ ref ] ) }
102+ className = { className }
103+ disabled = { disabled }
104+ disabledClassName = { colorStyles [ colors ] . disabled }
105+ loading = { loading }
106+ >
133107 < span
134108 role = 'img'
135109 className = { cn (
@@ -139,47 +113,16 @@ export const ActionButton = forwardRef<HTMLAnchorElement | HTMLButtonElement, Ac
139113 iconWrapperClassName ,
140114 ) }
141115 >
142- { showLoader ? (
143- < Spinner
144- preset = { 24 }
145- dataTestId = { getDataTestId ( dataTestId , 'loader' ) }
146- visible = { true }
147- className = { cn ( styles . loader , colorStyles [ colors ] . loader ) }
148- />
149- ) : (
150- icon
151- ) }
116+ < ButtonContent
117+ loading = { loading }
118+ loaderClassName = { cn ( styles . loader , colorStyles [ colors ] . loader ) }
119+ dataTestId = { getDataTestId ( dataTestId , 'loader' ) }
120+ >
121+ { icon }
122+ </ ButtonContent >
152123 </ span >
153124 < span className = { styles . label } > { children } </ span >
154- </ Fragment >
155- ) ;
156-
157- if ( href ) {
158- return (
159- < a
160- role = 'button'
161- ref = { mergeRefs ( [ componentRef , ref ] ) }
162- href = { href }
163- aria-disabled = { disabled || loading }
164- { ...componentProps }
165- { ...( rest as AnchorHTMLAttributes < HTMLAnchorElement > ) }
166- >
167- { buttonChildren }
168- </ a >
169- ) ;
170- }
171-
172- return (
173- < button
174- ref = { mergeRefs ( [ componentRef , ref ] ) }
175- // eslint-disable-next-line react/button-has-type
176- type = { type as ButtonHTMLAttributes < HTMLButtonElement > [ 'type' ] }
177- disabled = { disabled || loading }
178- { ...componentProps }
179- { ...( rest as ButtonHTMLAttributes < HTMLButtonElement > ) }
180- >
181- { buttonChildren }
182- </ button >
125+ </ BaseButtonCandidate >
183126 ) ;
184127 } ,
185128) ;
0 commit comments