@hyphen/hyphen-components 2.9.0

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 (319) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +70 -0
  3. package/package.json +138 -0
  4. package/src/components/Alert/Alert.constants.ts +19 -0
  5. package/src/components/Alert/Alert.mdx +29 -0
  6. package/src/components/Alert/Alert.module.scss +74 -0
  7. package/src/components/Alert/Alert.stories.tsx +102 -0
  8. package/src/components/Alert/Alert.test.tsx +187 -0
  9. package/src/components/Alert/Alert.tsx +157 -0
  10. package/src/components/Alert/Alert.types.ts +14 -0
  11. package/src/components/Badge/Badge.mdx +28 -0
  12. package/src/components/Badge/Badge.module.scss +155 -0
  13. package/src/components/Badge/Badge.stories.tsx +52 -0
  14. package/src/components/Badge/Badge.test.tsx +74 -0
  15. package/src/components/Badge/Badge.tsx +70 -0
  16. package/src/components/Box/Box.mdx +259 -0
  17. package/src/components/Box/Box.module.scss +16 -0
  18. package/src/components/Box/Box.stories.tsx +1679 -0
  19. package/src/components/Box/Box.test.tsx +478 -0
  20. package/src/components/Box/Box.tsx +636 -0
  21. package/src/components/Button/Button.constants.ts +10 -0
  22. package/src/components/Button/Button.mdx +71 -0
  23. package/src/components/Button/Button.module.scss +312 -0
  24. package/src/components/Button/Button.stories.tsx +117 -0
  25. package/src/components/Button/Button.test.tsx +460 -0
  26. package/src/components/Button/Button.tsx +241 -0
  27. package/src/components/Card/Card.mdx +46 -0
  28. package/src/components/Card/Card.module.scss +6 -0
  29. package/src/components/Card/Card.stories.tsx +101 -0
  30. package/src/components/Card/Card.test.tsx +11 -0
  31. package/src/components/Card/Card.tsx +61 -0
  32. package/src/components/Card/components/CardFooter/CardFooter.test.tsx +11 -0
  33. package/src/components/Card/components/CardFooter/CardFooter.tsx +35 -0
  34. package/src/components/Card/components/CardHeader/CardHeader.test.tsx +23 -0
  35. package/src/components/Card/components/CardHeader/CardHeader.tsx +54 -0
  36. package/src/components/Card/components/CardSection/CardSection.test.tsx +28 -0
  37. package/src/components/Card/components/CardSection/CardSection.tsx +102 -0
  38. package/src/components/Card/components/index.ts +3 -0
  39. package/src/components/CheckboxInput/CheckboxInput.mdx +98 -0
  40. package/src/components/CheckboxInput/CheckboxInput.stories.tsx +254 -0
  41. package/src/components/CheckboxInput/CheckboxInput.test.tsx +436 -0
  42. package/src/components/CheckboxInput/CheckboxInput.tsx +171 -0
  43. package/src/components/CheckboxInput/components/Checkbox.module.scss +174 -0
  44. package/src/components/CheckboxInput/components/Checkbox.test.tsx +201 -0
  45. package/src/components/CheckboxInput/components/Checkbox.tsx +176 -0
  46. package/src/components/CheckboxInput/components/CheckboxIcon.tsx +71 -0
  47. package/src/components/DateInput/DateInput.mdx +61 -0
  48. package/src/components/DateInput/DateInput.stories.tsx +168 -0
  49. package/src/components/DateInput/DateInput.test.tsx +258 -0
  50. package/src/components/DateInput/DateInput.tsx +189 -0
  51. package/src/components/DatePicker/DatePicker.mdx +52 -0
  52. package/src/components/DatePicker/DatePicker.module.scss +603 -0
  53. package/src/components/DatePicker/DatePicker.stories.tsx +199 -0
  54. package/src/components/DatePicker/DatePicker.test.tsx +26 -0
  55. package/src/components/DatePicker/DatePicker.tsx +138 -0
  56. package/src/components/Details/Details.mdx +30 -0
  57. package/src/components/Details/Details.module.scss +32 -0
  58. package/src/components/Details/Details.stories.tsx +38 -0
  59. package/src/components/Details/Details.test.tsx +189 -0
  60. package/src/components/Details/Details.tsx +51 -0
  61. package/src/components/Details/DetailsSummary.tsx +65 -0
  62. package/src/components/Drawer/Drawer.mdx +117 -0
  63. package/src/components/Drawer/Drawer.module.scss +96 -0
  64. package/src/components/Drawer/Drawer.stories.tsx +380 -0
  65. package/src/components/Drawer/Drawer.test.tsx +90 -0
  66. package/src/components/Drawer/Drawer.tsx +249 -0
  67. package/src/components/FormControl/FormControl.tsx +78 -0
  68. package/src/components/FormLabel/FormLabel.mdx +24 -0
  69. package/src/components/FormLabel/FormLabel.module.scss +19 -0
  70. package/src/components/FormLabel/FormLabel.stories.tsx +20 -0
  71. package/src/components/FormLabel/FormLabel.test.tsx +35 -0
  72. package/src/components/FormLabel/FormLabel.tsx +96 -0
  73. package/src/components/Formik/Formik.mdx +10 -0
  74. package/src/components/Formik/Formik.stories.tsx +307 -0
  75. package/src/components/Formik/FormikCheckboxInput/FormikCheckboxInput.test.tsx +172 -0
  76. package/src/components/Formik/FormikCheckboxInput/FormikCheckboxInput.tsx +41 -0
  77. package/src/components/Formik/FormikRadioGroup/FormikRadioGroup.test.tsx +205 -0
  78. package/src/components/Formik/FormikRadioGroup/FormikRadioGroup.tsx +37 -0
  79. package/src/components/Formik/FormikSelectInput/FormikSelectInput.test.tsx +210 -0
  80. package/src/components/Formik/FormikSelectInput/FormikSelectInput.tsx +41 -0
  81. package/src/components/Formik/FormikSelectInputInset/FormikSelectInputInset.test.tsx +153 -0
  82. package/src/components/Formik/FormikSelectInputInset/FormikSelectInputInset.tsx +44 -0
  83. package/src/components/Formik/FormikSelectInputNative/FormikSelectInputNative.test.tsx +161 -0
  84. package/src/components/Formik/FormikSelectInputNative/FormikSelectInputNative.tsx +46 -0
  85. package/src/components/Formik/FormikTextInput/FormikTextInput.test.tsx +176 -0
  86. package/src/components/Formik/FormikTextInput/FormikTextInput.tsx +38 -0
  87. package/src/components/Formik/FormikTextInputInset/FormikTextInputInset.test.tsx +170 -0
  88. package/src/components/Formik/FormikTextInputInset/FormikTextInputInset.tsx +42 -0
  89. package/src/components/Formik/FormikTextareaInput/FormikTextareaInput.test.tsx +186 -0
  90. package/src/components/Formik/FormikTextareaInput/FormikTextareaInput.tsx +42 -0
  91. package/src/components/Formik/FormikTextareaInputInset/FormikTextareaInputInset.test.tsx +179 -0
  92. package/src/components/Formik/FormikTextareaInputInset/FormikTextareaInputInset.tsx +42 -0
  93. package/src/components/Formik/FormikTimePicker/FormikTimePicker.test.tsx +224 -0
  94. package/src/components/Formik/FormikTimePicker/FormikTimePicker.tsx +37 -0
  95. package/src/components/Formik/FormikTimePickerNative/FormikTimePickerNative.test.tsx +175 -0
  96. package/src/components/Formik/FormikTimePickerNative/FormikTimePickerNative.tsx +38 -0
  97. package/src/components/Formik/FormikToggle/FormikToggle.test.tsx +172 -0
  98. package/src/components/Formik/FormikToggle/FormikToggle.tsx +38 -0
  99. package/src/components/Heading/Heading.constants.ts +19 -0
  100. package/src/components/Heading/Heading.mdx +35 -0
  101. package/src/components/Heading/Heading.module.scss +5 -0
  102. package/src/components/Heading/Heading.stories.tsx +90 -0
  103. package/src/components/Heading/Heading.test.tsx +67 -0
  104. package/src/components/Heading/Heading.tsx +67 -0
  105. package/src/components/HelpText/HelpText.module.scss +14 -0
  106. package/src/components/HelpText/HelpText.tsx +33 -0
  107. package/src/components/Icon/Icon.mdx +40 -0
  108. package/src/components/Icon/Icon.stories.tsx +72 -0
  109. package/src/components/Icon/Icon.test.tsx +30 -0
  110. package/src/components/Icon/Icon.tsx +61 -0
  111. package/src/components/InputValidationMessage/InputValidationMessage.module.scss +3 -0
  112. package/src/components/InputValidationMessage/InputValidationMessage.tsx +27 -0
  113. package/src/components/Modal/Modal.mdx +60 -0
  114. package/src/components/Modal/Modal.module.scss +135 -0
  115. package/src/components/Modal/Modal.stories.tsx +194 -0
  116. package/src/components/Modal/Modal.test.tsx +81 -0
  117. package/src/components/Modal/Modal.tsx +174 -0
  118. package/src/components/Modal/components/ModalBody/ModalBody.test.tsx +20 -0
  119. package/src/components/Modal/components/ModalBody/ModalBody.tsx +24 -0
  120. package/src/components/Modal/components/ModalFooter/ModalFooter.test.tsx +32 -0
  121. package/src/components/Modal/components/ModalFooter/ModalFooter.tsx +37 -0
  122. package/src/components/Modal/components/ModalHeader/ModalHeader.test.tsx +29 -0
  123. package/src/components/Modal/components/ModalHeader/ModalHeader.tsx +58 -0
  124. package/src/components/Modal/components/index.ts +5 -0
  125. package/src/components/Pagination/Pagination.mdx +26 -0
  126. package/src/components/Pagination/Pagination.stories.tsx +55 -0
  127. package/src/components/Pagination/Pagination.test.tsx +225 -0
  128. package/src/components/Pagination/Pagination.tsx +162 -0
  129. package/src/components/Pagination/Pagination.utilities.test.ts +133 -0
  130. package/src/components/Pagination/Pagination.utilities.ts +101 -0
  131. package/src/components/Popover/Popover.mdx +104 -0
  132. package/src/components/Popover/Popover.module.scss +74 -0
  133. package/src/components/Popover/Popover.stories.tsx +471 -0
  134. package/src/components/Popover/Popover.test.tsx +128 -0
  135. package/src/components/Popover/Popover.tsx +277 -0
  136. package/src/components/RadioGroup/RadioGroup.mdx +81 -0
  137. package/src/components/RadioGroup/RadioGroup.module.scss +23 -0
  138. package/src/components/RadioGroup/RadioGroup.stories.tsx +375 -0
  139. package/src/components/RadioGroup/RadioGroup.test.tsx +282 -0
  140. package/src/components/RadioGroup/RadioGroup.tsx +145 -0
  141. package/src/components/RadioGroup/RadioInput/RadioInput.module.scss +114 -0
  142. package/src/components/RadioGroup/RadioInput/RadioInput.test.tsx +156 -0
  143. package/src/components/RadioGroup/RadioInput/RadioInput.tsx +148 -0
  144. package/src/components/RadioGroup/RadioInput/RadioInputIcon.tsx +59 -0
  145. package/src/components/ResponsiveProvider/ResponsiveProvider.mdx +36 -0
  146. package/src/components/ResponsiveProvider/ResponsiveProvider.stories.tsx +54 -0
  147. package/src/components/ResponsiveProvider/ResponsiveProvider.test.tsx +70 -0
  148. package/src/components/ResponsiveProvider/ResponsiveProvider.tsx +73 -0
  149. package/src/components/SelectInput/SelectInput.mdx +115 -0
  150. package/src/components/SelectInput/SelectInput.module.scss +357 -0
  151. package/src/components/SelectInput/SelectInput.stories.tsx +373 -0
  152. package/src/components/SelectInput/SelectInput.test.tsx +403 -0
  153. package/src/components/SelectInput/SelectInput.tsx +245 -0
  154. package/src/components/SelectInputInset/SelectInputInset.mdx +56 -0
  155. package/src/components/SelectInputInset/SelectInputInset.module.scss +397 -0
  156. package/src/components/SelectInputInset/SelectInputInset.stories.tsx +189 -0
  157. package/src/components/SelectInputInset/SelectInputInset.test.tsx +305 -0
  158. package/src/components/SelectInputInset/SelectInputInset.tsx +235 -0
  159. package/src/components/SelectInputNative/SelectInputNative.mdx +87 -0
  160. package/src/components/SelectInputNative/SelectInputNative.module.scss +356 -0
  161. package/src/components/SelectInputNative/SelectInputNative.stories.tsx +282 -0
  162. package/src/components/SelectInputNative/SelectInputNative.test.tsx +341 -0
  163. package/src/components/SelectInputNative/SelectInputNative.tsx +121 -0
  164. package/src/components/Spinner/Spinner.mdx +29 -0
  165. package/src/components/Spinner/Spinner.module.scss +16 -0
  166. package/src/components/Spinner/Spinner.stories.tsx +48 -0
  167. package/src/components/Spinner/Spinner.test.tsx +47 -0
  168. package/src/components/Spinner/Spinner.tsx +116 -0
  169. package/src/components/Table/Table.mdx +216 -0
  170. package/src/components/Table/Table.module.scss +61 -0
  171. package/src/components/Table/Table.stories.tsx +884 -0
  172. package/src/components/Table/Table.test.tsx +437 -0
  173. package/src/components/Table/Table.tsx +171 -0
  174. package/src/components/Table/TableBody/TableBody.module.scss +19 -0
  175. package/src/components/Table/TableBody/TableBody.test.tsx +38 -0
  176. package/src/components/Table/TableBody/TableBody.tsx +96 -0
  177. package/src/components/Table/TableBody/TableBodyCell/TableBodyCell.module.scss +47 -0
  178. package/src/components/Table/TableBody/TableBodyCell/TableBodyCell.test.tsx +81 -0
  179. package/src/components/Table/TableBody/TableBodyCell/TableBodyCell.tsx +94 -0
  180. package/src/components/Table/TableHead/TableHead.test.tsx +20 -0
  181. package/src/components/Table/TableHead/TableHead.tsx +78 -0
  182. package/src/components/Table/TableHead/TableHeaderCell/TableHeaderCell.module.scss +72 -0
  183. package/src/components/Table/TableHead/TableHeaderCell/TableHeaderCell.test.tsx +187 -0
  184. package/src/components/Table/TableHead/TableHeaderCell/TableHeaderCell.tsx +192 -0
  185. package/src/components/Table/common/TableRow/TableRow.module.scss +5 -0
  186. package/src/components/Table/common/TableRow/TableRow.test.tsx +52 -0
  187. package/src/components/Table/common/TableRow/TableRow.tsx +155 -0
  188. package/src/components/TextInput/TextInput.mdx +96 -0
  189. package/src/components/TextInput/TextInput.module.scss +405 -0
  190. package/src/components/TextInput/TextInput.stories.tsx +268 -0
  191. package/src/components/TextInput/TextInput.test.tsx +231 -0
  192. package/src/components/TextInput/TextInput.tsx +263 -0
  193. package/src/components/TextInputInset/TextInputInset.mdx +62 -0
  194. package/src/components/TextInputInset/TextInputInset.module.scss +418 -0
  195. package/src/components/TextInputInset/TextInputInset.stories.tsx +213 -0
  196. package/src/components/TextInputInset/TextInputInset.test.tsx +222 -0
  197. package/src/components/TextInputInset/TextInputInset.tsx +261 -0
  198. package/src/components/TextareaInput/TextareaInput.mdx +117 -0
  199. package/src/components/TextareaInput/TextareaInput.module.scss +275 -0
  200. package/src/components/TextareaInput/TextareaInput.stories.tsx +293 -0
  201. package/src/components/TextareaInput/TextareaInput.test.tsx +195 -0
  202. package/src/components/TextareaInput/TextareaInput.tsx +182 -0
  203. package/src/components/TextareaInputInset/TextareaInputInset.mdx +55 -0
  204. package/src/components/TextareaInputInset/TextareaInputInset.module.scss +337 -0
  205. package/src/components/TextareaInputInset/TextareaInputInset.stories.tsx +160 -0
  206. package/src/components/TextareaInputInset/TextareaInputInset.test.tsx +199 -0
  207. package/src/components/TextareaInputInset/TextareaInputInset.tsx +213 -0
  208. package/src/components/ThemeProvider/ThemeProvider.mdx +11 -0
  209. package/src/components/ThemeProvider/ThemeProvider.stories.tsx +56 -0
  210. package/src/components/ThemeProvider/ThemeProvider.tsx +75 -0
  211. package/src/components/TimePicker/TimePicker.mdx +75 -0
  212. package/src/components/TimePicker/TimePicker.stories.tsx +149 -0
  213. package/src/components/TimePicker/TimePicker.test.tsx +97 -0
  214. package/src/components/TimePicker/TimePicker.tsx +83 -0
  215. package/src/components/TimePickerNative/TimePickerNative.mdx +67 -0
  216. package/src/components/TimePickerNative/TimePickerNative.stories.tsx +151 -0
  217. package/src/components/TimePickerNative/TimePickerNative.test.tsx +117 -0
  218. package/src/components/TimePickerNative/TimePickerNative.tsx +93 -0
  219. package/src/components/Toast/Toast.mdx +134 -0
  220. package/src/components/Toast/Toast.store.ts +280 -0
  221. package/src/components/Toast/Toast.stories.tsx +283 -0
  222. package/src/components/Toast/Toast.test.tsx +784 -0
  223. package/src/components/Toast/Toast.types.ts +98 -0
  224. package/src/components/Toast/ToastContainer.tsx +170 -0
  225. package/src/components/Toast/ToastNotification.module.scss +63 -0
  226. package/src/components/Toast/ToastNotification.tsx +176 -0
  227. package/src/components/Toast/index.ts +4 -0
  228. package/src/components/Toast/toast.ts +102 -0
  229. package/src/components/Toast/useToasts.ts +102 -0
  230. package/src/components/Toggle/Toggle.mdx +51 -0
  231. package/src/components/Toggle/Toggle.module.scss +294 -0
  232. package/src/components/Toggle/Toggle.stories.tsx +128 -0
  233. package/src/components/Toggle/Toggle.test.tsx +308 -0
  234. package/src/components/Toggle/Toggle.tsx +184 -0
  235. package/src/constants/keyCodes.ts +2 -0
  236. package/src/docs/Brands.mdx +153 -0
  237. package/src/docs/Colors.mdx +158 -0
  238. package/src/docs/DesignTokens.mdx +415 -0
  239. package/src/docs/GetStarted.mdx +47 -0
  240. package/src/docs/intro.mdx +12 -0
  241. package/src/fonts/AvenirBold.otf +0 -0
  242. package/src/fonts/AvenirBold.woff +0 -0
  243. package/src/fonts/AvenirBold.woff2 +0 -0
  244. package/src/fonts/AvenirLight.otf +0 -0
  245. package/src/fonts/AvenirLight.woff +0 -0
  246. package/src/fonts/AvenirLight.woff2 +0 -0
  247. package/src/fonts/AvenirRegular.otf +0 -0
  248. package/src/fonts/AvenirRegular.woff +0 -0
  249. package/src/fonts/AvenirRegular.woff2 +0 -0
  250. package/src/fonts/Geist-Bold.otf +0 -0
  251. package/src/fonts/Geist-Bold.woff +0 -0
  252. package/src/fonts/Geist-Bold.woff2 +0 -0
  253. package/src/fonts/Geist-Medium.otf +0 -0
  254. package/src/fonts/Geist-Medium.woff +0 -0
  255. package/src/fonts/Geist-Medium.woff2 +0 -0
  256. package/src/fonts/Geist-Regular.otf +0 -0
  257. package/src/fonts/Geist-Regular.woff +0 -0
  258. package/src/fonts/Geist-Regular.woff2 +0 -0
  259. package/src/fonts/Geist-SemiBold.otf +0 -0
  260. package/src/fonts/Geist-SemiBold.woff +0 -0
  261. package/src/fonts/Geist-SemiBold.woff2 +0 -0
  262. package/src/fonts/GeistMono-Regular.otf +0 -0
  263. package/src/fonts/GeistMono-Regular.woff +0 -0
  264. package/src/fonts/GeistMono-Regular.woff2 +0 -0
  265. package/src/hooks/index.ts +4 -0
  266. package/src/hooks/useBreakpoint/useBreakpoint.mdx +26 -0
  267. package/src/hooks/useBreakpoint/useBreakpoint.stories.tsx +30 -0
  268. package/src/hooks/useBreakpoint/useBreakpoint.test.tsx +19 -0
  269. package/src/hooks/useBreakpoint/useBreakpoint.ts +50 -0
  270. package/src/hooks/useIsomorphicLayoutEffect/useIsomorphicLayouEffect.ts +5 -0
  271. package/src/hooks/useOpenClose/useOpenClose.mdx +15 -0
  272. package/src/hooks/useOpenClose/useOpenClose.stories.tsx +41 -0
  273. package/src/hooks/useOpenClose/useOpenClose.test.tsx +119 -0
  274. package/src/hooks/useOpenClose/useOpenClose.tsx +95 -0
  275. package/src/hooks/useWindowSize/useWindowSize.mdx +25 -0
  276. package/src/hooks/useWindowSize/useWindowSize.stories.tsx +35 -0
  277. package/src/hooks/useWindowSize/useWindowSize.ts +24 -0
  278. package/src/index.ts +48 -0
  279. package/src/lib/cssShorthandToClasses.test.ts +149 -0
  280. package/src/lib/cssShorthandToClasses.ts +133 -0
  281. package/src/lib/doesStringIncludeCssUnit.ts +6 -0
  282. package/src/lib/generateResponsiveClasses.test.ts +24 -0
  283. package/src/lib/generateResponsiveClasses.ts +30 -0
  284. package/src/lib/getAutoCompleteValue.test.ts +27 -0
  285. package/src/lib/getAutoCompleteValue.ts +12 -0
  286. package/src/lib/getColumnKeys.ts +27 -0
  287. package/src/lib/getDimensionCss.test.ts +148 -0
  288. package/src/lib/getDimensionCss.ts +73 -0
  289. package/src/lib/getElementType.test.tsx +42 -0
  290. package/src/lib/getElementType.ts +42 -0
  291. package/src/lib/getFlexCss.test.ts +122 -0
  292. package/src/lib/getFlexCss.ts +67 -0
  293. package/src/lib/index.ts +15 -0
  294. package/src/lib/isFunction.ts +6 -0
  295. package/src/lib/mergeRefs.ts +15 -0
  296. package/src/lib/prefersReducedMotion.ts +12 -0
  297. package/src/lib/react-children-utilities/filter.ts +12 -0
  298. package/src/lib/react-children-utilities/index.ts +1 -0
  299. package/src/lib/reactRouterClickHandler.ts +37 -0
  300. package/src/lib/resolveValue.ts +7 -0
  301. package/src/lib/tokens.ts +139 -0
  302. package/src/modes.ts +8 -0
  303. package/src/styles/animation.scss +152 -0
  304. package/src/styles/cursor.scss +43 -0
  305. package/src/styles/display.scss +119 -0
  306. package/src/styles/flex.scss +453 -0
  307. package/src/styles/fonts.scss +44 -0
  308. package/src/styles/globals/utilities.scss +4 -0
  309. package/src/styles/mixins.scss +14 -0
  310. package/src/styles/overflow.scss +41 -0
  311. package/src/styles/position.scss +45 -0
  312. package/src/styles/reset.scss +108 -0
  313. package/src/styles/text-align.scss +21 -0
  314. package/src/styles/utilities.scss +9 -0
  315. package/src/styles/variables/forms.scss +71 -0
  316. package/src/styles/variables/index.scss +3 -0
  317. package/src/styles/white-space.scss +21 -0
  318. package/src/types/index.ts +201 -0
  319. package/src/types/lib.types.ts +3 -0
