2024-10-08 10:22:13 -04:00
|
|
|
import { forwardRef } from 'react'
|
2024-05-15 10:31:00 -04:00
|
|
|
import BootstrapVersionSwitcher from '../bootstrap-5/bootstrap-version-switcher'
|
2024-04-16 11:06:42 -04:00
|
|
|
import { Button as BS3Button } from 'react-bootstrap'
|
|
|
|
import type { ButtonProps } from '@/features/ui/components/types/button-props'
|
|
|
|
import type { ButtonProps as BS3ButtonPropsBase } from 'react-bootstrap'
|
2024-05-15 10:31:00 -04:00
|
|
|
import Button from '../bootstrap-5/button'
|
2024-06-06 11:37:47 -04:00
|
|
|
import classnames from 'classnames'
|
2024-09-04 07:00:21 -04:00
|
|
|
import { getAriaAndDataProps } from '@/features/utils/bootstrap-5'
|
2024-10-08 10:22:13 -04:00
|
|
|
import { callFnsInSequence } from '@/utils/functions'
|
2024-10-16 06:50:32 -04:00
|
|
|
import Icon from '@/shared/components/icon'
|
|
|
|
|
2024-05-30 11:09:57 -04:00
|
|
|
export type BS3ButtonSize = 'xsmall' | 'sm' | 'medium' | 'lg'
|
|
|
|
|
2024-05-15 10:31:00 -04:00
|
|
|
export type OLButtonProps = ButtonProps & {
|
2024-04-16 11:06:42 -04:00
|
|
|
bs3Props?: {
|
|
|
|
loading?: React.ReactNode
|
2024-05-30 11:09:57 -04:00
|
|
|
bsSize?: BS3ButtonSize
|
2024-06-13 08:44:38 -04:00
|
|
|
block?: boolean
|
2024-09-30 04:11:26 -04:00
|
|
|
className?: string
|
2024-10-08 10:22:13 -04:00
|
|
|
onMouseOver?: React.MouseEventHandler<HTMLButtonElement>
|
|
|
|
onMouseOut?: React.MouseEventHandler<HTMLButtonElement>
|
|
|
|
onFocus?: React.FocusEventHandler<HTMLButtonElement>
|
|
|
|
onBlur?: React.FocusEventHandler<HTMLButtonElement>
|
2024-04-16 11:06:42 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Resolve type mismatch of the onClick event handler
|
|
|
|
export type BS3ButtonProps = Omit<BS3ButtonPropsBase, 'onClick'> & {
|
|
|
|
onClick?: React.MouseEventHandler<any>
|
|
|
|
}
|
|
|
|
|
2024-06-06 11:37:47 -04:00
|
|
|
export function bs3ButtonProps(props: ButtonProps) {
|
|
|
|
const bs3ButtonProps: BS3ButtonProps = {
|
|
|
|
bsStyle: null,
|
2024-10-08 10:22:13 -04:00
|
|
|
bsSize: props.size,
|
2024-06-06 11:37:47 -04:00
|
|
|
className: classnames(`btn-${props.variant || 'primary'}`, props.className),
|
|
|
|
disabled: props.isLoading || props.disabled,
|
|
|
|
form: props.form,
|
|
|
|
href: props.href,
|
2024-10-11 05:22:38 -04:00
|
|
|
id: props.id,
|
2024-06-20 08:18:22 -04:00
|
|
|
target: props.target,
|
|
|
|
rel: props.rel,
|
2024-06-06 11:37:47 -04:00
|
|
|
onClick: props.onClick,
|
2024-10-09 08:13:50 -04:00
|
|
|
onMouseDown: props.onMouseDown as BS3ButtonProps['onMouseDown'],
|
2024-06-06 11:37:47 -04:00
|
|
|
type: props.type,
|
2024-10-08 10:22:13 -04:00
|
|
|
draggable: props.draggable,
|
|
|
|
download: props.download,
|
|
|
|
style: props.style,
|
|
|
|
active: props.active,
|
2024-06-06 11:37:47 -04:00
|
|
|
}
|
|
|
|
return bs3ButtonProps
|
|
|
|
}
|
|
|
|
|
2024-10-16 06:50:32 -04:00
|
|
|
function BS3ButtonContent({
|
|
|
|
children,
|
|
|
|
leadingIcon,
|
|
|
|
trailingIcon,
|
|
|
|
}: {
|
|
|
|
children: React.ReactNode
|
|
|
|
leadingIcon: OLButtonProps['leadingIcon']
|
|
|
|
trailingIcon: OLButtonProps['trailingIcon']
|
|
|
|
}) {
|
|
|
|
const leadingIconComponent =
|
|
|
|
leadingIcon && typeof leadingIcon === 'string' ? (
|
|
|
|
<Icon type={leadingIcon} />
|
|
|
|
) : (
|
|
|
|
leadingIcon
|
|
|
|
)
|
|
|
|
|
|
|
|
const trailingIconComponent =
|
|
|
|
trailingIcon && typeof trailingIcon === 'string' ? (
|
|
|
|
<Icon type={trailingIcon} />
|
|
|
|
) : (
|
|
|
|
trailingIcon
|
|
|
|
)
|
|
|
|
|
|
|
|
return (
|
|
|
|
<>
|
|
|
|
{leadingIconComponent ? <>{leadingIconComponent} </> : null}
|
|
|
|
{children}
|
|
|
|
{trailingIconComponent ? <> {trailingIconComponent}</> : null}
|
|
|
|
</>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2024-10-08 10:22:13 -04:00
|
|
|
const OLButton = forwardRef<HTMLButtonElement, OLButtonProps>(
|
|
|
|
({ bs3Props = {}, ...rest }, ref) => {
|
|
|
|
const { className: _, ...restBs3Props } = bs3Props
|
2024-04-16 11:06:42 -04:00
|
|
|
|
2024-10-08 10:22:13 -04:00
|
|
|
// BS3 OverlayTrigger automatically provides 'onMouseOver', 'onMouseOut', 'onFocus', 'onBlur' event handlers
|
|
|
|
const bs3FinalProps = {
|
|
|
|
...restBs3Props,
|
|
|
|
onMouseOver: callFnsInSequence(bs3Props?.onMouseOver, rest.onMouseOver),
|
|
|
|
onMouseOut: callFnsInSequence(bs3Props?.onMouseOut, rest.onMouseOut),
|
|
|
|
onFocus: callFnsInSequence(bs3Props?.onFocus, rest.onFocus),
|
|
|
|
onBlur: callFnsInSequence(bs3Props?.onBlur, rest.onBlur),
|
|
|
|
}
|
2024-04-16 11:06:42 -04:00
|
|
|
|
2024-10-08 10:22:13 -04:00
|
|
|
// Get all `aria-*` and `data-*` attributes
|
|
|
|
const extraProps = getAriaAndDataProps(rest)
|
2024-09-04 07:00:21 -04:00
|
|
|
|
2024-10-08 10:22:13 -04:00
|
|
|
return (
|
|
|
|
<BootstrapVersionSwitcher
|
|
|
|
bs3={
|
|
|
|
<BS3Button
|
|
|
|
{...bs3ButtonProps({
|
|
|
|
...rest,
|
|
|
|
// Override the `className` with bs3 specific className (if provided)
|
|
|
|
className: bs3Props?.className ?? rest.className,
|
|
|
|
})}
|
|
|
|
{...extraProps}
|
|
|
|
{...bs3FinalProps}
|
|
|
|
ref={ref as React.LegacyRef<any> | undefined}
|
|
|
|
>
|
2024-10-16 06:50:32 -04:00
|
|
|
{bs3Props?.loading || (
|
|
|
|
<BS3ButtonContent
|
|
|
|
leadingIcon={rest.leadingIcon}
|
|
|
|
trailingIcon={rest.trailingIcon}
|
|
|
|
>
|
|
|
|
{rest.children}
|
|
|
|
</BS3ButtonContent>
|
|
|
|
)}
|
2024-10-08 10:22:13 -04:00
|
|
|
</BS3Button>
|
|
|
|
}
|
|
|
|
bs5={<Button {...rest} ref={ref} />}
|
|
|
|
/>
|
|
|
|
)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
OLButton.displayName = 'OLButton'
|
|
|
|
|
|
|
|
export default OLButton
|