stargazer-ui 1.2.0 → 1.2.1

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 (349) 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 +59 -0
  8. package/dev/pages/ButtonPage.jsx +44 -0
  9. package/dev/pages/CardPage.jsx +81 -0
  10. package/dev/pages/DropdownPage.jsx +31 -0
  11. package/dev/pages/FormPage.jsx +130 -0
  12. package/dev/pages/ListPage.jsx +52 -0
  13. package/dev/pages/ModalPage.jsx +37 -0
  14. package/dev/pages/OverlayPage.jsx +35 -0
  15. package/dev/pages/components.jsx +19 -0
  16. package/{styles → dev}/stargazerui.css +392 -3075
  17. package/dev/stargazerui.css.map +1 -0
  18. package/dev/test.jsx +88 -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 +17 -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 +358 -0
  38. package/src/Dropdown/Dropdown.types.ts +52 -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 +445 -0
  47. package/src/Form/Form.types.ts +117 -0
  48. package/src/Form/index.ts +4 -0
  49. package/src/InputGroup/InputGroup.tsx +46 -0
  50. package/src/InputGroup/InputGroup.types.ts +21 -0
  51. package/src/InputGroup/index.ts +4 -0
  52. package/src/List/List.tsx +112 -0
  53. package/src/List/List.types.ts +34 -0
  54. package/src/List/index.ts +4 -0
  55. package/src/Modal/Modal.tsx +220 -0
  56. package/src/Modal/Modal.types.ts +49 -0
  57. package/src/Modal/index.ts +4 -0
  58. package/src/Nav/Nav.tsx +43 -0
  59. package/src/Nav/Nav.types.ts +21 -0
  60. package/src/Nav/index.ts +4 -0
  61. package/src/NavBar/Navbar.tsx +57 -0
  62. package/src/NavBar/Navbar.types.ts +24 -0
  63. package/src/NavBar/index.ts +4 -0
  64. package/src/NavDropdown/NavDropdown.tsx +93 -0
  65. package/src/NavDropdown/NavDropdown.types.ts +6 -0
  66. package/src/NavDropdown/index.ts +3 -0
  67. package/src/Overlay/Overlay.tsx +277 -0
  68. package/src/Overlay/Overlay.types.ts +20 -0
  69. package/{Overlay/index.d.ts → src/Overlay/index.ts} +3 -3
  70. package/src/Popout/Popout.tsx +155 -0
  71. package/src/Popout/Popout.types.ts +42 -0
  72. package/src/Popout/index.ts +3 -0
  73. package/src/Spinner/Spinner.tsx +15 -0
  74. package/src/Spinner/Spinner.types.ts +7 -0
  75. package/src/Spinner/index.ts +3 -0
  76. package/src/Table/Table.tsx +16 -0
  77. package/src/Table/Table.types.ts +9 -0
  78. package/src/Table/index.ts +3 -0
  79. package/src/Tabs/Tabs.tsx +215 -0
  80. package/src/Tabs/Tabs.types.ts +49 -0
  81. package/src/Tabs/index.ts +3 -0
  82. package/src/ToggleButton/ToggleButton.tsx +21 -0
  83. package/src/ToggleButton/ToggleButton.types.ts +8 -0
  84. package/src/ToggleButton/index.ts +3 -0
  85. package/{hooks/index.d.ts → src/hooks/index.ts} +6 -5
  86. package/src/hooks/useClassname.ts +5 -0
  87. package/src/hooks/useDraggable.ts +186 -0
  88. package/src/hooks/useKeepElementFocused.ts +37 -0
  89. package/src/hooks/useScreenSize.ts +24 -0
  90. package/src/index.ts +21 -0
  91. package/src/styles/_Card.scss +166 -0
  92. package/src/styles/_CloseButton.scss +51 -0
  93. package/src/styles/_CustomButton.scss +132 -0
  94. package/src/styles/_Dropdown.scss +120 -0
  95. package/src/styles/_FloatingLabel.scss +56 -0
  96. package/src/styles/_Forms.scss +7 -0
  97. package/src/styles/_Grid.scss +178 -0
  98. package/src/styles/_InputGroup.scss +71 -0
  99. package/src/styles/_List.scss +62 -0
  100. package/src/styles/_Modal.scss +234 -0
  101. package/src/styles/_ModalOld.scss +242 -0
  102. package/src/styles/_Nav.scss +36 -0
  103. package/src/styles/_NavBar.scss +116 -0
  104. package/src/styles/_NavDropdown.scss +34 -0
  105. package/src/styles/_OffCanvas.scss +260 -0
  106. package/src/styles/_OverLay.scss +56 -0
  107. package/src/styles/_Popout.scss +75 -0
  108. package/src/styles/_Spinner.scss +19 -0
  109. package/src/styles/_Table.scss +34 -0
  110. package/src/styles/_Tabs.scss +129 -0
  111. package/src/styles/_colors.scss +510 -0
  112. package/src/styles/_components.scss +40 -0
  113. package/src/styles/_functions.scss +134 -0
  114. package/src/styles/_mixins.scss +26 -0
  115. package/src/styles/_reset.scss +231 -0
  116. package/src/styles/_utilities.scss +2480 -0
  117. package/src/styles/_variables.scss +146 -0
  118. package/src/styles/forms/_FormCheck.scss +269 -0
  119. package/src/styles/forms/_FormControl.scss +102 -0
  120. package/src/styles/forms/_FormGroup.scss +21 -0
  121. package/src/styles/forms/_FormLabel.scss +3 -0
  122. package/src/styles/forms/_FormSelect.scss +164 -0
  123. package/src/styles/forms/_FormSlider.scss +116 -0
  124. package/src/styles/forms/_FormText.scss +6 -0
  125. package/{utils/BaseTypes.d.ts → src/utils/BaseTypes.ts} +30 -23
  126. package/src/utils/ContrastingColor.ts +25 -0
  127. package/src/utils/FileImportExport.js +50 -0
  128. package/src/utils/MergeClassnames.ts +5 -0
  129. package/src/utils/MergeRefs.ts +12 -0
  130. package/src/vite-env.d.ts +1 -0
  131. package/tsconfig-build.json +4 -0
  132. package/tsconfig.json +79 -0
  133. package/tsconfig.node.json +10 -0
  134. package/types/BaseTypes.d.ts +19 -0
  135. package/{Button → types/components/Button}/Button.types.d.ts +2 -1
  136. package/types/components/Button/index.d.ts +1 -0
  137. package/{Card → types/components/Card}/Card.types.d.ts +1 -3
  138. package/types/components/Card/index.d.ts +1 -0
  139. package/{CloseButton → types/components/CloseButton}/CloseButton.types.d.ts +1 -1
  140. package/types/components/CloseButton/index.d.ts +1 -0
  141. package/{Dropdown → types/components/Dropdown}/Dropdown.types.d.ts +10 -3
  142. package/types/components/Dropdown/index.d.ts +1 -0
  143. package/{FloatingLabel → types/components/FloatingLabel}/FloatingLabel.types.d.ts +1 -1
  144. package/types/components/FloatingLabel/index.d.ts +1 -0
  145. package/types/components/Form/Form.d.ts +17 -0
  146. package/types/components/Form/Form.types.d.ts +50 -0
  147. package/types/components/Form/index.d.ts +1 -0
  148. package/types/components/InputGroup/InputGroup.d.ts +6 -0
  149. package/types/components/InputGroup/InputGroup.types.d.ts +10 -0
  150. package/types/components/InputGroup/index.d.ts +1 -0
  151. package/{Modal → types/components/Modal}/Modal.d.ts +1 -1
  152. package/{Modal → types/components/Modal}/Modal.types.d.ts +2 -3
  153. package/types/components/Modal/index.d.ts +1 -0
  154. package/{Nav → types/components/Nav}/Nav.types.d.ts +1 -1
  155. package/types/components/Nav/index.d.ts +1 -0
  156. package/{NavBar → types/components/NavBar}/Navbar.d.ts +2 -1
  157. package/{NavBar → types/components/NavBar}/Navbar.types.d.ts +1 -2
  158. package/types/components/NavBar/index.d.ts +1 -0
  159. package/{NavDropdown → types/components/NavDropdown}/NavDropdown.d.ts +2 -2
  160. package/types/components/NavDropdown/index.d.ts +1 -0
  161. package/{Popout → types/components/Popout}/Popout.types.d.ts +1 -1
  162. package/types/components/Popout/index.d.ts +1 -0
  163. package/types/components/Spinner/index.d.ts +1 -0
  164. package/{Table → types/components/Table}/Table.types.d.ts +1 -1
  165. package/types/components/Table/index.d.ts +1 -0
  166. package/{Tabs → types/components/Tabs}/Tabs.types.d.ts +1 -9
  167. package/types/components/Tabs/index.d.ts +1 -0
  168. package/types/components/ToggleButton/ToggleButton.d.ts +9 -0
  169. package/types/components/ToggleButton/ToggleButton.types.d.ts +0 -0
  170. package/types/components/ToggleButton/index.d.ts +1 -0
  171. package/types/components/index.d.ts +16 -0
  172. package/types/index.d.ts +1 -0
  173. package/vite.config.js +57 -0
  174. package/vite.config.js.timestamp-1708777378490-e94428ceb2bf9.mjs +42 -0
  175. package/Bar/Bar.type.d.ts +0 -6
  176. package/Bar/index.js +0 -2
  177. package/Bar/index.js.map +0 -1
  178. package/Bar/package.json +0 -1
  179. package/Button/Button.js +0 -12
  180. package/Button/Button.js.map +0 -1
  181. package/Button/index.d.ts +0 -3
  182. package/Button/index.js +0 -7
  183. package/Button/index.js.map +0 -1
  184. package/Button/package.json +0 -1
  185. package/ButtonGroup/ButtonGroup.d.ts +0 -4
  186. package/ButtonGroup/ButtonGroup.js +0 -10
  187. package/ButtonGroup/ButtonGroup.js.map +0 -1
  188. package/ButtonGroup/ButtonGroup.types.d.ts +0 -7
  189. package/ButtonGroup/index.d.ts +0 -3
  190. package/ButtonGroup/index.js +0 -7
  191. package/ButtonGroup/index.js.map +0 -1
  192. package/ButtonGroup/package.json +0 -1
  193. package/Card/Card.js +0 -41
  194. package/Card/Card.js.map +0 -1
  195. package/Card/index.d.ts +0 -3
  196. package/Card/index.js +0 -7
  197. package/Card/index.js.map +0 -1
  198. package/Card/package.json +0 -1
  199. package/CloseButton/CloseButton.js +0 -11
  200. package/CloseButton/CloseButton.js.map +0 -1
  201. package/CloseButton/index.d.ts +0 -3
  202. package/CloseButton/index.js +0 -7
  203. package/CloseButton/index.js.map +0 -1
  204. package/CloseButton/package.json +0 -1
  205. package/Dropdown/Dropdown.js +0 -292
  206. package/Dropdown/Dropdown.js.map +0 -1
  207. package/Dropdown/index.d.ts +0 -4
  208. package/Dropdown/index.js +0 -8
  209. package/Dropdown/index.js.map +0 -1
  210. package/Dropdown/package.json +0 -1
  211. package/FileUploadButton/FileUploadButton.d.ts +0 -4
  212. package/FileUploadButton/FileUploadButton.js +0 -21
  213. package/FileUploadButton/FileUploadButton.js.map +0 -1
  214. package/FileUploadButton/FileUploadButton.types.d.ts +0 -7
  215. package/FileUploadButton/index.d.ts +0 -3
  216. package/FileUploadButton/index.js +0 -7
  217. package/FileUploadButton/index.js.map +0 -1
  218. package/FileUploadButton/package.json +0 -1
  219. package/FloatingLabel/FloatingLabel.js +0 -17
  220. package/FloatingLabel/FloatingLabel.js.map +0 -1
  221. package/FloatingLabel/index.d.ts +0 -3
  222. package/FloatingLabel/index.js +0 -7
  223. package/FloatingLabel/index.js.map +0 -1
  224. package/FloatingLabel/package.json +0 -1
  225. package/Form/Form.d.ts +0 -38
  226. package/Form/Form.js +0 -308
  227. package/Form/Form.js.map +0 -1
  228. package/Form/Form.types.d.ts +0 -105
  229. package/Form/index.d.ts +0 -4
  230. package/Form/index.js +0 -8
  231. package/Form/index.js.map +0 -1
  232. package/Form/package.json +0 -1
  233. package/InputGroup/InputGroup.d.ts +0 -7
  234. package/InputGroup/InputGroup.js +0 -31
  235. package/InputGroup/InputGroup.js.map +0 -1
  236. package/InputGroup/InputGroup.types.d.ts +0 -16
  237. package/InputGroup/index.d.ts +0 -4
  238. package/InputGroup/index.js +0 -7
  239. package/InputGroup/index.js.map +0 -1
  240. package/InputGroup/package.json +0 -1
  241. package/List/List.d.ts +0 -14
  242. package/List/List.js +0 -76
  243. package/List/List.js.map +0 -1
  244. package/List/List.types.d.ts +0 -28
  245. package/List/index.d.ts +0 -3
  246. package/List/index.js +0 -7
  247. package/List/index.js.map +0 -1
  248. package/List/package.json +0 -1
  249. package/Modal/Modal.js +0 -160
  250. package/Modal/Modal.js.map +0 -1
  251. package/Modal/index.d.ts +0 -3
  252. package/Modal/index.js +0 -7
  253. package/Modal/index.js.map +0 -1
  254. package/Modal/package.json +0 -1
  255. package/Nav/Nav.js +0 -28
  256. package/Nav/Nav.js.map +0 -1
  257. package/Nav/index.d.ts +0 -4
  258. package/Nav/index.js +0 -7
  259. package/Nav/index.js.map +0 -1
  260. package/Nav/package.json +0 -1
  261. package/NavBar/Navbar.js +0 -36
  262. package/NavBar/Navbar.js.map +0 -1
  263. package/NavBar/index.d.ts +0 -4
  264. package/NavBar/index.js +0 -8
  265. package/NavBar/index.js.map +0 -1
  266. package/NavBar/package.json +0 -1
  267. package/NavDropdown/NavDropdown.js +0 -77
  268. package/NavDropdown/NavDropdown.js.map +0 -1
  269. package/NavDropdown/index.d.ts +0 -3
  270. package/NavDropdown/index.js +0 -7
  271. package/NavDropdown/index.js.map +0 -1
  272. package/NavDropdown/package.json +0 -1
  273. package/Overlay/Overlay.d.ts +0 -4
  274. package/Overlay/Overlay.js +0 -228
  275. package/Overlay/Overlay.js.map +0 -1
  276. package/Overlay/Overlay.types.d.ts +0 -18
  277. package/Overlay/index.js +0 -7
  278. package/Overlay/index.js.map +0 -1
  279. package/Overlay/package.json +0 -1
  280. package/Popout/Popout.js +0 -110
  281. package/Popout/Popout.js.map +0 -1
  282. package/Popout/index.d.ts +0 -3
  283. package/Popout/index.js +0 -7
  284. package/Popout/index.js.map +0 -1
  285. package/Popout/package.json +0 -1
  286. package/Spinner/Spinner.js +0 -12
  287. package/Spinner/Spinner.js.map +0 -1
  288. package/Spinner/index.d.ts +0 -3
  289. package/Spinner/index.js +0 -7
  290. package/Spinner/index.js.map +0 -1
  291. package/Spinner/package.json +0 -1
  292. package/Table/Table.js +0 -11
  293. package/Table/Table.js.map +0 -1
  294. package/Table/index.d.ts +0 -3
  295. package/Table/index.js +0 -7
  296. package/Table/index.js.map +0 -1
  297. package/Table/package.json +0 -1
  298. package/Tabs/Tabs.js +0 -158
  299. package/Tabs/Tabs.js.map +0 -1
  300. package/Tabs/index.d.ts +0 -3
  301. package/Tabs/index.js +0 -7
  302. package/Tabs/index.js.map +0 -1
  303. package/Tabs/package.json +0 -1
  304. package/ToggleButton/ToggleButton.d.ts +0 -4
  305. package/ToggleButton/ToggleButton.js +0 -17
  306. package/ToggleButton/ToggleButton.js.map +0 -1
  307. package/ToggleButton/ToggleButton.types.d.ts +0 -7
  308. package/ToggleButton/index.d.ts +0 -3
  309. package/ToggleButton/index.js +0 -7
  310. package/ToggleButton/index.js.map +0 -1
  311. package/ToggleButton/package.json +0 -1
  312. package/hooks/index.js +0 -6
  313. package/hooks/index.js.map +0 -1
  314. package/hooks/package.json +0 -1
  315. package/hooks/useClassname.d.ts +0 -2
  316. package/hooks/useClassname.js +0 -7
  317. package/hooks/useClassname.js.map +0 -1
  318. package/hooks/useDraggable.d.ts +0 -23
  319. package/hooks/useDraggable.js +0 -147
  320. package/hooks/useDraggable.js.map +0 -1
  321. package/hooks/useKeepElementFocused.d.ts +0 -2
  322. package/hooks/useKeepElementFocused.js +0 -37
  323. package/hooks/useKeepElementFocused.js.map +0 -1
  324. package/hooks/useScreenSize.d.ts +0 -5
  325. package/hooks/useScreenSize.js +0 -21
  326. package/hooks/useScreenSize.js.map +0 -1
  327. package/index.d.ts +0 -18
  328. package/index.js +0 -19
  329. package/index.js.map +0 -1
  330. package/styles/stargazerui.css.map +0 -1
  331. package/utils/ContrastingColor.d.ts +0 -1
  332. package/utils/MergeClassnames.d.ts +0 -2
  333. package/utils/MergeClassnames.js +0 -7
  334. package/utils/MergeClassnames.js.map +0 -1
  335. package/utils/MergeRefs.d.ts +0 -2
  336. package/utils/MergeRefs.js +0 -16
  337. package/utils/MergeRefs.js.map +0 -1
  338. /package/{Button → types/components/Button}/Button.d.ts +0 -0
  339. /package/{Card → types/components/Card}/Card.d.ts +0 -0
  340. /package/{CloseButton → types/components/CloseButton}/CloseButton.d.ts +0 -0
  341. /package/{Dropdown → types/components/Dropdown}/Dropdown.d.ts +0 -0
  342. /package/{FloatingLabel → types/components/FloatingLabel}/FloatingLabel.d.ts +0 -0
  343. /package/{Nav → types/components/Nav}/Nav.d.ts +0 -0
  344. /package/{NavDropdown → types/components/NavDropdown}/NavDropdown.types.d.ts +0 -0
  345. /package/{Popout → types/components/Popout}/Popout.d.ts +0 -0
  346. /package/{Spinner → types/components/Spinner}/Spinner.d.ts +0 -0
  347. /package/{Spinner → types/components/Spinner}/Spinner.types.d.ts +0 -0
  348. /package/{Table → types/components/Table}/Table.d.ts +0 -0
  349. /package/{Tabs → types/components/Tabs}/Tabs.d.ts +0 -0
