overleaf/services/web/frontend/js/features/ui/components/ol/ol-button.tsx
Rebeka Dekany f8efc3e2ae Merge pull request #20740 from overleaf/rd-ide-offcanvas
[web] Implement the editor's left menu in Offcanvas

GitOrigin-RevId: 999e995d664b1dc958f56643f05e95b8aa2d6290
2024-10-14 11:09:31 +00:00

91 lines
3.1 KiB
TypeScript

import { forwardRef } from 'react'
import BootstrapVersionSwitcher from '../bootstrap-5/bootstrap-version-switcher'
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'
import Button from '../bootstrap-5/button'
import classnames from 'classnames'
import { getAriaAndDataProps } from '@/features/utils/bootstrap-5'
import { callFnsInSequence } from '@/utils/functions'
export type BS3ButtonSize = 'xsmall' | 'sm' | 'medium' | 'lg'
export type OLButtonProps = ButtonProps & {
bs3Props?: {
loading?: React.ReactNode
bsSize?: BS3ButtonSize
block?: boolean
className?: string
onMouseOver?: React.MouseEventHandler<HTMLButtonElement>
onMouseOut?: React.MouseEventHandler<HTMLButtonElement>
onFocus?: React.FocusEventHandler<HTMLButtonElement>
onBlur?: React.FocusEventHandler<HTMLButtonElement>
}
}
// Resolve type mismatch of the onClick event handler
export type BS3ButtonProps = Omit<BS3ButtonPropsBase, 'onClick'> & {
onClick?: React.MouseEventHandler<any>
}
export function bs3ButtonProps(props: ButtonProps) {
const bs3ButtonProps: BS3ButtonProps = {
bsStyle: null,
bsSize: props.size,
className: classnames(`btn-${props.variant || 'primary'}`, props.className),
disabled: props.isLoading || props.disabled,
form: props.form,
href: props.href,
id: props.id,
target: props.target,
rel: props.rel,
onClick: props.onClick,
onMouseDown: props.onMouseDown as BS3ButtonProps['onMouseDown'],
type: props.type,
draggable: props.draggable,
download: props.download,
style: props.style,
active: props.active,
}
return bs3ButtonProps
}
const OLButton = forwardRef<HTMLButtonElement, OLButtonProps>(
({ bs3Props = {}, ...rest }, ref) => {
const { className: _, ...restBs3Props } = bs3Props
// 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),
}
// Get all `aria-*` and `data-*` attributes
const extraProps = getAriaAndDataProps(rest)
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}
>
{bs3Props?.loading || rest.children}
</BS3Button>
}
bs5={<Button {...rest} ref={ref} />}
/>
)
}
)
OLButton.displayName = 'OLButton'
export default OLButton