@react-ui-org/react-ui 0.42.1 → 0.44.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (167) hide show
  1. package/CONTRIBUTING.md +44 -25
  2. package/README.md +1 -1
  3. package/dist/lib.development.js +1597 -651
  4. package/dist/lib.js +1 -9
  5. package/package.json +47 -46
  6. package/src/lib/components/{ui/Alert → Alert}/Alert.jsx +17 -14
  7. package/src/lib/components/{ui/Alert → Alert}/Alert.scss +3 -3
  8. package/src/lib/components/{ui/Alert → Alert}/README.mdx +6 -6
  9. package/src/lib/components/{ui/Alert → Alert}/_settings.scss +1 -1
  10. package/src/lib/components/{ui/Alert → Alert}/_theme.scss +0 -0
  11. package/src/lib/components/{ui/Alert → Alert}/_tools.scss +0 -0
  12. package/src/lib/components/{ui/Alert → Alert}/index.js +0 -0
  13. package/src/lib/components/{ui/Badge → Badge}/Badge.jsx +2 -2
  14. package/src/lib/components/{ui/Badge → Badge}/Badge.scss +3 -3
  15. package/src/lib/components/{ui/Badge → Badge}/README.mdx +3 -3
  16. package/src/lib/components/{ui/Badge → Badge}/index.js +0 -0
  17. package/src/lib/components/Button/Button.jsx +198 -0
  18. package/src/lib/components/{ui/Button → Button}/Button.scss +0 -0
  19. package/src/lib/components/{ui/Button → Button}/README.mdx +161 -76
  20. package/src/lib/components/Button/_base.scss +148 -0
  21. package/src/lib/components/{ui/Button → Button}/_priorities.scss +0 -4
  22. package/src/lib/components/{ui/Button → Button}/_settings.scss +2 -3
  23. package/src/lib/components/{ui/Button → Button}/_theme.scss +3 -11
  24. package/src/lib/components/{ui/Button → Button}/_tools.scss +27 -44
  25. package/src/lib/components/Button/helpers/getRootLabelVisibilityClassName.js +33 -0
  26. package/src/lib/components/{ui/Button → Button}/helpers/getRootPriorityClassName.js +0 -4
  27. package/src/lib/components/{ui/Button → Button}/index.js +0 -0
  28. package/src/lib/components/{ui/ButtonGroup → ButtonGroup}/ButtonGroup.jsx +9 -11
  29. package/src/lib/components/{ui/ButtonGroup → ButtonGroup}/ButtonGroup.scss +0 -0
  30. package/src/lib/components/ButtonGroup/ButtonGroupContext.js +3 -0
  31. package/src/lib/components/{ui/ButtonGroup → ButtonGroup}/README.mdx +30 -6
  32. package/src/lib/components/ButtonGroup/index.js +2 -0
  33. package/src/lib/components/{layout/CTA → CTA}/CTA.jsx +5 -2
  34. package/src/lib/components/{layout/CTA → CTA}/CTA.scss +2 -2
  35. package/src/lib/components/{layout/CTA → CTA}/CTACenter.jsx +1 -1
  36. package/src/lib/components/{layout/CTA → CTA}/CTAEnd.jsx +1 -1
  37. package/src/lib/components/{layout/CTA → CTA}/CTAStart.jsx +1 -1
  38. package/src/lib/components/{layout/CTA → CTA}/README.mdx +4 -4
  39. package/src/lib/components/{layout/CTA → CTA}/index.js +0 -0
  40. package/src/lib/components/{ui/Card → Card}/Card.jsx +6 -4
  41. package/src/lib/components/{ui/Card → Card}/Card.scss +1 -1
  42. package/src/lib/components/{ui/Card → Card}/CardBody.jsx +1 -1
  43. package/src/lib/components/{ui/Card → Card}/CardFooter.jsx +1 -1
  44. package/src/lib/components/{ui/Card → Card}/README.mdx +4 -4
  45. package/src/lib/components/{ui/Card → Card}/_theme.scss +0 -0
  46. package/src/lib/components/{ui/Card → Card}/_tools.scss +0 -0
  47. package/src/lib/components/{ui/Card → Card}/index.js +0 -0
  48. package/src/lib/components/{layout/Center → Center}/Center.jsx +1 -1
  49. package/src/lib/components/{layout/Center → Center}/Center.scss +0 -0
  50. package/src/lib/components/{layout/Center → Center}/README.mdx +2 -2
  51. package/src/lib/components/{layout/Center → Center}/index.js +0 -0
  52. package/src/lib/components/CheckboxField/CheckboxField.jsx +164 -0
  53. package/src/lib/components/{ui/CheckboxField → CheckboxField}/CheckboxField.scss +5 -5
  54. package/src/lib/components/{ui/CheckboxField → CheckboxField}/README.mdx +17 -14
  55. package/src/lib/components/{ui/CheckboxField → CheckboxField}/index.js +0 -0
  56. package/src/lib/components/FileInputField/FileInputField.jsx +162 -0
  57. package/src/lib/components/{ui/FileInputField → FileInputField}/FileInputField.scss +5 -5
  58. package/src/lib/components/{ui/FileInputField → FileInputField}/README.mdx +8 -6
  59. package/src/lib/components/{ui/FileInputField → FileInputField}/index.js +0 -0
  60. package/src/lib/components/{layout/FormLayout → FormLayout}/FormLayout.jsx +16 -18
  61. package/src/lib/components/{layout/FormLayout → FormLayout}/FormLayout.scss +3 -3
  62. package/src/lib/components/FormLayout/FormLayoutContext.js +3 -0
  63. package/src/lib/components/{layout/FormLayout → FormLayout}/FormLayoutCustomField.jsx +33 -30
  64. package/src/lib/components/{layout/FormLayout → FormLayout}/FormLayoutCustomField.scss +4 -4
  65. package/src/lib/components/{layout/FormLayout → FormLayout}/README.mdx +37 -47
  66. package/src/lib/components/{layout/FormLayout → FormLayout}/_theme.scss +0 -0
  67. package/src/lib/components/{layout/FormLayout → FormLayout}/index.js +1 -0
  68. package/src/lib/components/{layout/Grid → Grid}/Grid.jsx +23 -5
  69. package/src/lib/components/{layout/Grid → Grid}/Grid.scss +13 -4
  70. package/src/lib/components/{layout/Grid → Grid}/GridSpan.jsx +10 -3
  71. package/src/lib/components/{layout/Grid → Grid}/README.mdx +42 -38
  72. package/src/lib/components/{layout/Grid → Grid}/_theme.scss +1 -2
  73. package/src/lib/components/{layout/Grid → Grid}/_tools.scss +2 -2
  74. package/src/lib/components/{layout/Grid → Grid}/helpers/generateResponsiveCustomProperties.js +0 -0
  75. package/src/lib/components/{layout/Grid → Grid}/index.js +0 -0
  76. package/src/lib/components/Link/Link.jsx +45 -0
  77. package/src/lib/components/Link/Link.scss +11 -0
  78. package/src/lib/components/Link/README.mdx +85 -0
  79. package/src/lib/components/Link/_theme.scss +4 -0
  80. package/src/lib/components/Link/index.js +1 -0
  81. package/src/lib/components/{layout/List → List}/List.jsx +1 -1
  82. package/src/lib/components/{layout/List → List}/List.scss +2 -2
  83. package/src/lib/components/{layout/List → List}/ListItem.jsx +1 -1
  84. package/src/lib/components/{layout/List → List}/README.mdx +3 -3
  85. package/src/lib/components/{layout/List → List}/_theme.scss +0 -0
  86. package/src/lib/components/{layout/List → List}/index.js +0 -0
  87. package/src/lib/components/{layout/Media → Media}/Media.jsx +4 -2
  88. package/src/lib/components/{layout/Media → Media}/Media.scss +1 -1
  89. package/src/lib/components/{layout/Media → Media}/MediaBody.jsx +1 -1
  90. package/src/lib/components/{layout/Media → Media}/MediaObject.jsx +1 -1
  91. package/src/lib/components/{layout/Media → Media}/README.mdx +2 -2
  92. package/src/lib/components/{layout/Media → Media}/index.js +0 -0
  93. package/src/lib/components/{ui/Modal → Modal}/Modal.jsx +28 -27
  94. package/src/lib/components/{ui/Modal → Modal}/Modal.scss +5 -5
  95. package/src/lib/components/{ui/Modal → Modal}/README.mdx +42 -42
  96. package/src/lib/components/{ui/Modal → Modal}/_settings.scss +4 -4
  97. package/src/lib/components/{ui/Modal → Modal}/_theme.scss +0 -0
  98. package/src/lib/components/{ui/Modal → Modal}/index.js +0 -0
  99. package/src/lib/components/{ui/Paper → Paper}/Paper.jsx +8 -1
  100. package/src/lib/components/{ui/Paper → Paper}/Paper.scss +5 -0
  101. package/src/lib/components/{ui/Paper → Paper}/README.mdx +15 -3
  102. package/src/lib/components/{ui/Paper → Paper}/_theme.scss +2 -0
  103. package/src/lib/components/{ui/Paper → Paper}/index.js +0 -0
  104. package/src/lib/components/{ui/Radio → Radio}/README.mdx +20 -17
  105. package/src/lib/components/Radio/Radio.jsx +188 -0
  106. package/src/lib/components/{ui/Radio → Radio}/Radio.scss +9 -9
  107. package/src/lib/components/{ui/Radio → Radio}/index.js +0 -0
  108. package/src/lib/components/{ui/ScrollView → ScrollView}/README.mdx +11 -11
  109. package/src/lib/components/{ui/ScrollView → ScrollView}/ScrollView.jsx +9 -10
  110. package/src/lib/components/{ui/ScrollView → ScrollView}/ScrollView.scss +6 -6
  111. package/src/lib/components/{ui/ScrollView → ScrollView}/_theme.scss +0 -0
  112. package/src/lib/components/{ui/ScrollView → ScrollView}/index.js +0 -0
  113. package/src/lib/components/{ui/SelectField → SelectField}/README.mdx +47 -44
  114. package/src/lib/components/SelectField/SelectField.jsx +219 -0
  115. package/src/lib/components/{ui/SelectField → SelectField}/SelectField.scss +6 -6
  116. package/src/lib/components/{ui/SelectField → SelectField}/index.js +0 -0
  117. package/src/lib/components/{ui/Table → Table}/README.mdx +10 -10
  118. package/src/lib/components/{ui/Table → Table}/Table.jsx +9 -13
  119. package/src/lib/components/{ui/Table → Table}/Table.scss +1 -1
  120. package/src/lib/components/{ui/Table → Table}/_settings.scss +4 -4
  121. package/src/lib/components/{ui/Table → Table}/index.js +0 -0
  122. package/src/lib/components/{ui/Tabs → Tabs}/README.mdx +4 -4
  123. package/src/lib/components/{ui/Tabs → Tabs}/Tabs.jsx +4 -4
  124. package/src/lib/components/{ui/Tabs → Tabs}/Tabs.scss +1 -1
  125. package/src/lib/components/{ui/Tabs → Tabs}/TabsItem.jsx +4 -3
  126. package/src/lib/components/{ui/Tabs → Tabs}/TabsItem.scss +3 -3
  127. package/src/lib/components/{ui/Tabs → Tabs}/_theme.scss +0 -0
  128. package/src/lib/components/{ui/Tabs → Tabs}/index.js +0 -0
  129. package/src/lib/components/{ui/Text → Text}/README.mdx +19 -19
  130. package/src/lib/components/{ui/Text → Text}/Text.jsx +1 -1
  131. package/src/lib/components/{ui/Text → Text}/Text.scss +0 -0
  132. package/src/lib/components/{ui/Text → Text}/helpers/getRootHyphensClassName.js +0 -0
  133. package/src/lib/components/{ui/Text → Text}/helpers/getRootWordWrappingClassName.js +0 -0
  134. package/src/lib/components/{ui/Text → Text}/index.js +0 -0
  135. package/src/lib/components/{ui/TextArea → TextArea}/README.mdx +8 -6
  136. package/src/lib/components/{ui/TextArea → TextArea}/TextArea.jsx +78 -78
  137. package/src/lib/components/{ui/TextArea → TextArea}/TextArea.scss +6 -6
  138. package/src/lib/components/{ui/TextArea → TextArea}/index.js +0 -0
  139. package/src/lib/components/{ui/TextField → TextField}/README.mdx +7 -6
  140. package/src/lib/components/{ui/TextField → TextField}/TextField.jsx +20 -22
  141. package/src/lib/components/{ui/TextField → TextField}/TextField.scss +6 -6
  142. package/src/lib/components/{ui/TextField → TextField}/index.js +0 -0
  143. package/src/lib/components/{ui/Toggle → Toggle}/README.mdx +17 -14
  144. package/src/lib/components/Toggle/Toggle.jsx +163 -0
  145. package/src/lib/components/{ui/Toggle → Toggle}/Toggle.scss +5 -5
  146. package/src/lib/components/{ui/Toggle → Toggle}/index.js +0 -0
  147. package/src/lib/components/{layout/Toolbar → Toolbar}/README.mdx +29 -29
  148. package/src/lib/components/{layout/Toolbar → Toolbar}/Toolbar.jsx +1 -1
  149. package/src/lib/components/{layout/Toolbar → Toolbar}/Toolbar.scss +1 -1
  150. package/src/lib/components/{layout/Toolbar → Toolbar}/ToolbarGroup.jsx +1 -1
  151. package/src/lib/components/{layout/Toolbar → Toolbar}/ToolbarItem.jsx +1 -1
  152. package/src/lib/components/{layout/Toolbar → Toolbar}/_theme.scss +0 -0
  153. package/src/lib/components/{layout/Toolbar → Toolbar}/index.js +0 -0
  154. package/src/lib/components/{ui/withForwardedRef.jsx → withForwardedRef.jsx} +0 -0
  155. package/src/lib/helpers/resolveContextOrProp.js +7 -0
  156. package/src/lib/index.js +34 -35
  157. package/src/lib/styles/tools/_accessibility.scss +9 -0
  158. package/src/lib/theme.scss +25 -7
  159. package/src/lib/components/ui/Button/Button.jsx +0 -191
  160. package/src/lib/components/ui/Button/_base.scss +0 -154
  161. package/src/lib/components/ui/Button/helpers/getRootLabelVisibilityClassName.js +0 -11
  162. package/src/lib/components/ui/ButtonGroup/index.js +0 -1
  163. package/src/lib/components/ui/CheckboxField/CheckboxField.jsx +0 -173
  164. package/src/lib/components/ui/FileInputField/FileInputField.jsx +0 -158
  165. package/src/lib/components/ui/Radio/Radio.jsx +0 -179
  166. package/src/lib/components/ui/SelectField/SelectField.jsx +0 -214
  167. package/src/lib/components/ui/Toggle/Toggle.jsx +0 -174
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: CheckboxField
3
- menu: 'UI'
4
- route: /components/ui/checkbox-field
3
+ menu: 'Inputs'
4
+ route: /components/checkbox-field
5
5
  ---