@@ -0,0 +1,171 @@
1
+ import React from 'react';
2
+ import classNames from 'classnames';
3
+ import { cssShorthandToClasses } from '../../lib/cssShorthandToClasses';
4
+ import { InputValidationMessage } from '../InputValidationMessage/InputValidationMessage';
5
+ import { FormLabel } from '../FormLabel/FormLabel';
6
+ import { Box } from '../Box/Box';
7
+ import { Checkbox, CheckboxSize, CheckboxProps } from './components/Checkbox';
8
+
9
+ const labelMarginSizeMap = {
10
+ sm: '2xs 0 0 0',
11
+ md: 'xs 0 0 0',
12
+ lg: 'sm 0 0 0',
13
+ };
14
+
15
+ const computedResponsiveSize = (
16
+ // eslint-disable-line @typescript-eslint/explicit-module-boundary-types
17
+ size: CheckboxInputProps['size']
18
+ ) => {
19
+ if (size && !(typeof size === 'string') && typeof size === 'object') {
20
+ return Object.entries(size).reduce(
21
+ (acc, [key, value]) => ({
22
+ ...acc,
23
+ [key]: labelMarginSizeMap[value || 'md'],
24
+ }),
25
+ {}
26
+ );
27
+ }
28
+
29
+ return labelMarginSizeMap[size || 'md'] as string;
30
+ };
31
+ export interface CheckboxInputProps {
32
+ /**
33
+ * The id attribute of the input.
34
+ */
35
+ id: string;
36
+ /**
37
+ * The checkbox input "checked" attribute.
38
+ */
39
+ isChecked: boolean;
40
+ /**
41
+ * Custom content to be displayed to right of checkbox.
42
+ */
43
+ label: string;
44
+ /**
45
+ * Callback function when input is changed.
46
+ */
47
+ onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
48
+ /**
49
+ * Additional classes to add.
50
+ */
51
+ className?: string;
52
+ /**
53
+ * Mark the input field as invalid and display a validation message.
54
+ * Pass a string or node to render a validation message below the input.
55
+ */
56
+ error?: React.ReactNode;
57
+ /**
58
+ * Additional clarifying text to help describe the input
59
+ */
60
+ helpText?: React.ReactNode;
61
+ /**
62
+ * Determines if the label is not shown for stylistic reasons.
63
+ * Note the label is still a required prop and will be used as the aria-label for accessibility reasons.
64
+ */
65
+ hideLabel?: boolean;
66
+ /**
67
+ * If the input should be disabled and not focusable.
68
+ */
69
+ isDisabled?: boolean;
70
+ /**
71
+ * Whether the checkbox is rendered in an indeterminate state.
72
+ * NOTE: this change is only visual and it does not affect the checked or unchecked state of the checkbox.
73
+ */
74
+ isIndeterminate?: CheckboxProps['isIndeterminate'];
75
+ /**
76
+ * The required and aria-required attributes on the input
77
+ */
78
+ isRequired?: boolean;
79
+ /**
80
+ * Callback function when input is blurred.
81
+ */
82
+ onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;
83
+ /**
84
+ * Callback function when input is focused.
85
+ */
86
+ onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void;
87
+ /**
88
+ * Visual indicator that the field is required, that gets appended to the label
89
+ */
90
+ requiredIndicator?: React.ReactNode;
91
+ /**
92
+ * The size of the checkbox.
93
+ */
94
+ size?: CheckboxSize;
95
+ /**
96
+ * Additional props to be spread to rendered element
97
+ */
98
+ [x: string]: any; // eslint-disable-line
99
+ }
100
+
101
+ export const CheckboxInput: React.FC<CheckboxInputProps> = ({
102
+ id,
103
+ isChecked,
104
+ label,
105
+ onChange,
106
+ className = '',
107
+ error = false,
108
+ hideLabel = false,
109
+ helpText,
110
+ isDisabled = false,
111
+ isIndeterminate = false,
112
+ isRequired = false,
113
+ onBlur = undefined,
114
+ onFocus = undefined,
115
+ requiredIndicator = ' *',
116
+ size = 'md',
117
+ ...restProps
118
+ }) => {
119
+ const handleBlur = (event: React.FocusEvent<HTMLInputElement>): void => {
120
+ if (onBlur) onBlur(event);
121
+ };
122
+
123
+ const handleChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
124
+ onChange(event);
125
+ };
126
+
127
+ const handleFocus = (event: React.FocusEvent<HTMLInputElement>): void => {
128
+ if (onFocus) onFocus(event);
129
+ };
130
+
131
+ const checkboxProps = {
132
+ id,
133
+ isChecked: !!isChecked,
134
+ isDisabled,
135
+ isIndeterminate,
136
+ onBlur: handleBlur,
137
+ onChange: handleChange,
138
+ onFocus: handleFocus,
139
+ isRequired,
140
+ size,
141
+ label,
142
+ className: classNames(
143
+ 'hyphen-components__variables__form-control',
144
+ 'm-right-md'
145
+ ),
146
+ error,
147
+ };
148
+
149
+ const labelProps = {
150
+ inputId: id,
151
+ helpText,
152
+ isDisabled,
153
+ isFieldRequired: isRequired,
154
+ requiredIndicator,
155
+ className: classNames(
156
+ ...cssShorthandToClasses('m', computedResponsiveSize(size))
157
+ ),
158
+ };
159
+
160
+ return (
161
+ <Box className={className} {...restProps}>
162
+ <Box alignItems="flex-start" direction="row">
163
+ <Checkbox {...checkboxProps} labelledby={`${id}Label`} />
164
+ {label && !hideLabel && <FormLabel {...labelProps}>{label}</FormLabel>}
165
+ </Box>
166
+ {error && error !== true && (
167
+ <InputValidationMessage>{error}</InputValidationMessage>
168
+ )}
169
+ </Box>
170
+ );
171
+ };
@@ -0,0 +1,174 @@
1
+ @import '../../../styles/mixins';
2
+ @import '@hyphen/hyphen-design-tokens/build/scss/variables';
3
+
4
+ $sm-dimension: 20px;
5
+ $md-dimension: 24px;
6
+ $lg-dimension: 36px;
7
+
8
+ @mixin size-sm {
9
+ border-radius: var(--size-border-radius-xs);
10
+ height: $sm-dimension;
11
+ font-size: var(--size-font-size-lg);
12
+
13
+ * {
14
+ width: $sm-dimension;
15
+ height: $sm-dimension;
16
+ }
17
+ }
18
+
19
+ %size-sm {
20
+ @include size-sm;
21
+ }
22
+ .size-sm {
23
+ @extend %size-sm;
24
+ }
25
+
26
+ @mixin size-md {
27
+ border-radius: var(--size-border-radius-sm);
28
+ height: $md-dimension;
29
+ font-size: var(--size-font-size-xl);
30
+
31
+ * {
32
+ width: $md-dimension;
33
+ height: $md-dimension;
34
+ }
35
+ }
36
+
37
+ %size-md {
38
+ @include size-md;
39
+ }
40
+ .size-md {
41
+ @extend %size-md;
42
+ }
43
+
44
+ @mixin size-lg {
45
+ border-radius: var(--size-border-radius-sm);
46
+ height: $lg-dimension;
47
+ font-size: var(--size-font-size-2xl);
48
+
49
+ * {
50
+ width: $lg-dimension;
51
+ height: $lg-dimension;
52
+ }
53
+ }
54
+
55
+ %size-lg {
56
+ @include size-lg;
57
+ }
58
+ .size-lg {
59
+ @extend %size-lg;
60
+ }
61
+
62
+ .checkbox {
63
+ &.hidden {
64
+ @include accessible-hidden-element;
65
+
66
+ height: 0;
67
+ }
68
+
69
+ input + div {
70
+ background: var(--form-control-background-color, var(--color-base-white));
71
+ color: var(--form-control-checkbox-color, var(--color-base-grey-500));
72
+ }
73
+
74
+ input:checked + div,
75
+ input:indeterminate + div {
76
+ color: var(
77
+ --form-control-checkbox-color-checked,
78
+ var(--color-base-primary-500)
79
+ );
80
+ }
81
+
82
+ // stylelint-disable
83
+ input[aria-invalid='true'] + div {
84
+ color: var(--form-control-font-color-error, var(--color-base-danger-500));
85
+ }
86
+ // stylelint-enable
87
+
88
+ input:focus + div {
89
+ outline: 0;
90
+ box-shadow: var(
91
+ --form-control-box-shadow-focus,
92
+ var(--INTERNAL_form-control-box-shadow-focus)
93
+ );
94
+ }
95
+
96
+ // Show focus styles on keyboard focus.
97
+ input:focus-visible + div {
98
+ outline: 0;
99
+ box-shadow: var(
100
+ --form-control-box-shadow-focus,
101
+ var(--INTERNAL_form-control-box-shadow-focus)
102
+ );
103
+ }
104
+
105
+ input:disabled + div {
106
+ background: var(
107
+ --form-control-background-color-disabled,
108
+ var(--color-base-grey-50)
109
+ );
110
+ color: var(
111
+ --form-control-checkbox-color-disabled,
112
+ var(--color-base-grey-200)
113
+ );
114
+ }
115
+
116
+ // Hide focus styles if they are not needed, for example, when an element receives focus via the mouse.
117
+ input:focus:not(:focus-visible) + div {
118
+ outline: 0;
119
+ box-shadow: none;
120
+ }
121
+
122
+ input:checked:disabled + div {
123
+ color: var(
124
+ --form-control-checkbox-color-checked-disabled,
125
+ var(--color-base-primary-200)
126
+ );
127
+ }
128
+
129
+ &.size-sm {
130
+ @extend %size-sm;
131
+ }
132
+ &.size-md {
133
+ @extend %size-md;
134
+ }
135
+ &.size-lg {
136
+ @extend %size-lg;
137
+ }
138
+
139
+ @media (min-width: $size-breakpoint-tablet) {
140
+ &.size-sm-tablet {
141
+ @include size-sm;
142
+ }
143
+ &.size-md-tablet {
144
+ @include size-md;
145
+ }
146
+ &.size-lg-tablet {
147
+ @include size-lg;
148
+ }
149
+ }
150
+
151
+ @media (min-width: $size-breakpoint-desktop) {
152
+ &.size-sm-desktop {
153
+ @include size-sm;
154
+ }
155
+ &.size-md-desktop {
156
+ @include size-md;
157
+ }
158
+ &.size-lg-desktop {
159
+ @include size-lg;
160
+ }
161
+ }
162
+
163
+ @media (min-width: $size-breakpoint-hd) {
164
+ &.size-sm-hd {
165
+ @include size-sm;
166
+ }
167
+ &.size-md-hd {
168
+ @include size-md;
169
+ }
170
+ &.size-lg-hd {
171
+ @include size-lg;
172
+ }
173
+ }
174
+ }
@@ -0,0 +1,201 @@
1
+ import React from 'react';
2
+ import { fireEvent, render, screen } from '@testing-library/react';
3
+ import { Checkbox } from './Checkbox';
4
+
5
+ describe('Checkbox', () => {
6
+ describe('Default', () => {
7
+ test('It renders a checkbox input and checkbox-btn svg icon element', () => {
8
+ render(
9
+ <Checkbox
10
+ id="testCheckbox"
11
+ label="test checkbox"
12
+ onChange={jest.fn(() => null)}
13
+ isChecked={false}
14
+ />
15
+ );
16
+
17
+ const input = screen.getByLabelText('test checkbox');
18
+ expect(input).toBeInTheDocument();
19
+ expect(
20
+ screen.getByTestId('icon-testid--checkbox-btn')
21
+ ).toBeInTheDocument();
22
+ });
23
+ });
24
+
25
+ describe('Checked', () => {
26
+ test('It renders a checked checkbox input element and checkbox-btn-checked svg icon', () => {
27
+ render(
28
+ <Checkbox
29
+ id="testCheckbox"
30
+ label="test checkbox"
31
+ onChange={jest.fn(() => null)}
32
+ isChecked
33
+ />
34
+ );
35
+
36
+ const input = screen.getByLabelText('test checkbox');
37
+ expect(input).toHaveAttribute('checked');
38
+ expect(
39
+ screen.getByTestId('icon-testid--checkbox-btn-checked')
40
+ ).toBeInTheDocument();
41
+ });
42
+ });
43
+
44
+ describe('Indeterminate', () => {
45
+ test('It renders an indeterminate icon if isIndeterminate is true and checkbox is checked', () => {
46
+ render(
47
+ <Checkbox
48
+ id="testCheckbox"
49
+ label="test checkbox"
50
+ onChange={jest.fn(() => null)}
51
+ isChecked
52
+ isIndeterminate
53
+ />
54
+ );
55
+
56
+ const input = screen.getByLabelText('test checkbox');
57
+ expect(input).toHaveAttribute('checked');
58
+ expect(
59
+ screen.getByTestId('icon-testid--checkbox-btn-indeterminate')
60
+ ).toBeInTheDocument();
61
+ });
62
+
63
+ test('It renders an indeterminate icon if isIndeterminate is true and checkbox is unchecked', () => {
64
+ render(
65
+ <Checkbox
66
+ id="testCheckbox"
67
+ label="test checkbox"
68
+ onChange={jest.fn(() => null)}
69
+ isChecked={false}
70
+ isIndeterminate
71
+ />
72
+ );
73
+
74
+ expect(
75
+ screen.getByTestId('icon-testid--checkbox-btn-indeterminate')
76
+ ).toBeInTheDocument();
77
+ });
78
+ });
79
+
80
+ describe('Disabled', () => {
81
+ test('input element is disabled', () => {
82
+ render(
83
+ <Checkbox
84
+ isChecked={false}
85
+ id="testCheckbox"
86
+ label="test checkbox"
87
+ onChange={jest.fn(() => null)}
88
+ isDisabled
89
+ />
90
+ );
91
+
92
+ const input = screen.getByLabelText('test checkbox');
93
+ expect(input).toHaveAttribute('disabled');
94
+ });
95
+ });
96
+
97
+ describe('onChange', () => {
98
+ test('onChange event fires callback function', () => {
99
+ const mockedHandleChange = jest.fn(() => null);
100
+
101
+ const { getByLabelText } = render(
102
+ <Checkbox
103
+ id="testCheckbox"
104
+ label="test checkbox"
105
+ isChecked={false}
106
+ onChange={mockedHandleChange}
107
+ />
108
+ );
109
+ const checkbox = getByLabelText('test checkbox');
110
+ fireEvent.click(checkbox);
111
+ expect(mockedHandleChange).toHaveBeenCalledTimes(1);
112
+ });
113
+
114
+ test('calls onChange and passes checked value in event', () => {
115
+ let value = true;
116
+ const mockedHandleChange = jest.fn((event) => {
117
+ value = event.target.checked;
118
+ });
119
+
120
+ const { getByLabelText } = render(
121
+ <Checkbox
122
+ id="testCheckbox"
123
+ label="test checkbox"
124
+ onChange={mockedHandleChange}
125
+ isChecked={value}
126
+ />
127
+ );
128
+ const checkbox = getByLabelText('test checkbox');
129
+ fireEvent.click(checkbox);
130
+ expect(mockedHandleChange).toBeCalledTimes(1);
131
+ expect(value).toBe(false);
132
+ });
133
+ });
134
+
135
+ describe('onFocus', () => {
136
+ test('onFocus event fires callback function if defined', () => {
137
+ const mockedHandleFocus = jest.fn(() => null);
138
+
139
+ const { getByText, getByLabelText } = render(
140
+ <div>
141
+ <button type="button">focus</button>
142
+ <Checkbox
143
+ id="testCheckbox"
144
+ label="test checkbox"
145
+ isChecked={false}
146
+ onChange={() => null}
147
+ onFocus={mockedHandleFocus}
148
+ onBlur={undefined}
149
+ />
150
+ </div>
151
+ );
152
+ getByLabelText('test checkbox').focus();
153
+ getByText('focus').focus();
154
+ expect(mockedHandleFocus).toHaveBeenCalledTimes(1);
155
+ });
156
+ });
157
+
158
+ describe('onBlur', () => {
159
+ test('onBlur event fires callback function if defined', () => {
160
+ const mockedHandleBlur = jest.fn(() => null);
161
+
162
+ const { getByText, getByLabelText } = render(
163
+ <div>
164
+ <button type="button">focus</button>
165
+ <Checkbox
166
+ id="testCheckbox"
167
+ label="test checkbox"
168
+ isChecked={false}
169
+ onChange={() => null}
170
+ onBlur={mockedHandleBlur}
171
+ />
172
+ </div>
173
+ );
174
+ getByLabelText('test checkbox').focus();
175
+ getByText('focus').focus();
176
+ expect(mockedHandleBlur).toHaveBeenCalledTimes(1);
177
+ });
178
+ });
179
+
180
+ describe('Hidden', () => {
181
+ test('the radio input is hidden', () => {
182
+ const mockedHandleChange = jest.fn(() => {}); // eslint-disable-line
183
+
184
+ render(
185
+ <Checkbox
186
+ id="mockId"
187
+ name="mockName"
188
+ onChange={mockedHandleChange}
189
+ isHidden
190
+ isChecked
191
+ label="mockLabel"
192
+ />
193
+ );
194
+
195
+ const checkboxInputContainer = screen
196
+ .getByRole('checkbox')
197
+ .closest('div');
198
+ expect(checkboxInputContainer).toHaveClass('hidden');
199
+ });
200
+ });
201
+ });
@@ -0,0 +1,176 @@
1
+ import React from 'react';
2
+ import classNames from 'classnames';
3
+ import { ResponsiveProp } from '../../../types';
4
+ import { generateResponsiveClasses } from '../../../lib/generateResponsiveClasses';
5
+ import { Box, BoxProps } from '../../Box/Box';
6
+ import { CheckboxIcon } from './CheckboxIcon'; // eslint-disable-line import/no-cycle
7
+ import styles from './Checkbox.module.scss';
8
+
9
+ type BaseSize = 'sm' | 'md' | 'lg';
10
+ export type CheckboxSize = BaseSize | ResponsiveProp<BaseSize>;
11
+
12
+ export interface CheckboxProps
13
+ extends Omit<BoxProps, 'radius' | 'background' | 'as' | 'height'> {
14
+ /**
15
+ * The id attribute of the input.
16
+ */
17
+ id: string;
18
+ /**
19
+ * The checkbox input "checked" attribute.
20
+ */
21
+ isChecked: boolean;
22
+ /**
23
+ * Custom content to be displayed to right of checkbox.
24
+ */
25
+ label: string;
26
+ /**
27
+ * Callback function when input is changed.
28
+ */
29
+ onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
30
+ /**
31
+ * Custom class to apply to the checkbox container.
32
+ */
33
+ className?: string;
34
+ /**
35
+ * Mark the input field as invalid and display a validation message.
36
+ * Pass a string or node to render a validation message below the input.
37
+ */
38
+ error?: React.ReactNode;
39
+ /**
40
+ * id of the element that labels the Checkbox
41
+ */
42
+ labelledby?: string;
43
+ /**
44
+ * If the input should be disabled and not focusable.
45
+ */
46
+ isDisabled?: boolean;
47
+ /**
48
+ * If the radio input should be hidden to make way for a custom checkbox.
49
+ */
50
+ isHidden?: boolean;
51
+ /**
52
+ * Whether the checkbox is rendered in an indeterminate state.
53
+ * NOTE: this change is only visual and it does not affect the checked or unchecked state of the checkbox.
54
+ */
55
+ isIndeterminate?: boolean;
56
+ /**
57
+ * The required and aria-required attributes on the input
58
+ */
59
+ isRequired?: boolean;
60
+ /**
61
+ * Callback function when input is blurred.
62
+ */
63
+ onBlur?: (event: React.FocusEvent<HTMLInputElement>) => void;
64
+ /**
65
+ * Callback function when input is focused.
66
+ */
67
+ onFocus?: (event: React.FocusEvent<HTMLInputElement>) => void;
68
+ /**
69
+ * The size of the checkbox.
70
+ */
71
+ size?: CheckboxSize;
72
+ /**
73
+ * Value of the checkbox input element
74
+ */
75
+ value?: string | number;
76
+ }
77
+
78
+ export const Checkbox: React.FC<CheckboxProps> = React.forwardRef(
79
+ (
80
+ {
81
+ className = '',
82
+ display = 'inline',
83
+ id,
84
+ isChecked,
85
+ label,
86
+ labelledby,
87
+ onChange,
88
+ error = false,
89
+ isDisabled = false,
90
+ isHidden = false,
91
+ isIndeterminate = false,
92
+ isRequired = false,
93
+ onBlur = undefined,
94
+ onFocus = undefined,
95
+ size = 'md',
96
+ value = undefined,
97
+ ...restProps
98
+ },
99
+ ref
100
+ ) => {
101
+ const inputRef = React.useRef<HTMLInputElement>(null);
102
+
103
+ React.useEffect(() => {
104
+ if (inputRef?.current) {
105
+ inputRef.current.indeterminate = isIndeterminate;
106
+ }
107
+ }, [isIndeterminate]);
108
+
109
+ const handleBlur = (event: React.FocusEvent<HTMLInputElement>): void => {
110
+ if (onBlur) onBlur(event);
111
+ };
112
+
113
+ const handleChange = (event: React.ChangeEvent<HTMLInputElement>): void => {
114
+ onChange(event);
115
+ };
116
+
117
+ const handleFocus = (event: React.FocusEvent<HTMLInputElement>): void => {
118
+ if (onFocus) onFocus(event);
119
+ };
120
+
121
+ const inputProps = {
122
+ 'aria-invalid': !!error,
123
+ 'aria-label': label,
124
+ 'aria-labelledby': labelledby,
125
+ 'aria-required': isRequired,
126
+ id,
127
+ checked: !!isChecked,
128
+ disabled: isDisabled,
129
+ onBlur: handleBlur,
130
+ onChange: handleChange,
131
+ onFocus: handleFocus,
132
+ required: isRequired,
133
+ type: 'checkbox',
134
+ ref: inputRef,
135
+ ...(value && { value }),
136
+ };
137
+
138
+ const responsiveClasses = generateResponsiveClasses('size', size);
139
+
140
+ const containerClasses = classNames(
141
+ styles.checkbox,
142
+ className,
143
+ ...responsiveClasses.map((c) => styles[c]),
144
+ { [styles.hidden]: isHidden }
145
+ );
146
+
147
+ const iconClasses = classNames(...responsiveClasses.map((c) => styles[c]));
148
+
149
+ return (
150
+ <Box
151
+ display={display}
152
+ ref={ref}
153
+ style={{ position: 'relative' }}
154
+ className={containerClasses}
155
+ {...restProps}
156
+ >
157
+ <input
158
+ {...inputProps}
159
+ style={{
160
+ position: 'absolute',
161
+ opacity: '0',
162
+ }}
163
+ />
164
+ {!isHidden && (
165
+ <CheckboxIcon
166
+ isChecked={isChecked}
167
+ isDisabled={isDisabled}
168
+ isIndeterminate={isIndeterminate}
169
+ className={iconClasses}
170
+ error={error}
171
+ />
172
+ )}
173
+ </Box>
174
+ );
175
+ }
176
+ );