UNPKG

@instructure/canvas-rce

Version:

A component wrapping Canvas's usage of Tinymce

187 lines (186 loc) 6.72 kB
/* * Copyright (C) 2019 - present Instructure, Inc. * * This file is part of Canvas. * * Canvas is free software: you can redistribute it and/or modify it under * the terms of the GNU Affero General Public License as published by the Free * Software Foundation, version 3 of the License. * * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more * details. * * You should have received a copy of the GNU Affero General Public License along * with this program. If not, see <http://www.gnu.org/licenses/>. */ import React from 'react'; import { bool, func, number, shape, string, object } from 'prop-types'; import { ScreenReaderContent } from '@instructure/ui-a11y-content'; import { FormFieldGroup } from '@instructure/ui-form-field'; import { IconLockLine, IconWarningSolid } from '@instructure/ui-icons'; import { Flex } from '@instructure/ui-flex'; import { Text } from '@instructure/ui-text'; import { RadioInput, RadioInputGroup } from '@instructure/ui-radio-input'; import formatMessage from '../../../../format-message'; import DimensionInput from './DimensionInput'; export { default as useDimensionsState } from './useDimensionsState'; const errorMessage = message => { return /*#__PURE__*/React.createElement(Flex, { gap: "xx-small", alignItems: "center" }, /*#__PURE__*/React.createElement(IconWarningSolid, { color: "error" }), /*#__PURE__*/React.createElement(Text, { color: "danger", size: "small" }, message)); }; const getMessage = (dimensionsState, minWidth, minHeight, minPercentage) => { let result = { text: formatMessage('Aspect ratio will be preserved'), type: 'hint' }; if (dimensionsState.usePercentageUnits) { if (!dimensionsState.isNumeric) { result = { text: formatMessage('Percentage must be a number'), type: 'error' }; } else if (!dimensionsState.isAtLeastMinimums) { result = { text: formatMessage('Percentage must be at least {percentage}%', { percentage: minPercentage }), type: 'error' }; } } else if (!dimensionsState.isNumeric) { result = { text: formatMessage('Width and height must be numbers'), type: 'error' }; } else if (!dimensionsState.isAtLeastMinimums) { result = { text: formatMessage('Pixels must be at least {width} x {height}px', { width: minWidth, height: minHeight }), type: 'error' }; } return result; }; export default function DimensionsInput(props) { const { dimensionsState, minHeight, minWidth, minPercentage, hidePercentage, dimensionsRef } = props; const handleDimensionTypeChange = e => { dimensionsState.setUsePercentageUnits(e.target.value === 'percentage'); }; const message = getMessage(dimensionsState, minWidth, minHeight, minPercentage); const secondaryMessage = { ...message, text: '' }; const displayMessage = message => { if (!message) { return; } return /*#__PURE__*/React.createElement("div", { "data-testid": "message" }, message.type === 'error' ? errorMessage(message.text) : /*#__PURE__*/React.createElement(Text, { size: "small" }, message.text)); }; return /*#__PURE__*/React.createElement(Flex, { direction: "column" }, /*#__PURE__*/React.createElement(Flex.Item, { padding: "small" }, hidePercentage ? /*#__PURE__*/React.createElement(Text, { weight: "bold" }, formatMessage('Custom width and height (Pixels)')) : /*#__PURE__*/React.createElement(RadioInputGroup, { "data-testid": "dimension-type", name: "dimension-type", description: formatMessage('Dimension Type'), onChange: handleDimensionTypeChange, value: dimensionsState.usePercentageUnits ? 'percentage' : 'pixels' }, /*#__PURE__*/React.createElement(RadioInput, { label: formatMessage('Percentage'), value: "percentage" }), /*#__PURE__*/React.createElement(RadioInput, { label: formatMessage('Pixels'), value: "pixels" }))), /*#__PURE__*/React.createElement(Flex.Item, { padding: "small" }, /*#__PURE__*/React.createElement(FormFieldGroup, { description: /*#__PURE__*/React.createElement(ScreenReaderContent, null, formatMessage('Dimensions')) }, /*#__PURE__*/React.createElement(Flex, { alignItems: "start", direction: "row", "data-testid": "input-number-container" }, dimensionsState.usePercentageUnits ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Flex.Item, { shouldShrink: true, shouldGrow: true }, /*#__PURE__*/React.createElement(DimensionInput, { dimensionState: dimensionsState.percentageState, label: formatMessage('Percentage'), messages: [secondaryMessage], dimensionsRef: dimensionsRef })), /*#__PURE__*/React.createElement(Flex.Item, { padding: "x-small small" }, "%")) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Flex.Item, { shouldShrink: true }, /*#__PURE__*/React.createElement(DimensionInput, { dimensionState: dimensionsState.widthState, label: formatMessage('Width'), minValue: minWidth, messages: [secondaryMessage], dimensionsRef: dimensionsRef })), /*#__PURE__*/React.createElement(Flex.Item, { padding: "x-small small" }, /*#__PURE__*/React.createElement(IconLockLine, null)), /*#__PURE__*/React.createElement(Flex.Item, { shouldShrink: true }, /*#__PURE__*/React.createElement(DimensionInput, { dimensionState: dimensionsState.heightState, label: formatMessage('Height'), minValue: minHeight, messages: [secondaryMessage] }))))), displayMessage(message))); } DimensionsInput.propTypes = { dimensionsState: shape({ heightState: shape({ addOffset: func.isRequired, inputValue: string.isRequired, setInputValue: func.isRequired }).isRequired, isNumeric: bool.isRequired, usePercentageUnits: bool.isRequired, setUsePercentageUnits: func.isRequired, widthState: shape({ addOffset: func.isRequired, inputValue: string.isRequired, setInputValue: func.isRequired }).isRequired, percentageState: shape({ addOffset: func.isRequired, inputValue: string.isRequired, setInputValue: func.isRequired }).isRequired }), minHeight: number.isRequired, minWidth: number.isRequired, minPercentage: number.isRequired, hidePercentage: bool, dimensionsRef: object }; DimensionsInput.defaultProps = { hidePercentage: false };