UNPKG

@atlaskit/form

Version:

A form allows people to input information.

275 lines (265 loc) 13 kB
/* field.tsx generated by @compiled/babel-plugin v0.39.1 */ "use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof3 = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = Field; require("./field.compiled.css"); var _runtime = require("@compiled/react/runtime"); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _typeof2 = _interopRequireDefault(require("@babel/runtime/helpers/typeof")); var _react = _interopRequireWildcard(require("react")); var _useId = require("@atlaskit/ds-lib/use-id"); var _fieldIdContext = require("./field-id-context"); var _form = require("./form"); var _label = require("./label"); var _messages = require("./messages"); var _requiredAsterisk = _interopRequireDefault(require("./required-asterisk")); function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof3(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } var fieldWrapperStyles = null; function isEvent(event) { return Boolean(event && event.target); } function isFunction(x) { return typeof x === 'function'; } // Must be exported to satisfy error TS4023 from Jira builds // src/packages/servicedesk/virtual-agent/common/src/ui/base-text-field/index.tsx(10,14): // error TS4023: Exported variable `BaseTextField` has or is using name // `FieldComponentProps` from external module // `/opt/atlassian/pipelines/agent/build/jira/tsDist/@atlaskit__form/app/src/field` // but cannot be named. function usePreviousRef(current) { var ref = (0, _react.useRef)(current); // will be updated on the next render (0, _react.useEffect)(function () { ref.current = current; }); // return the existing current (pre render) return ref; } function isShallowEqual(previousValue, currentValue) { if (previousValue === currentValue) { return true; } // not checking functions if (typeof previousValue === 'function' && typeof currentValue === 'function') { return true; } if (Array.isArray(previousValue) && Array.isArray(currentValue)) { return JSON.stringify(previousValue) === JSON.stringify(currentValue); } if ((0, _typeof2.default)(previousValue) === 'object' && (0, _typeof2.default)(currentValue) === 'object') { return JSON.stringify(previousValue) === JSON.stringify(currentValue); } return false; } function Field(props) { var _getCurrentValue; var _props$children = props.children, children = _props$children === void 0 ? function () { return null; } : _props$children, component = props.component; var _useContext = (0, _react.useContext)(_form.FormContext), registerField = _useContext.registerField, getCurrentValue = _useContext.getCurrentValue; var isDisabled = (0, _react.useContext)(_form.IsDisabledContext) || props.isDisabled || false; var defaultValue = isFunction(props.defaultValue) ? props.defaultValue() : props.defaultValue; var latestPropsRef = usePreviousRef(props); /** * HACK: defaultValue can potentially be an array or object which cannot be * passed directly into a `useEffect` dependency array, since it will trigger * the hook every time. */ var isDefaultValueChanged = !isShallowEqual(latestPropsRef.current.defaultValue, props.defaultValue); var _useState = (0, _react.useState)({ fieldProps: { onChange: function onChange() {}, onBlur: function onBlur() {}, onFocus: function onFocus() {}, /* Previously, defaultValue was being set as undefined in Field.defaultProps, which * effectively made it an optional prop to external consumers of Field. However the * prop types defined defaultValue as required, so inside the component it was not * valid for defaultValue to be undefined. We need to suppress the error * after changing defaultValue to explicitly be an optional prop. * If default value has changed we are using new default value. * Otherwise we need to check if we already have value for this field * (because we are using changing key prop to re-run field level validation, and that * cause the component re-mounting) to not override the actual value with the default value. */ // @ts-ignore value: isDefaultValueChanged ? defaultValue : (_getCurrentValue = getCurrentValue(props.name)) !== null && _getCurrentValue !== void 0 ? _getCurrentValue : defaultValue }, error: undefined, valid: false, meta: { dirty: false, dirtySinceLastSubmit: false, touched: false, valid: false, validating: false, submitting: false, submitFailed: false, error: undefined, submitError: undefined } }), _useState2 = (0, _slicedToArray2.default)(_useState, 2), state = _useState2[0], setState = _useState2[1]; var latestStateRef = usePreviousRef(state); (0, _react.useEffect)(function () { function fieldStateToMeta() { var value = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; return { dirty: value.dirty || false, dirtySinceLastSubmit: value.dirtySinceLastSubmit || false, touched: value.touched || false, valid: value.valid || false, submitting: value.submitting || false, submitFailed: value.submitFailed || false, error: value.error, submitError: value.submitError, validating: !!value.validating }; } var unregister = registerField(latestPropsRef.current.name, /** * Similar as for setting initial state value. * Additionally we are checking if the default value is a function, * it is used in checkbox fields, where fields with same name and * defaultIsChecked should create array of values. In this situation we can't * override the default value on re-registering, but also we don't need to change * the key prop to re-run validation. */ // @ts-ignore isDefaultValueChanged || // @ts-ignore isFunction(latestPropsRef.current.defaultValue) ? latestPropsRef.current.defaultValue : latestStateRef.current.fieldProps.value, function (fieldState) { /** * Do not update dirtySinceLastSubmit until submission has finished. */ var modifiedDirtySinceLastSubmit = fieldState.submitting ? latestStateRef.current.meta.dirtySinceLastSubmit : fieldState.dirtySinceLastSubmit; /** * Do not update submitFailed until submission has finished. */ var modifiedSubmitFailed = fieldState.submitting ? latestStateRef.current.meta.submitFailed : fieldState.submitFailed; /** * Do not use submitError if the value has changed. */ var modifiedSubmitError = modifiedDirtySinceLastSubmit && latestPropsRef.current.validate ? undefined : fieldState.submitError; var modifiedError = modifiedSubmitError || (fieldState.touched || fieldState.dirty) && fieldState.error; /** * If there has been a submit error, then use logic in modifiedError to determine validity, * so we can determine when there is a submit error which we do not want to display * because the value has been changed. */ var modifiedValid = modifiedSubmitFailed ? modifiedError === undefined : fieldState.valid; function getTransform(eventOrValue, currentValue) { if (latestPropsRef.current.transform) { return latestPropsRef.current.transform(eventOrValue, currentValue); } if (isEvent(eventOrValue)) { var currentTarget = eventOrValue.currentTarget; if (currentTarget.type === 'checkbox') { if (currentTarget.checked) { return currentTarget.value || true; } return currentTarget.value ? undefined : false; } else if (currentTarget) { return currentTarget.value; } return; } else { return eventOrValue; } } setState({ fieldProps: { onChange: function onChange(e) { fieldState.change(getTransform(e, fieldState.value)); }, onBlur: fieldState.blur, onFocus: fieldState.focus, value: fieldState.value }, error: modifiedError || undefined, /** * The following parameters are optionally typed in final-form to indicate that not all parameters need * to be subscribed to. We cast them as booleans (using || false), since this is what they are semantically. */ valid: modifiedValid || false, meta: fieldStateToMeta(fieldState) }); }, { dirty: true, dirtySinceLastSubmit: true, touched: true, valid: true, submitting: true, submitFailed: true, value: true, error: true, submitError: true, validating: true }, { getValidator: function getValidator() { return function validate(value, formState, fieldState) { var supplied = latestPropsRef.current.validate; if (supplied && fieldState) { return supplied(value, formState, fieldStateToMeta(fieldState)); } }; } }); return unregister; }, [latestPropsRef, latestStateRef, registerField, props.name, props.isRequired, isDefaultValueChanged]); var uid = (0, _useId.useId)(); var fieldId = (0, _react.useMemo)(function () { return props.id ? props.id : "".concat(props.name, "-").concat(uid); }, [props.id, props.name, uid]); var getDescribedBy = function getDescribedBy() { var value = ''; if (state.error) { value += "".concat(fieldId, "-error "); } if (state.valid) { value += "".concat(fieldId, "-valid "); } return "".concat(value).concat(fieldId, "-helper"); }; var extendedFieldProps = _objectSpread(_objectSpread({}, state.fieldProps), {}, { name: props.name, isDisabled: isDisabled, isInvalid: Boolean(state.error), isRequired: Boolean(props.isRequired), 'aria-required': String(Boolean(props.isRequired)), 'aria-invalid': state.error ? 'true' : 'false', 'aria-describedby': getDescribedBy(), 'aria-labelledby': "".concat(fieldId, "-label"), id: fieldId }); return /*#__PURE__*/_react.default.createElement("div", { "data-testid": props.testId, className: (0, _runtime.ax)(["_1pfhu2gc"]) }, props.label && /*#__PURE__*/_react.default.createElement(_label.Label, { htmlFor: fieldId, id: "".concat(fieldId, "-label"), testId: props.testId && "".concat(props.testId, "--label") }, props.label, props.isRequired && /*#__PURE__*/_react.default.createElement(_requiredAsterisk.default, null), props.elementAfterLabel), /*#__PURE__*/_react.default.createElement(_fieldIdContext.FieldId.Provider, { value: fieldId }, component ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, component({ fieldProps: extendedFieldProps }), /*#__PURE__*/_react.default.createElement(_messages.MessageWrapper, null, props.helperMessage && /*#__PURE__*/_react.default.createElement(_messages.HelperMessage, null, props.helperMessage), state.error && /*#__PURE__*/_react.default.createElement(_messages.ErrorMessage, null, props.errorMessage || state.error), state.meta.touched && state.valid && props.validMessage && /*#__PURE__*/_react.default.createElement(_messages.ValidMessage, null, props.validMessage))) : children({ fieldProps: extendedFieldProps, error: state.error, valid: state.valid, meta: state.meta }))); }