Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
Size: Mime:
import React from 'react'
import {
  isFunction,
  isString,
  isReal,
  isStringOrNumber,
  EMPTY_OBJ,
  NO_OP,
} from 'exotic'
import {
  BaseButtonProps as Props,
  ButtonState as State,
  ButtonRole,
  BaseButtonStandardProps,
  AccessibleButtonAttributes,
  PassThroughAttributes,
} from './typings'
import { classes } from './fixture'

export function toIconOrderClassName(props: Props) {
  const { iconOrder } = props
  switch (iconOrder) {
    case 'left':
      return -1
    case 'right':
      return 10
    default:
      return iconOrder
  }
}
export function makeButtonState(props: Props): State {
  // const state = {
  //   isFocused: !!props.isFocused,
  //   isDisabled: !!props.is
  // }
  // handleBlur = event => {
  // }
  // handleFocus = event => {
  // }
}

/**
 * ========= group 1 =========
 */

// this.hasSnackbar === true
export function isAnimated(props: Props): boolean {
  return props.isAnimated === true || props.hasAnimation === true || props.shouldAnimate === true
}
export function isDisabled(props: Props): boolean {
  return props.states === 'disabled' || props.isDisabled
}
export function isSelected(props: Props, state?: State): boolean {
  return props.states === 'selected' || props.isSelected || state.isSelected
}
export function isFocused(props: Props, state?: State): boolean {
  return props.states === 'focused' || props.isFocused || state.isFocused
}
export function isResting(props: Props, state?: State): boolean {
  return props.states === 'resting' || props.isResting || state.isResting
}
export function isPushed(props: Props, state?: State): boolean {
  return props.states === 'pushed' || props.isPushed || state.isPushed
}
export function isCenter(props: Props): boolean {
  return Boolean(props.center || props.isCenter)
}
export function isLink(props: Props): boolean {
  return props.to !== undefined || props.isLink === true
}
export function isGhost(props: Props): boolean {
  return props.ghost || props.isGhost
}
export function isIconLeft(props: Props): boolean {
  return props.iconOrder === 'left' || !!props.iconOrder
}
export function isIconRight(props: Props): boolean {
  return props.iconOrder === 'right' || !!props.iconOrder
}

/**
 * @alias isSecondary
 * ^ (on a secondary button color......)
 *
 * @description makes it gray but not disabled, or less attention
 */
export function isLowPriority(props: Props): boolean {
  return props.isLowPriority
}
export function hasSnackbar(props: Props): boolean {
  return Boolean(
    props.snackbarText !== undefined ||
      props.snackbar !== undefined ||
      props.onSnackbarClose !== undefined ||
      props.onSnacbkarUndo !== undefined ||
      props.snackbarTimeout !== undefined
  )
}

export function toRemappedProps(props: Props, state: State = EMPTY_OBJ): BaseButtonStandardProps {
  return {
    isAnimated: isAnimated(props),
    isDisabled: isDisabled(props),
    isSelected: isSelected(props, state),
    isFocused: isFocused(props, state),
    isResting: isResting(props, state),
    isPushed: isPushed(props, state),
    isLowPriority: isLowPriority(props),
    isLink: isLink(props),
    isCenter: isCenter(props),
    isGhost: isGhost(props),
    hasSnackbar: hasSnackbar(props),

    // yagni icon top bottom center - but it's used in mobile menu
    isIconLeft: isIconLeft(props),
    isIconRight: isIconRight(props),

    // @todo this one is from the component...
    eventHandlers: props.eventHandlers,

    renderSnackbar: props.renderSnackbar,
    renderIconAndText: props.renderIconAndText,
    render: props.render,
  }
}

/**
 * @todo right, left... ?
 */
