@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,42 @@
1
+ import React from 'react';
2
+ /**
3
+ * Returns a createElement() type based on the props of the Component.
4
+ * Useful for calculating what type a component should render as.
5
+ *
6
+ * @param {function} Component A function or ReactClass.
7
+ * @param {object} props A ReactElement props object
8
+ * @param {function} [getDefault] A function that returns a default element type.
9
+ * @returns {string} A ReactElement type
10
+ */
11
+ export function getElementType( // eslint-disable-line import/prefer-default-export
12
+ Component: React.Component | React.FC,
13
+ props: { [key: string]: unknown },
14
+ getDefault?: () => string
15
+ ): string {
16
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
17
+ // @ts-ignore
18
+ const { defaultProps = {} } = Component;
19
+
20
+ // ----------------------------------------
21
+ // user defined "as" element type
22
+
23
+ if (props.as && props.as !== defaultProps.as) return props.as as string;
24
+
25
+ // ----------------------------------------
26
+ // computed default element type
27
+
28
+ if (getDefault) {
29
+ const computedDefault = getDefault();
30
+ if (computedDefault) return computedDefault;
31
+ }
32
+
33
+ // ----------------------------------------
34
+ // infer anchor links
35
+
36
+ if (props.href) return 'a';
37
+
38
+ // ----------------------------------------
39
+ // use defaultProp or 'div'
40
+
41
+ return defaultProps.as || 'div';
42
+ }
@@ -0,0 +1,122 @@
1
+ import { getFlexCss } from './getFlexCss';
2
+
3
+ describe('getFlexCss', () => {
4
+ describe('Single value shorthand applies classes', () => {
5
+ const flexValues = ['initial', 'auto', 'unset', 'none', 'inherit'];
6
+ flexValues.map((value) =>
7
+ test(`returns expected css object with class flex: ${value} is passed`, () => {
8
+ const flexCss = getFlexCss(value);
9
+
10
+ expect(flexCss).toEqual({
11
+ classes: [`flex-${value}`],
12
+ styles: {},
13
+ });
14
+ })
15
+ );
16
+ });
17
+
18
+ describe('Single value shorthand applies styles', () => {
19
+ const flexValues = ['1', '1rem', '10%', '2em', '100px', '50vw', '50vh'];
20
+ flexValues.map((value) =>
21
+ test(`returns expected css object with class flex: ${value} is passed`, () => {
22
+ const flexCss = getFlexCss(value);
23
+
24
+ expect(flexCss).toEqual({
25
+ styles: { flex: value },
26
+ classes: [],
27
+ });
28
+ })
29
+ );
30
+ });
31
+
32
+ describe('Two-value shorthand applies styles with flex integer values', () => {
33
+ const flexValues = ['1 0', 'auto 1', '0 2'];
34
+ flexValues.map((value) =>
35
+ test(`returns expected css object with class flex: ${value} is passed`, () => {
36
+ const flexCss = getFlexCss(value);
37
+ const flexProps = value.split(' ');
38
+
39
+ expect(flexCss).toEqual({
40
+ styles: {
41
+ flexGrow: Number.isNaN(Number(flexProps[0]))
42
+ ? flexProps[0]
43
+ : Number(flexProps[0]),
44
+ flexShrink: Number.isNaN(Number(flexProps[1]))
45
+ ? flexProps[1]
46
+ : Number(flexProps[1]),
47
+ },
48
+ classes: [],
49
+ });
50
+ })
51
+ );
52
+ });
53
+
54
+ describe('Two-value shorthand applies styles with css unit values', () => {
55
+ const flexValues = ['10px 10px', '1 10vw', '0 50%'];
56
+ flexValues.map((value) =>
57
+ test(`returns expected css object with class flex: ${value} is passed`, () => {
58
+ const flexCss = getFlexCss(value);
59
+ const flexProps = value.split(' ');
60
+
61
+ expect(flexCss).toEqual({
62
+ styles: {
63
+ flexGrow: Number.isNaN(Number(flexProps[0]))
64
+ ? flexProps[0]
65
+ : Number(flexProps[0]),
66
+ flexBasis: Number.isNaN(Number(flexProps[1]))
67
+ ? flexProps[1]
68
+ : Number(flexProps[1]),
69
+ },
70
+ classes: [],
71
+ });
72
+ })
73
+ );
74
+ });
75
+
76
+ describe('Two-value shorthand applies styles to correct flex property', () => {
77
+ const flexValues = ['10px inherit', '1 auto', '0 initial'];
78
+ flexValues.map((value) =>
79
+ test(`returns expected css object with class flex: ${value} is passed`, () => {
80
+ const flexCss = getFlexCss(value);
81
+ const flexProps = value.split(' ');
82
+
83
+ expect(flexCss).toEqual({
84
+ styles: {
85
+ flexGrow: Number.isNaN(Number(flexProps[0]))
86
+ ? flexProps[0]
87
+ : Number(flexProps[0]),
88
+ flexShrink: Number.isNaN(Number(flexProps[1]))
89
+ ? flexProps[1]
90
+ : Number(flexProps[1]),
91
+ },
92
+ classes: [],
93
+ });
94
+ })
95
+ );
96
+ });
97
+
98
+ describe('Three-value shorthand applies styles with css unit values', () => {
99
+ const flexValues = ['1 auto 10px', 'auto 0 10%', '0 1 50%', '1 1 1'];
100
+ flexValues.map((value) =>
101
+ test(`returns expected css object with class flex: ${value} is passed`, () => {
102
+ const flexCss = getFlexCss(value);
103
+ const flexProps = value.split(' ');
104
+
105
+ expect(flexCss).toEqual({
106
+ styles: {
107
+ flexGrow: Number.isNaN(Number(flexProps[0]))
108
+ ? flexProps[0]
109
+ : Number(flexProps[0]),
110
+ flexShrink: Number.isNaN(Number(flexProps[1]))
111
+ ? flexProps[1]
112
+ : Number(flexProps[1]),
113
+ flexBasis: Number.isNaN(Number(flexProps[2]))
114
+ ? flexProps[2]
115
+ : Number(flexProps[2]),
116
+ },
117
+ classes: [],
118
+ });
119
+ })
120
+ );
121
+ });
122
+ });
@@ -0,0 +1,67 @@
1
+ import { StylesAndClasses, FlexProperty, ResponsiveProp } from '../types';
2
+ import { doesStringIncludeCssUnit } from './doesStringIncludeCssUnit';
3
+
4
+ const flexValues = ['initial', 'auto', 'unset', 'none', 'inherit'];
5
+
6
+ export function parsePropertyValue(value: string): string | number {
7
+ return Number.isNaN(Number(value)) ? value : Number(value);
8
+ }
9
+
10
+ export function getFlexStyles(value?: string): FlexProperty | undefined {
11
+ if (value === undefined) return value;
12
+
13
+ const styles: FlexProperty = {};
14
+
15
+ // Single value
16
+ if (!value.includes(' ') && !flexValues.includes(value)) {
17
+ styles.flex = value;
18
+ return styles;
19
+ }
20
+
21
+ // CSS shorthand
22
+ if (value.includes(' ')) {
23
+ const flexProps = value.split(' ');
24
+ styles.flexGrow = parsePropertyValue(flexProps[0]);
25
+
26
+ if (flexProps.length === 2) {
27
+ if (doesStringIncludeCssUnit(flexProps[1])) {
28
+ styles.flexBasis = parsePropertyValue(flexProps[1]);
29
+ } else {
30
+ styles.flexShrink = parsePropertyValue(flexProps[1]);
31
+ }
32
+ } else if (flexProps.length === 3) {
33
+ styles.flexShrink = parsePropertyValue(flexProps[1]);
34
+ styles.flexBasis = parsePropertyValue(flexProps[2]);
35
+ }
36
+ }
37
+
38
+ return styles;
39
+ }
40
+
41
+ export function getFlexClasses(value?: string): string[] | undefined {
42
+ if (value === undefined || value.split(' ').length > 1) return [];
43
+
44
+ const classes = [];
45
+ if (
46
+ typeof value === 'string' &&
47
+ !doesStringIncludeCssUnit(value) &&
48
+ Number.isNaN(Number(value))
49
+ ) {
50
+ classes.push(`flex-${value}`);
51
+ }
52
+
53
+ return classes;
54
+ }
55
+
56
+ /**
57
+ * Returns an object of styles and class names that correspond with the given flex value
58
+ * @param {string} [value] spacing token value
59
+ */
60
+ export function getFlexCss(
61
+ value?: ResponsiveProp<FlexProperty> | string
62
+ ): StylesAndClasses<FlexProperty> {
63
+ return {
64
+ styles: getFlexStyles(value as string),
65
+ classes: getFlexClasses(value as string),
66
+ };
67
+ }
@@ -0,0 +1,15 @@
1
+ export * from './cssShorthandToClasses';
2
+ export * from './doesStringIncludeCssUnit';
3
+ export * from './generateResponsiveClasses';
4
+ export * from './getAutoCompleteValue';
5
+ export * from './getColumnKeys';
6
+ export * from './getDimensionCss';
7
+ export * from './getElementType';
8
+ export * from './getFlexCss';
9
+ export * from './isFunction';
10
+ export * from './mergeRefs';
11
+ export * from './prefersReducedMotion';
12
+ export * from './reactRouterClickHandler';
13
+ export * from './resolveValue';
14
+ export * from './react-children-utilities';
15
+ export * from './tokens';
@@ -0,0 +1,6 @@
1
+ import { ValueOrFunction, ValueFunction } from '../types';
2
+
3
+ export const isFunction = <TValue, TArg>( // eslint-disable-line import/prefer-default-export
4
+ valOrFunction: ValueOrFunction<TValue, TArg>
5
+ ): valOrFunction is ValueFunction<TValue, TArg> =>
6
+ typeof valOrFunction === 'function';
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+
3
+ export function mergeRefs<T = any>(
4
+ refs: Array<React.MutableRefObject<T> | React.LegacyRef<T> | undefined | null>
5
+ ): React.RefCallback<T> {
6
+ return (value) => {
7
+ refs.forEach((ref) => {
8
+ if (typeof ref === 'function') {
9
+ ref(value);
10
+ } else if (ref != null) {
11
+ (ref as React.MutableRefObject<T | null>).current = value;
12
+ }
13
+ });
14
+ };
15
+ }
@@ -0,0 +1,12 @@
1
+ export const prefersReducedMotion = (() => {
2
+ // eslint-disable-line import/prefer-default-export
3
+ let shouldReduceMotion: boolean | undefined;
4
+
5
+ return () => {
6
+ if (shouldReduceMotion === undefined) {
7
+ const mediaQuery = window?.matchMedia('(prefers-reduced-motion: reduce)');
8
+ shouldReduceMotion = !mediaQuery || mediaQuery.matches;
9
+ }
10
+ return shouldReduceMotion;
11
+ };
12
+ })();
@@ -0,0 +1,12 @@
1
+ import { ReactNode, Children } from 'react';
2
+
3
+ export type FilterFunction = (
4
+ child: ReactNode,
5
+ index?: number,
6
+ children?: ReactNode[]
7
+ ) => boolean;
8
+
9
+ export const filter = (
10
+ children: ReactNode,
11
+ filterFn: FilterFunction
12
+ ): ReactNode[] => Children.toArray(children).filter(filterFn);
@@ -0,0 +1 @@
1
+ export * from './filter';
@@ -0,0 +1,37 @@
1
+ import { MouseEvent, AnchorHTMLAttributes } from 'react';
2
+
3
+ export const isModifiedEvent = (
4
+ e: MouseEvent<HTMLButtonElement | HTMLAnchorElement>
5
+ ): boolean => !!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey);
6
+
7
+ /**
8
+ * Due to react-router's handling of custom components used in RR <Link>
9
+ * we must add this validation that ensures the router will execute the passed `navigate`
10
+ * prop, thus navigating the user without triggering a refresh.
11
+ *
12
+ * SOURCES:
13
+ * https://github.com/ReactTraining/react-router/issues/7727
14
+ * https://github.com/ReactTraining/react-router/issues/7761
15
+ * */
16
+ // eslint-disable-next-line import/prefer-default-export
17
+ export const handleReactRouterClick = (
18
+ event: MouseEvent<HTMLButtonElement | HTMLAnchorElement>,
19
+ onClick:
20
+ | ((e: MouseEvent<HTMLButtonElement | HTMLAnchorElement>) => void)
21
+ | undefined,
22
+ target: AnchorHTMLAttributes<HTMLAnchorElement>['target'] | undefined,
23
+ navigate: (() => void) | undefined
24
+ ): void => {
25
+ if (onClick) onClick(event);
26
+
27
+ if (
28
+ !event.defaultPrevented && // onClick prevented default
29
+ event.button === 0 && // ignore everything but left clicks
30
+ (!target || target === '_self') && // let browser handle "target=_blank" etc.
31
+ !isModifiedEvent(event) && // ignore clicks with modifier keys
32
+ navigate
33
+ ) {
34
+ event.preventDefault();
35
+ navigate();
36
+ }
37
+ };
@@ -0,0 +1,7 @@
1
+ import { ValueOrFunction } from '../types';
2
+ import { isFunction } from './isFunction';
3
+
4
+ export const resolveValue = <TValue, TArg>( // eslint-disable-line import/prefer-default-export
5
+ valOrFunction: ValueOrFunction<TValue, TArg>,
6
+ arg: TArg
7
+ ): TValue => (isFunction(valOrFunction) ? valOrFunction(arg) : valOrFunction);
@@ -0,0 +1,139 @@
1
+ import designTokens from '@hyphen/hyphen-design-tokens/build/json/variables';
2
+ import { ICON_NAMES as iconNames } from '@hyphen/hyphen-design-tokens/build/assets/icons';
3
+
4
+ import {
5
+ BaseColor,
6
+ BackgroundColor,
7
+ BorderColor,
8
+ BorderRadiusSize,
9
+ BorderSize,
10
+ Breakpoint,
11
+ BreakpointSizeWithBase,
12
+ BoxShadowSize,
13
+ ColorName,
14
+ FontColor,
15
+ FontSize,
16
+ FontFamily,
17
+ FontWeight,
18
+ HeadingSize,
19
+ HeightSize,
20
+ IconName,
21
+ LineHeightSize,
22
+ SpacingSize,
23
+ WidthSize,
24
+ ZIndexSize,
25
+ } from '../types';
26
+
27
+ export const ICON_NAMES = iconNames as IconName[];
28
+
29
+ export const BORDER_RADIUS_OPTIONS = Object.keys(
30
+ designTokens.size['border-radius']
31
+ ) as BorderRadiusSize[];
32
+ // export const BORDER_RADIUS_VALUES = Object.values(designTokens.size['border-radius']);
33
+
34
+ export const BORDER_SIZE_OPTIONS = Object.keys(
35
+ designTokens.size['border-width']
36
+ ) as BorderSize[];
37
+ // export const BORDER_SIZE_VALUES = Object.values(designTokens.size['border-width']);
38
+
39
+ export const BREAKPOINT_OPTIONS = Object.keys(
40
+ designTokens.size.breakpoint
41
+ ) as BreakpointSizeWithBase[];
42
+ // export const BREAKPOINT_VALUES = Object.values(designTokens.size.breakpoint);
43
+
44
+ export const BREAKPOINTS = [
45
+ ...Object.entries(designTokens.size.breakpoint),
46
+ ['base', { value: '0' }],
47
+ ].map(([name, data]) => {
48
+ if (typeof data === 'object' && data !== null && 'value' in data) {
49
+ return {
50
+ name,
51
+ minWidth: parseInt(data['value'] as string, 10),
52
+ };
53
+ }
54
+ }) as Breakpoint[];
55
+
56
+ export const BASE_COLOR_OPTIONS = (
57
+ Object.keys(designTokens.color.base) as ColorName[]
58
+ )
59
+ .map((colorName) => {
60
+ if (
61
+ colorName === 'white' ||
62
+ colorName === 'black' ||
63
+ colorName === 'magenta'
64
+ )
65
+ return `${colorName}`;
66
+ return Object.keys(designTokens.color.base[colorName]).map((colorGrade) =>
67
+ colorGrade === 'base' ? colorName : `${colorName}-${colorGrade}`
68
+ );
69
+ })
70
+ .flat() as BaseColor[];
71
+
72
+ export const BASE_COLOR_NAMES = Object.keys(
73
+ designTokens.color.base
74
+ ) as ColorName[];
75
+ // export const BASE_COLOR_VALUES = Object.values(designTokens.color.base);
76
+
77
+ export const FONT_COLOR_OPTIONS = Object.keys(
78
+ designTokens.color.font
79
+ ) as FontColor[];
80
+ // export const FONT_COLOR_VALUES = designTokens.color.font;
81
+
82
+ export const BACKGROUND_COLOR_OPTIONS = Object.keys(
83
+ designTokens.color.background
84
+ ) as BackgroundColor[];
85
+ // export const BACKGROUND_COLOR_VALUES = designTokens.color.background;
86
+
87
+ export const BORDER_COLOR_OPTIONS = Object.keys(
88
+ designTokens.color.border
89
+ ) as BorderColor[];
90
+ // export const BORDER_COLOR_VALUES = designTokens.color.border;
91
+
92
+ export const FONT_SIZE_OPTIONS = Object.keys(
93
+ (designTokens.size as any)['font-size']
94
+ ) as FontSize[];
95
+ // export const FONT_SIZE_VALUES = Object.values(designTokens.size['font-size']);
96
+
97
+ export const FONT_FAMILY_OPTIONS = Object.keys(
98
+ designTokens.assets['font-family']
99
+ ) as FontFamily[];
100
+ // export const FONT_FAMILY_VALUES = designTokens.assets['font-family'];
101
+
102
+ export const FONT_WEIGHT_OPTIONS = Object.keys(
103
+ (designTokens.size as any)['font-weight']
104
+ ) as FontWeight[];
105
+ // export const FONT_WEIGHT_VALUES = designTokens.size['font-weight'];
106
+
107
+ export const HEADING_SIZE_OPTIONS = Object.keys(
108
+ designTokens.size.heading
109
+ ) as HeadingSize[];
110
+
111
+ export const HEIGHT_OPTIONS = Object.keys(
112
+ (designTokens.size as any).dimension
113
+ ) as HeightSize[];
114
+ // export const HEIGHT_VALUES = designTokens.size.dimension;
115
+
116
+ export const LINE_HEIGHT_OPTIONS = Object.keys(
117
+ designTokens.size['line-height']
118
+ ) as LineHeightSize[];
119
+ // export const LINE_HEIGHT_VALUES = designTokens.size['line-height'];
120
+
121
+ export const SPACING_OPTIONS = Object.keys(
122
+ designTokens.size.spacing
123
+ ) as SpacingSize[];
124
+ // export const SPACING_VALUES = designTokens.size.spacing;
125
+
126
+ export const WIDTH_OPTIONS = Object.keys(
127
+ (designTokens.size as any).dimension
128
+ ) as WidthSize[];
129
+ // export const WIDTH_VALUES = designTokens.size.dimension;
130
+
131
+ export const Z_INDEX_OPTIONS = Object.keys(
132
+ designTokens.size['z-index']
133
+ ) as ZIndexSize[];
134
+ export const Z_INDEX_VALUES = designTokens.size['z-index'];
135
+
136
+ export const BOX_SHADOW_OPTIONS = Object.keys(
137
+ designTokens.size['box-shadow']
138
+ ) as BoxShadowSize[];
139
+ // export const BOX_SHADOW_VALUES = designTokens.size['box-shadow'];
package/src/modes.ts ADDED
@@ -0,0 +1,8 @@
1
+ export const allModes = {
2
+ light: {
3
+ theme: 'light',
4
+ },
5
+ dark: {
6
+ theme: 'dark',
7
+ },
8
+ };
@@ -0,0 +1,152 @@
1
+ @keyframes fadeIn {
2
+ 0% {
3
+ opacity: 0;
4
+ }
5
+
6
+ 100% {
7
+ opacity: 1;
8
+ }
9
+ }
10
+
11
+ @keyframes fadeInDown {
12
+ 0% {
13
+ opacity: 0;
14
+ transform: translateY(-30%);
15
+ }
16
+
17
+ 100% {
18
+ opacity: 1;
19
+ transform: translateY(0);
20
+ }
21
+ }
22
+
23
+ @keyframes fadeInUp {
24
+ 0% {
25
+ opacity: 0;
26
+ transform: translateY(30%);
27
+ }
28
+
29
+ 100% {
30
+ opacity: 1;
31
+ transform: translateY(0);
32
+ }
33
+ }
34
+
35
+ @keyframes fadeInLeft {
36
+ 0% {
37
+ opacity: 0;
38
+ transform: translateX(30%);
39
+ }
40
+
41
+ 100% {
42
+ opacity: 1;
43
+ transform: translateX(0);
44
+ }
45
+ }
46
+
47
+ @keyframes fadeInRight {
48
+ 0% {
49
+ opacity: 0;
50
+ transform: translateX(-30%);
51
+ }
52
+
53
+ 100% {
54
+ opacity: 1;
55
+ transform: translateX(0);
56
+ }
57
+ }
58
+
59
+
60
+ @keyframes slideInUp {
61
+ from {
62
+ transform: translateY(100%);
63
+ visibility: visible;
64
+ }
65
+
66
+ to {
67
+ transform: translateY(0);
68
+ }
69
+ }
70
+
71
+ @keyframes zoomIn {
72
+ 0% {
73
+ transform: scale3d(0.3, 0.3, 0.3);
74
+ opacity: 0;
75
+ }
76
+
77
+ 50% {
78
+ opacity: 1;
79
+ }
80
+ }
81
+
82
+ @keyframes enterTop {
83
+ 0% {
84
+ transform: translate3d(0, -200%, 0);
85
+ opacity: 0.5;
86
+ }
87
+
88
+ 100% {
89
+ transform: translate3d(0, 0, 0);
90
+ opacity: 1;
91
+ }
92
+ }
93
+
94
+ @keyframes enterBottom {
95
+ 0% {
96
+ transform: translate3d(0, 200%, 0);
97
+ opacity: 0.5;
98
+ }
99
+
100
+ 100% {
101
+ transform: translate3d(0, 0, 0);
102
+ opacity: 1;
103
+ }
104
+ }
105
+
106
+ @keyframes exitTop {
107
+ 0% {
108
+ transform: translate3d(0, 0, -1px);
109
+ opacity: 1;
110
+ }
111
+
112
+ 100% {
113
+ transform: translate3d(0, -150%, -1px);
114
+ opacity: 0;
115
+ }
116
+ }
117
+
118
+ @keyframes exitBottom {
119
+ 0% {
120
+ transform: translate3d(0, 0, -1px);
121
+ opacity: 1;
122
+ }
123
+
124
+ 100% {
125
+ transform: translate3d(0, 150%, -1px);
126
+ opacity: 0;
127
+ }
128
+ }
129
+
130
+ @keyframes exitLeft {
131
+ 0% {
132
+ transform: translate3d(0, 0, -1px);
133
+ opacity: 1;
134
+ }
135
+
136
+ 100% {
137
+ transform: translate3d(-150%, 0, -1px);
138
+ opacity: 0;
139
+ }
140
+ }
141
+
142
+ @keyframes exitRight {
143
+ 0% {
144
+ transform: translate3d(0, 0, -1px);
145
+ opacity: 1;
146
+ }
147
+
148
+ 100% {
149
+ transform: translate3d(150%, 0, -1px);
150
+ opacity: 0;
151
+ }
152
+ }
@@ -0,0 +1,43 @@
1
+ .cursor-auto { cursor: auto; }
2
+ .cursor-default { cursor: default; }
3
+ .cursor-none { cursor: none; }
4
+
5
+ .cursor-context-menu { cursor: context-menu; }
6
+ .cursor-help { cursor: help; }
7
+ .cursor-pointer { cursor: pointer; }
8
+ .cursor-progress { cursor: progress; }
9
+ .cursor-wait { cursor: wait; }
10
+
11
+ .cursor-cell { cursor: cell; }
12
+ .cursor-crosshair { cursor: crosshair; }
13
+ .cursor-text { cursor: text; }
14
+ .cursor-vertical-text { cursor: vertical-text; }
15
+
16
+ .cursor-alias { cursor: alias; }
17
+ .cursor-copy { cursor: copy; }
18
+ .cursor-move { cursor: move; }
19
+ .cursor-no-drop { cursor: no-drop; }
20
+ .cursor-not-allowed { cursor: not-allowed; }
21
+ .cursor-grab { cursor: grab; }
22
+ .cursor-grabbing { cursor: grabbing; }
23
+
24
+ .cursor-all-scroll { cursor: all-scroll; }
25
+ .cursor-col-resize { cursor: col-resize; }
26
+ .cursor-row-resize { cursor: row-resize; }
27
+ .cursor-n-resize { cursor: n-resize; }
28
+ .cursor-e-resize { cursor: e-resize; }
29
+ .cursor-s-resize { cursor: s-resize; }
30
+ .cursor-w-resize { cursor: w-resize; }
31
+ .cursor-ne-resize { cursor: ne-resize; }
32
+ .cursor-nw-resize { cursor: nw-resize; }
33
+ .cursor-se-resize { cursor: se-resize; }
34
+ .cursor-sw-resize { cursor: sw-resize; }
35
+ .cursor-ew-resize { cursor: ew-resize; }
36
+ .cursor-ns-resize { cursor: ns-resize; }
37
+ .cursor-nesw-resize { cursor: nesw-resize; }
38
+ .cursor-nwse-resize { cursor: nwse-resize; }
39
+
40
+ .cursor-zoom-in { cursor: zoom-in; }
41
+ .cursor-zoom-out { cursor: zoom-out; }
42
+
43
+