@ilo-org/react 0.7.8 → 0.8.1

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.
Files changed (174) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/lib/cjs/components/Checkbox/Checkbox.js +28 -16
  3. package/lib/cjs/components/Checkbox/index.js +25 -3
  4. package/lib/cjs/components/DatePicker/DatePicker.js +21 -16
  5. package/lib/cjs/components/DatePicker/index.js +4 -4
  6. package/lib/cjs/components/Dropdown/Dropdown.js +19 -15
  7. package/lib/cjs/components/Dropdown/index.js +3 -3
  8. package/lib/cjs/components/Fieldset/Fieldset.js +33 -9
  9. package/lib/cjs/components/Fieldset/index.js +2 -2
  10. package/lib/cjs/components/FileUpload/FileUpload.js +29 -15
  11. package/lib/cjs/components/FileUpload/index.js +3 -3
  12. package/lib/cjs/components/Form/Form.js +8 -55
  13. package/lib/cjs/components/Form/index.js +10 -20
  14. package/lib/cjs/components/FormControl/FormControl.js +79 -0
  15. package/lib/cjs/components/FormControl/index.js +16 -0
  16. package/lib/cjs/components/Input/Input.js +1 -1
  17. package/lib/cjs/components/NumberPicker/NumberPicker.js +21 -16
  18. package/lib/cjs/components/NumberPicker/index.js +4 -4
  19. package/lib/cjs/components/Radio/Radio.js +34 -17
  20. package/lib/cjs/components/Radio/index.js +19 -4
  21. package/lib/cjs/components/TextInput/TextInput.js +30 -0
  22. package/lib/cjs/components/TextInput/index.js +52 -0
  23. package/lib/cjs/components/Textarea/Textarea.js +19 -19
  24. package/lib/cjs/components/Textarea/index.js +26 -5
  25. package/lib/cjs/components/Toggle/Toggle.js +33 -0
  26. package/lib/cjs/components/Toggle/index.js +51 -0
  27. package/lib/cjs/components/Tooltip/Tooltip.js +2 -2
  28. package/lib/cjs/components/index.js +10 -11
  29. package/lib/cjs/hooks/usePrevious.js +20 -0
  30. package/lib/cjs/index.js +10 -11
  31. package/lib/esm/components/Checkbox/Checkbox.js +31 -19
  32. package/lib/esm/components/Checkbox/index.js +27 -2
  33. package/lib/esm/components/DatePicker/DatePicker.js +22 -17
  34. package/lib/esm/components/DatePicker/index.js +4 -4
  35. package/lib/esm/components/Dropdown/Dropdown.js +20 -16
  36. package/lib/esm/components/Dropdown/index.js +3 -3
  37. package/lib/esm/components/Fieldset/Fieldset.js +31 -11
  38. package/lib/esm/components/Fieldset/index.js +1 -1
  39. package/lib/esm/components/FileUpload/FileUpload.js +31 -17
  40. package/lib/esm/components/FileUpload/index.js +3 -3
  41. package/lib/esm/components/Form/Form.js +10 -57
  42. package/lib/esm/components/Form/index.js +13 -20
  43. package/lib/esm/components/FormControl/FormControl.js +73 -0
  44. package/lib/esm/components/{ChoiceGroup → FormControl}/index.js +3 -6
  45. package/lib/esm/components/NumberPicker/NumberPicker.js +21 -16
  46. package/lib/esm/components/NumberPicker/index.js +4 -4
  47. package/lib/esm/components/Radio/Radio.js +34 -17
  48. package/lib/esm/components/Radio/index.js +21 -3
  49. package/lib/esm/components/TextInput/TextInput.js +28 -0
  50. package/lib/esm/components/TextInput/index.js +49 -0
  51. package/lib/esm/components/Textarea/Textarea.js +19 -19
  52. package/lib/esm/components/Textarea/index.js +28 -4
  53. package/lib/esm/components/Toggle/Toggle.js +31 -0
  54. package/lib/esm/components/Toggle/index.js +48 -0
  55. package/lib/esm/components/Tooltip/Tooltip.js +2 -2
  56. package/lib/esm/components/index.js +8 -5
  57. package/lib/esm/hooks/usePrevious.js +15 -0
  58. package/lib/esm/index.js +8 -5
  59. package/lib/types/react/src/components/Checkbox/Checkbox.args.d.ts +52 -0
  60. package/lib/types/react/src/components/Checkbox/Checkbox.d.ts +5 -3
  61. package/lib/types/react/src/components/Checkbox/Checkbox.props.d.ts +4 -13
  62. package/lib/types/react/src/components/Checkbox/index.d.ts +1 -0
  63. package/lib/types/react/src/components/DatePicker/DatePicker.d.ts +4 -3
  64. package/lib/types/react/src/components/DatePicker/DatePicker.props.d.ts +10 -43
  65. package/lib/types/react/src/components/Dropdown/Dropdown.d.ts +5 -3
  66. package/lib/types/react/src/components/Dropdown/Dropdown.props.d.ts +16 -42
  67. package/lib/types/react/src/components/Fieldset/Fieldset.d.ts +6 -0
  68. package/lib/types/react/src/components/Fieldset/Fieldset.props.d.ts +14 -21
  69. package/lib/types/react/src/components/FileUpload/FileUpload.d.ts +5 -3
  70. package/lib/types/react/src/components/FileUpload/FileUpload.props.d.ts +7 -44
  71. package/lib/types/react/src/components/Form/Form.args.d.ts +2 -0
  72. package/lib/types/react/src/components/Form/Form.d.ts +1 -2
  73. package/lib/types/react/src/components/Form/Form.props.d.ts +4 -111
  74. package/lib/types/react/src/components/Form/index.d.ts +1 -0
  75. package/lib/types/react/src/components/FormControl/FormControl.d.ts +9 -0
  76. package/lib/types/react/src/components/FormControl/FormControl.props.d.ts +55 -0
  77. package/lib/types/react/src/components/FormControl/index.d.ts +2 -0
  78. package/lib/types/react/src/components/FormElement/FormElement.props.d.ts +2 -2
  79. package/lib/types/react/src/components/Input/Input.props.d.ts +2 -2
  80. package/lib/types/react/src/components/NumberPicker/NumberPicker.d.ts +5 -3
  81. package/lib/types/react/src/components/NumberPicker/NumberPicker.props.d.ts +5 -42
  82. package/lib/types/react/src/components/Radio/Radio.args.d.ts +8 -0
  83. package/lib/types/react/src/components/Radio/Radio.d.ts +5 -3
  84. package/lib/types/react/src/components/Radio/Radio.props.d.ts +4 -14
  85. package/lib/types/react/src/components/Radio/index.d.ts +1 -0
  86. package/lib/types/react/src/components/TextInput/TextInput.args.d.ts +10 -0
  87. package/lib/types/react/src/components/TextInput/TextInput.d.ts +6 -0
  88. package/lib/types/react/src/components/TextInput/TextInput.props.d.ts +17 -0
  89. package/lib/types/react/src/components/TextInput/index.d.ts +2 -0
  90. package/lib/types/react/src/components/Textarea/Textarea.args.d.ts +10 -0
  91. package/lib/types/react/src/components/Textarea/Textarea.d.ts +5 -3
  92. package/lib/types/react/src/components/Textarea/Textarea.props.d.ts +17 -39
  93. package/lib/types/react/src/components/Textarea/index.d.ts +2 -0
  94. package/lib/types/react/src/components/Toggle/Toggle.args.d.ts +12 -0
  95. package/lib/types/react/src/components/Toggle/Toggle.d.ts +5 -0
  96. package/lib/types/react/src/components/Toggle/Toggle.props.d.ts +22 -0
  97. package/lib/types/react/src/components/Toggle/index.d.ts +3 -0
  98. package/lib/types/react/src/components/Tooltip/Tooltip.props.d.ts +4 -0
  99. package/lib/types/react/src/components/index.d.ts +1 -5
  100. package/lib/types/react/src/hooks/usePrevious.d.ts +2 -0
  101. package/lib/types/react/src/types/index.d.ts +57 -1
  102. package/package.json +20 -19
  103. package/src/components/Checkbox/Checkbox.args.ts +31 -9
  104. package/src/components/Checkbox/Checkbox.props.ts +5 -13
  105. package/src/components/Checkbox/Checkbox.tsx +78 -76
  106. package/src/components/Checkbox/index.ts +1 -0
  107. package/src/components/DatePicker/DatePicker.args.ts +6 -32
  108. package/src/components/DatePicker/DatePicker.props.ts +11 -51
  109. package/src/components/DatePicker/DatePicker.tsx +71 -110
  110. package/src/components/Dropdown/Dropdown.args.ts +42 -192
  111. package/src/components/Dropdown/Dropdown.props.ts +18 -49
  112. package/src/components/Dropdown/Dropdown.tsx +73 -62
  113. package/src/components/Fieldset/Fieldset.props.ts +14 -23
  114. package/src/components/Fieldset/Fieldset.tsx +75 -69
  115. package/src/components/FileUpload/FileUpload.args.ts +25 -27
  116. package/src/components/FileUpload/FileUpload.props.ts +8 -53
  117. package/src/components/FileUpload/FileUpload.tsx +103 -72
  118. package/src/components/Form/Form.args.ts +2 -184
  119. package/src/components/Form/Form.props.ts +4 -133
  120. package/src/components/Form/Form.tsx +17 -77
  121. package/src/components/Form/index.ts +1 -0
  122. package/src/components/FormControl/FormControl.props.ts +72 -0
  123. package/src/components/FormControl/FormControl.tsx +169 -0
  124. package/src/components/FormControl/index.ts +2 -0
  125. package/src/components/FormElement/FormElement.props.ts +2 -2
  126. package/src/components/Input/Input.props.ts +2 -2
  127. package/src/components/Navigation/Navigation.args.ts +2 -1
  128. package/src/components/NumberPicker/NumberPicker.args.ts +18 -26
  129. package/src/components/NumberPicker/NumberPicker.props.ts +7 -52
  130. package/src/components/NumberPicker/NumberPicker.tsx +73 -56
  131. package/src/components/Radio/Radio.args.ts +1 -7
  132. package/src/components/Radio/Radio.props.ts +6 -14
  133. package/src/components/Radio/Radio.tsx +90 -52
  134. package/src/components/Radio/index.ts +1 -0
  135. package/src/components/TextInput/TextInput.args.ts +75 -0
  136. package/src/components/TextInput/TextInput.props.ts +20 -0
  137. package/src/components/TextInput/TextInput.tsx +71 -0
  138. package/src/components/TextInput/index.ts +2 -0
  139. package/src/components/Textarea/Textarea.args.ts +19 -37
  140. package/src/components/Textarea/Textarea.props.ts +18 -46
  141. package/src/components/Textarea/Textarea.tsx +44 -59
  142. package/src/components/Textarea/index.ts +2 -0
  143. package/src/components/Toggle/Toggle.args.ts +62 -0
  144. package/src/components/Toggle/Toggle.props.ts +27 -0
  145. package/src/components/Toggle/Toggle.tsx +85 -0
  146. package/src/components/Toggle/index.ts +3 -0
  147. package/src/components/Tooltip/Tooltip.props.ts +5 -0
  148. package/src/components/Tooltip/Tooltip.tsx +2 -0
  149. package/src/components/index.ts +1 -5
  150. package/src/hooks/usePrevious.ts +15 -0
  151. package/src/types/forms.args.ts +288 -0
  152. package/src/types/index.ts +69 -1
  153. package/tsconfig.json +2 -1
  154. package/lib/cjs/components/ChoiceGroup/ChoiceGroup.js +0 -34
  155. package/lib/cjs/components/ChoiceGroup/index.js +0 -19
  156. package/lib/cjs/components/FormGroup/FormGroup.js +0 -58
  157. package/lib/cjs/components/FormGroup/index.js +0 -26
  158. package/lib/esm/components/ChoiceGroup/ChoiceGroup.js +0 -32
  159. package/lib/esm/components/FormGroup/FormGroup.js +0 -56
  160. package/lib/esm/components/FormGroup/index.js +0 -20
  161. package/lib/types/react/src/components/ChoiceGroup/ChoiceGroup.d.ts +0 -4
  162. package/lib/types/react/src/components/ChoiceGroup/ChoiceGroup.props.d.ts +0 -20
  163. package/lib/types/react/src/components/ChoiceGroup/index.d.ts +0 -1
  164. package/lib/types/react/src/components/FormGroup/FormGroup.d.ts +0 -4
  165. package/lib/types/react/src/components/FormGroup/FormGroup.props.d.ts +0 -81
  166. package/lib/types/react/src/components/FormGroup/index.d.ts +0 -1
  167. package/src/components/ChoiceGroup/ChoiceGroup.args.ts +0 -95
  168. package/src/components/ChoiceGroup/ChoiceGroup.props.ts +0 -25
  169. package/src/components/ChoiceGroup/ChoiceGroup.tsx +0 -54
  170. package/src/components/ChoiceGroup/index.ts +0 -1
  171. package/src/components/FormGroup/FormGroup.args.ts +0 -85
  172. package/src/components/FormGroup/FormGroup.props.ts +0 -102
  173. package/src/components/FormGroup/FormGroup.tsx +0 -73
  174. package/src/components/FormGroup/index.ts +0 -1
