@bspk/ui 1.3.20 → 1.3.22

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 (290) hide show
  1. package/dist/components/Accordion/Accordion.js +1 -1
  2. package/dist/components/Accordion/Accordion.js.map +1 -1
  3. package/dist/components/Accordion/accordion.css +19 -12
  4. package/dist/components/Accordion/accordion.css.js +19 -12
  5. package/dist/components/BottomNavigation/BottomNavigation.d.ts +0 -1
  6. package/dist/components/BottomNavigation/BottomNavigation.js +0 -1
  7. package/dist/components/BottomNavigation/BottomNavigation.js.map +1 -1
  8. package/dist/components/BottomNavigation/bottom-navigation.css +1 -0
  9. package/dist/components/BottomNavigation/bottom-navigation.css.js +1 -0
  10. package/dist/components/Button/button.css +4 -0
  11. package/dist/components/Button/button.css.js +4 -0
  12. package/dist/components/Checkbox/Checkbox.js +3 -3
  13. package/dist/components/Checkbox/Checkbox.js.map +1 -1
  14. package/dist/components/CheckboxGroup/CheckboxGroup.d.ts +4 -5
  15. package/dist/components/CheckboxGroup/CheckboxGroup.js +8 -13
  16. package/dist/components/CheckboxGroup/CheckboxGroup.js.map +1 -1
  17. package/dist/components/CheckboxGroup/CheckboxGroupExample.js +5 -0
  18. package/dist/components/CheckboxGroup/CheckboxGroupExample.js.map +1 -1
  19. package/dist/components/CheckboxGroup/checkbox-group.css +2 -0
  20. package/dist/components/CheckboxGroup/checkbox-group.css.js +2 -0
  21. package/dist/components/CheckboxGroupField/CheckboxGroupField.d.ts +3 -3
  22. package/dist/components/CheckboxGroupField/CheckboxGroupField.js +6 -4
  23. package/dist/components/CheckboxGroupField/CheckboxGroupField.js.map +1 -1
  24. package/dist/components/ChipGroup/ChipGroup.d.ts +0 -1
  25. package/dist/components/ChipGroup/ChipGroup.js +0 -1
  26. package/dist/components/ChipGroup/ChipGroup.js.map +1 -1
  27. package/dist/components/ChipGroup/chip-group.css +3 -0
  28. package/dist/components/ChipGroup/chip-group.css.js +3 -0
  29. package/dist/components/DatePicker/DatePicker.d.ts +4 -8
  30. package/dist/components/DatePicker/DatePicker.js +6 -18
  31. package/dist/components/DatePicker/DatePicker.js.map +1 -1
  32. package/dist/components/DatePicker/DatePickerExample.js +3 -3
  33. package/dist/components/DatePicker/DatePickerExample.js.map +1 -1
  34. package/dist/components/DatePickerField/DatePickerField.d.ts +4 -4
  35. package/dist/components/DatePickerField/DatePickerField.js +6 -4
  36. package/dist/components/DatePickerField/DatePickerField.js.map +1 -1
  37. package/dist/components/Dialog/Dialog.d.ts +2 -3
  38. package/dist/components/Dialog/Dialog.js +2 -3
  39. package/dist/components/Dialog/Dialog.js.map +1 -1
  40. package/dist/components/Fab/Fab.d.ts +8 -5
  41. package/dist/components/Fab/Fab.js +8 -5
  42. package/dist/components/Fab/Fab.js.map +1 -1
  43. package/dist/components/Fab/fab.css +1 -0
  44. package/dist/components/Fab/fab.css.js +1 -0
  45. package/dist/components/Field/Field.d.ts +32 -18
  46. package/dist/components/Field/Field.js +8 -38
  47. package/dist/components/Field/Field.js.map +1 -1
  48. package/dist/components/Field/FieldExample.d.ts +1 -0
  49. package/dist/components/Field/FieldExample.js +10 -3
  50. package/dist/components/Field/FieldExample.js.map +1 -1
  51. package/dist/components/Field/Fieldset.d.ts +40 -0
  52. package/dist/components/Field/Fieldset.js +44 -0
  53. package/dist/components/Field/Fieldset.js.map +1 -0
  54. package/dist/components/Field/field.css +5 -7
  55. package/dist/components/Field/field.css.js +5 -7
  56. package/dist/components/Field/index.d.ts +1 -3
  57. package/dist/components/Field/index.js +1 -3
  58. package/dist/components/Field/index.js.map +1 -1
  59. package/dist/components/Field/utils.d.ts +8 -38
  60. package/dist/components/Field/utils.js +6 -33
  61. package/dist/components/Field/utils.js.map +1 -1
  62. package/dist/components/FileUpload/FileUpload.js +1 -1
  63. package/dist/components/FileUpload/FileUpload.js.map +1 -1
  64. package/dist/components/FileUploadItem/FileUploadItem.js +1 -1
  65. package/dist/components/FileUploadItem/FileUploadItem.js.map +1 -1
  66. package/dist/components/Flex/Flex.d.ts +11 -7
  67. package/dist/components/Flex/Flex.js +12 -8
  68. package/dist/components/Flex/Flex.js.map +1 -1
  69. package/dist/components/InlineAlert/InlineAlert.d.ts +2 -2
  70. package/dist/components/InlineAlert/InlineAlert.js +2 -2
  71. package/dist/components/InlineAlert/InlineAlert.js.map +1 -1
  72. package/dist/components/Input/Input.d.ts +60 -15
  73. package/dist/components/Input/Input.js +42 -25
  74. package/dist/components/Input/Input.js.map +1 -1
  75. package/dist/components/Input/InputExample.js +4 -4
  76. package/dist/components/Input/InputExample.js.map +1 -1
  77. package/dist/components/Input/index.d.ts +0 -1
  78. package/dist/components/Input/index.js +0 -1
  79. package/dist/components/Input/index.js.map +1 -1
  80. package/dist/components/InputField/InputField.d.ts +4 -4
  81. package/dist/components/InputField/InputField.js +6 -4
  82. package/dist/components/InputField/InputField.js.map +1 -1
  83. package/dist/components/InputNumber/InputNumber.d.ts +8 -7
  84. package/dist/components/InputNumber/InputNumber.js +9 -16
  85. package/dist/components/InputNumber/InputNumber.js.map +1 -1
  86. package/dist/components/InputNumber/InputNumberExample.js +3 -3
  87. package/dist/components/InputNumber/InputNumberExample.js.map +1 -1
  88. package/dist/components/InputNumber/input-number.css +1 -0
  89. package/dist/components/InputNumber/input-number.css.js +1 -0
  90. package/dist/components/InputNumberField/InputNumberField.d.ts +4 -4
  91. package/dist/components/InputNumberField/InputNumberField.js +6 -4
  92. package/dist/components/InputNumberField/InputNumberField.js.map +1 -1
  93. package/dist/components/InputPhone/InputPhone.d.ts +8 -8
  94. package/dist/components/InputPhone/InputPhone.js +12 -18
  95. package/dist/components/InputPhone/InputPhone.js.map +1 -1
  96. package/dist/components/InputPhone/InputPhoneExample.js +3 -3
  97. package/dist/components/InputPhone/InputPhoneExample.js.map +1 -1
  98. package/dist/components/InputPhone/input-phone.css +1 -0
  99. package/dist/components/InputPhone/input-phone.css.js +1 -0
  100. package/dist/components/InputPhoneField/InputPhoneField.d.ts +4 -4
  101. package/dist/components/InputPhoneField/InputPhoneField.js +6 -4
  102. package/dist/components/InputPhoneField/InputPhoneField.js.map +1 -1
  103. package/dist/components/ListItem/list-item.css +1 -0
  104. package/dist/components/ListItem/list-item.css.js +1 -0
  105. package/dist/components/Modal/Modal.js +22 -26
  106. package/dist/components/Modal/Modal.js.map +1 -1
  107. package/dist/components/Modal/ModalExample.js +4 -1
  108. package/dist/components/Modal/ModalExample.js.map +1 -1
  109. package/dist/components/Modal/modal.css +4 -2
  110. package/dist/components/Modal/modal.css.js +4 -2
  111. package/dist/components/OTPInput/otp-input.css +1 -0
  112. package/dist/components/OTPInput/otp-input.css.js +1 -0
  113. package/dist/components/Pagination/Pagination.js +2 -2
  114. package/dist/components/Pagination/Pagination.js.map +1 -1
  115. package/dist/components/Password/Password.d.ts +9 -7
  116. package/dist/components/Password/Password.js +13 -17
  117. package/dist/components/Password/Password.js.map +1 -1
  118. package/dist/components/Password/PasswordExample.js +3 -3
  119. package/dist/components/Password/PasswordExample.js.map +1 -1
  120. package/dist/components/PasswordField/PasswordField.d.ts +4 -4
  121. package/dist/components/PasswordField/PasswordField.js +6 -4
  122. package/dist/components/PasswordField/PasswordField.js.map +1 -1
  123. package/dist/components/Popover/Popover.d.ts +0 -1
  124. package/dist/components/Popover/Popover.js +0 -1
  125. package/dist/components/Popover/Popover.js.map +1 -1
  126. package/dist/components/RadioGroup/RadioGroup.d.ts +1 -2
  127. package/dist/components/RadioGroup/RadioGroup.js +5 -11
  128. package/dist/components/RadioGroup/RadioGroup.js.map +1 -1
  129. package/dist/components/RadioGroupField/RadioGroupField.d.ts +3 -3
  130. package/dist/components/RadioGroupField/RadioGroupField.js +6 -4
  131. package/dist/components/RadioGroupField/RadioGroupField.js.map +1 -1
  132. package/dist/components/SearchBar/SearchBar.d.ts +0 -1
  133. package/dist/components/SearchBar/SearchBar.js +0 -1
  134. package/dist/components/SearchBar/SearchBar.js.map +1 -1
  135. package/dist/components/SegmentedControl/SegmentedControl.d.ts +0 -1
  136. package/dist/components/SegmentedControl/SegmentedControl.js +0 -1
  137. package/dist/components/SegmentedControl/SegmentedControl.js.map +1 -1
  138. package/dist/components/Select/Select.d.ts +7 -6
  139. package/dist/components/Select/Select.js +10 -15
  140. package/dist/components/Select/Select.js.map +1 -1
  141. package/dist/components/Select/SelectExample.js +3 -3
  142. package/dist/components/Select/SelectExample.js.map +1 -1
  143. package/dist/components/SelectField/SelectField.d.ts +4 -4
  144. package/dist/components/SelectField/SelectField.js +6 -4
  145. package/dist/components/SelectField/SelectField.js.map +1 -1
  146. package/dist/components/Slider/Slider.d.ts +1 -2
  147. package/dist/components/Slider/Slider.js +1 -2
  148. package/dist/components/Slider/Slider.js.map +1 -1
  149. package/dist/components/Snackbar/Snackbar.d.ts +0 -1
  150. package/dist/components/Snackbar/Snackbar.js +0 -1
  151. package/dist/components/Snackbar/Snackbar.js.map +1 -1
  152. package/dist/components/Switch/Switch.d.ts +0 -1
  153. package/dist/components/Switch/Switch.js +0 -1
  154. package/dist/components/Switch/Switch.js.map +1 -1
  155. package/dist/components/TabGroup/TabGroup.d.ts +0 -1
  156. package/dist/components/TabGroup/TabGroup.js +0 -1
  157. package/dist/components/TabGroup/TabGroup.js.map +1 -1
  158. package/dist/components/TabList/TabList.d.ts +0 -1
  159. package/dist/components/TabList/TabList.js +0 -1
  160. package/dist/components/TabList/TabList.js.map +1 -1
  161. package/dist/components/TabList/tab-list.css +1 -0
  162. package/dist/components/TabList/tab-list.css.js +1 -0
  163. package/dist/components/Table/table.css +2 -1
  164. package/dist/components/Table/table.css.js +2 -1
  165. package/dist/components/Textarea/Textarea.d.ts +4 -7
  166. package/dist/components/Textarea/Textarea.js +5 -16
  167. package/dist/components/Textarea/Textarea.js.map +1 -1
  168. package/dist/components/Textarea/TextareaExample.js +3 -3
  169. package/dist/components/Textarea/TextareaExample.js.map +1 -1
  170. package/dist/components/TextareaField/TextareaField.d.ts +4 -4
  171. package/dist/components/TextareaField/TextareaField.js +6 -4
  172. package/dist/components/TextareaField/TextareaField.js.map +1 -1
  173. package/dist/components/TimePicker/TimePicker.d.ts +8 -6
  174. package/dist/components/TimePicker/TimePicker.js +10 -14
  175. package/dist/components/TimePicker/TimePicker.js.map +1 -1
  176. package/dist/components/TimePicker/TimePickerExample.js +3 -3
  177. package/dist/components/TimePicker/TimePickerExample.js.map +1 -1
  178. package/dist/components/TimePickerField/TimePickerField.d.ts +4 -4
  179. package/dist/components/TimePickerField/TimePickerField.js +6 -4
  180. package/dist/components/TimePickerField/TimePickerField.js.map +1 -1
  181. package/dist/types/common.d.ts +2 -0
  182. package/dist/types/common.js.map +1 -1
  183. package/dist/utils/demo.js +1 -1
  184. package/dist/utils/demo.js.map +1 -1
  185. package/package.json +3 -4
  186. package/src/components/Accordion/Accordion.tsx +2 -2
  187. package/src/components/Accordion/accordion.scss +10 -1
  188. package/src/components/BottomNavigation/BottomNavigation.tsx +0 -1
  189. package/src/components/BottomNavigation/bottom-navigation.scss +1 -0
  190. package/src/components/Button/button.scss +4 -0
  191. package/src/components/Checkbox/Checkbox.tsx +3 -3
  192. package/src/components/CheckboxGroup/CheckboxGroup.tsx +37 -52
  193. package/src/components/CheckboxGroup/CheckboxGroupExample.tsx +6 -0
  194. package/src/components/CheckboxGroup/checkbox-group.scss +2 -0
  195. package/src/components/CheckboxGroupField/CheckboxGroupField.tsx +15 -11
  196. package/src/components/ChipGroup/ChipGroup.tsx +0 -1
  197. package/src/components/ChipGroup/chip-group.scss +4 -0
  198. package/src/components/DatePicker/DatePicker.tsx +9 -20
  199. package/src/components/DatePicker/DatePickerExample.tsx +3 -5
  200. package/src/components/DatePickerField/DatePickerField.rtl.test.tsx +1 -1
  201. package/src/components/DatePickerField/DatePickerField.tsx +10 -6
  202. package/src/components/Dialog/Dialog.tsx +2 -3
  203. package/src/components/Fab/Fab.tsx +8 -5
  204. package/src/components/Fab/fab.scss +1 -0
  205. package/src/components/Field/Field.rtl.test.tsx +8 -6
  206. package/src/components/Field/Field.tsx +64 -61
  207. package/src/components/Field/FieldExample.tsx +27 -5
  208. package/src/components/Field/Fieldset.tsx +78 -0
  209. package/src/components/Field/field.scss +23 -27
  210. package/src/components/Field/index.tsx +1 -3
  211. package/src/components/Field/utils.ts +15 -77
  212. package/src/components/FileUpload/FileUpload.tsx +1 -1
  213. package/src/components/FileUploadItem/FileUploadItem.tsx +1 -1
  214. package/src/components/Flex/Flex.tsx +12 -7
  215. package/src/components/InlineAlert/InlineAlert.rtl.test.tsx +1 -1
  216. package/src/components/InlineAlert/InlineAlert.tsx +3 -3
  217. package/src/components/Input/Input.tsx +140 -48
  218. package/src/components/Input/InputExample.tsx +4 -6
  219. package/src/components/Input/index.tsx +0 -1
  220. package/src/components/InputField/InputField.tsx +10 -6
  221. package/src/components/InputNumber/InputNumber.tsx +11 -16
  222. package/src/components/InputNumber/InputNumberExample.tsx +7 -4
  223. package/src/components/InputNumber/input-number.scss +1 -0
  224. package/src/components/InputNumberField/InputNumberField.tsx +10 -6
  225. package/src/components/InputPhone/InputPhone.tsx +14 -18
  226. package/src/components/InputPhone/InputPhoneExample.tsx +7 -6
  227. package/src/components/InputPhone/input-phone.scss +1 -0
  228. package/src/components/InputPhoneField/InputPhoneField.tsx +10 -6
  229. package/src/components/ListItem/list-item.scss +1 -0
  230. package/src/components/Modal/Modal.tsx +26 -30
  231. package/src/components/Modal/ModalExample.tsx +7 -2
  232. package/src/components/Modal/modal.scss +1 -1
  233. package/src/components/OTPInput/otp-input.scss +1 -0
  234. package/src/components/Pagination/Pagination.tsx +2 -2
  235. package/src/components/Password/Password.tsx +15 -17
  236. package/src/components/Password/PasswordExample.tsx +13 -5
  237. package/src/components/PasswordField/PasswordField.tsx +10 -6
  238. package/src/components/Popover/Popover.tsx +0 -1
  239. package/src/components/RadioGroup/RadioGroup.tsx +14 -20
  240. package/src/components/RadioGroupField/RadioGroupField.tsx +16 -11
  241. package/src/components/SearchBar/SearchBar.tsx +0 -1
  242. package/src/components/SegmentedControl/SegmentedControl.tsx +0 -1
  243. package/src/components/Select/Select.tsx +13 -14
  244. package/src/components/Select/SelectExample.tsx +7 -4
  245. package/src/components/SelectField/SelectField.rtl.test.tsx +7 -18
  246. package/src/components/SelectField/SelectField.tsx +10 -6
  247. package/src/components/Slider/Slider.tsx +1 -2
  248. package/src/components/Snackbar/Snackbar.tsx +0 -1
  249. package/src/components/Switch/Switch.tsx +0 -1
  250. package/src/components/TabGroup/TabGroup.tsx +0 -1
  251. package/src/components/TabList/TabList.tsx +0 -1
  252. package/src/components/TabList/tab-list.scss +1 -0
  253. package/src/components/Table/table.scss +2 -1
  254. package/src/components/Textarea/Textarea.tsx +8 -17
  255. package/src/components/Textarea/TextareaExample.tsx +3 -5
  256. package/src/components/TextareaField/TextareaField.tsx +10 -6
  257. package/src/components/TimePicker/TimePicker.tsx +12 -15
  258. package/src/components/TimePicker/TimePickerExample.tsx +3 -5
  259. package/src/components/TimePickerField/TimePickerField.tsx +10 -6
  260. package/src/types/common.ts +8 -0
  261. package/src/utils/demo.ts +1 -1
  262. package/dist/components/Field/FieldDescription.d.ts +0 -9
  263. package/dist/components/Field/FieldDescription.js +0 -13
  264. package/dist/components/Field/FieldDescription.js.map +0 -1
  265. package/dist/components/Field/FieldError.d.ts +0 -11
  266. package/dist/components/Field/FieldError.js +0 -14
  267. package/dist/components/Field/FieldError.js.map +0 -1
  268. package/dist/components/Field/FieldLabel.d.ts +0 -21
  269. package/dist/components/Field/FieldLabel.js +0 -14
  270. package/dist/components/Field/FieldLabel.js.map +0 -1
  271. package/dist/components/FormField/FormField.d.ts +0 -66
  272. package/dist/components/FormField/FormField.js +0 -31
  273. package/dist/components/FormField/FormField.js.map +0 -1
  274. package/dist/components/FormField/FormFieldExample.d.ts +0 -9
  275. package/dist/components/FormField/FormFieldExample.js +0 -99
  276. package/dist/components/FormField/FormFieldExample.js.map +0 -1
  277. package/dist/components/FormField/index.d.ts +0 -1
  278. package/dist/components/FormField/index.js +0 -2
  279. package/dist/components/FormField/index.js.map +0 -1
  280. package/dist/components/Input/InputElement.d.ts +0 -82
  281. package/dist/components/Input/InputElement.js +0 -64
  282. package/dist/components/Input/InputElement.js.map +0 -1
  283. package/src/components/Field/FieldDescription.tsx +0 -17
  284. package/src/components/Field/FieldError.tsx +0 -25
  285. package/src/components/Field/FieldLabel.tsx +0 -44
  286. package/src/components/FormField/FormField.rtl.test.tsx +0 -20
  287. package/src/components/FormField/FormField.tsx +0 -95
  288. package/src/components/FormField/FormFieldExample.tsx +0 -277
  289. package/src/components/FormField/index.tsx +0 -1
  290. package/src/components/Input/InputElement.tsx +0 -192
