stargazer-ui 1.5.21 → 1.5.23

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 (377) hide show
  1. package/.babelrc.json +10 -0
  2. package/.eslintrc.cjs +18 -0
  3. package/.gitattributes +2 -0
  4. package/LICENSE +21 -0
  5. package/dev/index.html +16 -0
  6. package/dev/index.jsx +46 -0
  7. package/dev/index.scss +74 -0
  8. package/dev/pages/ButtonPage.jsx +44 -0
  9. package/dev/pages/CardPage.jsx +81 -0
  10. package/dev/pages/DropdownPage.jsx +32 -0
  11. package/dev/pages/FormPage.jsx +163 -0
  12. package/dev/pages/ListPage.jsx +52 -0
  13. package/dev/pages/ModalPage.jsx +38 -0
  14. package/dev/pages/OverlayPage.jsx +39 -0
  15. package/dev/pages/components.jsx +19 -0
  16. package/dev/stargazerui.css +3762 -0
  17. package/dev/stargazerui.css.map +1 -0
  18. package/dev/test.jsx +87 -0
  19. package/package.json +79 -1
  20. package/rollup.config.js +140 -0
  21. package/scripts/writePackageJsons.js +42 -0
  22. package/src/Bar/Bar.tsx +0 -0
  23. package/src/Bar/Bar.type.ts +9 -0
  24. package/src/Bar/index.ts +0 -0
  25. package/src/Button/Button.tsx +20 -0
  26. package/src/Button/Button.types.ts +8 -0
  27. package/src/Button/index.ts +3 -0
  28. package/src/ButtonGroup/ButtonGroup.tsx +14 -0
  29. package/src/ButtonGroup/ButtonGroup.types.ts +8 -0
  30. package/src/ButtonGroup/index.ts +3 -0
  31. package/src/Card/Card.tsx +70 -0
  32. package/src/Card/Card.types.ts +33 -0
  33. package/src/Card/index.ts +3 -0
  34. package/src/CloseButton/CloseButton.tsx +14 -0
  35. package/src/CloseButton/CloseButton.types.ts +6 -0
  36. package/src/CloseButton/index.ts +3 -0
  37. package/src/Dropdown/Dropdown.tsx +441 -0
  38. package/src/Dropdown/Dropdown.types.ts +60 -0
  39. package/src/Dropdown/index.ts +4 -0
  40. package/src/FileUploadButton/FileUploadButton.tsx +27 -0
  41. package/src/FileUploadButton/FileUploadButton.types.ts +9 -0
  42. package/src/FileUploadButton/index.ts +3 -0
  43. package/src/FloatingLabel/FloatingLabel.tsx +22 -0
  44. package/src/FloatingLabel/FloatingLabel.types.ts +11 -0
  45. package/src/FloatingLabel/index.ts +3 -0
  46. package/src/Form/Form.tsx +399 -0
  47. package/src/Form/Form.types.ts +169 -0
  48. package/src/Form/FormSelect.tsx +620 -0
  49. package/src/Form/index.ts +4 -0
  50. package/src/InputGroup/InputGroup.tsx +46 -0
  51. package/src/InputGroup/InputGroup.types.ts +22 -0
  52. package/src/InputGroup/index.ts +4 -0
  53. package/src/List/List.tsx +112 -0
  54. package/src/List/List.types.ts +34 -0
  55. package/src/List/index.ts +4 -0
  56. package/src/Modal/Modal.tsx +229 -0
  57. package/src/Modal/Modal.types.ts +49 -0
  58. package/src/Modal/index.ts +4 -0
  59. package/src/Nav/Nav.tsx +43 -0
  60. package/src/Nav/Nav.types.ts +21 -0
  61. package/src/Nav/index.ts +4 -0
  62. package/src/NavBar/Navbar.tsx +57 -0
  63. package/src/NavBar/Navbar.types.ts +24 -0
  64. package/src/NavBar/index.ts +4 -0
  65. package/src/NavDropdown/NavDropdown.tsx +93 -0
  66. package/src/NavDropdown/NavDropdown.types.ts +7 -0
  67. package/src/NavDropdown/index.ts +3 -0
  68. package/src/Overlay/Overlay.tsx +305 -0
  69. package/src/Overlay/Overlay.types.ts +24 -0
  70. package/{Overlay/index.d.ts → src/Overlay/index.ts} +3 -3
  71. package/src/Popout/Popout.tsx +155 -0
  72. package/src/Popout/Popout.types.ts +42 -0
  73. package/src/Popout/index.ts +3 -0
  74. package/src/Spinner/Spinner.tsx +15 -0
  75. package/src/Spinner/Spinner.types.ts +7 -0
  76. package/src/Spinner/index.ts +3 -0
  77. package/src/Table/Table.tsx +16 -0
  78. package/src/Table/Table.types.ts +9 -0
  79. package/src/Table/index.ts +3 -0
  80. package/src/Tabs/Tabs.tsx +233 -0
  81. package/src/Tabs/Tabs.types.ts +52 -0
  82. package/src/Tabs/index.ts +3 -0
  83. package/src/ToggleButton/ToggleButton.tsx +21 -0
  84. package/src/ToggleButton/ToggleButton.types.ts +8 -0
  85. package/src/ToggleButton/index.ts +3 -0
  86. package/src/assets/tooltip-pointer.svg +3 -0
  87. package/src/assets/warning.svg +39 -0
  88. package/{hooks/index.d.ts → src/hooks/index.ts} +7 -6
  89. package/src/hooks/useClassname.ts +5 -0
  90. package/src/hooks/useDraggable.ts +186 -0
  91. package/src/hooks/useKeepElementFocused.ts +37 -0
  92. package/src/hooks/useQueryParams.ts +12 -0
  93. package/src/hooks/useScreenSize.ts +24 -0
  94. package/src/index.ts +21 -0
  95. package/src/styles/_Card.scss +166 -0
  96. package/src/styles/_CloseButton.scss +51 -0
  97. package/src/styles/_CustomButton.scss +134 -0
  98. package/src/styles/_Dropdown.scss +127 -0
  99. package/src/styles/_FloatingLabel.scss +56 -0
  100. package/src/styles/_Forms.scss +7 -0
  101. package/src/styles/_Grid.scss +178 -0
  102. package/src/styles/_InputGroup.scss +71 -0
  103. package/src/styles/_List.scss +62 -0
  104. package/src/styles/_Modal.scss +234 -0
  105. package/src/styles/_ModalOld.scss +242 -0
  106. package/src/styles/_Nav.scss +36 -0
  107. package/src/styles/_NavBar.scss +116 -0
  108. package/src/styles/_NavDropdown.scss +33 -0
  109. package/src/styles/_OffCanvas.scss +260 -0
  110. package/src/styles/_OverLay.scss +79 -0
  111. package/src/styles/_Popout.scss +75 -0
  112. package/src/styles/_Resizable.scss +64 -0
  113. package/src/styles/_Spinner.scss +19 -0
  114. package/src/styles/_Table.scss +34 -0
  115. package/src/styles/_Tabs.scss +129 -0
  116. package/src/styles/_colors.scss +510 -0
  117. package/src/styles/_components.scss +41 -0
  118. package/src/styles/_functions.scss +134 -0
  119. package/src/styles/_mixins.scss +26 -0
  120. package/src/styles/_reset.scss +239 -0
  121. package/src/styles/_utilities.scss +2480 -0
  122. package/src/styles/_variables.scss +164 -0
  123. package/src/styles/forms/_FormCheck.scss +270 -0
  124. package/src/styles/forms/_FormControl.scss +135 -0
  125. package/src/styles/forms/_FormGroup.scss +26 -0
  126. package/src/styles/forms/_FormLabel.scss +3 -0
  127. package/src/styles/forms/_FormSelect.scss +222 -0
  128. package/src/styles/forms/_FormSlider.scss +116 -0
  129. package/src/styles/forms/_FormText.scss +6 -0
  130. package/{utils/BaseTypes.d.ts → src/utils/BaseTypes.ts} +32 -25
  131. package/src/utils/ContrastingColor.ts +25 -0
  132. package/src/utils/CreateSyntheticEvent.ts +30 -0
  133. package/src/utils/FileImportExport.js +50 -0
  134. package/src/utils/IsInputKey.ts +18 -0
  135. package/src/utils/MergeClassnames.ts +5 -0
  136. package/src/utils/MergeRefs.ts +12 -0
  137. package/src/utils/createFastContext.tsx +119 -0
  138. package/src/utils/index.ts +4 -0
  139. package/src/vite-env.d.ts +1 -0
  140. package/tsconfig-build.json +4 -0
  141. package/tsconfig.json +79 -0
  142. package/tsconfig.node.json +10 -0
  143. package/types/BaseTypes.d.ts +19 -0
  144. package/{Button → types/components/Button}/Button.types.d.ts +2 -1
  145. package/types/components/Button/index.d.ts +1 -0
  146. package/{Card → types/components/Card}/Card.d.ts +12 -12
  147. package/{Card → types/components/Card}/Card.types.d.ts +1 -3
  148. package/types/components/Card/index.d.ts +1 -0
  149. package/{CloseButton → types/components/CloseButton}/CloseButton.types.d.ts +1 -1
  150. package/types/components/CloseButton/index.d.ts +1 -0
  151. package/types/components/Dropdown/Dropdown.d.ts +71 -0
  152. package/{Dropdown → types/components/Dropdown}/Dropdown.types.d.ts +12 -13
  153. package/types/components/Dropdown/index.d.ts +1 -0
  154. package/{FloatingLabel → types/components/FloatingLabel}/FloatingLabel.types.d.ts +1 -1
  155. package/types/components/FloatingLabel/index.d.ts +1 -0
  156. package/types/components/Form/Form.d.ts +17 -0
  157. package/types/components/Form/Form.types.d.ts +50 -0
  158. package/types/components/Form/index.d.ts +1 -0
  159. package/types/components/InputGroup/InputGroup.d.ts +6 -0
  160. package/types/components/InputGroup/InputGroup.types.d.ts +10 -0
  161. package/types/components/InputGroup/index.d.ts +1 -0
  162. package/{Modal → types/components/Modal}/Modal.d.ts +19 -19
  163. package/{Modal → types/components/Modal}/Modal.types.d.ts +2 -3
  164. package/types/components/Modal/index.d.ts +1 -0
  165. package/{Nav → types/components/Nav}/Nav.d.ts +12 -12
  166. package/{Nav → types/components/Nav}/Nav.types.d.ts +1 -1
  167. package/types/components/Nav/index.d.ts +1 -0
  168. package/{NavBar → types/components/NavBar}/Navbar.d.ts +8 -7
  169. package/{NavBar → types/components/NavBar}/Navbar.types.d.ts +1 -2
  170. package/types/components/NavBar/index.d.ts +1 -0
  171. package/types/components/NavDropdown/NavDropdown.d.ts +35 -0
  172. package/{NavDropdown → types/components/NavDropdown}/NavDropdown.types.d.ts +1 -2
  173. package/types/components/NavDropdown/index.d.ts +1 -0
  174. package/{Popout → types/components/Popout}/Popout.d.ts +6 -6
  175. package/{Popout → types/components/Popout}/Popout.types.d.ts +1 -1
  176. package/types/components/Popout/index.d.ts +1 -0
  177. package/types/components/Spinner/index.d.ts +1 -0
  178. package/{Table → types/components/Table}/Table.types.d.ts +1 -1
  179. package/types/components/Table/index.d.ts +1 -0
  180. package/{Tabs → types/components/Tabs}/Tabs.types.d.ts +2 -12
  181. package/types/components/Tabs/index.d.ts +1 -0
  182. package/types/components/ToggleButton/ToggleButton.d.ts +9 -0
  183. package/types/components/ToggleButton/ToggleButton.types.d.ts +0 -0
  184. package/types/components/ToggleButton/index.d.ts +1 -0
  185. package/types/components/index.d.ts +16 -0
  186. package/types/index.d.ts +1 -0
  187. package/vite.config.js +57 -0
  188. package/vite.config.js.timestamp-1708777378490-e94428ceb2bf9.mjs +42 -0
  189. package/Bar/Bar.type.d.ts +0 -6
  190. package/Bar/index.js +0 -2
  191. package/Bar/index.js.map +0 -1
  192. package/Bar/package.json +0 -1
  193. package/Button/Button.js +0 -15
  194. package/Button/Button.js.map +0 -1
  195. package/Button/index.d.ts +0 -3
  196. package/Button/index.js +0 -7
  197. package/Button/index.js.map +0 -1
  198. package/Button/package.json +0 -1
  199. package/ButtonGroup/ButtonGroup.d.ts +0 -4
  200. package/ButtonGroup/ButtonGroup.js +0 -11
  201. package/ButtonGroup/ButtonGroup.js.map +0 -1
  202. package/ButtonGroup/ButtonGroup.types.d.ts +0 -7
  203. package/ButtonGroup/index.d.ts +0 -3
  204. package/ButtonGroup/index.js +0 -7
  205. package/ButtonGroup/index.js.map +0 -1
  206. package/ButtonGroup/package.json +0 -1
  207. package/Card/Card.js +0 -42
  208. package/Card/Card.js.map +0 -1
  209. package/Card/index.d.ts +0 -3
  210. package/Card/index.js +0 -7
  211. package/Card/index.js.map +0 -1
  212. package/Card/package.json +0 -1
  213. package/CloseButton/CloseButton.js +0 -11
  214. package/CloseButton/CloseButton.js.map +0 -1
  215. package/CloseButton/index.d.ts +0 -3
  216. package/CloseButton/index.js +0 -7
  217. package/CloseButton/index.js.map +0 -1
  218. package/CloseButton/package.json +0 -1
  219. package/Dropdown/Dropdown.d.ts +0 -39
  220. package/Dropdown/Dropdown.js +0 -380
  221. package/Dropdown/Dropdown.js.map +0 -1
  222. package/Dropdown/index.d.ts +0 -4
  223. package/Dropdown/index.js +0 -8
  224. package/Dropdown/index.js.map +0 -1
  225. package/Dropdown/package.json +0 -1
  226. package/FileUploadButton/FileUploadButton.d.ts +0 -4
  227. package/FileUploadButton/FileUploadButton.js +0 -20
  228. package/FileUploadButton/FileUploadButton.js.map +0 -1
  229. package/FileUploadButton/FileUploadButton.types.d.ts +0 -7
  230. package/FileUploadButton/index.d.ts +0 -3
  231. package/FileUploadButton/index.js +0 -7
  232. package/FileUploadButton/index.js.map +0 -1
  233. package/FileUploadButton/package.json +0 -1
  234. package/FloatingLabel/FloatingLabel.js +0 -15
  235. package/FloatingLabel/FloatingLabel.js.map +0 -1
  236. package/FloatingLabel/index.d.ts +0 -3
  237. package/FloatingLabel/index.js +0 -7
  238. package/FloatingLabel/index.js.map +0 -1
  239. package/FloatingLabel/package.json +0 -1
  240. package/Form/Form.d.ts +0 -37
  241. package/Form/Form.js +0 -227
  242. package/Form/Form.js.map +0 -1
  243. package/Form/Form.types.d.ts +0 -159
  244. package/Form/FormSelect.d.ts +0 -12
  245. package/Form/FormSelect.js +0 -492
  246. package/Form/FormSelect.js.map +0 -1
  247. package/Form/index.d.ts +0 -4
  248. package/Form/index.js +0 -8
  249. package/Form/index.js.map +0 -1
  250. package/Form/package.json +0 -1
  251. package/InputGroup/InputGroup.d.ts +0 -7
  252. package/InputGroup/InputGroup.js +0 -31
  253. package/InputGroup/InputGroup.js.map +0 -1
  254. package/InputGroup/InputGroup.types.d.ts +0 -17
  255. package/InputGroup/index.d.ts +0 -4
  256. package/InputGroup/index.js +0 -7
  257. package/InputGroup/index.js.map +0 -1
  258. package/InputGroup/package.json +0 -1
  259. package/List/List.d.ts +0 -14
  260. package/List/List.js +0 -77
  261. package/List/List.js.map +0 -1
  262. package/List/List.types.d.ts +0 -28
  263. package/List/index.d.ts +0 -3
  264. package/List/index.js +0 -7
  265. package/List/index.js.map +0 -1
  266. package/List/package.json +0 -1
  267. package/Modal/Modal.js +0 -157
  268. package/Modal/Modal.js.map +0 -1
  269. package/Modal/index.d.ts +0 -3
  270. package/Modal/index.js +0 -7
  271. package/Modal/index.js.map +0 -1
  272. package/Modal/package.json +0 -1
  273. package/Nav/Nav.js +0 -29
  274. package/Nav/Nav.js.map +0 -1
  275. package/Nav/index.d.ts +0 -4
  276. package/Nav/index.js +0 -7
  277. package/Nav/index.js.map +0 -1
  278. package/Nav/package.json +0 -1
  279. package/NavBar/Navbar.js +0 -36
  280. package/NavBar/Navbar.js.map +0 -1
  281. package/NavBar/index.d.ts +0 -4
  282. package/NavBar/index.js +0 -8
  283. package/NavBar/index.js.map +0 -1
  284. package/NavBar/package.json +0 -1
  285. package/NavDropdown/NavDropdown.d.ts +0 -19
  286. package/NavDropdown/NavDropdown.js +0 -75
  287. package/NavDropdown/NavDropdown.js.map +0 -1
  288. package/NavDropdown/index.d.ts +0 -3
  289. package/NavDropdown/index.js +0 -7
  290. package/NavDropdown/index.js.map +0 -1
  291. package/NavDropdown/package.json +0 -1
  292. package/Overlay/Overlay.d.ts +0 -4
  293. package/Overlay/Overlay.js +0 -241
  294. package/Overlay/Overlay.js.map +0 -1
  295. package/Overlay/Overlay.types.d.ts +0 -22
  296. package/Overlay/index.js +0 -7
  297. package/Overlay/index.js.map +0 -1
  298. package/Overlay/package.json +0 -1
  299. package/Popout/Popout.js +0 -111
  300. package/Popout/Popout.js.map +0 -1
  301. package/Popout/index.d.ts +0 -3
  302. package/Popout/index.js +0 -7
  303. package/Popout/index.js.map +0 -1
  304. package/Popout/package.json +0 -1
  305. package/Spinner/Spinner.js +0 -11
  306. package/Spinner/Spinner.js.map +0 -1
  307. package/Spinner/index.d.ts +0 -3
  308. package/Spinner/index.js +0 -7
  309. package/Spinner/index.js.map +0 -1
  310. package/Spinner/package.json +0 -1
  311. package/Table/Table.js +0 -12
  312. package/Table/Table.js.map +0 -1
  313. package/Table/index.d.ts +0 -3
  314. package/Table/index.js +0 -7
  315. package/Table/index.js.map +0 -1
  316. package/Table/package.json +0 -1
  317. package/Tabs/Tabs.js +0 -162
  318. package/Tabs/Tabs.js.map +0 -1
  319. package/Tabs/index.d.ts +0 -3
  320. package/Tabs/index.js +0 -7
  321. package/Tabs/index.js.map +0 -1
  322. package/Tabs/package.json +0 -1
  323. package/ToggleButton/ToggleButton.d.ts +0 -4
  324. package/ToggleButton/ToggleButton.js +0 -18
  325. package/ToggleButton/ToggleButton.js.map +0 -1
  326. package/ToggleButton/ToggleButton.types.d.ts +0 -7
  327. package/ToggleButton/index.d.ts +0 -3
  328. package/ToggleButton/index.js +0 -7
  329. package/ToggleButton/index.js.map +0 -1
  330. package/ToggleButton/package.json +0 -1
  331. package/hooks/index.js +0 -7
  332. package/hooks/index.js.map +0 -1
  333. package/hooks/package.json +0 -1
  334. package/hooks/useClassname.d.ts +0 -2
  335. package/hooks/useClassname.js +0 -7
  336. package/hooks/useClassname.js.map +0 -1
  337. package/hooks/useDraggable.d.ts +0 -23
  338. package/hooks/useDraggable.js +0 -147
  339. package/hooks/useDraggable.js.map +0 -1
  340. package/hooks/useKeepElementFocused.d.ts +0 -2
  341. package/hooks/useKeepElementFocused.js +0 -37
  342. package/hooks/useKeepElementFocused.js.map +0 -1
  343. package/hooks/useQueryParams.d.ts +0 -2
  344. package/hooks/useQueryParams.js +0 -13
  345. package/hooks/useQueryParams.js.map +0 -1
  346. package/hooks/useScreenSize.d.ts +0 -5
  347. package/hooks/useScreenSize.js +0 -21
  348. package/hooks/useScreenSize.js.map +0 -1
  349. package/index.d.ts +0 -19
  350. package/index.js +0 -20
  351. package/index.js.map +0 -1
  352. package/styles/stargazerui.css +0 -6658
  353. package/styles/stargazerui.css.map +0 -1
  354. package/utils/ContrastingColor.d.ts +0 -1
  355. package/utils/CreateSyntheticEvent.d.ts +0 -2
  356. package/utils/CreateSyntheticEvent.js +0 -33
  357. package/utils/CreateSyntheticEvent.js.map +0 -1
  358. package/utils/IsInputKey.d.ts +0 -7
  359. package/utils/IsInputKey.js +0 -20
  360. package/utils/IsInputKey.js.map +0 -1
  361. package/utils/MergeClassnames.d.ts +0 -2
  362. package/utils/MergeClassnames.js +0 -7
  363. package/utils/MergeClassnames.js.map +0 -1
  364. package/utils/MergeRefs.d.ts +0 -1
  365. package/utils/MergeRefs.js +0 -16
  366. package/utils/MergeRefs.js.map +0 -1
  367. package/utils/createFastContext.d.ts +0 -16
  368. package/utils/createFastContext.js +0 -101
  369. package/utils/createFastContext.js.map +0 -1
  370. package/utils/index.d.ts +0 -4
  371. /package/{Button → types/components/Button}/Button.d.ts +0 -0
  372. /package/{CloseButton → types/components/CloseButton}/CloseButton.d.ts +0 -0
  373. /package/{FloatingLabel → types/components/FloatingLabel}/FloatingLabel.d.ts +0 -0
  374. /package/{Spinner → types/components/Spinner}/Spinner.d.ts +0 -0
  375. /package/{Spinner → types/components/Spinner}/Spinner.types.d.ts +0 -0
  376. /package/{Table → types/components/Table}/Table.d.ts +0 -0
  377. /package/{Tabs → types/components/Tabs}/Tabs.d.ts +0 -0
