UNPKG

@atlaskit/form

Version:

A form allows people to input information.

216 lines (210 loc) 8.35 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _typeof = require("@babel/runtime/helpers/typeof"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = exports.IsDisabledContext = exports.FormContext = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _react = _interopRequireWildcard(require("react")); var _finalForm = require("final-form"); var _finalFormFocus = _interopRequireDefault(require("final-form-focus")); var _set = _interopRequireDefault(require("lodash/set")); var _forwardRefWithGeneric = _interopRequireDefault(require("@atlaskit/ds-lib/forward-ref-with-generic")); var _mergeRefs = _interopRequireDefault(require("@atlaskit/ds-lib/merge-refs")); var _utils = require("./utils"); 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" != _typeof(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); } /** * __Form context__ * * A form context creates a context for the field values and allows them to be accessed by the children. */ var FormContext = exports.FormContext = /*#__PURE__*/(0, _react.createContext)({ registerField: function registerField() { return function () {}; }, getCurrentValue: function getCurrentValue() { return undefined; }, subscribe: function subscribe() { return function () {}; } }); /** * __Is disabled context__ * * An is disabled context creates the context for when a value is disabled. */ var IsDisabledContext = exports.IsDisabledContext = /*#__PURE__*/(0, _react.createContext)(false); var FormBase = function FormBase(props, ref) { var autocomplete = props.autocomplete, userProvidedFormProps = props.formProps, id = props.id, label = props.label, labelId = props.labelId, name = props.name, noValidate = props.noValidate, onSubmit = props.onSubmit, testId = props.testId, xcss = props.xcss; var formRef = (0, _react.useRef)(null); var onSubmitRef = (0, _react.useRef)(onSubmit); onSubmitRef.current = onSubmit; var _useState = (0, _react.useState)(function () { // Types here would break the existing API var finalForm = (0, _finalForm.createForm)({ onSubmit: function onSubmit() { return onSubmitRef.current.apply(onSubmitRef, arguments); }, destroyOnUnregister: true, initialValues: {}, mutators: { setDefaultValue: function setDefaultValue(_ref, state) { var _ref2 = (0, _slicedToArray2.default)(_ref, 2), name = _ref2[0], defaultValue = _ref2[1]; if (state.formState.initialValues) { var initialValues = state.formState.initialValues; var values = state.formState.values; var _value = name && typeof defaultValue === 'function' ? defaultValue(initialValues[name]) : defaultValue; (0, _set.default)(initialValues, name, _value); (0, _set.default)(values, name, _value); } } } }); (0, _finalFormFocus.default)(function () { return formRef.current ? Array.from(formRef.current.querySelectorAll('input')) : []; }, _utils.getFirstErrorField)(finalForm); return finalForm; }), _useState2 = (0, _slicedToArray2.default)(_useState, 1), form = _useState2[0]; var _useState3 = (0, _react.useState)({ dirty: false, submitting: false }), _useState4 = (0, _slicedToArray2.default)(_useState3, 2), state = _useState4[0], setState = _useState4[1]; (0, _react.useEffect)(function () { var unsubscribe = form.subscribe(function (_ref3) { var dirty = _ref3.dirty, submitting = _ref3.submitting; setState({ dirty: dirty, submitting: submitting }); }, { dirty: true, submitting: true }); return unsubscribe; }, [form]); var registerField = (0, _react.useCallback)(function (name, defaultValue, subscriber, subscription, config) { form.pauseValidation(); var unsubscribe = form.registerField(name, subscriber, subscription, config); form.mutators.setDefaultValue(name, defaultValue); form.resumeValidation(); return unsubscribe; }, [form]); var handleSubmit = function handleSubmit(e) { if (e) { e.preventDefault(); } form.submit(); }; var handleReset = function handleReset(initialValues) { form.reset(initialValues); }; var handleKeyDown = function handleKeyDown(e) { if (e.key === 'Enter' && (e.ctrlKey || e.metaKey) && formRef.current) { var submitButton = formRef.current.querySelector('button:not([type]), button[type="submit"], input[type="submit"]'); if (submitButton) { submitButton.click(); } e.preventDefault(); } }; var _props$isDisabled = props.isDisabled, isDisabled = _props$isDisabled === void 0 ? false : _props$isDisabled, children = props.children; var dirty = state.dirty, submitting = state.submitting; /** * This method is needed in FormContext to use it on the field level * to check the current value of the field in case of the component re-mounting. */ var getCurrentValue = (0, _react.useCallback)(function (name) { var formState = form.getState(); return (formState === null || formState === void 0 ? void 0 : formState.values[name]) || undefined; }, [form]); var FormContextValue = (0, _react.useMemo)(function () { return { registerField: registerField, getCurrentValue: getCurrentValue, subscribe: form.subscribe }; }, [registerField, getCurrentValue, form.subscribe]); var conditionalFormProps = { autocomplete: autocomplete, className: xcss, id: id, 'aria-label': label, 'aria-labelledby': labelId, name: name, noValidate: noValidate, 'data-testid': testId }; // Abstracting so we can use the same for both rendering patterns var formProps = { onKeyDown: handleKeyDown, onSubmit: handleSubmit, ref: ref ? (0, _mergeRefs.default)([ref, formRef]) : formRef }; // We don't want to add undefined values to the component Object.keys(conditionalFormProps).forEach(function (attr) { if (conditionalFormProps[attr] !== undefined) { formProps[attr] = conditionalFormProps[attr]; } }); var childrenContent = function () { if (typeof children === 'function') { var result = children.length > 0 ? children({ formProps: formProps, dirty: dirty, reset: handleReset, submitting: submitting, disabled: isDisabled, getState: function getState() { return form.getState(); }, getValues: function getValues() { return form.getState().values; }, setFieldValue: form.change, resetFieldState: form.resetFieldState }) : children(); return result === undefined ? null : result; } else { return /*#__PURE__*/_react.default.createElement("form", (0, _extends2.default)({}, formProps, userProvidedFormProps), children); } }(); return /*#__PURE__*/_react.default.createElement(FormContext.Provider, { value: FormContextValue }, /*#__PURE__*/_react.default.createElement(IsDisabledContext.Provider, { value: isDisabled }, childrenContent)); }; /** * __Form__ * * A form allows users to input information. * * - [Examples](https://atlassian.design/components/form/examples) * - [Code](https://atlassian.design/components/form/code) * - [Usage](https://atlassian.design/components/form/usage) */ var Form = (0, _forwardRefWithGeneric.default)(FormBase); var _default = exports.default = Form;