ol-button.tsx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import { forwardRef } from 'react'
  2. import BootstrapVersionSwitcher from '../bootstrap-5/bootstrap-version-switcher'
  3. import { Button as BS3Button } from 'react-bootstrap'
  4. import type { ButtonProps } from '@/features/ui/components/types/button-props'
  5. import type { ButtonProps as BS3ButtonPropsBase } from 'react-bootstrap'
  6. import Button from '../bootstrap-5/button'
  7. import classnames from 'classnames'
  8. import { getAriaAndDataProps } from '@/features/utils/bootstrap-5'
  9. import { callFnsInSequence } from '@/utils/functions'
  10. export type BS3ButtonSize = 'xsmall' | 'sm' | 'medium' | 'lg'
  11. export type OLButtonProps = ButtonProps & {
  12. bs3Props?: {
  13. loading?: React.ReactNode
  14. bsSize?: BS3ButtonSize
  15. block?: boolean
  16. className?: string
  17. onMouseOver?: React.MouseEventHandler<HTMLButtonElement>
  18. onMouseOut?: React.MouseEventHandler<HTMLButtonElement>
  19. onFocus?: React.FocusEventHandler<HTMLButtonElement>
  20. onBlur?: React.FocusEventHandler<HTMLButtonElement>
  21. }
  22. }
  23. // Resolve type mismatch of the onClick event handler
  24. export type BS3ButtonProps = Omit<BS3ButtonPropsBase, 'onClick'> & {
  25. onClick?: React.MouseEventHandler<any>
  26. }
  27. export function bs3ButtonProps(props: ButtonProps) {
  28. const bs3ButtonProps: BS3ButtonProps = {
  29. bsStyle: null,
  30. bsSize: props.size,
  31. className: classnames(`btn-${props.variant || 'primary'}`, props.className),
  32. disabled: props.isLoading || props.disabled,
  33. form: props.form,
  34. href: props.href,
  35. target: props.target,
  36. rel: props.rel,
  37. onClick: props.onClick,
  38. onMouseDown: props.onMouseDown as BS3ButtonProps['onMouseDown'],
  39. type: props.type,
  40. draggable: props.draggable,
  41. download: props.download,
  42. style: props.style,
  43. active: props.active,
  44. }
  45. return bs3ButtonProps
  46. }
  47. const OLButton = forwardRef<HTMLButtonElement, OLButtonProps>(
  48. ({ bs3Props = {}, ...rest }, ref) => {
  49. const { className: _, ...restBs3Props } = bs3Props
  50. // BS3 OverlayTrigger automatically provides 'onMouseOver', 'onMouseOut', 'onFocus', 'onBlur' event handlers
  51. const bs3FinalProps = {
  52. ...restBs3Props,
  53. onMouseOver: callFnsInSequence(bs3Props?.onMouseOver, rest.onMouseOver),
  54. onMouseOut: callFnsInSequence(bs3Props?.onMouseOut, rest.onMouseOut),
  55. onFocus: callFnsInSequence(bs3Props?.onFocus, rest.onFocus),
  56. onBlur: callFnsInSequence(bs3Props?.onBlur, rest.onBlur),
  57. }
  58. // Get all `aria-*` and `data-*` attributes
  59. const extraProps = getAriaAndDataProps(rest)
  60. return (
  61. <BootstrapVersionSwitcher
  62. bs3={
  63. <BS3Button
  64. {...bs3ButtonProps({
  65. ...rest,
  66. // Override the `className` with bs3 specific className (if provided)
  67. className: bs3Props?.className ?? rest.className,
  68. })}
  69. {...extraProps}
  70. {...bs3FinalProps}
  71. ref={ref as React.LegacyRef<any> | undefined}
  72. >
  73. {bs3Props?.loading || rest.children}
  74. </BS3Button>
  75. }
  76. bs5={<Button {...rest} ref={ref} />}
  77. />
  78. )
  79. }
  80. )
  81. OLButton.displayName = 'OLButton'
  82. export default OLButton