{"version":3,"file":"button.mjs","names":[],"sources":["../../../../package/common/button/button.tsx"],"sourcesContent":["import cx from 'classnames';\nimport { useRef, type ReactElement } from 'react';\n\nimport styles from './button.module.pcss';\nimport Loader from '../loader';\nimport { ButtonStyleType, ButtonSize, ButtonType } from './button.types';\nimport { ThemeColor } from '../themeProvider/color.types';\nimport type { ButtonProps } from './button.types';\nimport Ripple from '../ripple';\nimport type { RippleHandle } from '../ripple';\nimport { useComponentDefaults } from '../configProvider';\nimport { renderIcon } from '../utils/renderIcon';\nimport { ariaKeyshortcuts, formatHotkey } from '../hooks/useHotkeys';\nimport { toneProps, useToneCheck } from '../styles/tone';\nimport { useLinkClick } from '../utils/navigation';\n\nconst CLASS_BY_STYLE: Record<ButtonStyleType, string> = {\n  filled: styles.buttonStyleFilled,\n  light: styles.buttonStyleLight,\n  outlined: styles.buttonStyleOutlined,\n  plain: styles.buttonStylePlain,\n};\n\nconst CLASS_BY_SIZE: Record<ButtonSize, string> = {\n  small: styles.buttonSizeSmall,\n  medium: styles.buttonSizeMedium,\n  large: styles.buttonSizeLarge,\n  icon: styles.buttonSizeIcon,\n};\n\n// Ripple's own default is white, which vanishes on a transparent button over a light page.\nconst RIPPLE_BACKGROUND = 'color-mix(in srgb, currentcolor 20%, transparent)';\n\nfunction Button(props: ButtonProps): ReactElement {\n  const {\n    className,\n    style,\n    type = ButtonType.Button,\n    styleType = ButtonStyleType.Outlined,\n    color = ThemeColor.Primary,\n    size = ButtonSize.Medium,\n    children,\n    icon,\n    shortcut,\n    // The caller's own wins: it may list a second binding the hint leaves out.\n    'aria-keyshortcuts': keyshortcuts = ariaKeyshortcuts(shortcut),\n    isLoading = false,\n    disabled = false,\n    title = undefined,\n    classNames,\n    styles: slotStyles,\n    ...rest\n  } = useComponentDefaults('Button', props);\n\n  const rippleRef = useRef<RippleHandle>(null);\n  const followLink = useLinkClick();\n  const tone = toneProps(color);\n  useToneCheck('Button', [color]);\n  const isInactive = isLoading || disabled;\n\n  const rootProps = {\n    className: cx(\n      styles.button,\n      CLASS_BY_STYLE[styleType],\n      tone.className,\n      CLASS_BY_SIZE[size],\n      {\n        [styles.buttonLink]: rest.href !== undefined,\n        [styles.buttonNotAllowed]: isInactive,\n        [styles.buttonDisabled]: disabled,\n      },\n      className,\n    ),\n    style: { ...tone.style, ...style },\n    title,\n    'aria-keyshortcuts': keyshortcuts,\n  };\n\n  const content = (\n    <Ripple ref={rippleRef} className={styles.buttonRipple} disabled={isInactive} rippleBackground={RIPPLE_BACKGROUND}>\n      <div className={cx(styles.buttonBackground, classNames?.background)} style={slotStyles?.background}>\n        <div className={cx(styles.buttonContent, classNames?.content)} style={slotStyles?.content}>\n          {isLoading ? (\n            <div\n              className={cx(styles.buttonLoadingContainer, classNames?.loadingContainer)}\n              style={slotStyles?.loadingContainer}\n            >\n              <Loader size='1.2em' color={ThemeColor.Neutral} />\n            </div>\n          ) : null}\n          <div\n            className={cx(classNames?.label, {\n              [styles.buttonLoading]: isLoading,\n              [styles.buttonWithIcon]: !!icon,\n            })}\n            style={slotStyles?.label}\n          >\n            {icon ? renderIcon(icon) : null}\n            {shortcut ? (\n              // One inline run with the label, so the hint sits on its baseline: the icon's flex\n              // row would make the hint its own item and centre it instead.\n              <span>\n                {children}\n                {/* Out of the accessible name, which would read \"Save Ctrl+S\": aria-keyshortcuts says it. */}\n                <span\n                  aria-hidden\n                  className={cx(styles.buttonShortcut, classNames?.shortcut)}\n                  style={slotStyles?.shortcut}\n                >\n                  {formatHotkey(shortcut)}\n                </span>\n              </span>\n            ) : (\n              children\n            )}\n          </div>\n        </div>\n      </div>\n    </Ripple>\n  );\n\n  if (rest.href !== undefined) {\n    const { href, onClick, ref, ...anchorRest } = rest;\n    return (\n      <a\n        {...anchorRest}\n        {...rootProps}\n        // An <a> cannot be disabled. Without its href and tabIndex it leaves the tab order and goes\n        // nowhere, and the role keeps it announced as the link it is, dimmed.\n        {...(disabled ? { role: 'link', tabIndex: undefined } : { href })}\n        aria-disabled={isInactive || anchorRest['aria-disabled'] || undefined}\n        onClick={(event) => {\n          if (isInactive) {\n            event.preventDefault();\n            return;\n          }\n          if (event.detail === 0) rippleRef.current?.addRipple();\n          void onClick?.(event);\n          followLink(event);\n        }}\n        ref={ref}\n      >\n        {content}\n      </a>\n    );\n  }\n\n  const { onClick, ref, ...buttonRest } = rest;\n  return (\n    <button\n      {...buttonRest}\n      {...rootProps}\n      type={type}\n      // Loading is aria-disabled, not disabled, which would drop the keyboard focus mid-submit. The\n      // click is cancelled instead, which also stops the form it submits.\n      aria-disabled={isLoading || buttonRest['aria-disabled'] || undefined}\n      disabled={disabled}\n      onClick={(event) => {\n        if (isLoading) {\n          event.preventDefault();\n          return;\n        }\n        if (event.detail === 0) rippleRef.current?.addRipple();\n        return onClick?.(event);\n      }}\n      ref={ref}\n    >\n      {content}\n    </button>\n  );\n}\n\nButton.StyleType = ButtonStyleType;\nButton.Size = ButtonSize;\nButton.Type = ButtonType;\n\nexport default Button;\n"],"mappings":"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"}