@@ -1,137 +1,8 @@
1
- import { CheckboxProps } from "../Checkbox/Checkbox.props";
2
- import { DatePickerProps } from "../DatePicker/DatePicker.props";
3
- import { DropdownProps } from "../Dropdown/Dropdown.props";
4
- import { FileUploadProps } from "../FileUpload/FileUpload.props";
5
- import { NumberPickerProps } from "../NumberPicker/NumberPicker.props";
6
- import { RadioProps } from "../Radio/Radio.props";
7
- import { TextareaProps } from "../Textarea/Textarea.props";
8
- import { InputProps } from "../Input/Input.props";
9
- import { FormGroupProps } from "../FormGroup/FormGroup.props";
10
-
11
- export interface InputItem {
12
- type: "input";
13
- field: InputProps;
14
- choicegroupid?: never;
15
- legend?: never;
16
- grouptooltip?: never;
17
- grouperror?: never;
18
- grouphelper?: never;
19
- }
20
-
21
- export interface DropdownItem {
22
- type: "dropdown";
23
- field: DropdownProps;
24
- choicegroupid?: never;
25
- legend?: never;
26
- grouptooltip?: never;
27
- grouperror?: never;
28
- grouphelper?: never;
29
- }
30
-
31
- export interface CheckboxItem {
32
- type: "checkbox";
33
- field: CheckboxProps | CheckboxProps[];
34
- choicegroupid: string;
35
- legend?: string;
36
- grouptooltip?: string;
37
- grouperror?: string;
38
- grouphelper?: string;
39
- }
40
-
41
- export interface RadioItem {
42
- type: "radio";
43
- field: RadioProps | RadioProps[];
44
- choicegroupid: string;
45
- legend?: string;
46
- grouptooltip?: string;
47
- grouperror?: string;
48
- grouphelper?: string;
49
- }
50
-
51
- export interface FileUploadItem {
52
- type: "file";
53
- field: FileUploadProps;
54
- choicegroupid?: never;
55
- legend?: never;
56
- grouptooltip?: never;
57
- grouperror?: never;
58
- grouphelper?: never;
59
- }
60
-
61
- export interface NumberPickerItem {
62
- type: "number";
63
- field: NumberPickerProps;
64
- choicegroupid?: never;
65
- legend?: never;
66
- grouptooltip?: never;
67
- grouperror?: never;
68
- grouphelper?: never;
69
- }
70
-
71
- export interface DatePickerItem {
72
- type: "date";
73
- field: DatePickerProps;
74
- choicegroupid?: never;
75
- legend?: never;
76
- grouptooltip?: never;
77
- grouperror?: never;
78
- grouphelper?: never;
79
- }
80
-
81
- export interface TextareaItem {
82
- type: "textarea";
83
- field: TextareaProps;
84
- choicegroupid?: never;
85
- legend?: never;
86
- grouptooltip?: never;
87
- grouperror?: never;
88
- grouphelper?: never;
89
- }
90
-
91
- export interface FormGroupItem {
92
- type: "formgroup";
93
- field: FormGroupProps;
94
- choicegroupid?: string;
95
- legend?: string;
96
- grouptooltip?: string;
97
- grouperror?: string;
98
- grouphelper?: string;
99
- }
100
-
101
- type FormItem =
102
- | InputItem
103
- | DropdownItem
104
- | CheckboxItem
105
- | RadioItem
106
- | FileUploadItem
107
- | NumberPickerItem
108
- | DatePickerItem
109
- | TextareaItem
110
- | FormGroupItem;
111
-
112
- export interface FormProps {
113
- /**
114
- * The form's action attribute
115
- */
116
- action: Required<string>;
117
-
118
- /**
119
- * Specify an optional className to be added to your Form component.
120
- */
121
- className?: string;
122
-
123
- /**
124
- * The ID of the form
125
- */
126
- formid: Required<string>;
127
-
128
- /**
129
- * The inputs in this form group
130
- */
131
- items: FormItem[];
1
+ export interface FormProps extends React.FormHTMLAttributes<HTMLFormElement> {
2
+ children?: React.ReactNode;
132
3
 
133
4
  /**
134
- * The label for the form's submit button
5
+ * The theme of the form. Also sets the theme of the form's children.
135
6
  */
136
- submitlabel: string;
7
+ theme?: "light" | "dark";
137
8
  }
@@ -1,83 +1,23 @@
1
- import { FC } from "react";
1
+ import { forwardRef } from "react";
2
+ import { useGlobalSettings } from "../../hooks";
2
3
  import classNames from "classnames";
3
- import useGlobalSettings from "../../hooks/useGlobalSettings";
4
- import { Button } from "../Button";
5
4
  import { FormProps } from "./Form.props";
6
- import { FormGroup } from "../FormGroup";
7
- import { Checkbox } from "../Checkbox";
8
- import { ChoiceGroup } from "../ChoiceGroup";
9
- import { DatePicker } from "../DatePicker";
10
- import { Dropdown } from "../Dropdown";
11
- import { FileUpload } from "../FileUpload";
12
- import { Input } from "../Input";
13
- import { NumberPicker } from "../NumberPicker";
14
- import { Textarea } from "../Textarea";
15
5
 
16
- const Form: FC<FormProps> = ({
17
- action,
18
- className,
19
- formid,
20
- items,
21
- submitlabel,
22
- }) => {
23
- const { prefix } = useGlobalSettings();
24
- const baseClass = `${prefix}--form`;
25
- const formClasses = classNames(className, {
26
- [baseClass]: true,
27
- });
6
+ const Form = forwardRef<HTMLFormElement, FormProps>(
7
+ ({ children, theme = "light", ...props }, ref) => {
8
+ const { prefix } = useGlobalSettings();
28
9
 
29
- return (
30
- <form className={formClasses} id={formid} action={action}>
31
- {items.map((item, i) => {
32
- if (item?.type === "input") {
33
- return <Input {...(item?.field as any)} key={i} />;
34
- }
35
- if (item?.type === "dropdown") {
36
- return <Dropdown {...(item?.field as any)} key={i} />;
37
- }
38
- if (item?.type === "checkbox" && Array.isArray(item?.field) === false) {
39
- return <Checkbox {...(item?.field as any)} key={i} />;
40
- }
41
- if (
42
- (item?.type === "checkbox" || item?.type === "radio") &&
43
- Array.isArray(item?.field)
44
- ) {
45
- return (
46
- <ChoiceGroup
47
- items={item?.field as any}
48
- legend={item?.legend as any}
49
- choicegroupid={item?.choicegroupid as any}
50
- grouperror={item?.grouperror as any}
51
- grouphelper={item?.grouphelper as any}
52
- grouptooltip={item?.grouptooltip as any}
53
- key={i}
54
- />
55
- );
56
- }
57
- if (item?.type === "file") {
58
- return <FileUpload {...(item?.field as any)} key={i} />;
59
- }
60
- if (item?.type === "date") {
61
- return <DatePicker {...(item?.field as any)} key={i} />;
62
- }
63
- if (item?.type === "number") {
64
- return <NumberPicker {...(item?.field as any)} key={i} />;
65
- }
66
- if (item?.type === "textarea") {
67
- return <Textarea {...(item?.field as any)} key={i} />;
68
- }
69
- if (item?.type === "formgroup") {
70
- return <FormGroup {...(item?.field as any)} key={i} />;
71
- }
72
- })}
73
- <Button
74
- kind={"submit"}
75
- label={submitlabel}
76
- size={"large"}
77
- type={"primary"}
78
- />
79
- </form>
80
- );
81
- };
10
+ const baseClass = `${prefix}--form`;
11
+ const themeClass = `${baseClass}__theme__${theme}`;
12
+
13
+ const formClasses = classNames(baseClass, themeClass);
14
+
15
+ return (
16
+ <form ref={ref} className={formClasses} {...props}>
17
+ {children}
18
+ </form>
19
+ );
20
+ }
21
+ );
82
22
 
83
23
  export default Form;
@@ -1 +1,2 @@
1
1
  export { default as Form } from "./Form";
2
+ export * as FormArgs from "./Form.args";
@@ -0,0 +1,72 @@
1
+ import { ReactElement } from "react";
2
+ import { DropdownProps } from "../Dropdown/Dropdown.props";
3
+ import { InputProps } from "../Input/Input.props";
4
+ import { TextareaProps } from "../Textarea";
5
+ import { ToggleProps } from "../Toggle";
6
+
7
+ export interface FormControlPublicProps {
8
+ /**
9
+ * Optional className to add to the FormControl wrapper
10
+ */
11
+ className?: string;
12
+
13
+ /**
14
+ * Is the input disabled?
15
+ */
16
+ disabled?: boolean;
17
+
18
+ /**
19
+ * Does the input have an error?
20
+ */
21
+ error?: boolean;
22
+
23
+ /**
24
+ * The message to display in case of an error
25
+ */
26
+ errorMessage?: string;
27
+
28
+ /**
29
+ * Helper text to display with the label
30
+ */
31
+ helper?: string;
32
+
33
+ /**
34
+ * The FormControl's label
35
+ */
36
+ label: string;
37
+
38
+ /**
39
+ * Where to place the label
40
+ */
41
+ labelPlacement?: "top" | "start" | "bottom" | "end";
42
+
43
+ /**
44
+ * The size of your label. Defaults to "medium"
45
+ */
46
+ labelSize?: "small" | "medium" | "large";
47
+
48
+ /**
49
+ * Inline styles for the input
50
+ */
51
+ style?: React.CSSProperties;
52
+
53
+ /**
54
+ * Optional text to render in a tooltip
55
+ */
56
+ tooltip?: string;
57
+ }
58
+
59
+ export interface FormControlPrivateProps {
60
+ /**
61
+ * The id of the underlying input element
62
+ */
63
+ fieldId: string;
64
+
65
+ children:
66
+ | ReactElement<ToggleProps>
67
+ | ReactElement<InputProps>
68
+ | ReactElement<DropdownProps>
69
+ | ReactElement<TextareaProps>;
70
+ }
71
+
72
+ export type FormControlProps = FormControlPublicProps & FormControlPrivateProps;
@@ -0,0 +1,169 @@
1
+ import classnames from "classnames";
2
+ import { nanoid } from "nanoid";
3
+ import {
4
+ FC,
5
+ createContext,
6
+ useContext,
7
+ useEffect,
8
+ useMemo,
9
+ useState,
10
+ } from "react";
11
+ import { useGlobalSettings } from "../../hooks";
12
+ import { Tooltip } from "../Tooltip";
13
+ import { FormControlProps } from "./FormControl.props";
14
+
15
+ interface AllyFields {
16
+ tooltip?: string;
17
+ helper?: string;
18
+ errorMessage?: string;
19
+ }
20
+
21
+ interface AllyFieldsIds {
22
+ tooltipId?: string;
23
+ helperId?: string;
24
+ errorId?: string;
25
+ }
26
+
27
+ export interface FormControlContextProps {
28
+ ariaDescribedBy?: string;
29
+ }
30
+
31
+ // Calculates unique IDs for the internal accessibility elements
32
+ // TODO: When we upgrade to React 8, this should use useId instead
33
+ function getA11yFields(
34
+ baseClass = "",
35
+ { tooltip, helper, errorMessage }: AllyFields = {}
36
+ ) {
37
+ return {
38
+ tooltipId: tooltip && `${baseClass}--tooltip--${nanoid()}`,
39
+ helperId: helper && `${baseClass}--helper--${nanoid()}`,
40
+ errorId: errorMessage && `${baseClass}--error--${nanoid()}`,
41
+ };
42
+ }
43
+
44
+ // Calculates the aria-describedby attribute value based on whether or not there's an error
45
+ function getAriaDescribedBy(getAllyFields: AllyFieldsIds, hasError?: boolean) {
46
+ const { tooltipId, helperId, errorId } = getAllyFields;
47
+
48
+ const ariaDescribedBy = classnames(tooltipId, {
49
+ [`${helperId}`]: !hasError,
50
+ [`${errorId}`]: hasError,
51
+ });
52
+
53
+ // For some reason, classnames seems to return "undefined" as a string sometimes
54
+ if (!ariaDescribedBy || ariaDescribedBy === "undefined") {
55
+ return undefined;
56
+ }
57
+ return ariaDescribedBy;
58
+ }
59
+
60
+ // The context passed down to form elements wrapped by the form control
61
+ export const FormControlContext: React.Context<FormControlContextProps> =
62
+ createContext({});
63
+
64
+ // Hook to get the context value
65
+ export const useFormControl = () => useContext(FormControlContext);
66
+
67
+ const FormControl: FC<FormControlProps> = ({
68
+ children,
69
+ className,
70
+ label,
71
+ helper,
72
+ errorMessage,
73
+ tooltip,
74
+ style,
75
+ error,
76
+ disabled,
77
+ fieldId,
78
+ labelSize = "medium",
79
+ labelPlacement = "top",
80
+ }) => {
81
+ const { prefix } = useGlobalSettings();
82
+
83
+ // Classes applied to the outer container
84
+ const baseClass = `${prefix}--form-control`;
85
+
86
+ // The ids of the tooltip, helper, and error only get calculated on first render
87
+ const a11yFields = useMemo(
88
+ () => getA11yFields(baseClass, { helper, errorMessage, tooltip }),
89
+ [baseClass, helper, errorMessage, tooltip]
90
+ );
91
+
92
+ // The ids of the tooltip, helper, and error
93
+ const { tooltipId, helperId, errorId } = a11yFields;
94
+
95
+ // The aria-describedby attribute value
96
+ const [ariaDescribedBy, setAriaDescribedBy] = useState<string | undefined>(
97
+ undefined
98
+ );
99
+
100
+ // Update the aria-describedby attribute value when the error changes
101
+ useEffect(() => {
102
+ setAriaDescribedBy(
103
+ getAriaDescribedBy({ tooltipId, helperId, errorId }, error)
104
+ );
105
+ }, [tooltipId, helperId, errorId, error]);
106
+
107
+ // The context passed down to form elements wrapped by the form control
108
+ const contextValue: FormControlContextProps = {
109
+ ariaDescribedBy,
110
+ };
111
+
112
+ // Classes applied to the outer container
113
+ const errorClass = `${baseClass}__error`;
114
+ const disabledClass = `${baseClass}__disabled`;
115
+ const labelPlacementClass = `${baseClass}__label-placement__${labelPlacement}`;
116
+
117
+ const formControlClass = classnames(
118
+ baseClass,
119
+ className,
120
+ labelPlacementClass,
121
+ [{ [errorClass]: error }, { [disabledClass]: disabled }]
122
+ );
123
+
124
+ // Classes applies to the label
125
+ const labelBaseClass = `${baseClass}--label`;
126
+ const labelSizeClass = `${labelBaseClass}__size__${labelSize}`;
127
+ const labelClass = classnames(labelBaseClass, labelSizeClass);
128
+
129
+ // Helper class
130
+ const helperClass = `${baseClass}--helper`;
131
+
132
+ // Show the error message if there is an error and an error message
133
+ const showError = !!error && !!errorMessage;
134
+
135
+ // Show the helper text if there is no error and a helper text
136
+ const showHelper = !showError && !!helper;
137
+
138
+ return (
139
+ <FormControlContext.Provider value={contextValue}>
140
+ <div className={formControlClass} style={style}>
141
+ <span className={labelClass}>
142
+ <label htmlFor={fieldId}>{label}</label>
143
+ {tooltip && (
144
+ <Tooltip
145
+ id={tooltipId}
146
+ className={`${baseClass}--legend--tooltip`}
147
+ icon={true}
148
+ label={tooltip}
149
+ theme={"dark"}
150
+ />
151
+ )}
152
+ </span>
153
+ {children}
154
+ {showHelper && (
155
+ <span id={helperId} className={helperClass}>
156
+ {helper}
157
+ </span>
158
+ )}
159
+ {showError && (
160
+ <span id={errorId} className={helperClass} aria-live="assertive">
161
+ {errorMessage}
162
+ </span>
163
+ )}
164
+ </div>
165
+ </FormControlContext.Provider>
166
+ );
167
+ };
168
+
169
+ export default FormControl;
@@ -0,0 +1,2 @@
1
+ export { default as FormControl } from "./FormControl";
2
+ export type { FormControlProps } from "./FormControl.props";
@@ -1,5 +1,5 @@
1
1
  import { ReactElement } from "react";
2
- import { InputTypes, FieldTypes } from "../../types";
2
+ import { TextInputTypes, FieldTypes } from "../../types";
3
3
  import { DropdownProps } from "../Dropdown/Dropdown.props";
4
4
  import { InputProps } from "../Input/Input.props";
5
5
  import { TextareaProps } from "../Textarea/Textarea.props";
@@ -56,5 +56,5 @@ export interface FormElementProps {
56
56
  /**
57
57
  * The type of field
58
58
  */
59
- type?: InputTypes | FieldTypes;
59
+ type?: TextInputTypes | FieldTypes;
60
60
  }
@@ -1,4 +1,4 @@
1
- import { InputTypes } from "../../types";
1
+ import { TextInputTypes } from "../../types";
2
2
 
3
3
  export interface InputProps {
4
4
  /**
@@ -59,5 +59,5 @@ export interface InputProps {
59
59
  /**
60
60
  * The input's type.
61
61
  */
62
- type: InputTypes;
62
+ type: TextInputTypes;
63
63
  }
@@ -1,9 +1,10 @@
1
1
  import { NavigationProps } from "./Navigation.props";
2
2
  import ilo_logo_white from "@ilo-org/brand-assets/logo_en_horizontal_white.svg";
3
+ import ilo_logo_blue from "@ilo-org/brand-assets/logo_en_horizontal_blue.svg";
3
4
 
4
5
  const basic: NavigationProps = {
5
6
  logo: ilo_logo_white,
6
- mobilelogo: ilo_logo_white,
7
+ mobilelogo: ilo_logo_blue,
7
8
  siteurl: "https://www.ilo.org/",
8
9
  tagline: {
9
10
  tag: "Advancing social justice, promoting decent work",
@@ -1,53 +1,45 @@
1
- import { NumberPickerProps } from "./NumberPicker.props";
1
+ import { LabelledNumberPickerProps } from "./NumberPicker.props";
2
2
 
3
- const basic: NumberPickerProps = {
4
- callback: () => {},
3
+ const basic: LabelledNumberPickerProps = {
4
+ label: "How many items would you like?",
5
+ id: "numberpicker",
5
6
  disabled: false,
6
7
  error: false,
7
- helper: false,
8
- label: "Number Picker Field Label",
9
8
  name: "text",
10
- placeholder: "Number Picker Field",
9
+ placeholder: "Select a number",
11
10
  required: false,
12
11
  };
13
12
 
14
- const hashelper: NumberPickerProps = {
15
- callback: () => {},
13
+ const hashelper: LabelledNumberPickerProps = {
14
+ label: "How many items would you like?",
15
+ id: "numberpicker",
16
16
  disabled: false,
17
17
  error: false,
18
- helper: "Here is the helper text",
19
- label: "Number Picker Field Label",
20
18
  name: "text",
21
- placeholder: "Number Picker Field",
19
+ placeholder: "Select a number",
22
20
  required: false,
23
21
  };
24
22
 
25
- const haserror: NumberPickerProps = {
26
- callback: () => {},
23
+ const haserror: LabelledNumberPickerProps = {
24
+ label: "How many items would you like?",
25
+ id: "numberpicker",
27
26
  disabled: false,
28
- error: "This one has an error",
29
- helper: false,
30
- label: "Number Picker Field Label",
27
+ error: true,
31
28
  name: "text",
32
- placeholder: "Number Picker Field",
29
+ placeholder: "Select a number",
33
30
  required: false,
34
31
  };
35
32
 
36
- const hastooltip: NumberPickerProps = {
37
- callback: () => {},
33
+ const hastooltip: LabelledNumberPickerProps = {
34
+ label: "How many items would you like?",
35
+ id: "numberpicker",
38
36
  disabled: false,
39
37
  error: false,
40
- helper: false,
41
- label: "Number Picker Field Label",
42
38
  name: "text",
43
- placeholder: "Number Picker Field",
39
+ placeholder: "Select a number",
44
40
  required: false,
45
- tooltip: "This is the tooltip",
46
41
  };
47
42
 
48
- /**
49
- * Sample prop definitions NumberPicker's enumerable properties (imported in stories and test)
50
- */
51
43
  const NumberPickerArgs = {
52
44
  basic,
53
45
  hashelper,
@@ -1,56 +1,11 @@
1
- export interface NumberPickerProps {
1
+ import { FormFieldProps } from "../../types";
2
+ import { LabelledFormFieldProps } from "../../types";
3
+ export interface NumberPickerProps extends FormFieldProps<HTMLInputElement> {
2
4
  /**
3
- * The input's onChange callback.
4
- */
5
- callback: (e: React.ChangeEvent<HTMLInputElement>) => any;
6
-
7
- /**
8
- * Specify an optional className to be added to your input.
9
- */
10
- className?: string;
11
-
12
- /**
13
- * Is the input disabled?
14
- */
15
- disabled?: boolean;
16
-
17
- /**
18
- * Does the input have an error?
19
- */
20
- error?: string | false;
21
-
22
- /**
23
- * The input's helper text
24
- */
25
- helper: string | false;
26
-
27
- /**
28
- * The input's id attribute
29
- */
30
- id?: string;
31
-
32
- /**
33
- * Does this input have a label?
34
- */
35
- label: string;
36
-
37
- /**
38
- * The input's name attribute
39
- */
40
- name?: Required<string>;
41
-
42
- /**
43
- * Specify an optional className to be added to your NumberPicker component.
5
+ * The placeholder text when the input is empty.
44
6
  */
45
7
  placeholder?: string;
46
-
47
- /**
48
- * Specify whether this input is required
49
- */
50
- required?: boolean;
51
-
52
- /**
53
- * Does this NumberPicker have a tooltip?
54
- */
55
- tooltip?: string;
56
8
  }
9
+
10
+ export type LabelledNumberPickerProps =
11
+ LabelledFormFieldProps<NumberPickerProps>;