@atlaskit/form 8.3.1 → 8.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/CheckboxField/package.json +4 -4
- package/Field/package.json +4 -4
- package/Fieldset/package.json +4 -4
- package/Form/package.json +4 -4
- package/FormFooter/package.json +4 -4
- package/FormHeader/package.json +4 -4
- package/FormSection/package.json +4 -4
- package/Messages/package.json +4 -4
- package/RangeField/package.json +4 -4
- package/dist/cjs/{CheckboxField.js → checkbox-field.js} +12 -3
- package/dist/cjs/entry-points/checkbox-field.js +15 -0
- package/dist/cjs/entry-points/field.js +15 -0
- package/dist/cjs/entry-points/fieldset.js +15 -0
- package/dist/cjs/entry-points/form-footer.js +15 -0
- package/dist/cjs/entry-points/form-header.js +15 -0
- package/dist/cjs/entry-points/form-section.js +15 -0
- package/dist/cjs/entry-points/form.js +15 -0
- package/dist/cjs/entry-points/messages.js +25 -0
- package/dist/cjs/entry-points/range-field.js +15 -0
- package/dist/cjs/{Field.js → field.js} +80 -15
- package/dist/cjs/fieldset.js +72 -0
- package/dist/cjs/form-footer.js +39 -0
- package/dist/cjs/form-header.js +107 -0
- package/dist/cjs/form-section.js +93 -0
- package/dist/cjs/{Form.js → form.js} +11 -0
- package/dist/cjs/index.js +20 -20
- package/dist/cjs/messages.js +157 -0
- package/dist/cjs/{RangeField.js → range-field.js} +11 -2
- package/dist/cjs/version.json +1 -1
- package/dist/es2019/{CheckboxField.js → checkbox-field.js} +10 -1
- package/dist/es2019/entry-points/checkbox-field.js +1 -0
- package/dist/es2019/entry-points/field.js +1 -0
- package/dist/es2019/entry-points/fieldset.js +1 -0
- package/dist/es2019/entry-points/form-footer.js +1 -0
- package/dist/es2019/entry-points/form-header.js +1 -0
- package/dist/es2019/entry-points/form-section.js +1 -0
- package/dist/es2019/entry-points/form.js +1 -0
- package/dist/es2019/entry-points/messages.js +1 -0
- package/dist/es2019/entry-points/range-field.js +1 -0
- package/dist/es2019/{Field.js → field.js} +73 -13
- package/dist/es2019/fieldset.js +61 -0
- package/dist/es2019/form-footer.js +30 -0
- package/dist/es2019/form-header.js +94 -0
- package/dist/es2019/form-section.js +81 -0
- package/dist/es2019/{Form.js → form.js} +12 -0
- package/dist/es2019/index.js +9 -9
- package/dist/es2019/messages.js +122 -0
- package/dist/es2019/{RangeField.js → range-field.js} +10 -1
- package/dist/es2019/version.json +1 -1
- package/dist/esm/{CheckboxField.js → checkbox-field.js} +10 -1
- package/dist/esm/entry-points/checkbox-field.js +1 -0
- package/dist/esm/entry-points/field.js +1 -0
- package/dist/esm/entry-points/fieldset.js +1 -0
- package/dist/esm/entry-points/form-footer.js +1 -0
- package/dist/esm/entry-points/form-header.js +1 -0
- package/dist/esm/entry-points/form-section.js +1 -0
- package/dist/esm/entry-points/form.js +1 -0
- package/dist/esm/entry-points/messages.js +1 -0
- package/dist/esm/entry-points/range-field.js +1 -0
- package/dist/esm/{Field.js → field.js} +73 -13
- package/dist/esm/fieldset.js +60 -0
- package/dist/esm/form-footer.js +30 -0
- package/dist/esm/form-header.js +90 -0
- package/dist/esm/form-section.js +78 -0
- package/dist/esm/{Form.js → form.js} +12 -0
- package/dist/esm/index.js +9 -9
- package/dist/esm/messages.js +130 -0
- package/dist/esm/{RangeField.js → range-field.js} +11 -2
- package/dist/esm/version.json +1 -1
- package/dist/types/checkbox-field.d.ts +51 -0
- package/dist/types/entry-points/checkbox-field.d.ts +2 -0
- package/dist/types/entry-points/field.d.ts +2 -0
- package/dist/types/entry-points/fieldset.d.ts +1 -0
- package/dist/types/entry-points/form-footer.d.ts +1 -0
- package/dist/types/entry-points/form-header.d.ts +1 -0
- package/dist/types/entry-points/form-section.d.ts +1 -0
- package/dist/types/entry-points/form.d.ts +1 -0
- package/dist/types/entry-points/messages.d.ts +1 -0
- package/dist/types/entry-points/range-field.d.ts +2 -0
- package/dist/types/field.d.ts +78 -0
- package/dist/types/fieldset.d.ts +24 -0
- package/dist/types/form-footer.d.ts +23 -0
- package/dist/types/form-header.d.ts +32 -0
- package/dist/types/form-section.d.ts +28 -0
- package/dist/types/{Form.d.ts → form.d.ts} +23 -1
- package/dist/types/index.d.ts +13 -13
- package/dist/types/messages.d.ts +48 -0
- package/dist/types/range-field.d.ts +41 -0
- package/extract-react-types/checkbox-field-props.tsx +1 -1
- package/extract-react-types/field-props.tsx +5 -0
- package/extract-react-types/fieldset-props.tsx +5 -0
- package/extract-react-types/form-footer-props.tsx +5 -0
- package/extract-react-types/form-header-props.tsx +5 -0
- package/extract-react-types/form-props.tsx +5 -0
- package/extract-react-types/form-section-props.tsx +5 -0
- package/extract-react-types/range-field-props.tsx +1 -1
- package/package.json +30 -13
- package/dist/cjs/Fieldset.js +0 -32
- package/dist/cjs/FormFooter.js +0 -63
- package/dist/cjs/FormHeader.js +0 -57
- package/dist/cjs/FormSection.js +0 -57
- package/dist/cjs/Messages.js +0 -91
- package/dist/cjs/styled/Field.js +0 -41
- package/dist/cjs/styled/FormFooter.js +0 -25
- package/dist/cjs/styled/FormHeader.js +0 -49
- package/dist/cjs/styled/FormSection.js +0 -41
- package/dist/es2019/Fieldset.js +0 -14
- package/dist/es2019/FormFooter.js +0 -19
- package/dist/es2019/FormHeader.js +0 -13
- package/dist/es2019/FormSection.js +0 -13
- package/dist/es2019/Messages.js +0 -60
- package/dist/es2019/styled/Field.js +0 -29
- package/dist/es2019/styled/FormFooter.js +0 -11
- package/dist/es2019/styled/FormHeader.js +0 -40
- package/dist/es2019/styled/FormSection.js +0 -32
- package/dist/esm/Fieldset.js +0 -15
- package/dist/esm/FormFooter.js +0 -45
- package/dist/esm/FormHeader.js +0 -39
- package/dist/esm/FormSection.js +0 -39
- package/dist/esm/Messages.js +0 -63
- package/dist/esm/styled/Field.js +0 -21
- package/dist/esm/styled/FormFooter.js +0 -13
- package/dist/esm/styled/FormHeader.js +0 -29
- package/dist/esm/styled/FormSection.js +0 -24
- package/dist/types/CheckboxField.d.ts +0 -21
- package/dist/types/Field.d.ts +0 -45
- package/dist/types/Fieldset.d.ts +0 -7
- package/dist/types/FormFooter.d.ts +0 -15
- package/dist/types/FormHeader.d.ts +0 -13
- package/dist/types/FormSection.d.ts +0 -13
- package/dist/types/Messages.d.ts +0 -14
- package/dist/types/RangeField.d.ts +0 -17
- package/dist/types/styled/Field.d.ts +0 -11
- package/dist/types/styled/FormFooter.d.ts +0 -9
- package/dist/types/styled/FormHeader.d.ts +0 -19
- package/dist/types/styled/FormSection.d.ts +0 -15
- package/types/package.json +0 -7
|
@@ -1,8 +1,56 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
1
2
|
import React, { useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
+
import { css, jsx } from '@emotion/core';
|
|
2
4
|
import { uid } from 'react-uid';
|
|
3
5
|
import invariant from 'tiny-invariant';
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
+
import { R400 } from '@atlaskit/theme/colors';
|
|
7
|
+
import { useGlobalTheme } from '@atlaskit/theme/components';
|
|
8
|
+
import { fontFamily as getFontFamily, gridSize as getGridSize } from '@atlaskit/theme/constants';
|
|
9
|
+
import { h200 } from '@atlaskit/theme/typography';
|
|
10
|
+
import { token } from '@atlaskit/tokens';
|
|
11
|
+
import { FormContext, IsDisabledContext } from './form';
|
|
12
|
+
const gridSize = getGridSize();
|
|
13
|
+
const fontFamily = getFontFamily();
|
|
14
|
+
const fieldWrapperStyles = css({
|
|
15
|
+
marginTop: `${gridSize}px`
|
|
16
|
+
});
|
|
17
|
+
const labelStyles = css({
|
|
18
|
+
display: 'inline-block',
|
|
19
|
+
marginTop: 0,
|
|
20
|
+
marginBottom: `${gridSize * 0.5}px`,
|
|
21
|
+
fontFamily: `${fontFamily}`
|
|
22
|
+
});
|
|
23
|
+
const requiredIndicatorStyles = css({
|
|
24
|
+
paddingLeft: `${gridSize * 0.25}px`,
|
|
25
|
+
color: `${token('color.text.danger', R400)}`,
|
|
26
|
+
fontFamily: `${fontFamily}`
|
|
27
|
+
}); // eslint-disable-next-line @repo/internal/react/consistent-css-prop-usage
|
|
28
|
+
|
|
29
|
+
const lightH200Styles = css(h200({
|
|
30
|
+
theme: {
|
|
31
|
+
mode: 'light'
|
|
32
|
+
}
|
|
33
|
+
})); // eslint-disable-next-line @repo/internal/react/consistent-css-prop-usage
|
|
34
|
+
|
|
35
|
+
const darkH200Styles = css(h200({
|
|
36
|
+
theme: {
|
|
37
|
+
mode: 'dark'
|
|
38
|
+
}
|
|
39
|
+
}));
|
|
40
|
+
|
|
41
|
+
const Label = ({
|
|
42
|
+
children,
|
|
43
|
+
fieldId
|
|
44
|
+
}) => {
|
|
45
|
+
const {
|
|
46
|
+
mode
|
|
47
|
+
} = useGlobalTheme();
|
|
48
|
+
return jsx("label", {
|
|
49
|
+
css: [mode === 'light' ? lightH200Styles : darkH200Styles, labelStyles],
|
|
50
|
+
id: `${fieldId}-label`,
|
|
51
|
+
htmlFor: fieldId
|
|
52
|
+
}, children);
|
|
53
|
+
};
|
|
6
54
|
|
|
7
55
|
function isEvent(event) {
|
|
8
56
|
return Boolean(event && event.target);
|
|
@@ -12,8 +60,11 @@ function isFunction(x) {
|
|
|
12
60
|
return typeof x === 'function';
|
|
13
61
|
}
|
|
14
62
|
|
|
15
|
-
|
|
16
|
-
|
|
63
|
+
/**
|
|
64
|
+
* __Field id__
|
|
65
|
+
*
|
|
66
|
+
* A field id uses the context API. It provides the id of the field to message components. This links the message with the field of screenreaders.
|
|
67
|
+
*/
|
|
17
68
|
export const FieldId = /*#__PURE__*/React.createContext(undefined);
|
|
18
69
|
|
|
19
70
|
function usePreviousRef(current) {
|
|
@@ -110,12 +161,18 @@ export default function Field(props) {
|
|
|
110
161
|
|
|
111
162
|
const unregister = registerField(latestPropsRef.current.name, // @ts-ignore
|
|
112
163
|
latestPropsRef.current.defaultValue, fieldState => {
|
|
113
|
-
/**
|
|
164
|
+
/**
|
|
165
|
+
* Do not update dirtySinceLastSubmit until submission has finished.
|
|
166
|
+
*/
|
|
114
167
|
const modifiedDirtySinceLastSubmit = fieldState.submitting ? latestStateRef.current.meta.dirtySinceLastSubmit : fieldState.dirtySinceLastSubmit;
|
|
115
|
-
/**
|
|
168
|
+
/**
|
|
169
|
+
* Do not update submitFailed until submission has finished.
|
|
170
|
+
*/
|
|
116
171
|
|
|
117
172
|
const modifiedSubmitFailed = fieldState.submitting ? latestStateRef.current.meta.submitFailed : fieldState.submitFailed;
|
|
118
|
-
/**
|
|
173
|
+
/**
|
|
174
|
+
* Do not use submitError if the value has changed.
|
|
175
|
+
*/
|
|
119
176
|
|
|
120
177
|
const modifiedSubmitError = modifiedDirtySinceLastSubmit && latestPropsRef.current.validate ? undefined : fieldState.submitError;
|
|
121
178
|
const modifiedError = modifiedSubmitError || (fieldState.touched || fieldState.dirty) && fieldState.error;
|
|
@@ -192,7 +249,8 @@ export default function Field(props) {
|
|
|
192
249
|
});
|
|
193
250
|
return unregister;
|
|
194
251
|
}, [latestPropsRef, latestStateRef, registerField, props.name, hasDefaultValueChanged]);
|
|
195
|
-
const fieldId = useMemo(
|
|
252
|
+
const fieldId = useMemo( // eslint-disable-next-line @repo/internal/react/disallow-unstable-values
|
|
253
|
+
() => props.id ? props.id : `${props.name}-${uid({
|
|
196
254
|
id: props.name
|
|
197
255
|
})}`, [props.id, props.name]);
|
|
198
256
|
const extendedFieldProps = { ...state.fieldProps,
|
|
@@ -204,12 +262,14 @@ export default function Field(props) {
|
|
|
204
262
|
'aria-labelledby': `${fieldId}-label ${fieldId}-helper ${fieldId}-valid ${fieldId}-error`,
|
|
205
263
|
id: fieldId
|
|
206
264
|
};
|
|
207
|
-
return
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
265
|
+
return jsx("div", {
|
|
266
|
+
css: fieldWrapperStyles
|
|
267
|
+
}, props.label && jsx(Label, {
|
|
268
|
+
fieldId: fieldId
|
|
269
|
+
}, props.label, props.isRequired && jsx("span", {
|
|
270
|
+
css: requiredIndicatorStyles,
|
|
211
271
|
"aria-hidden": "true"
|
|
212
|
-
}, "*")),
|
|
272
|
+
}, "*")), jsx(FieldId.Provider, {
|
|
213
273
|
value: fieldId
|
|
214
274
|
}, props.children({
|
|
215
275
|
fieldProps: extendedFieldProps,
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import { css, jsx } from '@emotion/core';
|
|
3
|
+
import { useGlobalTheme } from '@atlaskit/theme/components';
|
|
4
|
+
import { fontFamily as getFontFamily, gridSize as getGridSize } from '@atlaskit/theme/constants';
|
|
5
|
+
import { h200 } from '@atlaskit/theme/typography';
|
|
6
|
+
const fontFamily = getFontFamily();
|
|
7
|
+
const gridSize = getGridSize();
|
|
8
|
+
const fieldsetLabelStyles = css({
|
|
9
|
+
display: 'inline-block',
|
|
10
|
+
marginTop: 0,
|
|
11
|
+
marginBottom: 0,
|
|
12
|
+
fontFamily: `${fontFamily}`
|
|
13
|
+
});
|
|
14
|
+
const fieldSetStyles = css({
|
|
15
|
+
marginTop: `${gridSize}px`
|
|
16
|
+
}); // eslint-disable-next-line @repo/internal/react/consistent-css-prop-usage
|
|
17
|
+
|
|
18
|
+
const lightH200Styles = css(h200({
|
|
19
|
+
theme: {
|
|
20
|
+
mode: 'light'
|
|
21
|
+
}
|
|
22
|
+
})); // eslint-disable-next-line @repo/internal/react/consistent-css-prop-usage
|
|
23
|
+
|
|
24
|
+
const darkH200Styles = css(h200({
|
|
25
|
+
theme: {
|
|
26
|
+
mode: 'dark'
|
|
27
|
+
}
|
|
28
|
+
}));
|
|
29
|
+
|
|
30
|
+
const FieldsetLabel = ({
|
|
31
|
+
children
|
|
32
|
+
}) => {
|
|
33
|
+
const {
|
|
34
|
+
mode
|
|
35
|
+
} = useGlobalTheme();
|
|
36
|
+
return jsx("label", {
|
|
37
|
+
css: [mode === 'light' ? lightH200Styles : darkH200Styles, fieldsetLabelStyles]
|
|
38
|
+
}, children);
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* __Fieldset__
|
|
42
|
+
*
|
|
43
|
+
* A fieldset groups a number of fields together. For example, when multiple CheckboxFields share the same name,
|
|
44
|
+
* a fieldset can be used to group them together. This makes the form more accessible.
|
|
45
|
+
*
|
|
46
|
+
* - [Examples](https://atlaskit.atlassian.com/packages/design-system/form/docs/fields)
|
|
47
|
+
* - [Code](https://atlaskit.atlassian.com/packages/design-system/form/docs/fields)
|
|
48
|
+
* - [Usage](https://atlaskit.atlassian.com/packages/design-system/form/docs/fields)
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
const Fieldset = ({
|
|
53
|
+
children,
|
|
54
|
+
legend
|
|
55
|
+
}) => {
|
|
56
|
+
return jsx("fieldset", {
|
|
57
|
+
css: fieldSetStyles
|
|
58
|
+
}, legend && jsx("legend", null, jsx(FieldsetLabel, null, legend)), children);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export default Fieldset;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import { css, jsx } from '@emotion/core';
|
|
3
|
+
import { gridSize as getGridSize } from '@atlaskit/theme/constants';
|
|
4
|
+
const gridSize = getGridSize();
|
|
5
|
+
const formFooterWrapperStyles = css({
|
|
6
|
+
display: 'flex',
|
|
7
|
+
marginTop: `${gridSize * 3}px`,
|
|
8
|
+
justifyContent: 'flex-end'
|
|
9
|
+
});
|
|
10
|
+
const justifyContentStyles = css({
|
|
11
|
+
justifyContent: 'flex-start'
|
|
12
|
+
});
|
|
13
|
+
/**
|
|
14
|
+
* __Form footer__
|
|
15
|
+
*
|
|
16
|
+
* A form footer has the content to be shown at the bottom of the form. This is usually the submit button.
|
|
17
|
+
*
|
|
18
|
+
* - [Examples](https://atlaskit.atlassian.com/packages/design-system/form/docs/layout)
|
|
19
|
+
* - [Code](https://atlaskit.atlassian.com/packages/design-system/form/docs/layout)
|
|
20
|
+
* - [Usage](https://atlaskit.atlassian.com/packages/design-system/form/docs/layout)
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
export default function FormFooter({
|
|
24
|
+
align = 'end',
|
|
25
|
+
children
|
|
26
|
+
}) {
|
|
27
|
+
return jsx("footer", {
|
|
28
|
+
css: [formFooterWrapperStyles, align === 'start' && justifyContentStyles]
|
|
29
|
+
}, children);
|
|
30
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import { css, jsx } from '@emotion/core';
|
|
3
|
+
import { useGlobalTheme } from '@atlaskit/theme/components';
|
|
4
|
+
import { fontFamily as getFontFamily, gridSize as getGridSize } from '@atlaskit/theme/constants';
|
|
5
|
+
import { h700 } from '@atlaskit/theme/typography';
|
|
6
|
+
const gridSize = getGridSize();
|
|
7
|
+
const fontFamily = getFontFamily();
|
|
8
|
+
const formHeaderContentStyles = css({
|
|
9
|
+
minWidth: '100%',
|
|
10
|
+
marginTop: `${gridSize}px`
|
|
11
|
+
});
|
|
12
|
+
const formHeaderDescriptionStyles = css({
|
|
13
|
+
marginTop: `${gridSize}px`
|
|
14
|
+
});
|
|
15
|
+
const formHeaderTitleStyles = css({
|
|
16
|
+
marginTop: 0,
|
|
17
|
+
marginRight: `${gridSize * 4}px`,
|
|
18
|
+
lineHeight: `${gridSize * 4}px`,
|
|
19
|
+
overflow: 'hidden',
|
|
20
|
+
textOverflow: 'ellipsis',
|
|
21
|
+
whiteSpace: 'nowrap'
|
|
22
|
+
});
|
|
23
|
+
const formHeaderWrapperStyles = css({
|
|
24
|
+
fontFamily: `${fontFamily}`
|
|
25
|
+
}); // eslint-disable-next-line @repo/internal/react/consistent-css-prop-usage
|
|
26
|
+
|
|
27
|
+
const darkH700Styles = css(h700({
|
|
28
|
+
theme: {
|
|
29
|
+
mode: 'dark'
|
|
30
|
+
}
|
|
31
|
+
})); // eslint-disable-next-line @repo/internal/react/consistent-css-prop-usage
|
|
32
|
+
|
|
33
|
+
const lightH700Styles = css(h700({
|
|
34
|
+
theme: {
|
|
35
|
+
mode: 'light'
|
|
36
|
+
}
|
|
37
|
+
}));
|
|
38
|
+
|
|
39
|
+
const FormHeaderContent = ({
|
|
40
|
+
children
|
|
41
|
+
}) => {
|
|
42
|
+
return jsx("div", {
|
|
43
|
+
css: formHeaderContentStyles
|
|
44
|
+
}, children);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const FormHeaderDescription = ({
|
|
48
|
+
children
|
|
49
|
+
}) => {
|
|
50
|
+
return jsx("div", {
|
|
51
|
+
css: formHeaderDescriptionStyles
|
|
52
|
+
}, children);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const FormHeaderTitle = ({
|
|
56
|
+
children
|
|
57
|
+
}) => {
|
|
58
|
+
const {
|
|
59
|
+
mode
|
|
60
|
+
} = useGlobalTheme();
|
|
61
|
+
return jsx("h2", {
|
|
62
|
+
css: [mode === 'light' ? lightH700Styles : darkH700Styles, formHeaderTitleStyles]
|
|
63
|
+
}, children);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const FormHeaderWrapper = ({
|
|
67
|
+
children
|
|
68
|
+
}) => {
|
|
69
|
+
return jsx("div", {
|
|
70
|
+
css: formHeaderWrapperStyles
|
|
71
|
+
}, children);
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* __Form header__
|
|
75
|
+
*
|
|
76
|
+
* A form header contains the form component's heading and subheadings. This provides the correct padding
|
|
77
|
+
* and styling for it.
|
|
78
|
+
*
|
|
79
|
+
* - [Examples](https://atlaskit.atlassian.com/packages/design-system/form/docs/layout)
|
|
80
|
+
* - [Code](https://atlaskit.atlassian.com/packages/design-system/form/docs/layout)
|
|
81
|
+
* - [Usage](https://atlaskit.atlassian.com/packages/design-system/form/docs/layout)
|
|
82
|
+
*/
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
const FormHeader = ({
|
|
86
|
+
children,
|
|
87
|
+
description,
|
|
88
|
+
title
|
|
89
|
+
}) => {
|
|
90
|
+
return jsx(FormHeaderWrapper, null, title && jsx(FormHeaderTitle, null, title), description && jsx(FormHeaderDescription, null, description), jsx(FormHeaderContent, null, children));
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export default FormHeader;
|
|
94
|
+
export { FormHeaderContent, FormHeaderDescription, FormHeaderTitle };
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { css, jsx } from '@emotion/core';
|
|
4
|
+
import { useGlobalTheme } from '@atlaskit/theme/components';
|
|
5
|
+
import { gridSize as getGridSize } from '@atlaskit/theme/constants';
|
|
6
|
+
import { h600 } from '@atlaskit/theme/typography';
|
|
7
|
+
const gridSize = getGridSize();
|
|
8
|
+
const formSectionDescriptionStyles = css({
|
|
9
|
+
marginTop: `${gridSize}px`
|
|
10
|
+
});
|
|
11
|
+
const formSectionTitleStyles = css({
|
|
12
|
+
marginTop: 0,
|
|
13
|
+
marginRight: `${gridSize * 4}px`,
|
|
14
|
+
lineHeight: `${gridSize * 4}px`,
|
|
15
|
+
overflow: 'hidden',
|
|
16
|
+
textOverflow: 'ellipsis',
|
|
17
|
+
whiteSpace: 'nowrap'
|
|
18
|
+
});
|
|
19
|
+
const formSectionWrapperStyles = css({
|
|
20
|
+
marginTop: `${gridSize * 3}px`
|
|
21
|
+
}); // eslint-disable-next-line @repo/internal/react/consistent-css-prop-usage
|
|
22
|
+
|
|
23
|
+
const lightH600Styles = css(h600({
|
|
24
|
+
theme: {
|
|
25
|
+
mode: 'light'
|
|
26
|
+
}
|
|
27
|
+
})); // eslint-disable-next-line @repo/internal/react/consistent-css-prop-usage
|
|
28
|
+
|
|
29
|
+
const darkH600Styles = css(h600({
|
|
30
|
+
theme: {
|
|
31
|
+
mode: 'dark'
|
|
32
|
+
}
|
|
33
|
+
}));
|
|
34
|
+
|
|
35
|
+
const FormSectionWrapper = ({
|
|
36
|
+
children
|
|
37
|
+
}) => {
|
|
38
|
+
return jsx("div", {
|
|
39
|
+
css: formSectionWrapperStyles
|
|
40
|
+
}, children);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const FormSectionTitle = ({
|
|
44
|
+
children
|
|
45
|
+
}) => {
|
|
46
|
+
const {
|
|
47
|
+
mode
|
|
48
|
+
} = useGlobalTheme();
|
|
49
|
+
return jsx("h3", {
|
|
50
|
+
css: [formSectionTitleStyles, mode === 'light' ? lightH600Styles : darkH600Styles]
|
|
51
|
+
}, children);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const FormSectionDescription = ({
|
|
55
|
+
children
|
|
56
|
+
}) => {
|
|
57
|
+
return jsx("div", {
|
|
58
|
+
css: formSectionDescriptionStyles
|
|
59
|
+
}, children);
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* __Form section__
|
|
63
|
+
*
|
|
64
|
+
* A form section is used to define a section of a form layout. This contains a section title, content
|
|
65
|
+
* and a description of the section.
|
|
66
|
+
*
|
|
67
|
+
* - [Examples](https://atlaskit.atlassian.com/packages/design-system/form/docs/layout)
|
|
68
|
+
* - [Code](https://atlaskit.atlassian.com/packages/design-system/form/docs/layout)
|
|
69
|
+
* - [Usage](https://atlaskit.atlassian.com/packages/design-system/form/docs/layout)
|
|
70
|
+
*/
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
const FormSection = ({
|
|
74
|
+
children,
|
|
75
|
+
description,
|
|
76
|
+
title
|
|
77
|
+
}) => {
|
|
78
|
+
return jsx(FormSectionWrapper, null, title && jsx(FormSectionTitle, null, title), description && jsx(FormSectionDescription, null, description), children);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export default FormSection;
|
|
@@ -2,9 +2,21 @@ import React, { createContext, useCallback, useEffect, useRef, useState } from '
|
|
|
2
2
|
import { createForm } from 'final-form';
|
|
3
3
|
import createDecorator from 'final-form-focus';
|
|
4
4
|
import set from 'lodash/set';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* __Form context__
|
|
8
|
+
*
|
|
9
|
+
* A form context creates a context for the field values and allows them to be accessed by the children.
|
|
10
|
+
*/
|
|
5
11
|
export const FormContext = /*#__PURE__*/createContext(function () {
|
|
6
12
|
return () => {};
|
|
7
13
|
});
|
|
14
|
+
/**
|
|
15
|
+
* __Is disabled context__
|
|
16
|
+
*
|
|
17
|
+
* An is disabled context creates the context for when a value is disabled.
|
|
18
|
+
*/
|
|
19
|
+
|
|
8
20
|
export const IsDisabledContext = /*#__PURE__*/createContext(false);
|
|
9
21
|
export default function Form(props) {
|
|
10
22
|
const formRef = useRef(null);
|
package/dist/es2019/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
export { default } from './
|
|
2
|
-
export { default as FormHeader } from './
|
|
3
|
-
export { default as FormFooter } from './
|
|
4
|
-
export { default as FormSection } from './
|
|
5
|
-
export { default as Field } from './
|
|
6
|
-
export { default as CheckboxField } from './
|
|
7
|
-
export { default as RangeField } from './
|
|
8
|
-
export { HelperMessage, ErrorMessage, ValidMessage } from './
|
|
9
|
-
export { default as Fieldset } from './
|
|
1
|
+
export { default } from './form';
|
|
2
|
+
export { default as FormHeader } from './form-header';
|
|
3
|
+
export { default as FormFooter } from './form-footer';
|
|
4
|
+
export { default as FormSection } from './form-section';
|
|
5
|
+
export { default as Field } from './field';
|
|
6
|
+
export { default as CheckboxField } from './checkbox-field';
|
|
7
|
+
export { default as RangeField } from './range-field';
|
|
8
|
+
export { HelperMessage, ErrorMessage, ValidMessage } from './messages';
|
|
9
|
+
export { default as Fieldset } from './fieldset'; // eslint-disable-next-line import/no-unresolved
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/** @jsx jsx */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { css, jsx } from '@emotion/core';
|
|
4
|
+
import SuccessIcon from '@atlaskit/icon/glyph/editor/success';
|
|
5
|
+
import ErrorIcon from '@atlaskit/icon/glyph/error';
|
|
6
|
+
import { G400, N200, R400 } from '@atlaskit/theme/colors';
|
|
7
|
+
import { useGlobalTheme } from '@atlaskit/theme/components';
|
|
8
|
+
import { fontFamily as getFontFamily, gridSize as getGridSize } from '@atlaskit/theme/constants';
|
|
9
|
+
import { h200 } from '@atlaskit/theme/typography';
|
|
10
|
+
import { token } from '@atlaskit/tokens';
|
|
11
|
+
import { FieldId } from './field';
|
|
12
|
+
const gridSize = getGridSize();
|
|
13
|
+
const fontFamily = getFontFamily(); // eslint-disable-next-line @repo/internal/react/consistent-css-prop-usage
|
|
14
|
+
|
|
15
|
+
const lightH200Styles = css(h200({
|
|
16
|
+
theme: {
|
|
17
|
+
mode: 'light'
|
|
18
|
+
}
|
|
19
|
+
})); // eslint-disable-next-line @repo/internal/react/consistent-css-prop-usage
|
|
20
|
+
|
|
21
|
+
const darkH200Styles = css(h200({
|
|
22
|
+
theme: {
|
|
23
|
+
mode: 'dark'
|
|
24
|
+
}
|
|
25
|
+
}));
|
|
26
|
+
const messageErrorColorStyles = css({
|
|
27
|
+
color: token('color.text.danger', R400)
|
|
28
|
+
});
|
|
29
|
+
const messageNeutralColorStyles = css({
|
|
30
|
+
color: token('color.text.lowEmphasis', N200)
|
|
31
|
+
});
|
|
32
|
+
const messageValidColorStyles = css({
|
|
33
|
+
color: token('color.text.success', G400)
|
|
34
|
+
});
|
|
35
|
+
const messageStyles = css({
|
|
36
|
+
display: 'flex',
|
|
37
|
+
marginTop: `${gridSize * 0.5}px`,
|
|
38
|
+
justifyContent: 'baseline',
|
|
39
|
+
fontFamily: `${fontFamily}`,
|
|
40
|
+
fontWeight: 'normal'
|
|
41
|
+
});
|
|
42
|
+
const iconWrapperStyles = css({
|
|
43
|
+
display: 'flex'
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const IconWrapper = ({
|
|
47
|
+
children
|
|
48
|
+
}) => {
|
|
49
|
+
return jsx("span", {
|
|
50
|
+
css: iconWrapperStyles
|
|
51
|
+
}, children);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const Message = ({
|
|
55
|
+
children,
|
|
56
|
+
error,
|
|
57
|
+
valid,
|
|
58
|
+
fieldId,
|
|
59
|
+
testId
|
|
60
|
+
}) => {
|
|
61
|
+
const {
|
|
62
|
+
mode
|
|
63
|
+
} = useGlobalTheme();
|
|
64
|
+
return jsx("div", {
|
|
65
|
+
css: [mode === 'light' ? lightH200Styles : darkH200Styles, messageStyles, error ? messageErrorColorStyles : valid ? messageValidColorStyles : messageNeutralColorStyles],
|
|
66
|
+
"data-testid": testId,
|
|
67
|
+
id: fieldId
|
|
68
|
+
}, children);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* __Helper message__
|
|
73
|
+
*
|
|
74
|
+
* A helper message tells the user what kind of input the field takes. For example, a helper message could be
|
|
75
|
+
* 'Password should be more than 4 characters'
|
|
76
|
+
*
|
|
77
|
+
*/
|
|
78
|
+
export const HelperMessage = ({
|
|
79
|
+
children,
|
|
80
|
+
testId
|
|
81
|
+
}) => jsx(FieldId.Consumer, null, fieldId => jsx(Message, {
|
|
82
|
+
fieldId: fieldId ? `${fieldId}-helper` : undefined,
|
|
83
|
+
testId: testId
|
|
84
|
+
}, children));
|
|
85
|
+
/**
|
|
86
|
+
* __Error message__
|
|
87
|
+
*
|
|
88
|
+
* An error message is used to tell a user that the field input is invalid. For example, an error message could be
|
|
89
|
+
* 'Invalid username, needs to be more than 4 characters'.
|
|
90
|
+
*
|
|
91
|
+
*/
|
|
92
|
+
|
|
93
|
+
export const ErrorMessage = ({
|
|
94
|
+
children,
|
|
95
|
+
testId
|
|
96
|
+
}) => jsx(FieldId.Consumer, null, fieldId => jsx(Message, {
|
|
97
|
+
error: true,
|
|
98
|
+
fieldId: fieldId ? `${fieldId}-error` : undefined,
|
|
99
|
+
testId: testId
|
|
100
|
+
}, jsx(IconWrapper, null, jsx(ErrorIcon, {
|
|
101
|
+
size: "small",
|
|
102
|
+
label: "error"
|
|
103
|
+
})), children));
|
|
104
|
+
/**
|
|
105
|
+
* __Valid message__
|
|
106
|
+
*
|
|
107
|
+
* A valid message is used to tell a user that the field input is valid. For example,
|
|
108
|
+
* a helper message could be 'Nice one, this username is available'.
|
|
109
|
+
*
|
|
110
|
+
*/
|
|
111
|
+
|
|
112
|
+
export const ValidMessage = ({
|
|
113
|
+
children,
|
|
114
|
+
testId
|
|
115
|
+
}) => jsx(FieldId.Consumer, null, fieldId => jsx(Message, {
|
|
116
|
+
fieldId: fieldId ? `${fieldId}-valid` : undefined,
|
|
117
|
+
testId: testId,
|
|
118
|
+
valid: true
|
|
119
|
+
}, jsx(IconWrapper, null, jsx(SuccessIcon, {
|
|
120
|
+
size: "small",
|
|
121
|
+
label: "success"
|
|
122
|
+
})), children));
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import _extends from "@babel/runtime/helpers/extends";
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import Field from './
|
|
3
|
+
import Field from './field';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* __Range field__
|
|
7
|
+
*
|
|
8
|
+
* A range field is where a user can submit a range input as a part of a form.
|
|
9
|
+
*
|
|
10
|
+
* - [Examples](https://atlaskit.atlassian.com/packages/design-system/form/docs/fields#rangefield-reference)
|
|
11
|
+
* - [Code](https://atlaskit.atlassian.com/packages/design-system/form/docs/fields#rangefield-reference)
|
|
12
|
+
* - [Usage](https://atlaskit.atlassian.com/packages/design-system/form/docs/fields#rangefield-reference)
|
|
13
|
+
*/
|
|
5
14
|
const RangeField = props => {
|
|
6
15
|
const {
|
|
7
16
|
children,
|
package/dist/es2019/version.json
CHANGED
|
@@ -8,8 +8,17 @@ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (O
|
|
|
8
8
|
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
|
|
9
9
|
|
|
10
10
|
import React, { useCallback } from 'react';
|
|
11
|
-
import Field from './
|
|
11
|
+
import Field from './field';
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* __Checkbox field__
|
|
15
|
+
*
|
|
16
|
+
* A checkbox field is a form field that lets users select an item. Users can check or uncheck the checkbox.
|
|
17
|
+
*
|
|
18
|
+
* - [Examples] https://atlaskit.atlassian.com/packages/design-system/form/docs/fields#checkboxfield-reference
|
|
19
|
+
* - [Code] https://atlaskit.atlassian.com/packages/design-system/form/docs/fields#checkboxfield-reference
|
|
20
|
+
* - [Usage] https://atlaskit.atlassian.com/packages/design-system/form/docs/fields#checkboxfield-reference
|
|
21
|
+
*/
|
|
13
22
|
var CheckboxField = function CheckboxField(props) {
|
|
14
23
|
var children = props.children,
|
|
15
24
|
_props$defaultIsCheck = props.defaultIsChecked,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as CheckboxField } from '../checkbox-field';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '../field';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Fieldset } from '../fieldset';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as FormFooter } from '../form-footer';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as FormHeader } from '../form-header';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as FormSection } from '../form-section';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from '../form';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { HelperMessage, ErrorMessage, ValidMessage } from '../messages';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as RangeField } from '../range-field';
|