import * as React from 'react' ; import { Interactive , createInteractive , InteractiveProps , InteractiveExtendableProps , InteractiveState , InteractiveStateChange , } from 'react-interactive' ; import { BrowserRouter , Link } from 'react-router-dom' ; import { styled } from '../stitches.config' ; const InteractiveNav = createInteractive ( 'nav' ) ; const InteractiveRouterLink = createInteractive ( Link ) ; export const DemoCreateInteractiveAs = ( ) => ( < > < Interactive . Button type = "submit" ref = { ( element ) => { } } hoverStyle = { { fontWeight : 'bold' } } > Interactive . Button < /Interactive.Button> < Interactive . A href = "https://rafgraph.dev" ref = { ( element ) => { } } hoverStyle = { { fontWeight : 'bold' } } > Interactive . A < /Interactive.A> < Interactive . Div ref = { ( element ) => { } } hoverStyle = { { fontWeight : 'bold' } } onStateChange = { ( { state , prevState } ) => { } } > Interactive . Div < /Interactive.Div> < InteractiveNav ref = { ( element ) => { } } hoverStyle = { { fontWeight : 'bold' } } onStateChange = { ( { state , prevState } ) => { } } > InteractiveNav < /InteractiveNav> < InteractiveRouterLink to = "/some-path" ref = { ( element ) => { } } hoverStyle = { { fontWeight : 'bold' } } onStateChange = { ( { state , prevState } ) => { } } > InteractiveRouterLink < /InteractiveRouterLink> < />); const DemoOnStateChangeAndChildren = ( ) => { const handleInteractiveStateChange = React . useCallback ( ( { state , prevState } ) => { } , [ ] ) ; const childrenAsAFunction = React . useCallback ( ( { hover , active , focus } ) => `Current state - active: ${ active }, hover: ${ hover }, focus: ${ focus }` , [ ] ) ; return ( < Interactive as = "button" onStateChange = { handleInteractiveStateChange } > { childrenAsAFunction } < /Interactive>); } ; const propsForInteractiveButton = { as : 'button' , type : 'submit' , children : 'propsForInteractiveButton' , ref : ( element ) => { } , hoverStyle : { fontWeight : 'bold' } , onStateChange : ( { state , prevState } ) => { } , } ; const propsForInteractiveRouterLink = { as : Link , to : '/some-path' , children : 'propsForInteractiveRouterLink' , ref : ( element ) => { } , hoverStyle : { fontWeight : 'bold' } , onStateChange : ( { state , prevState } ) => { } , } ; const DemoPropsForInteractive = ( ) => ( < > < Interactive { ... propsForInteractiveButton } / > < Interactive { ... propsForInteractiveRouterLink } / > < Interactive as = "button" type = "submit" ref = { ( element ) => { } } hoverStyle = { { fontWeight : 'bold' } } onStateChange = { ( { state , prevState } ) => { } } > Interactive - as - button < /Interactive> < Interactive as = { Link } to = "/some-path" ref = { ( element ) => { } } hoverStyle = { { fontWeight : 'bold' } } onStateChange = { ( { state , prevState } ) => { } } > Interactive - as - Link < /Interactive> < />); interface WrapAsTagNameProps extends InteractiveExtendableProps < 'button' > { additionalProp ? : string ; } const WrapAsTagNameWithoutRef = ( { additionalProp , ... props } ) => { return < Interactive { ... props } as = "button" / > ; } ; const WrapAsTagNameWithRef = React . forwardRef < HTMLButtonElement , WrapAsTagNameProps > ( ( { additionalProp , ... props } , ref ) => { return < Interactive { ... props } as = "button" ref = { ref } / > ; } ) ; type WrapAsTagNameWithRefProps = React . ComponentPropsWithRef < typeof WrapAsTagNameWithRef > ; const propsForWrapAsTagNameWithRef = { additionalProp : 'something' , children : 'propsForWrapAsTagNameWithRef' , ref : ( ) => { } , type : 'submit' , hoverStyle : { fontWeight : 'bold' } , } ; const DemoWrapAsTagName = ( ) => ( < > < WrapAsTagNameWithoutRef type = "submit" hoverStyle = { { fontWeight : 'bold' } } > WrapAsTagNameWithoutRef < /WrapAsTagNameWithoutRef> < WrapAsTagNameWithRef ref = { ( element ) => { } } type = "submit" hoverStyle = { { fontWeight : 'bold' } } > WrapAsTagNameWithRef < /WrapAsTagNameWithRef> < WrapAsTagNameWithRef { ... propsForWrapAsTagNameWithRef } /> < Interactive as = "button" ref = { { current : null } } type = "submit" hoverStyle = { { fontWeight : 'bold' } } > Interactive - as - button < /Interactive> < />); interface MyComponentProps extends React . ComponentPropsWithoutRef < 'button' > { someMyComponentProp ? : string ; } const MyComponent = React . forwardRef < HTMLButtonElement , MyComponentProps > ( ( { someMyComponentProp , ... props } , ref ) => { return < button { ... props } ref = { ref } / > ; } ) ; interface WrapAsComponentProps extends InteractiveExtendableProps < typeof MyComponent > { additionalProp ? : string ; } const WrapAsComponentWithoutRef = ( { additionalProp , ... props } ) => { return < Interactive { ... props } as = { MyComponent } />; } ; const WrapAsComponentWithRef = React . forwardRef < React . ElementRef < typeof MyComponent > , WrapAsComponentProps > ( ( { additionalProp , ... props } , ref ) => { return < Interactive { ... props } as = { MyComponent } ref = { ref } / > ; } ) ; type WrapAsComponentWithRefProps = React . ComponentPropsWithRef < typeof WrapAsComponentWithRef > ; const propsForWrapAsComponentWithRef = { additionalProp : 'something' , someMyComponentProp : 'something else' , children : 'propsForWrapAsTagNameWithRef' , ref : ( ) => { } , hoverStyle : { fontWeight : 'bold' } , } ; const DemoWrapAsComponent = ( ) => ( < > < WrapAsComponentWithoutRef additionalProp = "something" someMyComponentProp = "something else" hoverStyle = { { fontWeight : 'bold' } } > WrapAsComponentWithoutRef < /WrapAsComponentWithoutRef> < WrapAsComponentWithRef additionalProp = "something" someMyComponentProp = "something else" ref = { ( element ) => { } } hoverStyle = { { fontWeight : 'bold' } } > WrapAsComponentWithRef < /WrapAsComponentWithRef> < WrapAsComponentWithRef { ... propsForWrapAsComponentWithRef } /> < Interactive as = { MyComponent } someMyComponentProp = "something else" hoverStyle = { { fontWeight : 'bold' } } ref = { ( element ) => { } } > Interactive - as - MyComponent < /Interactive> < />); type WrapAsUnionProps = ( InteractiveExtendableProps < typeof Link > & { href ? : never ; } ) | ( InteractiveExtendableProps < 'a' > & { to ? : never ; replace ? : never ; } ) ; const WrapAsUnionWithRef = React . forwardRef < HTMLAnchorElement , WrapAsUnionProps > ( ( props , ref ) => { const As = props . to && ! props . disabled ? Link : 'a' ; let passThroughProps = props ; if ( props . disabled ) { const { to , replace , ... propsWithoutRouterProps } = props ; passThroughProps = propsWithoutRouterProps ; } return < Interactive { ... passThroughProps } as = { As } ref = { ref } / > ; } ) ; type WrapAsUnionWithRefProps = React . ComponentPropsWithRef < typeof WrapAsUnionWithRef > ; const propsForWrapAsUnionWithRef = { ref : ( element ) => { } , href : 'https://rafgraph.dev' , children : 'propsForWrapAsUnionWithRef' , hoverStyle : { fontWeight : 'bold' } , } ; const DemoWrapAsUnionWithRef = ( ) => ( < > < WrapAsUnionWithRef to = "/some-path" replace ref = { ( element ) => { } } hoverStyle = { { fontWeight : 'bold' } } > WrapAsUnionWithRef - RouterLink < /WrapAsUnionWithRef> < WrapAsUnionWithRef disabled to = "/some-path" replace ref = { ( element ) => { } } hoverStyle = { { fontWeight : 'bold' } } disabledStyle = { { opacity : 0.5 } } > WrapAsUnionWithRef - RouterLink - disabled < /WrapAsUnionWithRef> < WrapAsUnionWithRef href = "https://rafgraph.dev" ref = { ( element ) => { } } hoverStyle = { { fontWeight : 'bold' } } > WrapAsUnionWithRef - AnchorLink < /WrapAsUnionWithRef> < WrapAsUnionWithRef { ... propsForWrapAsUnionWithRef } /> < />); const ContainerDiv = styled ( 'div' , { '&>*' : { display : 'block' , } , '&>h1' : { fontSize : '20px' , } , } ) ; export const TypeScriptExamples = ( ) => ( < BrowserRouter > < ContainerDiv > < h1 > TypeScript Examples < /h1> < DemoCreateInteractiveAs / > < DemoOnStateChangeAndChildren /> < DemoPropsForInteractive / > < DemoWrapAsTagName /> < DemoWrapAsComponent / > < DemoWrapAsUnionWithRef /> < /ContainerDiv> < /BrowserRouter>);