@@ -0,0 +1,112 @@
1
+ import React, { forwardRef, createContext, useContext, useRef, cloneElement, ReactElement, useMemo } from "react"
2
+
3
+ import { ListType, ListSublistType, ListItemType, ListLabelType, FormContextType } from "./List.types"
4
+ import useDraggable, { insertPhantomElement } from "../hooks/useDraggable"
5
+ import useClassname from "../hooks/useClassname"
6
+ import mergeRefs from "../utils/MergeRefs"
7
+
8
+ export const ListContext = createContext<FormContextType | null>(null)
9
+ export const ListContextProvider = ({children, value} : {children: React.ReactNode, value:FormContextType}) => {
10
+ return (
11
+ <ListContext.Provider value={value}>
12
+ {children}
13
+ </ListContext.Provider>
14
+ )
15
+ }
16
+ export const useListContext = () => {
17
+ const context = useContext(ListContext)
18
+
19
+ return context
20
+ }
21
+
22
+ /*
23
+ const handlePhantomInsert = (event: React.PointerEvent, item: HTMLElement | null) => {
24
+ event.stopPropagation()
25
+ document.querySelectorAll(".phantom").forEach(phantom => phantom.remove())
26
+ if(item) { insertPhantomElement(item)}
27
+ }
28
+ */
29
+
30
+ const List = forwardRef<HTMLUListElement, ListType>( ({children, className, depth, tree=false, dragdrop=false, ...restProps}, ref) => {
31
+ const context = useListContext()
32
+ const initialContext = useMemo(() => ({
33
+ tree: tree,
34
+ draggable: dragdrop
35
+ }), [])
36
+
37
+ return (
38
+ <ul ref={ref} id="test-list" data-context={context ? "true":"false" } className={useClassname("sg-list", className)} style={{"--depth":depth} as React.CSSProperties} {...restProps}>
39
+ { !context ?
40
+ <ListContextProvider value={initialContext}>
41
+ {children}
42
+ </ListContextProvider>
43
+ :
44
+ children
45
+ }
46
+ </ul>
47
+ )
48
+ })
49
+ List.displayName = "List"
50
+
51
+ const Sublist = forwardRef<HTMLLIElement, ListSublistType>( ({children, className, depth, ...restProps}, ref) => {
52
+ const { draggable } = useListContext()!
53
+ const itemRef = useRef<HTMLLIElement>(null)
54
+
55
+ const { coordinates, isMouseDown} = useDraggable(itemRef, {draggable})
56
+
57
+ return (
58
+ <li ref={mergeRefs([ref,itemRef])} data-phantom="none" className={useClassname("sg-sublist", className)} style={{ "--depth":depth, top: coordinates.top, left: coordinates.left, width: coordinates.width } as React.CSSProperties} {...restProps}>
59
+ {children}
60
+ </li>
61
+ )
62
+ })
63
+ Sublist.displayName = "ListSubList"
64
+
65
+ const Item = forwardRef<HTMLLIElement, ListItemType>( ({children, className, ...restProps}, ref) => {
66
+ const { draggable } = useListContext()!
67
+ const itemRef = useRef<HTMLLIElement>(null)
68
+
69
+ const { coordinates, isMouseDown} = useDraggable(itemRef, {draggable})
70
+
71
+ return (
72
+ <li ref={itemRef} data-phantom="none" className={useClassname("sg-list-item", className)} style={{ top: coordinates.top, left: coordinates.left, width: coordinates.width } as React.CSSProperties} {...restProps} >
73
+ {children}
74
+ </li>
75
+ )
76
+ })
77
+ Item.displayName = "ListItem"
78
+
79
+ const Label = forwardRef<HTMLSpanElement, ListLabelType>( ({children, className, style, ...restProps}, ref) => {
80
+ const labelRef = useRef<HTMLElement>(null)
81
+ const computedClass = useClassname("sg-list-label", className)
82
+
83
+ //const coordinates = useDraggable(labelRef)
84
+ return (
85
+ (typeof children === "string") ?
86
+ <span ref={mergeRefs([ref, labelRef])} className={computedClass} style={{ ...style}} {...restProps}>
87
+ {children}
88
+ </span>
89
+ :
90
+ cloneElement(children as any,
91
+ {
92
+ ref: mergeRefs([ref, labelRef]),
93
+ className: computedClass,
94
+ style: { ...(children as ReactElement).props.style}
95
+ }
96
+ )
97
+
98
+ )
99
+ })
100
+ Label.displayName = "ListLabel"
101
+ /*
102
+ List.Sublist = Sublist
103
+ List.Item = Item
104
+ List.Label = Label
105
+
106
+ export default List
107
+ */
108
+ export default Object.assign(List, {
109
+ Sublist: Sublist,
110
+ Item: Item,
111
+ Label: Label
112
+ })
@@ -0,0 +1,34 @@
1
+ import { ReactNode } from "react"
2
+
3
+ import { BaseUListType, BaseLItemType, BaseSpanType } from "../utils/BaseTypes"
4
+
5
+ export type FormContextType = {
6
+ depth?: number,
7
+ tree?: boolean,
8
+ draggable?: boolean
9
+ }
10
+
11
+ export type ListType = {
12
+ children: ReactNode,
13
+ className: string,
14
+ depth: number,
15
+ tree: boolean,
16
+ dragdrop: boolean
17
+ } & BaseUListType
18
+
19
+ export type ListSublistType = {
20
+ children: ReactNode,
21
+ className: string
22
+ depth: number
23
+ } & BaseLItemType
24
+
25
+ export type ListItemType = {
26
+ children: ReactNode,
27
+ className: string,
28
+ } & BaseLItemType
29
+
30
+ export type ListLabelType = {
31
+ children: ReactNode,
32
+ className: string,
33
+ label: string
34
+ } & BaseSpanType
@@ -0,0 +1,4 @@
1
+ import List from "./List";
2
+
3
+ export type {ListType, ListSublistType, ListItemType, ListLabelType} from "./List.types"
4
+ export default List
@@ -0,0 +1,220 @@
1
+ import React, { createContext, useContext, useEffect, useState, forwardRef, useRef } from "react"
2
+ import { createPortal } from "react-dom"
3
+
4
+ import { ModalBodyType, ModalContextType, ModalFooterType, ModalHeaderType, ModalTitleType, ModalType, ErrorModalType } from "./Modal.types"
5
+
6
+ import CloseButton from "../CloseButton/CloseButton"
7
+ import Button from "../Button/Button"
8
+ import mergeRefs from "../utils/MergeRefs"
9
+
10
+ const ModalContext = createContext<ModalContextType>(null)
11
+ const ModalContextProvider = ({children, value}:{children:React.ReactNode, value:ModalContextType}) => {
12
+ return (
13
+ <ModalContext.Provider value={value}>
14
+ {children}
15
+ </ModalContext.Provider>
16
+ )
17
+ }
18
+ const useModalContext = () => {
19
+ const context = useContext(ModalContext)
20
+ if(!context) {
21
+ throw new Error(
22
+ "useModalContext has to be used within ModalContextProvider!"
23
+ )
24
+ }
25
+ return context
26
+ }
27
+
28
+ const Modal = forwardRef<HTMLDialogElement, ModalType>( ({ children, size = "md", show, backdrop = "static", fill=false, onHide, className, id, stretch, style, ...restProps
29
+ }, ref) => {
30
+ const [showModal, setShowModal] = useState<boolean>(show)
31
+ if(show && show != showModal) {
32
+ setShowModal(show)
33
+ }
34
+
35
+ const modalRef = useRef<HTMLDialogElement>(null)
36
+ useKeepElementFocused(modalRef)
37
+
38
+ let typeCheck : {show: boolean, onHide: boolean} | undefined = typeof(show) === "boolean" && typeof(onHide) === "function" ? undefined : {show: typeof(show) === "boolean", onHide: typeof(onHide) === "function"}
39
+ if(typeCheck) {
40
+ console.error(
41
+ !typeCheck.show ? "The variable 'show' must be used and must be a boolean used to decide when to show the modal!" : null,
42
+ !typeCheck.onHide ? "The variable 'onHide' must be used and must be a function which is used to set 'show' as the modal gets closed!" : null
43
+ )
44
+ }
45
+
46
+ const closeModal = () => {
47
+ const modal = modalRef.current!
48
+ modal.classList.add("close")
49
+ modal.addEventListener('animationend', (event) => {
50
+ console.log(event)
51
+ if(event.animationName === "scale-down") {
52
+ if(onHide) {
53
+ onHide()
54
+ }
55
+ setShowModal(false)
56
+ }
57
+ }, {once : true});
58
+ }
59
+
60
+ useEffect(() => {
61
+ const modal = modalRef.current
62
+
63
+ if(!modal) return
64
+
65
+ if(showModal) {
66
+ modal.classList.remove('close')
67
+ modal.showModal()
68
+ }
69
+ else {
70
+ // modal.classList.add('close')
71
+ modal.close()
72
+ }
73
+
74
+ }, [showModal])
75
+
76
+ let classNameComputed: string = `sg-modal-tag`
77
+ if(className) {
78
+ classNameComputed += " "+className
79
+ }
80
+ if(backdrop === "static" || backdrop === "true") {
81
+ classNameComputed += " sg-modal-static"
82
+ }
83
+ if(fill) classNameComputed += " sg-modal-fill"
84
+ if(size && !fill) classNameComputed += ` sg-modal-${size}`
85
+
86
+ const handleKeyDown = (event: React.KeyboardEvent<HTMLDialogElement>) => {
87
+ const key: string = event.key
88
+ if(key != "Escape") {return}
89
+
90
+ event.preventDefault()
91
+ closeModal()
92
+ }
93
+
94
+ return (
95
+ createPortal(
96
+ <dialog ref={mergeRefs([ref, modalRef])} className={classNameComputed} onKeyDown={(event) => handleKeyDown(event)} {...restProps } style={{"--height":stretch ? "80%":null, ...style} as React.CSSProperties}>
97
+ <ModalContextProvider value={closeModal}>
98
+ {!typeCheck ?
99
+ children :
100
+ <ErrorModal typeCheck={typeCheck} closeModal={closeModal}/>
101
+ }
102
+ </ModalContextProvider>
103
+ </dialog>
104
+ , document.body)
105
+ )
106
+ })
107
+ Modal.displayName = "Modal"
108
+
109
+ const Header = forwardRef<HTMLDivElement | HTMLSpanElement | HTMLHeadingElement, ModalHeaderType>(({children, as="", className = "", closeButton = false, onClick, ...restProps}, ref) => {
110
+ let validAs = ["div", "span", "h1", "h2", "h3", "h4", "h5", "h6"]
111
+ let Component = validAs.find(valid => valid === as) ? as : "div"
112
+ const closeModal = useModalContext()
113
+ const onCloseButtonClick = (event: React.MouseEvent) => {
114
+ if(onClick) {
115
+ onClick(event)
116
+ }
117
+ closeModal()
118
+ }
119
+
120
+ return (
121
+ <Component ref={ref} className={`sg-modal-header ${className}`} {...restProps}>
122
+ {children}
123
+ {closeButton ? <CloseButton variant onClick={event => onCloseButtonClick(event)}/> : null}
124
+ </Component>
125
+ )
126
+ })
127
+ Header.displayName = "ModalHeader"
128
+
129
+ const Title = forwardRef<HTMLDivElement | HTMLSpanElement | HTMLHeadingElement, ModalTitleType>( ({children, as="h4", className, ...restProps}, ref) => {
130
+ let validAs = ["div", "span", "h1", "h2", "h3", "h4", "h5", "h6"]
131
+ let Component = validAs.find(valid => valid === as) ? as : "h4"
132
+ return (
133
+ <Component ref={ref} className={`sg-modal-title ${className}`} {...restProps}>
134
+ {children}
135
+ </Component>
136
+ )
137
+ })
138
+ Title.displayName = "ModalTitle"
139
+
140
+ const Body = forwardRef<HTMLDivElement, ModalBodyType>( ({children, className, ...restProps}, ref) => {
141
+ return (
142
+ <div ref={ref} className={`sg-modal-body ${className}`} {...restProps}>
143
+ {children}
144
+ </div>
145
+ )
146
+ })
147
+ Body.displayName = "ModalBody"
148
+
149
+ const Footer = forwardRef<HTMLDivElement, ModalBodyType>( ({children, className, ...restProps}, ref) => {
150
+ return (
151
+ <div ref={ref} className={`sg-modal-footer ${className}`} {...restProps}>
152
+ {children}
153
+ </div>
154
+ )
155
+ })
156
+ Footer.displayName = "ModalFooter"
157
+
158
+ export default Object.assign(Modal, {
159
+ Header: Header,
160
+ Title: Title,
161
+ Body: Body,
162
+ Footer: Footer
163
+ })
164
+
165
+ export const useKeepElementFocused = function (elementRef: React.RefObject<HTMLDialogElement>) {
166
+ useEffect(() => {
167
+ const onKeyDown = (event: KeyboardEvent) => {
168
+ const focusableElements = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
169
+ const modal = elementRef.current
170
+ if(modal) {
171
+ const firstFocusableElement = modal.querySelectorAll(focusableElements)[0] as HTMLElement
172
+ const focusableContent = modal.querySelectorAll(focusableElements)
173
+ const lastFocusableElement = focusableContent[focusableContent.length - 1] as HTMLElement
174
+ let isTabPressed = event.key === 'Tab'
175
+
176
+ if (!isTabPressed) {
177
+ return;
178
+ }
179
+
180
+ if (event.shiftKey) {
181
+ if (document.activeElement === firstFocusableElement) {
182
+ lastFocusableElement.focus()
183
+ event.preventDefault()
184
+ }
185
+ } else if (document.activeElement === lastFocusableElement) {
186
+ firstFocusableElement.focus();
187
+ event.preventDefault()
188
+ }
189
+ }
190
+ }
191
+ document.addEventListener('keydown', onKeyDown, true )
192
+
193
+ return function cleanup() {
194
+ document.removeEventListener('keydown', onKeyDown, true )
195
+ }
196
+ }, [elementRef])
197
+ }
198
+
199
+ const ErrorModal = ({typeCheck, closeModal}:ErrorModalType) => {
200
+ return (
201
+ <>
202
+ <Header closeButton >
203
+ <Title>
204
+ An Error ocurred!
205
+ </Title>
206
+ </Header>
207
+ <Body>
208
+ <p>
209
+ {!typeCheck.show ? "The variable 'show' must be used and must be a boolean used to decide when to show the modal!" : null}
210
+ {!typeCheck.onHide ? "The variable 'onHide' must be used and must be a function which is used to set 'show' as the modal gets closed!" : null}
211
+ </p>
212
+ </Body>
213
+ <Footer>
214
+ <Button variant="danger" type="button" onClick={() => closeModal()}>
215
+ Close
216
+ </Button>
217
+ </Footer>
218
+ </>
219
+ )
220
+ }
@@ -0,0 +1,49 @@
1
+ import { ReactNode } from "react";
2
+
3
+ import { BaseDialogType, BaseDivType, BaseHeadingType, BaseSpanType } from "../utils/BaseTypes"
4
+
5
+ export type ModalContextType = Function | null
6
+
7
+ export type ModalType = {
8
+ children:ReactNode,
9
+ className?: string,
10
+ id?: string,
11
+ fill?: boolean,
12
+ size?: string,
13
+ show: boolean,
14
+ backdrop?: string,
15
+ onHide: Function,
16
+ stretch?: boolean
17
+ } & BaseDialogType
18
+
19
+ export type ModalHeaderType = {
20
+ children: ReactNode,
21
+ as?: React.ElementType,
22
+ className?: string,
23
+ closeButton?: boolean
24
+ onClick?: (event: React.MouseEvent) => void,
25
+ } & (BaseDivType | BaseHeadingType | BaseSpanType)
26
+
27
+ export type ModalTitleType = {
28
+ children: ReactNode,
29
+ as?: React.ElementType,
30
+ className?: string
31
+ } & (BaseDivType | BaseHeadingType | BaseSpanType)
32
+
33
+ export type ModalBodyType = {
34
+ children: ReactNode,
35
+ className?: string,
36
+ } & BaseDivType
37
+
38
+ export type ModalFooterType = {
39
+ children: ReactNode,
40
+ className?: string,
41
+ } & BaseDivType
42
+
43
+ export type ErrorModalType = {
44
+ typeCheck: {
45
+ show: boolean,
46
+ onHide: boolean
47
+ },
48
+ closeModal: Function
49
+ }
@@ -0,0 +1,4 @@
1
+ import Modal from "./Modal"
2
+
3
+ export type {ModalBodyType, ModalContextType, ModalFooterType, ModalHeaderType, ModalTitleType, ModalType} from "./Modal.types"
4
+ export default Modal
@@ -0,0 +1,43 @@
1
+ import React, { forwardRef } from "react";
2
+
3
+ import { NavType, NavItemType, NavLinkType } from "./Nav.types";
4
+
5
+ import { useNavbarContext } from "../NavBar/Navbar";
6
+
7
+ const Nav = forwardRef<HTMLElement, NavType>(({children, className, as="ul", ...restProps}, ref) => {
8
+ const Component = as
9
+ const navbarContext = useNavbarContext()
10
+ const navbarPrefix = navbarContext ? navbarContext : "sg-navbar-"
11
+
12
+ return (
13
+ <Component ref={ref} className={`${className} ${navbarPrefix}nav`} {...restProps}>
14
+ {children}
15
+ </Component>
16
+ )
17
+ })
18
+ Nav.displayName = "Nav"
19
+
20
+ const Item = forwardRef<HTMLElement, NavItemType>( ({children, className, as="li", ...restProps}, ref) => {
21
+ const Component = as
22
+ return (
23
+ <Component role="none" ref={ref} className={`sg-nav-item${className ? " "+className:""}`} {...restProps}>
24
+ {children}
25
+ </Component>
26
+ )
27
+ })
28
+ Item.displayName = "NavItem"
29
+
30
+ const Link = forwardRef<HTMLElement, NavLinkType>( ({children, className, as="a", ...restProps}, ref) => {
31
+ const Component = as
32
+ return (
33
+ <Component role="menuitem" ref={ref} className={`sg-nav-link${className ? " "+className:""}`} {...restProps}>
34
+ {children}
35
+ </Component>
36
+ )
37
+ })
38
+ Link.displayName = "NavLink"
39
+
40
+ export default Object.assign(Nav, {
41
+ Item: Item,
42
+ Link: Link
43
+ })
@@ -0,0 +1,21 @@
1
+ import { ReactNode } from "react";
2
+
3
+ import { BaseAnchorType, BaseElementType, BaseLItemType, BaseUListType } from "../utils/BaseTypes";
4
+
5
+ export type NavType = {
6
+ children: ReactNode,
7
+ className?: string,
8
+ as?: React.ElementType
9
+ } & (BaseUListType | BaseElementType)
10
+
11
+ export type NavItemType = {
12
+ children: ReactNode,
13
+ className?: string,
14
+ as?: React.ElementType
15
+ } & (BaseLItemType | BaseElementType)
16
+
17
+ export type NavLinkType = {
18
+ children: ReactNode,
19
+ className?: string,
20
+ as?: React.ElementType
21
+ } & (BaseAnchorType | BaseElementType)
@@ -0,0 +1,4 @@
1
+ import Nav from "./Nav"
2
+ export default Nav
3
+ export * from "./Nav"
4
+ export type {NavItemType, NavLinkType, NavType} from "./Nav.types"
@@ -0,0 +1,57 @@
1
+ import React, { createContext, forwardRef, useContext, useMemo } from "react";
2
+
3
+ import { NavbarBrandType, NavbarTextType, NavbarType, NavbarContextType } from "./Navbar.types";
4
+
5
+ export const NavbarContext = createContext<NavbarContextType>(null)
6
+
7
+ const NavbarContextProvider = ({children, value}:{children:React.ReactNode, value:NavbarContextType}) => {
8
+ return (
9
+ <NavbarContext.Provider value={value}>
10
+ {children}
11
+ </NavbarContext.Provider>
12
+ )
13
+ }
14
+ export const useNavbarContext = () => {
15
+ const context = useContext(NavbarContext)
16
+ return context
17
+ }
18
+
19
+ const Navbar = forwardRef<HTMLElement, NavbarType>(({children, className, navbarPrefix= "sg-navbar-", ...restProps}, ref) => {
20
+ const navbarContext = useMemo(() => {
21
+ return navbarPrefix
22
+ }, [navbarPrefix])
23
+
24
+ return (
25
+ <nav ref={ref} className={`sg-navbar${className ? " "+className:""}`} {...restProps}>
26
+ <NavbarContextProvider value={navbarContext}>
27
+ {children}
28
+ </NavbarContextProvider>
29
+ </nav>
30
+ )
31
+ })
32
+ Navbar.displayName = "Navbar"
33
+
34
+ const Brand = forwardRef<HTMLAnchorElement | HTMLElement, NavbarBrandType>( ({children, className, href="#", as="a", ...restProps}, ref) => {
35
+ const Component = as || (href && as != "Link" ? 'a' : 'span')
36
+ return (
37
+ <Component ref={ref} href={href} className={`sg-navbar-brand${className ? " "+className:""}`} {...restProps} >
38
+ {children}
39
+ </Component>
40
+ )
41
+ })
42
+ Brand.displayName = "NavbarBrand"
43
+
44
+ const Text = forwardRef<HTMLElement, NavbarTextType>( ({children, className, as="span", ...restProps}, ref) => {
45
+ const Component = as
46
+ return (
47
+ <Component ref={ref} className={`sg-navbar-text${className ? " "+className:""}`} {...restProps}>
48
+ {children}
49
+ </Component>
50
+ )
51
+ })
52
+ Text.displayName = "NavbarText"
53
+
54
+ export default Object.assign(Navbar, {
55
+ Brand: Brand,
56
+ Text: Text
57
+ })
@@ -0,0 +1,24 @@
1
+ import { ReactNode } from "react";
2
+
3
+ import { BaseAnchorType, BaseElementType, BaseNavType } from "../utils/BaseTypes";
4
+
5
+ export type NavbarContextType = string | null
6
+
7
+ export type NavbarType = {
8
+ children: ReactNode,
9
+ className?: string,
10
+ navbarPrefix?: string,
11
+ } & BaseNavType
12
+
13
+ export type NavbarBrandType = {
14
+ children: ReactNode,
15
+ className?: string,
16
+ as?: React.ElementType,
17
+ href?: string
18
+ } & (BaseAnchorType | BaseElementType)
19
+
20
+ export type NavbarTextType = {
21
+ children: ReactNode,
22
+ className?: string,
23
+ as?: React.ElementType
24
+ } & BaseElementType
@@ -0,0 +1,4 @@
1
+ import Navbar from "./Navbar"
2
+ export default Navbar
3
+ export { useNavbarContext } from "./Navbar"
4
+ export type {NavbarBrandType, NavbarContextType, NavbarTextType, NavbarType} from "./Navbar.types"
@@ -0,0 +1,93 @@
1
+ import React, { forwardRef, useCallback, useMemo, useState } from "react";
2
+
3
+ import { NavDropdownType } from "./NavDropdown.types";
4
+
5
+ import Dropdown, { DropdownContextProvider } from "../Dropdown/Dropdown";
6
+
7
+ const getDropdownMenuPlacement = (alignEnd: boolean, dropDirection: string, isRTL:boolean = false) => {
8
+ const topStart = isRTL ? 'top-end' : 'top-start';
9
+ const topEnd = isRTL ? 'top-start' : 'top-end';
10
+ const bottomStart = isRTL ? 'bottom-end' : 'bottom-start';
11
+ const bottomEnd = isRTL ? 'bottom-start' : 'bottom-end';
12
+ const leftStart = isRTL ? 'right-start' : 'left-start';
13
+ const leftEnd = isRTL ? 'right-end' : 'left-end';
14
+ const rightStart = isRTL ? 'left-start' : 'right-start';
15
+ const rightEnd = isRTL ? 'left-end' : 'right-end';
16
+ let placement = alignEnd ? bottomEnd : bottomStart;
17
+ if (dropDirection === 'up')
18
+ {
19
+ placement = alignEnd ? topEnd : topStart
20
+ }
21
+ else if (dropDirection === 'end') {
22
+ placement = alignEnd ? rightEnd : rightStart
23
+ } else if (dropDirection === 'start') {
24
+ placement = alignEnd ? leftEnd : leftStart
25
+ } else if (dropDirection === 'down-centered') {
26
+ placement = 'bottom'
27
+ } else if (dropDirection === 'up-centered') {
28
+ placement = 'top'
29
+ }
30
+ return placement;
31
+ }
32
+
33
+ const NavDropdown = forwardRef<HTMLDivElement, NavDropdownType>((
34
+ {
35
+ children, className, onSelect, onToggle, controlId, toggleProps, title, menuProps,
36
+ drop="down", align="start", autoClose=true, show="default", ...restProps
37
+ }, ref) => {
38
+ const [showInternal, setShowInternal] = useState<boolean>(show === "default" ? false : show as boolean)
39
+
40
+ // this is an object like {index: string} because we need it to rerender even if the case is the same
41
+ // aka we use a "next/previous" case to navigate through the dropdown menu so need to rerender consecutive "next" cases
42
+ const [activeDescendant, setActiveDescendant] = useState({case:""})
43
+
44
+ const internalOnToggle = useCallback((event: MouseEvent) => {
45
+ event.stopPropagation()
46
+ setShowInternal(prev => !prev)
47
+ }, [])
48
+
49
+ const alignEnd = align === "end"
50
+ const placement = getDropdownMenuPlacement(alignEnd, drop )
51
+
52
+ const controlIdcomputed = controlId
53
+ const contextValue = useMemo(() => ({
54
+ align,
55
+ drop,
56
+ showInternal: show != "default" && onToggle ? show as boolean : showInternal,
57
+ handleToggle: show != "default" && onToggle ? onToggle : internalOnToggle,
58
+ placement,
59
+ directionClasses: {
60
+ down: "dropdown",
61
+ 'down-centered': `dropdown-center`,
62
+ up: 'dropup',
63
+ 'up-centered': 'dropup-center dropup',
64
+ end: 'dropend',
65
+ start: 'dropstart'
66
+ },
67
+ controlId: controlIdcomputed,
68
+ activeDescendant,
69
+ setActiveDescendant,
70
+ navDropdown: false
71
+ }), [align, drop, show, showInternal, onToggle, internalOnToggle, placement, controlId, activeDescendant, setActiveDescendant])
72
+
73
+ return (
74
+ <div ref={ref} id={controlId+"-wrapper"} className={`sg-dropdown${className? " "+className:""} sg-nav-item`} {...restProps} >
75
+ <DropdownContextProvider value={contextValue}>
76
+ <Dropdown.Toggle navDropdown={true} {...toggleProps}>
77
+ {title}
78
+ </Dropdown.Toggle>
79
+ <Dropdown.Menu {...menuProps}>
80
+ {children}
81
+ </Dropdown.Menu>
82
+ </DropdownContextProvider>
83
+ </div>
84
+ )
85
+ })
86
+ NavDropdown.displayName = "NavDropdown"
87
+
88
+ export default Object.assign(NavDropdown, {
89
+ Toggle: Dropdown.Toggle,
90
+ Menu: Dropdown.Menu,
91
+ Item: Dropdown.Item,
92
+ Divider: Dropdown.Divider
93
+ })