@@ -0,0 +1,399 @@
1
+ import React, { forwardRef, useContext, createContext, useMemo, useState, useRef, useEffect, InvalidEvent } from "react";
2
+
3
+ import { HintType, ErrorType, FormTagContextType, FormCheckType, FormContextType, FormControlType, FormGroupType, FormLabelType, FormSliderType, FormTextType, FormType, FormSelectTagType, SliderContextType, WarningIconType } from "./Form.types";
4
+ import useClassname from "../hooks/useClassname";
5
+ import mergeClassnames from "../utils/MergeClassnames";
6
+ import mergeRefs from "../utils/MergeRefs";
7
+ import contrastingColor from "../utils/ContrastingColor";
8
+
9
+ import Overlay from "../Overlay";
10
+ import Select from "./FormSelect"
11
+ import OverlayTrigger from "react-bootstrap/OverlayTrigger"
12
+ import Tooltip from "react-bootstrap/Tooltip"
13
+
14
+ const WarningIcon = forwardRef<SVGSVGElement, WarningIconType>( ({className, alt, color, size, ...restProps}, ref) => {
15
+ const sizeComputed = {width: size ?? "1rem", height: size ?? "1rem"}
16
+ const classNameComputed = mergeClassnames("sg-form-control-error-icon", className)
17
+
18
+ return (
19
+ <svg
20
+ ref={ref} className={classNameComputed} color={color ?? "currentColor"} xmlns="http://www.w3.org/2000/svg"
21
+ width={sizeComputed.width} height={sizeComputed.height} viewBox="0 0 256 256"
22
+ {...restProps}
23
+ >
24
+ <path
25
+ fill="transparent"
26
+ stroke="currentColor"
27
+ strokeLinecap="round"
28
+ strokeLinejoin="round"
29
+ strokeWidth={28}
30
+ d="M128 83v65"
31
+ />
32
+ <circle cx={128} cy={183} r={14} fill="currentColor" />
33
+ <path
34
+ fill="transparent"
35
+ stroke="currentColor"
36
+ strokeLinecap="round"
37
+ strokeLinejoin="round"
38
+ strokeWidth={20}
39
+ d="M40 223h176l16-32-79-158h-50L24 191l16 32Z"
40
+ />
41
+ </svg>
42
+ )
43
+ })
44
+ WarningIcon.displayName = "WarningIcon"
45
+
46
+ const FormTagContext = createContext<FormTagContextType | null>(null)
47
+ const FormTagContextProvider = ({children, value} : {children: React.ReactNode, value:FormTagContextType}) => {
48
+ return(
49
+ <FormTagContext.Provider value={value}>
50
+ {children}
51
+ </FormTagContext.Provider>
52
+ )
53
+ }
54
+ export const useFormTagContext = () => {
55
+ const context = useContext(FormTagContext)
56
+ if(!context) {
57
+ return { noValidate: null}
58
+ }
59
+ return context
60
+ }
61
+
62
+ export const FormContext = createContext<FormContextType | null>(null)
63
+ export const FormContextProvider = ({children, value} : {children: React.ReactNode, value:FormContextType}) => {
64
+ return (
65
+ <FormContext.Provider value={value}>
66
+ {children}
67
+ </FormContext.Provider>
68
+ )
69
+ }
70
+ export const useFormContext = () => {
71
+ const context = useContext(FormContext)
72
+ if(!context) {
73
+ return {}
74
+ }
75
+ return context
76
+ }
77
+
78
+
79
+ const Form = forwardRef<HTMLFormElement, FormType>(({children, noValidate, ...restProps}, ref) => {
80
+ const context = useMemo(() => {
81
+ return {noValidate: !!noValidate}
82
+ }, [noValidate])
83
+ return (
84
+ <form ref={ref} noValidate={noValidate} {...restProps}>
85
+ <FormTagContextProvider value={context}>
86
+ {children}
87
+ </FormTagContextProvider>
88
+ </form>
89
+ )
90
+ })
91
+ Form.displayName = "Form"
92
+
93
+ export const ErrorMessage = forwardRef<HTMLParagraphElement, ErrorType>(({children, className, id, message, ...restProps}, ref) => {
94
+
95
+ const classNameComputed = mergeClassnames("sg-form-control-error", className)
96
+ return(
97
+ <p ref={ref} id={id+"-error-message"} className={classNameComputed} {...restProps}>
98
+ <WarningIcon width="1.25em" height="1.25em" />
99
+ <span>{message ?? children}</span>
100
+ </p>
101
+ )
102
+ })
103
+ ErrorMessage.displayName = "ErrorMessage"
104
+ export const HintMessage = forwardRef<HTMLParagraphElement, HintType>(({children, className, id, message, ...restProps}, ref) => {
105
+ const classNameComputed = mergeClassnames("sg-form-control-hint", className)
106
+ return(
107
+ <>
108
+ {message ?
109
+ <p ref={ref} id={id+"-hint-message"} className={classNameComputed} {...restProps}>
110
+ {message}
111
+ </p>
112
+ :
113
+ <div ref={ref} id={id} className={classNameComputed} {...restProps}>
114
+ {children}
115
+ </div>
116
+ }
117
+ </>
118
+ )
119
+ })
120
+ HintMessage.displayName = "HintMessage"
121
+
122
+ const Control = forwardRef<HTMLInputElement, FormControlType>( (
123
+ {as = "input", className = "", plaintext = false, id, type = "text", autoFocus=false, error, errorAsOverlay=false, hint, required, "aria-describedby":ariaDescribedby, ...restProps}, ref
124
+ ) => {
125
+ let Component = as
126
+
127
+ const { noValidate } = useFormTagContext()
128
+ const { controlId, isInputGroup, isFLoatingLabel } = useFormContext()
129
+ const isOverlay = isInputGroup || isFLoatingLabel || errorAsOverlay
130
+
131
+ let elementId = id ?? controlId
132
+
133
+ let computedClassName = mergeClassnames(
134
+ plaintext ? "sg-form-control-plaintext" : "sg-form-control",
135
+ className != "" ? className : "",
136
+ type == "color" ? "sg-form-control-color" : "",
137
+ error ? "invalid":""
138
+ )
139
+ const errorMessageId = error ? elementId+"-error-message":undefined
140
+ const hintMessageId = hint ? elementId+"-hint-message":undefined
141
+ const tooltipMessage = isOverlay && (error || hint) ?
142
+ <div className="sg-form-control-description tooltip">
143
+ {error? <ErrorMessage id={errorMessageId} message={error.message} /> : null}
144
+ {hint? <HintMessage id={hintMessageId} message={hint.message} /> : null}
145
+ </div> : undefined// "Testing a tooltip with a long message. This messsage is so long it hsould in theory trigger a wrap."
146
+
147
+ const describedby = mergeClassnames(ariaDescribedby, errorMessageId, hintMessageId)
148
+ return (
149
+ <>
150
+ <Overlay trigger={"focus"} position="auto" tooltip={tooltipMessage}>
151
+ <Component
152
+ required={(required && !noValidate) ?? undefined}
153
+ aria-required={required ?? undefined} aria-invalid={error ? "true":"false"} aria-describedby={describedby != "" ? describedby : null}
154
+ autoFocus={autoFocus} ref={ref}
155
+ id={elementId} type={type} className={computedClassName} {...restProps} />
156
+ </Overlay>
157
+ <div className="sg-form-control-description">
158
+ {error && !isOverlay ?
159
+ <ErrorMessage id={elementId} message={error.message} style={error.style} className={error.className}/>
160
+ : null }
161
+ {hint && !isOverlay ?
162
+ <HintMessage id={elementId} message={hint.message} style={hint.style} className={hint.className}/>
163
+ : null }
164
+ </div>
165
+ </>
166
+ )
167
+ })
168
+ Control.displayName = "FormControl"
169
+
170
+ const Group = forwardRef<HTMLDivElement, FormGroupType>( ({children, className, controlId, vertical, ...restProps}, ref) => {
171
+ const context = useMemo(() => {
172
+ return {controlId: controlId}
173
+ }, [controlId])
174
+ return (
175
+ <div ref={ref} className={`sg-form-group${className ? " "+className : ""}${vertical ? " sg-form-group-vertical":""}`} {...restProps}>
176
+ <FormContextProvider value={context}>
177
+ {children}
178
+ </FormContextProvider>
179
+ </div>
180
+ )
181
+ })
182
+ Group.displayName = "FormGroup"
183
+
184
+ const Label = forwardRef<HTMLLabelElement, FormLabelType>( ({children, className, htmlFor, ...restProps}, ref) => {
185
+ const { controlId } = useFormContext()
186
+
187
+ let elementHtmlFor = htmlFor ?? controlId
188
+ return (
189
+ <label ref={ref} htmlFor={elementHtmlFor} className={`sg-form-label${className ? " "+className : ""}`} {...restProps}>
190
+ {children}
191
+ </label>
192
+ )
193
+ })
194
+ Label.displayName = "FormLabel"
195
+
196
+ const Check = forwardRef<HTMLInputElement, FormCheckType>( ({ children,
197
+ classNameContainer, containerRef, containerId, styleContainer,
198
+ classNameLabel, labelRef, label, labelId, styleLabel,
199
+ className, type="checkbox", id, reverse=false, style, onChange, required, ...restProps
200
+ } , ref) => {
201
+ const { noValidate } = useFormTagContext()
202
+ const { controlId } = useFormContext()
203
+
204
+ const typeComputed = !["radio", "checkbox", "color"].includes(type) ? "checkbox" : type
205
+ const classNameComputed = mergeClassnames(
206
+ "sg-form-check-input",
207
+ className ?? ""
208
+ )
209
+ const classNameLabelComputed = mergeClassnames(
210
+ "sg-form-check-label",
211
+ classNameLabel ?? ""
212
+ )
213
+ const classNameContainerComputed = mergeClassnames(
214
+ "sg-form-check",
215
+ reverse ? " sg-form-check-reverse":"",
216
+ classNameContainer ?? "",
217
+ type === "switch" ? " sg-form-switch":""
218
+ )
219
+
220
+ const [contrastColor, setContrastColor] = useState<React.CSSProperties>({})
221
+ const onChangeInternal = (event: React.ChangeEvent<HTMLInputElement>) => {
222
+ //setContrastColor({backgroundColor: "#"+contrastingColor(event.target.value)})
223
+ if(onChange) onChange(event)
224
+ }
225
+ //required={(required && !noValidate) ?? undefined} aria-required={required ?? undefined}
226
+ const elementId = id ?? controlId
227
+ return (
228
+ <div ref={containerRef} id={containerId} style={styleContainer} className={classNameContainerComputed} >
229
+ {
230
+ controlId ?
231
+ <input required={(required && !noValidate) ?? undefined} aria-required={required ?? undefined} id={controlId} ref={ref} type={typeComputed} style={style} className={classNameComputed} onChange={event => onChangeInternal(event)} {...restProps} />
232
+ :
233
+ <label ref={labelRef} htmlFor={elementId} id={labelId} style={styleLabel} className={classNameLabelComputed}>
234
+ {reverse ? <span>{children ?? label}</span> : null}
235
+ <input required={(required && !noValidate) ?? undefined} aria-required={required ?? undefined} ref={ref} type={typeComputed} style={style} id={elementId} className={classNameComputed} onChange={event => onChangeInternal(event)} {...restProps} />
236
+ {!reverse ? <span>{children ?? label}</span> : null}
237
+ </label>
238
+ }
239
+ </div>
240
+ )
241
+ })
242
+ Check.displayName = "FormCheck"
243
+
244
+ const Text = forwardRef<HTMLElement, FormTextType>( ({children, className, ...restProps}, ref) => {
245
+ return (
246
+ <small ref={ref} className={`sg-form-text${className ? " "+className:""}`} {...restProps}>
247
+ {children}
248
+ </small>
249
+ )
250
+ })
251
+ Check.displayName = "FormText"
252
+
253
+ export const SliderContext = createContext<SliderContextType | null>(null)
254
+ export const SliderContextProvider = ({children, value} : {children: React.ReactNode, value:SliderContextType}) => {
255
+ return (
256
+ <SliderContext.Provider value={value}>
257
+ {children}
258
+ </SliderContext.Provider>
259
+ )
260
+ }
261
+ export const useSliderContext = () => {
262
+ const context = useContext(SliderContext)
263
+ if(!context) {
264
+ throw new Error("UseSliderContext must be used within a SliderContextProvider!")
265
+ }
266
+ return context
267
+ }
268
+
269
+ const Slider = forwardRef<HTMLSpanElement, FormSliderType>( ({className, style, controlId, min=1, max=10, step=1, defaultValue=6, value, onChange, ...restProps}, ref) => {
270
+ const internalRef = useRef<HTMLDivElement>(null)
271
+ //if(internalRef.current) console.log(internalRef.current)
272
+ const trackEmpty = useRef<HTMLDivElement>(null)
273
+ const trackFilled = useRef<HTMLDivElement>(null)
274
+ const thumbRef = useRef<HTMLSpanElement>(null)
275
+ const [ internalValue, setInternalValue ] = useState(value ? value + 1 - min : defaultValue - min)
276
+ if(value && value != internalValue + min) {
277
+ setInternalValue(value - min)
278
+ }
279
+ const internalMin = min < 1 ? 1 : min
280
+ const internalMax = min < 1 ? max + 1 - min : max
281
+
282
+ const [ isGrabbing, setIsGrabbing ] = useState(false)
283
+ const updateValue = (value: number) => {
284
+ let parsedValue = value < internalMin - 1 ? internalMin - 1 : value
285
+ parsedValue = parsedValue > internalMax - internalMin ? internalMax - internalMin : parsedValue
286
+ if(parsedValue === internalValue) return
287
+
288
+ setInternalValue(parsedValue)
289
+ if(onChange) {
290
+ onChange(Math.abs(parsedValue) + min)
291
+ }
292
+ }
293
+ const getNearestStep = (event: React.PointerEvent, targetElement: HTMLElement) => {
294
+ const { pageX } = event
295
+ const paddingLeft = parseFloat(window.getComputedStyle(targetElement, null).getPropertyValue('padding-left'))
296
+ const leftEdge = targetElement.getBoundingClientRect().left + paddingLeft
297
+
298
+ const width = targetElement.scrollWidth - 2*paddingLeft
299
+ const thresholdDeltaX = width*(step)/(internalMax-internalMin)
300
+
301
+ const relativeMousePositionX = (pageX - leftEdge)/thresholdDeltaX < 0 ? 0 : (pageX - leftEdge)/thresholdDeltaX
302
+ const nearestStep = Math.round((pageX - leftEdge)/thresholdDeltaX)
303
+ return { relativeMousePositionX, nearestStep }
304
+ }
305
+
306
+ const onPointerDownTrack = (event: React.PointerEvent) => {
307
+ if(!internalRef.current) return
308
+ const { nearestStep } = getNearestStep(event, internalRef.current)
309
+ updateValue(nearestStep*step)
310
+ }
311
+ const onPointerDown = (event: React.PointerEvent) => {
312
+ (event.target as HTMLElement).setPointerCapture(event.pointerId)
313
+ setIsGrabbing(true)
314
+ if(!thumbRef.current) return
315
+
316
+ }
317
+
318
+ const onPointerMove = (event: React.PointerEvent) => {
319
+ if(!isGrabbing) return
320
+ if(!internalRef.current) return
321
+ const { relativeMousePositionX, nearestStep } = getNearestStep(event, internalRef.current)
322
+ //console.log(nearestStep)
323
+ const lowerBoundary = nearestStep === 0 || relativeMousePositionX === 0? -0.05 : 0.95*nearestStep
324
+ const upperBoundary = nearestStep === 0 || relativeMousePositionX === 0? 0.05 : 1.05*nearestStep
325
+ if(lowerBoundary < relativeMousePositionX && relativeMousePositionX < upperBoundary) {
326
+ updateValue(nearestStep*step)
327
+ }
328
+
329
+ }
330
+
331
+ const onPointerUp = (event: React.PointerEvent) => {
332
+ setIsGrabbing(false)
333
+ }
334
+
335
+ const onKeyDown = (event: React.KeyboardEvent) => {
336
+ let caseTrue = false
337
+ switch (event.key) {
338
+ case "ArrowLeft":
339
+ case "ArrowDown":
340
+ updateValue(internalValue - 1)
341
+ event.preventDefault()
342
+ break
343
+ case "ArrowRight":
344
+ case "ArrowUp":
345
+ updateValue(internalValue + 1)
346
+ event.preventDefault()
347
+ break
348
+ case "End":
349
+ updateValue(internalMax - 1)
350
+ event.preventDefault()
351
+ break
352
+ case "Home":
353
+ updateValue(internalMin - 1)
354
+ event.preventDefault()
355
+ break
356
+ }
357
+ }
358
+ const filled = (internalValue)/(internalMax-internalMin)
359
+ const pointerActions = {onPointerDown, onPointerMove, onPointerUp}
360
+ return (
361
+ <div onPointerDown={onPointerDownTrack} ref={mergeRefs([ref, internalRef])} id={controlId} style={{...style, "--filled":filled*100+"%"} as React.CSSProperties} className={useClassname("sg-form-slider", className)}>
362
+ <span ref={trackFilled} className="sg-form-slider-filled" id={controlId+"-track-filled"}></span>
363
+ <span
364
+ role="slider" tabIndex={0} ref={thumbRef} data-grabbing={isGrabbing} id={controlId+"-track-thumb"}
365
+ {...pointerActions} onKeyDown={onKeyDown} className="sg-form-slider-thumb"
366
+ aria-valuenow={internalValue + min} aria-valuemax={max} aria-valuemin={min} {...restProps}
367
+ ></span>
368
+ <span ref={trackEmpty} className="sg-form-slider-empty" id={controlId+"-track-empty"}></span>
369
+ </div>
370
+ )
371
+ })
372
+ Slider.displayName = "FormSlider"
373
+
374
+ const SelectTag = forwardRef<HTMLSelectElement, FormSelectTagType>( ({children, className, id, required,...restProps}, ref) => {
375
+ const { noValidate } = useFormTagContext()
376
+ const { controlId } = useFormContext()
377
+ const elementId = id ?? controlId
378
+ const classNameComputed = mergeClassnames("sg-form-select-tag", className ?? "")
379
+ return (
380
+ <select ref={ref} required={(required && !noValidate) ?? undefined} aria-required={required ?? undefined} className={classNameComputed} id={elementId} {...restProps}>
381
+ {children}
382
+ </select>
383
+ )
384
+ })
385
+ SelectTag.displayName = "FormSelectTag"
386
+
387
+ export default Object.assign(Form, {
388
+ Control: Control,
389
+ Select: Select,
390
+ SelectTag: SelectTag,
391
+ Group: Group,
392
+ Label: Label,
393
+ Check: Check,
394
+ Text: Text,
395
+ Slider: Slider,
396
+ WarningIcon: WarningIcon,
397
+ Hint: HintMessage,
398
+ Error: ErrorMessage
399
+ })
@@ -0,0 +1,169 @@
1
+ import { ReactNode, Dispatch, Children, ReactElement, RefObject } from "react";
2
+
3
+ import { BaseElementType, BaseElementType2, BaseParagraphType, BaseDivType, BaseFormType, BaseInputType, BaseLabelType, BaseLItemType, BaseSelectType, BaseSpanType, BaseSliderType, BaseSmallType, BaseUListType, BaseSVGType, BaseButtonType } from "../utils/BaseTypes";
4
+ import { CustomSetState } from "./FormSelect";
5
+ export type FormTagContextType = {
6
+ noValidate: boolean
7
+ }
8
+ export type FormContextType = {
9
+ controlId?: string,
10
+ isInputGroup?: boolean,
11
+ isFLoatingLabel?: boolean,
12
+ }
13
+
14
+ export type FormType = {
15
+ children: ReactNode
16
+ } & BaseFormType
17
+
18
+ type ErrorMessageType = {
19
+ message: string,
20
+ type?: string,
21
+ className?: string,
22
+ style?: React.CSSProperties,
23
+ } & BaseParagraphType
24
+ type HintMessageType = {
25
+ message: string,
26
+ custom?: boolean,
27
+ className?: string,
28
+ style?: React.CSSProperties,
29
+ } & BaseParagraphType
30
+ export type ErrorType = {children?: ReactNode} & ErrorMessageType
31
+ export type HintType = {children?: ReactNode} & HintMessageType
32
+ export type FormControlType = {
33
+ as?: React.ElementType,
34
+ className?: string,
35
+ plaintext?: boolean,
36
+ id?: string,
37
+ type?: string,
38
+ autoFocus?: boolean,
39
+ error?: ErrorMessageType,
40
+ errorAsOverlay?: boolean
41
+ hint?: HintMessageType
42
+ } & BaseInputType
43
+
44
+ // Form Select types
45
+ export type SelectContextType<T> = {
46
+ internalButtonRef: RefObject<HTMLButtonElement>,
47
+ internalId:string,
48
+ showList: boolean,
49
+ activeDescendant: any,
50
+ inputValue: string,
51
+ selectedDescendant: T
52
+ setSelectedDescendant: Function,
53
+ items: ReactNode
54
+ }
55
+ export type FormSelectTagType = {
56
+ children: ReactNode,
57
+ className?: string,
58
+ id?: string,
59
+ required?: boolean,
60
+ value?: any,
61
+ error?: ErrorMessageType,
62
+ errorAsOverlay?: boolean
63
+ hint?: HintMessageType
64
+ } & BaseSelectType
65
+
66
+ export type FormSelectType = {
67
+ children: ReactNode,
68
+ className?: string,
69
+ id?: string,
70
+ required?: boolean,
71
+ value?: any,
72
+ error?: ErrorMessageType,
73
+ errorAsOverlay?: boolean
74
+ hint?: HintMessageType,
75
+ loading?: boolean,
76
+ listProps?: FormSelectListType
77
+ } & FormSelectControlType
78
+ export type FormSelectControlType = {
79
+ children?: ReactNode,
80
+ required?: boolean,
81
+ className?: string,
82
+ placeholder?: string,
83
+ searchable?: boolean,
84
+ value?: any,
85
+ label?: ReactNode,
86
+ handleSelectedDescendant?: Function
87
+ } & BaseButtonType
88
+
89
+ export type FormSelectInputType = {
90
+ className?: string,
91
+ id?: string
92
+ } & BaseInputType
93
+ export type FormSelectListType = {
94
+ children: ReactNode,
95
+ className?: string,
96
+ id?: string
97
+ } & BaseUListType
98
+ export type FormSelectOptionType = {
99
+ children?: ReactNode,
100
+ className?: string,
101
+ value: string,
102
+ disabled?: boolean,
103
+ label?: string,
104
+ selected?: boolean,
105
+ type?: string
106
+ } & BaseLItemType & BaseElementType
107
+
108
+
109
+ export type FormGroupType = {
110
+ children: ReactNode,
111
+ className?: string,
112
+ controlId: string,
113
+ vertical?: boolean
114
+ } & BaseDivType
115
+
116
+ export type FormLabelType = {
117
+ children: ReactNode,
118
+ className?: string,
119
+ htmlFor?: string
120
+ } & BaseLabelType
121
+
122
+ export type FormCheckType = {
123
+ children?: ReactNode,
124
+ style?: React.CSSProperties,
125
+ classNameContainer?:string,
126
+ containerRef?:React.LegacyRef<HTMLDivElement>,
127
+ containerId?: string,
128
+ styleContainer?: React.CSSProperties,
129
+ classNameLabel?: string,
130
+ labelRef?: React.LegacyRef<HTMLLabelElement>,
131
+ label?: string,
132
+ labelId?: string,
133
+ styleLabel?: React.CSSProperties,
134
+ className?: string,
135
+ type?: string,
136
+ controlId?: string,
137
+ reverse?: boolean,
138
+ } & BaseInputType
139
+
140
+ export type FormTextType = {
141
+ children: ReactNode,
142
+ className?: string,
143
+ } & BaseSmallType
144
+
145
+ export type FormSliderType = {
146
+ children?: ReactNode,
147
+ className?: string,
148
+ style?: React.CSSProperties,
149
+ controlId: string,
150
+ min?: number,
151
+ max?: number,
152
+ step?: number,
153
+ defaultValue?: number,
154
+ value: number,
155
+ onChange(value :number): () => any
156
+ } & BaseSpanType // BaseSliderType
157
+ export type SliderContextType = {
158
+ children: ReactNode,
159
+ controlId: string,
160
+ min?: number,
161
+ max?: number,
162
+ step?: number
163
+ }
164
+
165
+ export type WarningIconType = {
166
+ alt?: string,
167
+ size?: string | number,
168
+ color?: string
169
+ } & BaseSVGType