6
6
 
7
7
  # CheckboxField
@@ -29,9 +29,9 @@ And use it:
29
29
  const [agree, setAgree] = React.useState(true);
30
30
  return (
31
31
  <CheckboxField
32
- changeHandler={() => setAgree(!agree)}
33
32
  checked={agree}
34
33
  label="I agree"
34
+ onChange={() => setAgree(!agree)}
35
35
  />
36
36
  );
37
37
  }}
@@ -44,13 +44,13 @@ See [API](#api) for all available options.
44
44
  - Use the CheckboxField when there are lists of options and the user may
45
45
  **select any number of choices,** including zero, one, or several. For
46
46
  selecting just a single option from the list, use either the
47
- [Radio](/components/ui/radio) or [SelectField](/components/ui/select-field)
47
+ [Radio](/components/radio) or [SelectField](/components/select-field)
48
48
  component.
49
49
 
50
50
  - Use the CheckboxField for boolean (true/false) input **in forms that require
51
51
  to be confirmed** by a button to become active. To toggle things on or off
52
52
  with an immediate effect (without confirmation), use rather the
53
- [Toggle](/components/ui/toggle) component.
53
+ [Toggle](/components/toggle) component.
54
54
 
55
55
  - **Use positive wording for the checkbox label,** so that it's clear what will
56
56
  happen when the user turns on the checkbox. Avoid negations such as “Don't
@@ -81,10 +81,10 @@ turning the checkbox on or off.
81
81
  const [getNewsletter, setGetNewsletter] = React.useState(true);
82
82
  return (
83
83
  <CheckboxField
84
- changeHandler={() => setGetNewsletter(!getNewsletter)}
85
84
  checked={getNewsletter}
86
85
  helpText="We will not bother you more than once a month, we promise!"
87
86
  label="Send me newsletter"
87
+ onChange={() => setGetNewsletter(!getNewsletter)}
88
88
  />
89
89
  );
90
90
  }}
