stargazer-ui 1.5.7 → 1.5.9

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