@@ -1,84 +1,22 @@
1
- import { createContext, useContext, useEffect, useMemo } from 'react';
2
- import { useId } from '-/hooks/useId';
3
- import { CommonProps } from '-/types/common';
4
-
5
1
  export const errorMessageId = (id: string) => `${id}-field-error`;
6
2
  export const labelledById = (id: string) => `${id}-label`;
7
3
  export const describedById = (id: string) => `${id}-description`;
8
-
9
- /** The props that are provided via context to all Field subcomponents. */
10
- export type FieldContextProps = CommonProps<'required'> & {
11
- /** The aria-describedby attribute value that should be applied to the field input element. */
12
- ariaDescribedBy?: string;
13
- /** The aria-errormessage attribute value that should be applied to the field input element. */
14
- ariaErrorMessage?: string;
15
- /** Text that appears after the label, but before the input (e.g. "optional"). */
16
- labelTrailing?: string;
17
- /** The aria-labelledby attribute value that should be applied to the field input element. */
18
- ariaLabelledBy?: string;
19
- /** The htmlFor attribute value that should be applied to the field label element. */
20
- htmlFor?: string;
21
- /** The id of the field. */
22
- id: string;
23
- };
24
-
25
- export type FieldContext = FieldContextProps & {
26
- setContext: (next: Pick<FieldContextProps, 'htmlFor' | 'required'>) => void;
27
- };
28
-
29
- export const fieldContext = createContext<FieldContext | null>(null);
30
-
31
- /**
32
- * Retrieves the current Field context.
33
- *
34
- * Will return a default context if used outside of a Field component.
35
- */
36
- export function useFieldContext(): FieldContext {
37
- return (
38
- useContext(fieldContext) || {
39
- id: undefined as unknown as string,
40
- setContext: () => {},
41
- }
42
- );
43
- }
44
-
45
- /**
46
- * Initializes field-related attributes and state for a form control component.
47
- *
48
- * Creates id if not provided, manages invalid state, and syncs with Field context.
49
- */
50
- export function useFieldInit({
51
- idProp,
52
- required,
53
- disabled,
54
- readOnly,
55
- invalidProp,
4
+ export function propsWithAria<T extends Record<string, unknown>>({
5
+ errorMessage,
6
+ helperText,
7
+ controlProps,
8
+ id,
56
9
  }: {
57
- idProp: string | undefined;
58
- required: boolean | undefined;
59
- disabled: boolean | undefined;
60
- readOnly?: boolean | undefined;
61
- invalidProp: boolean | undefined;
62
- }): Pick<FieldContext, 'ariaDescribedBy' | 'ariaErrorMessage'> & { invalid: boolean; id: string } {
63
- const context = useContext(fieldContext);
64
- const controlId = useId(idProp || context?.htmlFor);
65
-
66
- const invalid = useMemo(
67
- () => !disabled && !readOnly && (invalidProp || !!context?.ariaErrorMessage),
68
- [disabled, readOnly, invalidProp, context?.ariaErrorMessage],
69
- );
70
-
71
- useEffect(() => {
72
- if (!context) return;
73
-
74
- if (controlId !== context?.htmlFor || !!required !== !!context?.required) {
75
- context.setContext({ htmlFor: controlId, required: required });
76
- }
77
- }, [context, controlId, required]);
78
-
10
+ errorMessage?: string;
11
+ helperText?: string;
12
+ controlProps: T;
13
+ id: string;
14
+ }) {
79
15
  return {
80
- ...(context || {}),
81
- invalid,
82
- id: controlId,
16
+ ...controlProps,
17
+ id,
18
+ 'aria-errormessage': errorMessage ? errorMessageId(id) : undefined,
19
+ 'aria-describedby': helperText ? describedById(id) : undefined,
20
+ 'aria-invalid': errorMessage ? true : undefined,
83
21
  };
84
22
  }
@@ -205,7 +205,7 @@ export function FileUpload({
205
205
  />
206
206
  <Button label="Browse" onClick={handleBrowseClick} />
207
207
  {files.length === 1 && files[0].status === 'error' && (
208
- <InlineAlert variant="error">{files[0].errorMessage || DEFAULT_ERROR_MESSAGE}</InlineAlert>
208
+ <InlineAlert label={files[0].errorMessage || DEFAULT_ERROR_MESSAGE} variant="error" />
209
209
  )}
210
210
  </div>
211
211
  <div data-bspk-owner="file-upload" data-file-entries>
@@ -72,7 +72,7 @@ export function FileUploadItem({
72
72
  </div>
73
73
  <div data-status>
74
74
  {status === 'error' ? (
75
- <InlineAlert variant="error">{errorMessage}</InlineAlert>
75
+ <InlineAlert label={errorMessage} variant="error" />
76
76
  ) : (
77
77
  <ProgressBar
78
78
  align="left"
@@ -44,13 +44,17 @@ export type FlexProps<As extends ElementType = ElementType> = {
44
44
  * Utility component used within other components for layout purposes.
45
45
  *
46
46
  * @example
47
- * import { Flex } from '@bspk/ui/Flex';
47
+ * import { Flex } from '-/components/Flex';
48
48
  *
49
- * <Flex gap="24" justify="center" style={{ width: '100%' }}>
50
- * <div>Alpha</div>
51
- * <div>Beta</div>
52
- * <div>Gamma</div>
53
- * </Flex>;
49
+ * () => {
50
+ * return (
51
+ * <Flex gap="24" justify="center" style={{ width: '100%' }}>
52
+ * <div>Alpha</div>
53
+ * <div>Beta</div>
54
+ * <div>Gamma</div>
55
+ * </Flex>
56
+ * );
57
+ * };
54
58
  *
55
59
  * @name Flex
56
60
  * @phase Utility
@@ -65,6 +69,7 @@ export function Flex<As extends ElementType = ElementType>({
65
69
  wrap,
66
70
  direction = 'row',
67
71
  padding,
72
+ full,
68
73
  ...props
69
74
  }: ElementProps<FlexProps<As>, As>) {
70
75
  const As: ElementType = as || 'div';
@@ -85,7 +90,7 @@ export function Flex<As extends ElementType = ElementType>({
85
90
  justifyContent: justify || 'flex-start',
86
91
  flexWrap: wrap ? 'wrap' : 'nowrap',
87
92
  padding: paddingValue,
88
- width: props.full ? '100%' : undefined,
93
+ width: full ? '100%' : undefined,
89
94
  ...style,
90
95
  }}
91
96
  >
@@ -2,7 +2,7 @@ import { InlineAlert } from './InlineAlert';
2
2
  import { hasNoBasicA11yIssues } from '-/rtl/hasNoBasicA11yIssues';
3
3
  import { render } from '-/rtl/util';
4
4
 
5
- const TestBed = () => <InlineAlert variant="informational">Example informational inline alert</InlineAlert>;
5
+ const TestBed = () => <InlineAlert label="Example informational inline alert" variant="informational" />;
6
6
 
7
7
  describe('InlineAlert (RTL)', () => {
8
8
  it('has no basic a11y issues', hasNoBasicA11yIssues(<TestBed />));
@@ -14,7 +14,7 @@ export type InlineAlertProps = CommonProps<'owner'> & {
14
14
  * @type multiline
15
15
  * @required
16
16
  */
17
- children: string;
17
+ label: string;
18
18
  /**
19
19
  * The color variant of the inline alert.
20
20
  *
@@ -37,11 +37,11 @@ export type InlineAlertProps = CommonProps<'owner'> & {
37
37
  * @name InlineAlert
38
38
  * @phase Stable
39
39
  */
40
- export function InlineAlert({ children, variant = 'informational', id, owner }: InlineAlertProps) {
40
+ export function InlineAlert({ label, variant = 'informational', id, owner }: InlineAlertProps) {
41
41
  return (
42
42
  <div data-bspk="inline-alert" data-bspk-owner={owner || undefined} data-variant={variant} id={id} role="alert">
43
43
  {VARIANT_ICON[variant]}
44
- <Txt variant="body-small">{children}</Txt>
44
+ <Txt variant="body-small">{label}</Txt>
45
45
  </div>
46
46
  );
47
47
  }
@@ -1,39 +1,89 @@
1
1
  import './input.scss';
2
- import { DEFAULT, InputElement, InputElementProps } from './InputElement';
3
- import { useFieldInit } from '-/components/Field';
4
- import { ElementProps } from '-/types/common';
2
+ import { SvgCancel } from '@bspk/icons/Cancel';
3
+ import { HTMLInputTypeAttribute, ReactNode, useMemo, useRef } from 'react';
4
+ import { Button } from '-/components/Button';
5
+ import { useTimeout } from '-/hooks/useTimeout';
6
+ import { CommonProps, ElementProps, SetRef, FieldControlProps } from '-/types/common';
5
7
 
6
- export type InputProps = Omit<InputElementProps, 'ariaDescribedBy' | 'ariaErrorMessage'>;
8
+ export const DEFAULT = {
9
+ size: 'medium',
10
+ value: '',
11
+ type: 'text' as Extract<HTMLInputTypeAttribute, 'number' | 'text'>,
12
+ autoComplete: 'off',
13
+ } as const;
14
+
15
+ export type InputBaseProps = CommonProps<'owner' | 'size'> &
16
+ FieldControlProps & {
17
+ /** The ref of the container. */
18
+ containerRef?: SetRef<HTMLDivElement>;
19
+ /** The ref of the input. */
20
+ inputRef?: SetRef<HTMLInputElement>;
21
+ /**
22
+ * The trailing element to display in the field.
23
+ *
24
+ * @exampleType string
25
+ */
26
+ trailing?: ReactNode;
27
+ /**
28
+ * The leading element to display in the field.
29
+ *
30
+ * @exampleType string
31
+ */
32
+ leading?: ReactNode;
33
+ /** The placeholder of the field. */
34
+ placeholder?: string;
35
+ /**
36
+ * The type of the input.
37
+ *
38
+ * @default text
39
+ */
40
+ type?: Extract<HTMLInputTypeAttribute, 'number' | 'password' | 'text'>;
41
+ /**
42
+ * Specifies if user agent has any permission to provide automated assistance in filling out form field values
43
+ *
44
+ * @default off
45
+ */
46
+ autoComplete?: 'off' | 'on';
47
+ /**
48
+ * Specifies if the clear button should be shown. This should almost always be true, but can be set to false.
49
+ *
50
+ * @default true
51
+ */
52
+ showClearButton?: boolean;
53
+ };
54
+
55
+ export type InputProps = InputBaseProps & {
56
+ inputProps?: Omit<React.InputHTMLAttributes<HTMLInputElement>, keyof InputBaseProps>;
57
+ };
7
58
 
8
59
  /**
9
- * An input that allows users to enter text, numbers or symbols in a singular line.
10
- *
11
- * For a more complete example with field usage, see the InputField component.
60
+ * An input that allows users to enter text, numbers or symbols in a singular line. This is a utility element and is not
61
+ * intended to be used directly but rather through the Input, and other components.
12
62
  *
13
63
  * @example
14
- * import { useState } from 'react';
15
64
  * import { Input } from '@bspk/ui/Input';
16
- * import { Field, FieldLabel, FieldDescription } from '@bspk/ui/Field';
17
65
  *
18
66
  * () => {
19
- * const [fieldDate, setFieldDate] = useState<string>();
67
+ * const [value, setValue] = useState<string>();
20
68
  *
21
69
  * return (
22
70
  * <div style={{ width: 320 }}>
23
- * <Field>
24
- * <FieldLabel>Example Label</FieldLabel>
25
- * <Input name="example-name" onChange={setFieldDate} value={fieldDate} />
26
- * <FieldDescription>This is an example input field.</FieldDescription>
71
+ * <Field
72
+ * controlId="example-control-id"
73
+ * helperText="This is an example input field."
74
+ * label="Example Input"
75
+ * >
76
+ * <Input id="example-control-id" name="example-name" onChange={setValue} value={value} />
27
77
  * </Field>
28
78
  * </div>
29
79
  * );
30
80
  * };
31
81
  *
32
82
  * @name Input
33
- * @phase UXReview
83
+ * @phase Utility
34
84
  */
35
85
  export function Input({
36
- invalid: invalidProp,
86
+ invalid,
37
87
  onChange,
38
88
  size = DEFAULT.size,
39
89
  value = DEFAULT.value,
@@ -42,7 +92,7 @@ export function Input({
42
92
  inputRef,
43
93
  required = false,
44
94
  placeholder,
45
- id: idProp,
95
+ id,
46
96
  leading,
47
97
  trailing,
48
98
  type = DEFAULT.type,
@@ -53,42 +103,84 @@ export function Input({
53
103
  showClearButton: showClearButtonProp = true,
54
104
  owner,
55
105
  inputProps,
106
+ 'aria-describedby': ariaDescribedBy,
107
+ 'aria-errormessage': ariaErrorMessage,
56
108
  ...props
57
109
  }: ElementProps<InputProps, 'div'>) {
58
- const { id, ariaDescribedBy, ariaErrorMessage, invalid } = useFieldInit({
59
- idProp,
60
- required,
61
- disabled,
62
- readOnly,
63
- invalidProp,
64
- });
110
+ const showClearButton = useMemo(
111
+ () => showClearButtonProp !== false && !readOnly && !disabled && !!value?.toString().length,
112
+ [showClearButtonProp, readOnly, disabled, value],
113
+ );
114
+
115
+ const inputRefInternal = useRef<HTMLInputElement | null>(null);
116
+
117
+ const focusTimeout = useTimeout();
65
118
 
66
119
  return (
67
- // data-bspk="input" -- because InputElement already has it :)
68
- <InputElement
120
+ <div
69
121
  {...props}
70
- aria-label={ariaLabel}
71
- ariaDescribedBy={ariaDescribedBy}
72
- ariaErrorMessage={ariaErrorMessage}
73
- autoComplete={autoComplete}
74
- containerRef={containerRef}
75
- disabled={disabled}
76
- id={id}
77
- inputProps={inputProps}
78
- inputRef={inputRef}
79
- invalid={invalid}
80
- leading={leading}
81
- name={name}
82
- onChange={onChange}
83
- owner={owner}
84
- placeholder={placeholder}
85
- readOnly={readOnly}
86
- showClearButton={showClearButtonProp}
87
- size={size}
88
- trailing={trailing}
89
- type={type}
90
- value={value}
91
- />
122
+ data-bspk="input"
123
+ data-bspk-owner={owner || undefined}
124
+ data-disabled={disabled || undefined}
125
+ data-empty={!value.toString().length || undefined}
126
+ data-invalid={invalid || undefined}
127
+ data-readonly={readOnly || undefined}
128
+ data-show-clear-button={showClearButton || undefined}
129
+ data-size={size}
130
+ ref={containerRef}
131
+ >
132
+ {leading && <span data-leading>{leading}</span>}
133
+
134
+ <input
135
+ {...inputProps}
136
+ aria-describedby={ariaDescribedBy || undefined}
137
+ aria-errormessage={ariaErrorMessage || undefined}
138
+ aria-invalid={invalid || undefined}
139
+ aria-label={ariaLabel}
140
+ autoComplete={autoComplete}
141
+ data-main-input
142
+ disabled={disabled || undefined}
143
+ id={id}
144
+ name={name}
145
+ onBlur={(event) => {
146
+ inputProps?.onBlur?.(event);
147
+ }}
148
+ onChange={(event) => {
149
+ onChange(event.target.value, event);
150
+ }}
151
+ onFocus={(event) => {
152
+ inputProps?.onFocus?.(event);
153
+ }}
154
+ placeholder={placeholder || ' '}
155
+ readOnly={readOnly || undefined}
156
+ ref={(node) => {
157
+ if (!node) return;
158
+ inputRef?.(node);
159
+ inputRefInternal.current = node;
160
+ }}
161
+ required={required || undefined}
162
+ type={type}
163
+ value={value || ''}
164
+ />
165
+ {trailing && <span data-trailing>{trailing}</span>}
166
+ {showClearButton && (
167
+ <Button
168
+ data-clear-button
169
+ icon={<SvgCancel />}
170
+ iconOnly
171
+ label="Clear"
172
+ onClick={() => {
173
+ onChange('');
174
+ inputRefInternal.current?.focus();
175
+ }}
176
+ onFocus={() => {
177
+ focusTimeout.clear();
178
+ }}
179
+ size={size}
180
+ variant="tertiary"
181
+ />
182
+ )}
183
+ </div>
92
184
  );
93
185
  }
94
186
 
@@ -1,6 +1,6 @@
1
1
  import { useState } from 'react';
2
2
  import { Input, InputProps } from '.';
3
- import { Field, FieldLabel, FieldDescription } from '-/components/Field';
3
+ import { Field } from '-/components/Field';
4
4
  import { ComponentExample } from '-/utils/demo';
5
5
 
6
6
  export type InputExampleProps = InputProps & { label: string; description?: string };
@@ -62,14 +62,12 @@ export const InputExample: ComponentExample<InputExampleProps> = {
62
62
  };
63
63
 
64
64
  export const Usage = () => {
65
- const [fieldDate, setFieldDate] = useState<string>();
65
+ const [value, setValue] = useState<string>();
66
66
 
67
67
  return (
68
68
  <div style={{ width: 320 }}>
69
- <Field>
70
- <FieldLabel>Example Label</FieldLabel>
71
- <Input name="example-name" onChange={setFieldDate} value={fieldDate} />
72
- <FieldDescription>This is an example input field.</FieldDescription>
69
+ <Field controlId="example-control-id" helperText="This is an example input field." label="Example Input">
70
+ <Input id="example-control-id" name="example-name" onChange={setValue} value={value} />
73
71
  </Field>
74
72
  </div>
75
73
  );
@@ -1,2 +1 @@
1
1
  export * from './Input';
2
- export * from './InputElement';
@@ -1,7 +1,8 @@
1
- import { FormField, FormFieldControlProps } from '-/components/FormField';
1
+ import { Field, FieldControlProps, propsWithAria } from '-/components/Field';
2
2
  import { Input, InputProps } from '-/components/Input';
3
+ import { useId } from '-/hooks/useId';
3
4
 
4
- export type InputFieldProps = FormFieldControlProps<InputProps>;
5
+ export type InputFieldProps = FieldControlProps<InputProps>;
5
6
 
6
7
  /**
7
8
  * A field wrapper for the Input component.
@@ -9,7 +10,7 @@ export type InputFieldProps = FormFieldControlProps<InputProps>;
9
10
  * This component takes properties from the FormField and Input components.
10
11
  *
11
12
  * @name InputField
12
- * @phase Stable
13
+ * @phase UXReview
13
14
  *
14
15
  * @generated
15
16
  */
@@ -19,18 +20,21 @@ export function InputField({
19
20
  labelTrailing,
20
21
  errorMessage,
21
22
  style,
23
+ id: idProp,
22
24
  ...controlProps
23
25
  }: InputFieldProps) {
26
+ const id = useId(idProp);
24
27
  return (
25
- <FormField
28
+ <Field
29
+ controlId={id}
26
30
  errorMessage={errorMessage}
27
31
  helperText={helperText}
28
32
  label={label}
29
33
  labelTrailing={labelTrailing}
30
34
  style={style}
31
35
  >
32
- <Input {...controlProps} />
33
- </FormField>
36
+ <Input {...propsWithAria({ id, controlProps, errorMessage, helperText })} />
37
+ </Field>
34
38
  );
35
39
  }
36
40
 
@@ -1,7 +1,6 @@
1
1
  import './input-number.scss';
2
2
  import { useEffect, useRef } from 'react';
3
3
  import { IncrementButton } from './IncrementButton';
4
- import { useFieldInit } from '-/components/Field';
5
4
  import { useId } from '-/hooks/useId';
6
5
  import { CommonProps, FieldControlProps } from '-/types/common';
7
6
 
@@ -51,24 +50,25 @@ export type InputNumberProps = CommonProps<'size'> &
51
50
  * For a more complete example with field usage, see the InputNumberField component.
52
51
  *
53
52
  * @example
54
- * import { InputNumber } from '@bspk/ui/InputNumber';
53
+ * import { InputNumber } from '-/components/InputNumber';
55
54
  *
56
55
  * () => {
57
56
  * const [value, setValue] = useState<number | undefined>();
58
57
  *
59
58
  * return (
60
59
  * <div style={{ width: 320 }}>
61
- * <Field>
62
- * <FieldLabel>Example Input Number</FieldLabel>
60
+ * <Field
61
+ * controlId="example-input-number"
62
+ * helperText="The input number allows you to increment or decrement a value."
63
+ * label="Example Input Number"
64
+ * >
63
65
  * <InputNumber
64
66
  * aria-label="Example aria-label"
67
+ * id="example-input-number"
65
68
  * name="example-name"
66
69
  * onChange={(nextValue) => setValue(nextValue)}
67
70
  * value={value}
68
71
  * />
69
- * <FieldDescription>
70
- * The input number allows you to increment or decrement a value.
71
- * </FieldDescription>
72
72
  * </Field>
73
73
  * </div>
74
74
  * );
@@ -89,21 +89,16 @@ export function InputNumber({
89
89
  'aria-label': ariaLabel = 'Input number',
90
90
  max: maxProp,
91
91
  min = 0,
92
- invalid: invalidProp = false,
92
+ invalid = false,
93
93
  step = 1,
94
94
  required = false,
95
+ 'aria-describedby': ariaDescribedBy,
96
+ 'aria-errormessage': ariaErrorMessage,
95
97
  ...inputElementProps
96
98
  }: InputNumberProps) {
97
- const { id, ariaDescribedBy, ariaErrorMessage, invalid } = useFieldInit({
98
- idProp,
99
- required,
100
- disabled,
101
- readOnly,
102
- invalidProp,
103
- });
99
+ const inputId = useId(idProp);
104
100
  const max = typeof maxProp === 'number' && maxProp >= min ? maxProp : Number.MAX_SAFE_INTEGER;
105
101
  const centered = align !== 'left';
106
- const inputId = useId(id);
107
102
  const value = isNumber(valueProp, min);
108
103
  const removeDisabled = disabled || value + step * -1 < min;
109
104
  const addDisabled = disabled || value + step > max;
@@ -1,6 +1,6 @@
1
1
  import { useState } from 'react';
2
2
  import { InputNumber, InputNumberProps } from './InputNumber';
3
- import { Field, FieldLabel, FieldDescription } from '-/components/Field';
3
+ import { Field } from '-/components/Field';
4
4
  import { ComponentExample } from '-/utils/demo';
5
5
 
6
6
  export const InputNumberExample: ComponentExample<InputNumberProps> = {
@@ -18,15 +18,18 @@ export const Usage = () => {
18
18
 
19
19
  return (
20
20
  <div style={{ width: 320 }}>
21
- <Field>
22
- <FieldLabel>Example Input Number</FieldLabel>
21
+ <Field
22
+ controlId="example-input-number"
23
+ helperText="The input number allows you to increment or decrement a value."
24
+ label="Example Input Number"
25
+ >
23
26
  <InputNumber
24
27
  aria-label="Example aria-label"
28
+ id="example-input-number"
25
29
  name="example-name"
26
30
  onChange={(nextValue) => setValue(nextValue)}
27
31
  value={value}
28
32
  />
29
- <FieldDescription>The input number allows you to increment or decrement a value.</FieldDescription>
30
33
  </Field>
31
34
  </div>
32
35
  );
@@ -16,6 +16,7 @@
16
16
 
17
17
  &:focus-within {
18
18
  outline: solid 2px var(--stroke-neutral-focus);
19
+ isolation: isolate;
19
20
  }
20
21
 
21
22
  [data-divider] {
@@ -1,7 +1,8 @@
1
- import { FormField, FormFieldControlProps } from '-/components/FormField';
1
+ import { Field, FieldControlProps, propsWithAria } from '-/components/Field';
2
2
  import { InputNumber, InputNumberProps } from '-/components/InputNumber';
3
+ import { useId } from '-/hooks/useId';
3
4
 
4
- export type InputNumberFieldProps = FormFieldControlProps<InputNumberProps>;
5
+ export type InputNumberFieldProps = FieldControlProps<InputNumberProps>;
5
6
 
6
7
  /**
7
8
  * A field wrapper for the InputNumber component.
@@ -9,7 +10,7 @@ export type InputNumberFieldProps = FormFieldControlProps<InputNumberProps>;
9
10
  * This component takes properties from the FormField and InputNumber components.
10
11
  *
11
12
  * @name InputNumberField
12
- * @phase Stable
13
+ * @phase UXReview
13
14
  *
14
15
  * @generated
15
16
  */
@@ -19,18 +20,21 @@ export function InputNumberField({
19
20
  labelTrailing,
20
21
  errorMessage,
21
22
  style,
23
+ id: idProp,
22
24
  ...controlProps
23
25
  }: InputNumberFieldProps) {
26
+ const id = useId(idProp);
24
27
  return (
25
- <FormField
28
+ <Field
29
+ controlId={id}
26
30
  errorMessage={errorMessage}
27
31
  helperText={helperText}
28
32
  label={label}
29
33
  labelTrailing={labelTrailing}
30
34
  style={style}
31
35
  >
32
- <InputNumber {...controlProps} />
33
- </FormField>
36
+ <InputNumber {...propsWithAria({ id, controlProps, errorMessage, helperText })} />
37
+ </Field>
34
38
  );
35
39
  }
36
40