@@ -100,10 +100,10 @@ label remains accessible to assistive technologies.
100
100
  const [checked, setChecked] = React.useState(true);
101
101
  return (
102
102
  <CheckboxField
103
- changeHandler={() => setChecked(!checked)}
104
103
  checked={checked}
105
104
  isLabelVisible={false}
106
105
  label="You cannot see this"
106
+ onChange={() => setChecked(!checked)}
107
107
  />
108
108
  );
109
109
  }}
@@ -116,10 +116,10 @@ It's also possible to display label before input:
116
116
  const [checked, setChecked] = React.useState(true);
117
117
  return (
118
118
  <CheckboxField
119
- changeHandler={() => setChecked(!checked)}
120
119
  checked={checked}
121
120
  label="Label precedes input"
122
121
  labelPosition="before"
122
+ onChange={() => setChecked(!checked)}
123
123
  />
124
124
  );
125
125
  }}
@@ -140,22 +140,22 @@ have.
140
140
  return (
141
141
  <>
142
142
  <CheckboxField
143
- changeHandler={() => setAgree(!agree)}
144
143
  checked={agree}
145
144
  label="I have read and agree with terms and conditions"
145
+ onChange={() => setAgree(!agree)}
146
146
  validationState="valid"
147
147
  />
148
148
  <CheckboxField
149
- changeHandler={() => setAgree(!agree)}
150
149
  checked={agree}
151
150
  label="I have read and agree with terms and conditions"
151
+ onChange={() => setAgree(!agree)}
152
152
  validationState="warning"
153
153
  validationText="Please wait 10 minutes until we verify your data."
154
154
  />
155
155
  <CheckboxField
156
- changeHandler={() => setAgree(!agree)}
157
156
  checked={agree}
158
157
  label="I have read and agree with terms and conditions"
158
+ onChange={() => setAgree(!agree)}
159
159
  required
160
160
  validationState="invalid"
161
161
  validationText="You must agree to be able to proceed."
@@ -183,9 +183,10 @@ Disabled state makes the input unavailable.
183
183
 
184
184
  ## API
185
185
 
186
- In addition to the options below, you can add any custom attributes that do not
187
- interfere with the API, and they will be passed to the `input` HTML element.
188
- This is useful mainly to improve component's accessibility.
186
+ In addition to the options below, you can specify [React synthetic events] or
187
+ any custom HTML attributes that do not interfere with the API, and they will be
188
+ passed to the `input` HTML element. This enables making the component
189
+ interactive and helps improve its accessibility.
189
190
 
190
191
  <Props table of={CheckboxField} />
191
192
 
@@ -198,3 +199,5 @@ options. On top of that, the following options are available for CheckboxField.
198
199
  |----------------------------------------------------------------------|----------------------------------------------|
199
200
  | `--rui-FormField--check__input--checkbox__border-radius` | Input corner radius |
200
201
  | `--rui-FormField--check__input--checkbox--checked__background-image` | Background image of checked input |
202
+
203
+ [React synthetic events]: https://reactjs.org/docs/events.html
@@ -0,0 +1,162 @@
1
+ import PropTypes from 'prop-types';
2
+ import React, { useContext } from 'react';
3
+ import getRootValidationStateClassName from '../../helpers/getRootValidationStateClassName';
4
+ import { resolveContextOrProp } from '../../helpers/resolveContextOrProp';
5
+ import { withProviderContext } from '../../provider';
6
+ import transferProps from '../../utils/transferProps';
7
+ import { FormLayoutContext } from '../FormLayout';
8
+ import withForwardedRef from '../withForwardedRef';
9
+ import styles from './FileInputField.scss';
10
+
11
+ export const FileInputField = ({
12
+ disabled,
13
+ forwardedRef,
14
+ fullWidth,
15
+ helpText,
16
+ id,
17
+ isLabelVisible,
18
+ label,
19
+ layout,
20
+ required,
21
+ validationState,
22
+ validationText,
23
+ ...restProps
24
+ }) => {
25
+ const context = useContext(FormLayoutContext);
26
+
27
+ return (
28
+ <label
29
+ className={[
30
+ styles.root,
31
+ fullWidth ? styles.isRootFullWidth : '',
32
+ context ? styles.isRootInFormLayout : '',
33
+ resolveContextOrProp(context && context.layout, layout) === 'horizontal'
34
+ ? styles.rootLayoutHorizontal
35
+ : styles.rootLayoutVertical,
36
+ disabled ? styles.isRootDisabled : '',
37
+ required ? styles.isRootRequired : '',
38
+ getRootValidationStateClassName(validationState, styles),
39
+ ].join(' ')}
40
+ htmlFor={id}
41
+ id={id && `${id}__label`}
42
+ >
43
+ <div
44
+ className={[
45
+ styles.label,
46
+ isLabelVisible ? '' : styles.isLabelHidden,
47
+ ].join(' ')}
48
+ id={id && `${id}__labelText`}
49
+ >
50
+ {label}
51
+ </div>
52
+ <div className={styles.field}>
53
+ <div className={styles.inputContainer}>
54
+ <input
55
+ {...transferProps(restProps)}
56
+ className={styles.input}
57
+ disabled={disabled}
58
+ id={id}
59
+ ref={forwardedRef}
60
+ required={required}
61
+ type="file"
62
+ />
63
+ </div>
64
+ {helpText && (
65
+ <div
66
+ className={styles.helpText}
67
+ id={id && `${id}__helpText`}
68
+ >
69
+ {helpText}
70
+ </div>
71
+ )}
72
+ {validationText && (
73
+ <div
74
+ className={styles.validationText}
75
+ id={id && `${id}__validationText`}
76
+ >
77
+ {validationText}
78
+ </div>
79
+ )}
80
+ </div>
81
+ </label>
82
+ );
83
+ };
84
+
85
+ FileInputField.defaultProps = {
86
+ disabled: false,
87
+ forwardedRef: undefined,
88
+ fullWidth: false,
89
+ helpText: null,
90
+ id: undefined,
91
+ isLabelVisible: true,
92
+ layout: 'vertical',
93
+ required: false,
94
+ validationState: null,
95
+ validationText: null,
96
+ };
97
+
98
+ FileInputField.propTypes = {
99
+ /**
100
+ * If `true`, the input will be disabled.
101
+ */
102
+ disabled: PropTypes.bool,
103
+ /**
104
+ * Reference forwarded to the `input` element.
105
+ */
106
+ forwardedRef: PropTypes.oneOfType([
107
+ PropTypes.func,
108
+ // eslint-disable-next-line react/forbid-prop-types
109
+ PropTypes.shape({ current: PropTypes.any }),
110
+ ]),
111
+ /**
112
+ * If `true`, the field will span the full width of its parent.
113
+ */
114
+ fullWidth: PropTypes.bool,
115
+ /**
116
+ * Optional help text.
117
+ */
118
+ helpText: PropTypes.node,
119
+ /**
120
+ * ID of the `<input>` HTML element.
121
+ *
122
+ * Also serves as base for ids of nested elements:
123
+ * * `<ID>__label`
124
+ * * `<ID>__labelText`
125
+ * * `<ID>__helpText`
126
+ * * `<ID>__validationText`
127
+ */
128
+ id: PropTypes.string,
129
+ /**
130
+ * If `false`, the label will be visually hidden (but remains accessible by assistive
131
+ * technologies).
132
+ */
133
+ isLabelVisible: PropTypes.bool,
134
+ /**
135
+ * Text field label.
136
+ */
137
+ label: PropTypes.string.isRequired,
138
+ /**
139
+ * Layout of the field.
140
+ *
141
+ * Ignored if the component is rendered within `FormLayout` component
142
+ * as the value is inherited in such case.
143
+ *
144
+ */
145
+ layout: PropTypes.oneOf(['horizontal', 'vertical']),
146
+ /**
147
+ * If `true`, the input will be required.
148
+ */
149
+ required: PropTypes.bool,
150
+ /**
151
+ * Alter the field to provide feedback based on validation result.
152
+ */
153
+ validationState: PropTypes.oneOf(['invalid', 'valid', 'warning']),
154
+ /**
155
+ * Validation message to be displayed.
156
+ */
157
+ validationText: PropTypes.node,
158
+ };
159
+
160
+ export const FileInputFieldWithContext = withForwardedRef(withProviderContext(FileInputField, 'FileInputField'));
161
+
162
+ export default FileInputFieldWithContext;
@@ -1,8 +1,8 @@
1
- @use '../../../styles/tools/form-fields/box-field-elements';
2
- @use '../../../styles/tools/form-fields/box-field-layout';
3
- @use '../../../styles/tools/form-fields/foundation';
4
- @use '../../../styles/tools/form-fields/variants';
5
- @use '../../../styles/tools/accessibility';
1
+ @use '../../styles/tools/form-fields/box-field-elements';
2
+ @use '../../styles/tools/form-fields/box-field-layout';
3
+ @use '../../styles/tools/form-fields/foundation';
4
+ @use '../../styles/tools/form-fields/variants';
5
+ @use '../../styles/tools/accessibility';
6
6
 
7
7
  // Foundation
8
8
  .root {
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: FileInputField
3
- menu: 'UI'
4
- route: /components/ui/file-input-field
3
+ menu: 'Inputs'
4
+ route: /components/file-input-field
5
5
  ---
6
6
 
7
7
  # FileInputField
@@ -189,10 +189,10 @@ It's possible to disable the whole input.
189
189
 
190
190
  ## API
191
191
 
192
- In addition to the options below, you can add any custom attributes that do not
193
- interfere with the API, and they will be passed to the `input` HTML element.
194
- This is useful mainly to improve component's
195
- [accessibility](#forwarding-html-attributes).
192
+ In addition to the options below, you can specify [React synthetic events] or
193
+ any custom HTML attributes that do not interfere with the API, and they will be
194
+ passed to the `input` HTML element. This enables making the component
195
+ interactive and helps improve its [accessibility](#forwarding-html-attributes).
196
196
 
197
197
  <Props table of={FileInputField} />
198
198
 
@@ -200,3 +200,5 @@ This is useful mainly to improve component's
200
200
 
201
201
  Head to [Forms Theming](/customize/theming/forms) to see shared form theming
202
202
  options.
203
+
204
+ [React synthetic events]: https://reactjs.org/docs/events.html
@@ -1,7 +1,7 @@
1
- import flattenChildren from 'react-keyed-flatten-children';
2
1
  import PropTypes from 'prop-types';
3
2
  import React from 'react';
4
- import { withProviderContext } from '../../../provider';
3
+ import { withProviderContext } from '../../provider';
4
+ import { FormLayoutContext } from './FormLayoutContext';
5
5
  import styles from './FormLayout.scss';
6
6
 
7
7
  const PREDEFINED_LABEL_WIDTH_VALUES = ['auto', 'default', 'limited'];
@@ -56,20 +56,11 @@ export const FormLayout = (props) => {
56
56
  ].join(' ')}
57
57
  {...hasCustomLabelWidth ? { style: { '--rui-custom-label-width': labelWidth } } : {}}
58
58
  >
59
- {/*
60
- Flatten children to one-dimensional array so we get over React Fragments with the `map()`
61
- function.
62
- */}
63
- {flattenChildren(children).map((child) => {
64
- if (!React.isValidElement(child)) {
65
- return null;
66
- }
67
-
68
- return React.cloneElement(child, {
69
- inFormLayout: true,
70
- layout: fieldLayout,
71
- });
72
- })}
59
+ <FormLayoutContext.Provider
60
+ value={{ layout: fieldLayout }}
61
+ >
62
+ {children}
63
+ </FormLayoutContext.Provider>
73
64
  </div>
74
65
  );
75
66
  };
@@ -88,8 +79,15 @@ FormLayout.propTypes = {
88
79
  */
89
80
  autoWidth: PropTypes.bool,
90
81
  /**
91
- * Supported form field components: CheckboxField, Radio, SelectField, TextArea, TextField,
92
- * Toggle, and FormLayoutCustomField.
82
+ * Supported form field components:
83
+ * * `CheckboxField`
84
+ * * `FileInputField`
85
+ * * `FormLayoutCustomField`
86
+ * * `Radio`
87
+ * * `SelectField`
88
+ * * `TextArea`
89
+ * * `TextField`
90
+ * * `Toggle`
93
91
  */
94
92
  children: PropTypes.node,
95
93
  /**
@@ -13,9 +13,9 @@
13
13
  // (a global default which can be customised per use).
14
14
  // https://github.com/react-ui-org/react-ui/issues/232
15
15
 
16
- @use '../../../styles/settings/forms';
17
- @use '../../../styles/tools/breakpoint';
18
- @use '../../../styles/tools/spacing';
16
+ @use '../../styles/settings/forms';
17
+ @use '../../styles/tools/breakpoint';
18
+ @use '../../styles/tools/spacing';
19
19
  @use 'theme';
20
20
 
21
21
  .root {
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+
3
+ export const FormLayoutContext = React.createContext(null);
@@ -1,9 +1,10 @@
1
1
  import PropTypes from 'prop-types';
2
- import React from 'react';
3
- import getRootSizeClassName from '../../../helpers/getRootSizeClassName';
4
- import getRootValidationStateClassName from '../../../helpers/getRootValidationStateClassName';
5
- import { withProviderContext } from '../../../provider';
2
+ import React, { useContext } from 'react';
3
+ import getRootSizeClassName from '../../helpers/getRootSizeClassName';
4
+ import getRootValidationStateClassName from '../../helpers/getRootValidationStateClassName';
5
+ import { withProviderContext } from '../../provider';
6
6
  import styles from './FormLayoutCustomField.scss';
7
+ import { FormLayoutContext } from './FormLayoutContext';
7
8
 
8
9
  const renderLabel = (id, label, labelForId) => {
9
10
  if (labelForId && label) {
@@ -40,31 +41,34 @@ export const FormLayoutCustomField = ({
40
41
  innerFieldSize,
41
42
  label,
42
43
  labelForId,
43
- layout,
44
44
  required,
45
45
  validationState,
46
- }) => (
47
- <div
48
- id={id}
49
- className={[
50
- styles.root,
51
- fullWidth ? styles.isRootFullWidth : '',
52
- layout === 'vertical' ? styles.rootLayoutVertical : styles.rootLayoutHorizontal,
53
- disabled ? styles.isRootDisabled : '',
54
- required ? styles.isRootRequired : '',
55
- getRootSizeClassName(innerFieldSize, styles),
56
- getRootValidationStateClassName(validationState, styles),
57
- ].join(' ')}
58
- >
59
- {renderLabel(id, label, labelForId)}
46
+ }) => {
47
+ const context = useContext(FormLayoutContext);
48
+
49
+ return (
60
50
  <div
61
- id={id && `${id}__field`}
62
- className={styles.field}
51
+ id={id}
52
+ className={[
53
+ styles.root,
54
+ fullWidth ? styles.isRootFullWidth : '',
55
+ context && context.layout === 'horizontal' ? styles.rootLayoutHorizontal : styles.rootLayoutVertical,
56
+ disabled ? styles.isRootDisabled : '',
57
+ required ? styles.isRootRequired : '',
58
+ getRootSizeClassName(innerFieldSize, styles),
59
+ getRootValidationStateClassName(validationState, styles),
60
+ ].join(' ')}
63
61
  >
64
- {children}
62
+ {renderLabel(id, label, labelForId)}
63
+ <div
64
+ id={id && `${id}__field`}
65
+ className={styles.field}
66
+ >
67
+ {children}
68
+ </div>
65
69
  </div>
66
- </div>
67
- );
70
+ );
71
+ };
68
72
 
69
73
  FormLayoutCustomField.defaultProps = {
70
74
  children: null,
@@ -74,7 +78,6 @@ FormLayoutCustomField.defaultProps = {
74
78
  innerFieldSize: null,
75
79
  label: null,
76
80
  labelForId: undefined,
77
- layout: 'vertical',
78
81
  required: false,
79
82
  validationState: null,
80
83
  };
@@ -94,6 +97,10 @@ FormLayoutCustomField.propTypes = {
94
97
  fullWidth: PropTypes.bool,
95
98
  /**
96
99
  * ID of the root HTML element.
100
+ *
101
+ * Also serves as base for ids of nested elements:
102
+ * * `<ID>__field`
103
+ * * `<ID>__label`
97
104
  */
98
105
  id: PropTypes.string,
99
106
  /**
@@ -105,13 +112,9 @@ FormLayoutCustomField.propTypes = {
105
112
  */
106
113
  label: PropTypes.string,
107
114
  /**
108
- * Optional ID of labelled field to keep accessibility features.
115
+ * Optional ID of labeled field to keep accessibility features. Only available if `label` is set.
109
116
  */
110
117
  labelForId: PropTypes.string,
111
- /**
112
- * Layout of the field, controlled by parent FormLayout.
113
- */
114
- layout: PropTypes.oneOf(['horizontal', 'vertical']),
115
118
  /**
116
119
  * If `true`, label will be styled as required.
117
120
  */
@@ -1,7 +1,7 @@
1
- @use '../../../styles/tools/form-fields/foundation';
2
- @use '../../../styles/tools/form-fields/box-field-layout';
3
- @use '../../../styles/tools/form-fields/box-field-sizes';
4
- @use '../../../styles/tools/form-fields/variants';
1
+ @use '../../styles/tools/form-fields/foundation';
2
+ @use '../../styles/tools/form-fields/box-field-layout';
3
+ @use '../../styles/tools/form-fields/box-field-sizes';
4
+ @use '../../styles/tools/form-fields/variants';
5
5
 
6
6
  // Foundation
7
7
  .root {