@atlaskit/form
Version:
A form allows people to input information.
133 lines (125 loc) • 5.07 kB
JavaScript
/* character-counter-field.tsx generated by @compiled/babel-plugin v0.39.1 */
import "./character-counter-field.compiled.css";
import * as React from 'react';
import { ax, ix } from "@compiled/react/runtime";
import { Fragment } from 'react';
import CharacterCounter from './character-counter';
import Field from './field';
import { ErrorMessage, HelperMessage, MessageWrapper } from './messages';
// Override label specific margin block end to fix double spacing issue
const fieldWrapperStyles = {
root: "_14uxze3t"
};
// Override helper message margins to fix inconsistent spacing issue
const helperMessageWrapperStyles = {
root: "_6rth1b66 _6ul5ze3t"
};
/**
* __Character Counter Field__
*
* A field component that wraps the standard Field with automatic character count validation.
* Validates minimum and maximum character limits and displays a character counter.
*/
export default function CharacterCounterField({
maxCharacters,
minCharacters,
children,
validate: userValidate,
overMaximumMessage,
underMaximumMessage,
underMinimumMessage,
helperMessage,
defaultValue,
id,
isRequired,
isDisabled,
label,
elementAfterLabel,
name,
testId
}) {
// Default validation function for character limits
// __TOO_SHORT__ and __TOO_LONG__ are default error codes recognised by the CharacterCounter component
const validateCharacterCount = value => {
const stringValue = String(value || '');
const length = stringValue.length;
// Check minimum length
if (minCharacters !== undefined && length < minCharacters) {
return '__TOO_SHORT__';
}
// Check maximum length
if (maxCharacters !== undefined && length > maxCharacters) {
return '__TOO_LONG__';
}
return undefined;
};
// Combine user validation and character validation
// Any user defined validation takes priority over character validation
// If there is no user defined validation for character limits e.g. used maxLength prior to CharacterCounterField,
// use the default error codes and display the appropriate error message
const combinedValidate = (value, formState, fieldState) => {
// First run character validation
const characterError = validateCharacterCount(value);
// Then run user's custom validation if provided
const userError = userValidate === null || userValidate === void 0 ? void 0 : userValidate(value, formState, fieldState);
// If user validation returns a promise, handle it
if (userError instanceof Promise) {
return userError.then(error => {
// User error takes priority over character validation
return error || characterError;
});
}
// User error takes priority over character validation
return userError || characterError;
};
return /*#__PURE__*/React.createElement("div", {
className: ax([fieldWrapperStyles.root])
}, /*#__PURE__*/React.createElement(Field, {
defaultValue: defaultValue,
id: id,
isRequired: isRequired,
isDisabled: isDisabled,
label: label,
elementAfterLabel: elementAfterLabel,
name: name,
testId: testId,
validate: combinedValidate
}, ({
fieldProps: extendedFieldProps,
error,
valid,
meta
}) => {
// Determine if error is a character count violation (handled by CharacterCounter)
// or an external validation error (needs ErrorMessage)
const isCharacterCountViolation = error === '__TOO_SHORT__' || error === '__TOO_LONG__';
const showExternalError = error && !isCharacterCountViolation;
const showCharacterCounter = (maxCharacters !== undefined || minCharacters !== undefined) && !showExternalError;
// Extend aria-describedby to reference the appropriate message component
const fieldPropsWithCounter = {
...extendedFieldProps,
'aria-describedby': showCharacterCounter ? `${extendedFieldProps['aria-describedby']} ${extendedFieldProps.id}-character-counter`.trim() : extendedFieldProps['aria-describedby']
};
return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement(MessageWrapper, null, helperMessage && /*#__PURE__*/React.createElement("div", {
className: ax([helperMessageWrapperStyles.root])
}, /*#__PURE__*/React.createElement(HelperMessage, {
testId: `${testId}-helper`
}, helperMessage))), children({
fieldProps: fieldPropsWithCounter,
error,
valid,
meta
}), /*#__PURE__*/React.createElement(MessageWrapper, null, showExternalError && /*#__PURE__*/React.createElement(ErrorMessage, {
testId: `${testId}-error`
}, error)), showCharacterCounter && /*#__PURE__*/React.createElement(CharacterCounter, {
maxCharacters: maxCharacters,
minCharacters: minCharacters,
currentValue: String(extendedFieldProps.value || ''),
shouldShowAsError: isCharacterCountViolation,
overMaximumMessage: overMaximumMessage,
underMaximumMessage: underMaximumMessage,
underMinimumMessage: underMinimumMessage,
testId: `${testId}-character-counter`
}));
}));
}