1- import { forwardRef , MouseEventHandler , useCallback , useContext } from 'react' ;
2- import { useHover } from '@react-aria/interactions' ;
3- import { useButton } from '@react-aria/button' ;
1+ import { forwardRef , MouseEventHandler } from 'react' ;
42import { AriaButtonProps } from '@react-types/button' ;
5- import { useFocusableRef } from '@react-spectrum/utils' ;
63import { FocusableRef } from '@react-types/shared' ;
74
8- import { UIKitContext } from '../../provider' ;
9- import { mergeProps } from '../../utils/react' ;
10- import { useFocus } from '../../utils/react/interactions' ;
115import {
126 BaseProps ,
137 BaseStyleProps ,
148 CONTAINER_STYLES ,
159 ContainerStyleProps ,
1610 extractStyles ,
17- filterBaseProps ,
1811 Styles ,
1912 TagNameProps ,
2013 TEXT_STYLES ,
2114 TextStyleProps ,
22- Element ,
15+ tasty ,
2316} from '../../tasty' ;
2417
18+ import { useAction } from './use-action' ;
19+
2520export interface CubeActionProps
2621 extends BaseProps ,
2722 TagNameProps ,
@@ -37,92 +32,11 @@ export interface CubeActionProps
3732 onMouseLeave ?: MouseEventHandler ;
3833}
3934
40- const FILTER_OPTIONS = { propNames : new Set ( [ 'onMouseEnter' , 'onMouseLeave' ] ) } ;
41-
42- /**
43- * Helper to open link.
44- * @param {String } href
45- * @param {String|Boolean } [target]
46- */
47- export function openLink ( href , target ?) {
48- const link = document . createElement ( 'a' ) ;
49-
50- link . href = href ;
51-
52- if ( target ) {
53- link . target = target === true ? '_blank' : target ;
54- }
55-
56- document . body . appendChild ( link ) ;
57-
58- link . click ( ) ;
59-
60- document . body . removeChild ( link ) ;
61- }
62-
63- export function parseTo ( to ) : {
64- newTab : boolean ;
65- nativeRoute : boolean ;
66- href : string | undefined ;
67- } {
68- const newTab = to && typeof to === 'string' && to . startsWith ( '!' ) ;
69- const nativeRoute = to && typeof to === 'string' && to . startsWith ( '@' ) ;
70- const href : string | undefined =
71- to && typeof to === 'string'
72- ? newTab || nativeRoute
73- ? to . slice ( 1 )
74- : to
75- : undefined ;
76-
77- return {
78- newTab,
79- nativeRoute,
80- href,
81- } ;
82- }
83-
84- export function performClickHandler ( evt , router , to , onPress ) {
85- const { newTab, nativeRoute, href } = parseTo ( to ) ;
86-
87- onPress ?.( evt ) ;
88-
89- if ( ! to ) return ;
90-
91- if ( evt . shiftKey || evt . metaKey || newTab ) {
92- openLink ( href , true ) ;
93-
94- return ;
95- }
96-
97- if ( nativeRoute ) {
98- openLink ( href || window . location . href ) ;
99- } else if ( href && href . startsWith ( '#' ) ) {
100- const id = href . slice ( 1 ) ;
101- const element = document . getElementById ( id ) ;
102-
103- if ( element ) {
104- element . scrollIntoView ( {
105- behavior : 'smooth' ,
106- block : 'start' ,
107- inline : 'nearest' ,
108- } ) ;
109-
110- return ;
111- }
112- }
113-
114- if ( router ) {
115- router . push ( href ) ;
116- } else if ( href ) {
117- window . location . href = href ;
118- }
119- }
120-
121- const DEFAULT_STYLES : Styles = {
35+ const DEFAULT_ACTION_STYLES : Styles = {
12236 reset : 'button' ,
12337 position : 'relative' ,
12438 margin : 0 ,
125- fontFamily : 'var(--font) ' ,
39+ preset : 'inherit ' ,
12640 border : 0 ,
12741 padding : 0 ,
12842 outline : {
@@ -131,74 +45,27 @@ const DEFAULT_STYLES: Styles = {
13145 } ,
13246 transition : 'theme' ,
13347 cursor : 'pointer' ,
48+ textDecoration : 'none' ,
49+ fill : '#clear' ,
13450} as const ;
13551
52+ const ActionElement = tasty ( {
53+ as : 'button' ,
54+ styles : DEFAULT_ACTION_STYLES ,
55+ } ) ;
56+
13657const STYLE_PROPS = [ ...CONTAINER_STYLES , ...TEXT_STYLES ] ;
13758
13859export const Action = forwardRef ( function Action (
13960 { to, as, htmlType, label, theme, mods, onPress, ...props } : CubeActionProps ,
14061 ref : FocusableRef < HTMLElement > ,
14162) {
142- as = to ? 'a' : as || 'button' ;
143-
144- const router = useContext ( UIKitContext ) . router ;
145- const isDisabled = props . isDisabled ;
146- const { newTab, href } = parseTo ( to ) ;
147- const target = newTab ? '_blank' : undefined ;
148- const domRef = useFocusableRef ( ref ) ;
149- const styles = extractStyles ( props , STYLE_PROPS , DEFAULT_STYLES ) ;
150-
151- const customOnPress = useCallback (
152- ( evt ) => {
153- performClickHandler ( evt , router , to , onPress ) ;
154- } ,
155- [ router , to , onPress ] ,
63+ const { actionProps } = useAction (
64+ { to, as, htmlType, label, onPress, mods, ...props } ,
65+ ref ,
15666 ) ;
15767
158- let { buttonProps, isPressed } = useButton (
159- {
160- ...props ,
161- onPress : customOnPress ,
162- } ,
163- domRef ,
164- ) ;
165- let { hoverProps, isHovered } = useHover ( { isDisabled } ) ;
166- let { focusProps, isFocused } = useFocus ( { isDisabled } , true ) ;
167-
168- const customProps = to
169- ? {
170- onClick ( evt ) {
171- evt . preventDefault ( ) ;
172- } ,
173- }
174- : { } ;
68+ const styles = extractStyles ( props , STYLE_PROPS ) ;
17569
176- return (
177- < Element
178- mods = { {
179- hovered : isHovered && ! isDisabled ,
180- pressed : isPressed && ! isDisabled ,
181- focused : isFocused && ! isDisabled ,
182- disabled : isDisabled ,
183- ...mods ,
184- } }
185- aria-label = { label }
186- data-theme = { theme }
187- { ...mergeProps (
188- buttonProps ,
189- hoverProps ,
190- focusProps ,
191- customProps ,
192- filterBaseProps ( props , FILTER_OPTIONS ) ,
193- ) }
194- ref = { domRef }
195- type = { htmlType || 'button' }
196- rel = { as === 'a' && newTab ? 'rel="noopener noreferrer"' : undefined }
197- as = { as }
198- isDisabled = { isDisabled }
199- styles = { styles }
200- target = { target }
201- href = { href }
202- />
203- ) ;
70+ return < ActionElement data-theme = { theme } { ...actionProps } styles = { styles } /> ;
20471} ) ;
0 commit comments