@atlaskit/editor-plugin-media
Version:
Media plugin for @atlaskit/editor-core
170 lines (166 loc) • 5.5 kB
JavaScript
import _extends from "@babel/runtime/helpers/extends";
/** @jsx jsx */
import { useCallback, useEffect, useMemo, useState } from 'react';
import { jsx } from '@emotion/react';
import Button from '@atlaskit/button';
import Form, { Field } from '@atlaskit/form';
import Textfield from '@atlaskit/textfield';
import Tooltip from '@atlaskit/tooltip';
import { PIXELENTRY_MIGRATION_BUTTON_TESTID } from './constants';
import { messages } from './messages';
import { pixelEntryForm, pixelEntryHiddenSubmit, pixelSizingFullWidthLabelStyles, pixelSizingHeightInput, pixelSizingInput, pixelSizingLabel, pixelSizingWidthInput, pixelSizingWrapper } from './styles';
export const PixelEntry = ({
width,
mediaWidth,
mediaHeight,
onSubmit,
minWidth,
maxWidth,
onChange,
intl: {
formatMessage
},
showMigration,
onMigrate
}) => {
const ratioWidth = useMemo(() => {
return mediaHeight / mediaWidth;
}, [mediaHeight, mediaWidth]);
const ratioHeight = useMemo(() => {
return mediaWidth / mediaHeight;
}, [mediaHeight, mediaWidth]);
const [computedWidth, setComputedWidth] = useState(width);
const [computedHeight, setComputedHeight] = useState(Math.round(ratioWidth * width));
// Handle update to width from outside component
useEffect(() => {
setComputedWidth(width);
setComputedHeight(Math.round(ratioWidth * width));
}, [width, ratioWidth]);
// Handle submit when user presses enter in form
const handleOnSubmit = data => {
if (data.inputWidth === '' || data.inputHeight === '') {
return;
}
if (onSubmit) {
let widthToBeSumitted = data.inputWidth;
let validation = 'valid';
if (data.inputWidth < minWidth) {
widthToBeSumitted = minWidth;
validation = 'less-than-min';
}
if (data.inputWidth > maxWidth) {
widthToBeSumitted = maxWidth;
validation = 'greater-than-max';
}
// If user keeps submitting an invalid input, node width attribute will be updated with the same value
// and won't upadte the state in useEffect (since width is the same)
// Thus, we set the state here to always display the correct dimension
if (validation !== 'valid') {
setComputedWidth(widthToBeSumitted);
setComputedHeight(Math.round(ratioWidth * widthToBeSumitted));
}
onSubmit({
width: widthToBeSumitted,
validation
});
}
};
// Handle updating computed fields based on
const handleOnChange = useCallback(type => event => {
const value = parseInt(event.currentTarget.value);
const newInputValue = isNaN(value) ? '' : value;
let newWidth = '';
switch (type) {
case 'inputWidth':
{
newWidth = newInputValue;
setComputedWidth(newInputValue);
const newHeight = newInputValue !== '' ? Math.round(ratioWidth * newInputValue) : '';
setComputedHeight(newHeight);
break;
}
case 'inputHeight':
{
setComputedHeight(newInputValue);
newWidth = newInputValue !== '' ? Math.round(ratioHeight * newInputValue) : '';
setComputedWidth(newWidth);
break;
}
}
const isInvalidInputValid = newWidth !== '' && (newWidth < minWidth || newWidth > maxWidth);
onChange && onChange(isInvalidInputValid);
}, [minWidth, maxWidth, onChange, ratioWidth, ratioHeight]);
if (showMigration) {
return jsx(Tooltip, {
content: formatMessage(messages.migrationButtonTooltip)
}, jsx(Button, {
appearance: "warning",
spacing: "compact",
onClick: onMigrate,
testId: PIXELENTRY_MIGRATION_BUTTON_TESTID
}, formatMessage(messages.migrationButtonText)));
}
return jsx("div", {
css: pixelEntryForm
}, jsx(Form, {
onSubmit: handleOnSubmit
}, ({
formProps
}) => {
return jsx("form", formProps, jsx("div", {
css: pixelSizingWrapper
}, jsx(Field, {
key: "inputWidth",
name: "inputWidth",
defaultValue: computedWidth
}, ({
fieldProps
}) => jsx(Tooltip, {
hideTooltipOnMouseDown: true,
content: formatMessage(messages.inputWidthTooltip, {
maxWidth
}),
position: "top"
}, jsx(Textfield, _extends({}, fieldProps, {
css: [pixelSizingWidthInput, pixelSizingInput],
appearance: "none",
isCompact: true,
onChange: handleOnChange('inputWidth'),
pattern: "\\d*",
"aria-label": formatMessage(messages.inputWidthAriaLabel, {
maxWidth
})
})))), jsx("span", {
css: pixelSizingLabel
}, "x"), jsx(Field, {
key: "inputHeight",
name: "inputHeight",
defaultValue: computedHeight
}, ({
fieldProps
}) => jsx(Tooltip, {
hideTooltipOnMouseDown: true,
content: formatMessage(messages.inputHeightTooltip),
position: "top"
}, jsx(Textfield, _extends({}, fieldProps, {
css: [pixelSizingHeightInput, pixelSizingInput],
appearance: "none",
isCompact: true,
onChange: handleOnChange('inputHeight'),
pattern: "\\d*",
"aria-label": formatMessage(messages.inputHeightAriaLabel)
})))), jsx(Button, {
css: pixelEntryHiddenSubmit,
type: "submit"
}, formatMessage(messages.submitButtonText))));
}));
};
export const FullWidthDisplay = ({
intl: {
formatMessage
}
}) => {
return jsx("div", {
css: pixelSizingFullWidthLabelStyles
}, jsx("span", null, formatMessage(messages.fullWidthLabel)));
};