export function toButtonClassName(props: Props) {
  // const extendedClassName = this.extendedClassName || this.props.extendedClassName || ''
  const defaultClassName = props.defaultClassName || ''
  const className = props.className || ''
  const isSquare = props.isSquare
  const squareClass = isSquare ? classes.default : ''
  const states = props.states
  const iconOrder = props.iconOrder

  const dynamic = {
    // ...priority 1-3?
    // [classes.isHighPriority]: this.isHighPriority,
    [classes.isIconLeft]: iconOrder === 'left' || !!iconOrder,
    [classes.isIconRight]: iconOrder === 'right' || !!iconOrder,
    [classes.isGhost]: isGhost,
    [classes.isLowPriority]: isLowPriority,
    [classes.isSelected]: isSelected,
    [classes.isDisabled]: isDisabled,
    [classes.isFocused]: isFocused,
    [classes.isResting]: isResting,
    [classes.isPushed]: isPushed,
    [classes.center]: isCenter,
  }

  // 'button'  - messes  a lot
  // return toClassName(defaultClassName, squareClass, className, dynamic, extendedClassName)
  // return classnames(defaultClassName, className, this.props.class || '')
}

/**
 * ========= group 2 =========
 */

export function toRole(props: Props): ButtonRole {
  return isString(props.role) ? props.role : isLink(props) === true ? 'link' : 'button'
}

/**
 * @todo toIdentifier(this, 'button')
 */
export function toIdentifier(props: Props): string {
  return props.identifier || props.id
}

export function toChildren(props: Props): string {
  return props.text || props.value || props.children
}

export function toLabel(props: Props): string | any {
  // || humanize(props.className) || throw new Error()
  return props['aria-label'] || props.label || toChildren(props)
}

export function toTabIndex(props: Props): string | number {
  if (props.tabIndex !== undefined) {
    return props.tabIndex
  } else if (props.isPresentational === true) {
    /**
     * @example a list of images like on the carousell,
     *          you want to tab each image,
     *          not tab the navigation
     */
    return undefined
  } else {
    return '0'
  }
  // return '-1' ?
}

/**
 * @alias toFinalProps
 * @alias toPassThroughProps
 * @alias attributeProps
 */
function toPassThroughProps(props: Props): PassThroughAttributes {
  // style
  const { className, role, tabIndex } = toAttributes(props)

  const attributes: PassThroughAttributes = {
    className,
  }

  if (tabIndex !== undefined) {
    // attributes.style = style
  }
  if (tabIndex !== undefined) {
    attributes.tabIndex = tabIndex
  }
  if (props.onSubmit !== undefined) {
    attributes.onSubmit = props.onSubmit
  }
  // next will be <link
  if (role !== 'button') {
    attributes.role = role
  }

  return attributes
}

// unused
export function toStyles(props: Props) {
  if (isReal(props.styled)) {
    return props.styled
  } else if (isString(props.height) || isString(props.width)) {
    return {
      height: props.height,
      width: props.width,
    }
  } else {
    return {}
  }
}

// eslint-disable-next-line
export function toAttributes(props: Props, state: State) {
  // const text = renderText(props, state)

  // @todo !!!!!! but may not want to do it here
  // const value = renderIconAndText(props, state)

  return {
    ...props,
    ...toRemappedProps(props),
    // value,
    identifier: toIdentifier(props),
    children: toChildren(props),
    label: toLabel(props),
    hasSnackbar: hasSnackbar(props),
    tabIndex: toTabIndex(props),
    role: toRole(props),
    // className: toButtonClassName(props),
    // styles: toStyles(props, state),
  }
}

/**
 * @todo tabindex for -1 inside of expandable divs
 *
 * @todo aria-flowto for compare & modal
 * https://www.w3.org/TR/wai-aria/states_and_properties#aria-flowto
 *
 * @todo aria-controls
 * https://www.w3.org/TR/wai-aria/states_and_properties#aria-controls
 *
 * @todo aria-busy
 * https://www.w3.org/TR/wai-aria/states_and_properties#aria-busy
 */
export function toAccessibleAttributes(props: Props, state: State): AccessibleButtonAttributes {
  const label = toLabel(props)
  const role = toRole(props)

  const accessibleAttributes = {
    // @todo isToggle for toggle states
    // 'aria-label': this.label,

    // can use for controlledby and controls
    id: toIdentifier(props),

    // ignoring this because button type button...
    // 'role': this.role,
    // 'aria-active'
  }
  if (isString(label)) {
    accessibleAttributes['aria-label'] = label
  }
  if (role !== 'link') {
    accessibleAttributes['aria-pressed'] = state.isActive
  }

  // should be `qa`?
  if (isString(props.dataQa)) {
    accessibleAttributes['data-qa'] = props.dataQa
  }

  return accessibleAttributes
}