UNPKG

@instructure/quiz-interactions

Version:

A React UI component Library for quiz interaction types.

178 lines (161 loc) • 5.68 kB
/** @jsx jsx */ import {Component} from 'react' import PropTypes from 'prop-types' import {IconButton} from '@instructure/ui-buttons' import {IconDragHandleLine} from '@instructure/ui-icons' import {ScreenReaderContent, PresentationContent} from '@instructure/ui-a11y-content' import {Text} from '@instructure/ui-text' import {jsx} from '@instructure/emotion' import {RichContentRenderer} from '@instructure/quiz-rce/components/RichContentRenderer/index' import Card from '../../../common/components/Card' import generateStyle from './styles' import generateComponentTheme from './theme' import t from '@instructure/quiz-i18n/format-message' import {v4 as uuid} from 'uuid' import {TextInput} from '@instructure/quiz-common/components/TextInput/index' import {withStyleOverrides} from '@instructure/quiz-common/util/withStyleOverrides' @withStyleOverrides(generateStyle, generateComponentTheme) export default class OrderGroup extends Component { static displayName = 'OrderGroup' static componentId = `Quizzes${this.displayName}` static propTypes = { bottomLabel: PropTypes.string, topLabel: PropTypes.string, choiceOrder: PropTypes.arrayOf(PropTypes.string).isRequired, choices: PropTypes.shape({ itemBody: RichContentRenderer.propTypes.content, }).isRequired, actionsContent: PropTypes.func, displayAnswersParagraph: PropTypes.bool, includeLabels: PropTypes.bool, onMoveChoice: PropTypes.func, readOnly: PropTypes.bool, styles: PropTypes.object, makeStyles: PropTypes.func, } static defaultProps = { bottomLabel: void 0, topLabel: void 0, actionsContent: void 0, displayAnswersParagraph: void 0, includeLabels: void 0, onMoveChoice: void 0, readOnly: false, } componentDidMount() { this.props.makeStyles() } componentDidUpdate() { this.props.makeStyles() } takeId = uuid() // =========== // RENDER // =========== renderActions = (choiceId, isFinalChoice, isFirstChoice, choicePosition) => { if (this.props.actionsContent) { return this.props.actionsContent(choiceId, isFinalChoice, isFirstChoice, choicePosition) } return ( // We need to wrap the button in a div for drag-and-drop to work in IE11 and Firefox <div> <IconButton size="small" withBackground={false} withBorder={false} readOnly={this.props.readOnly} renderIcon={IconDragHandleLine} screenReaderLabel={t('Reorder Choice')} /> </div> ) } renderChoice = (choiceId, index) => { const choicePosition = index + 1 const isFirstChoice = index === 0 const isFinalChoice = choicePosition === this.props.choiceOrder.length return ( <div key={choiceId} css={this.props.styles.choiceContainer} data-testid="choice-cointainer"> <div css={this.props.styles.choiceContainerContent}> {!this.props.displayAnswersParagraph && ( <div css={this.props.styles.choicePosition}> <ScreenReaderContent> {t('position {position, number}', {position: choicePosition})} </ScreenReaderContent> <PresentationContent> <Text color="primary">{t.number(choicePosition)}</Text> </PresentationContent> </div> )} <div css={this.props.styles.printedPositionInput}> <TextInput width="3rem" defaultValue={this.props.readOnly ? t.number(choicePosition) : ''} renderLabel="" readOnly /> </div> <div css={this.props.styles.choice} className="fs-mask"> {this.renderActions(choiceId, isFinalChoice, isFirstChoice, choicePosition)} <RichContentRenderer customStyles={this.props.styles.choiceBody} content={this.props.choices[choiceId.split('_')[0]].itemBody} /> </div> </div> </div> ) } renderChoicesContainer() { if (this.props.readOnly) { return ( <div css={this.props.styles.container}>{this.props.choiceOrder.map(this.renderChoice)}</div> ) } return ( <div css={this.props.styles.container}> {this.props.choiceOrder.map((choiceId, i) => { const id = `${choiceId}_${this.takeId}` return ( <Card key={choiceId} index={i} id={id} choices={this.props.choices} moveCard={this.props.onMoveChoice} > {this.renderChoice(id, i)} </Card> ) })} </div> ) } render() { return ( <div> {this.props.includeLabels && ( <div css={this.props.styles.topLabel} data-automation="sdk-ordering-toplabel"> <ScreenReaderContent> {t('Top label: {label}', {label: this.props.topLabel})} </ScreenReaderContent> <PresentationContent> <Text color="primary">{this.props.topLabel}</Text> </PresentationContent> </div> )} {this.renderChoicesContainer()} {this.props.includeLabels && ( <div css={this.props.styles.bottomLabel} data-automation="sdk-ordering-bottomlabel"> <ScreenReaderContent> {t('Bottom label: {label}', {label: this.props.bottomLabel})} </ScreenReaderContent> <PresentationContent> <Text color="primary">{this.props.bottomLabel}</Text> </PresentationContent> </div> )} </div> ) } }