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,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
+ })
@@ -0,0 +1,7 @@
1
+ import { DropdownType } from "../Dropdown/Dropdown.types"
2
+ import { BaseDivType } from "../utils"
3
+
4
+ export type NavDropdownType = {
5
+ toggleProps?: any,
6
+ menuProps?:any
7
+ } & DropdownType & BaseDivType
@@ -0,0 +1,3 @@
1
+ import NavDropdown from "./NavDropdown"
2
+ export default NavDropdown
3
+ export type { NavDropdownType } from "./NavDropdown.types"
@@ -0,0 +1,305 @@
1
+ import React, { useEffect, useRef, useState, cloneElement, forwardRef, ReactNode, useLayoutEffect, ReactElement } from "react";
2
+ import { createPortal } from "react-dom";
3
+ import { OverlayType, PositionObject } from "./Overlay.types";
4
+
5
+ import mergeRefs from "../utils/MergeRefs";
6
+ import mergeClassnames from "../utils/MergeClassnames";
7
+
8
+
9
+ const setPosition = (referenceElement:any, overlayElement:any, position:string, arrowElement: any, isArrow: boolean=false, boundaryCorrection: PositionObject = {top:0, left:0, bottom: 0, right: 0}) => {
10
+ if(!overlayElement.current) return {top:0, left:0}
11
+ const refCurrent = referenceElement.current as HTMLElement
12
+ const overlayCurrent = overlayElement.current as HTMLElement
13
+ const arrowCurrent = arrowElement.current as HTMLElement
14
+
15
+ const refTop = refCurrent.getBoundingClientRect().top
16
+ const refHeight = refCurrent.getBoundingClientRect().height
17
+ const refLeft = refCurrent.getBoundingClientRect().left
18
+ const refWidth = refCurrent.getBoundingClientRect().width
19
+
20
+ const overlayHeight = overlayCurrent.getBoundingClientRect().height
21
+ const overlayWidth = overlayCurrent.getBoundingClientRect().width
22
+
23
+ const arrowRect = arrowCurrent.getBoundingClientRect()
24
+ const arrowHeight = arrowRect.height//position === "top" || position === "bottom" ? arrowRect.height : arrowRect.width
25
+ const arrowWidth = arrowRect.width//position === "top" || position === "bottom" ? arrowRect.width : arrowRect.height
26
+ console.log(isArrow,overlayWidth)
27
+
28
+ const overlayBorderWidth = parseFloat(getComputedStyle(overlayCurrent).borderWidth.split("px")[0])
29
+ const arrowOffsetHeight = (isArrow ? (position === "bottom" ? -1 : 1)*arrowHeight/2 : arrowHeight - overlayBorderWidth) + 2
30
+ const arrowOffsetWidth = (isArrow ? 0 : arrowWidth - overlayBorderWidth) + 2
31
+
32
+ const correctPosition = (position:string, offset:number, boundary:number) => {
33
+ const positionKey = position as keyof typeof tempPos
34
+ if(overlayCurrent.getBoundingClientRect()[positionKey]<= boundary) {
35
+ return offset
36
+ }
37
+ else {
38
+ return tempPos[positionKey]
39
+ }
40
+ }
41
+
42
+ let tempPos: PositionObject
43
+ switch(position) {
44
+ case "right":
45
+ tempPos = {
46
+ top: refTop + refHeight/2 - overlayHeight/2,
47
+ left: refLeft + refWidth + arrowOffsetWidth
48
+ }
49
+ //tempPos.bottom = correctPosition("bottom", window.scrollY + window.innerHeight, 0)
50
+ //tempPos.top = correctPosition("top", window.scrollY, 48)
51
+ return tempPos
52
+ case "bottom":
53
+ tempPos = {
54
+ top: refTop + refHeight + arrowOffsetHeight,
55
+ left: refLeft + refWidth/2 - (isArrow ? overlayWidth/2 : overlayWidth)/2
56
+ }
57
+ //tempPos.right = correctPosition("right", 12, 0)
58
+ //tempPos.left = correctPosition("left", 0, 0)
59
+ return tempPos
60
+ case "left":
61
+ tempPos = {
62
+ top: refTop + refHeight/2 - overlayHeight/2,
63
+ left: refLeft - overlayWidth - arrowOffsetWidth
64
+ }
65
+ //tempPos.bottom = correctPosition("bottom", window.scrollY + window.innerHeight, 0)
66
+ //tempPos.top = correctPosition("top", window.scrollY, 48)
67
+ return tempPos
68
+ case "top":
69
+ default:
70
+ tempPos = {
71
+ top: refTop - overlayHeight - arrowOffsetHeight,
72
+ left: refLeft + refWidth/2 - (isArrow ? overlayWidth/2 : overlayWidth)/2
73
+ }
74
+ //tempPos.right = correctPosition("right", 12, 0)
75
+ //tempPos.left = correctPosition("left", 0, 0)
76
+ return tempPos
77
+ }
78
+ }
79
+
80
+ const updateAutoPosition = (autoPositionRef:any, positionRef:any, overlayRef:any, arrowRef:any) => {
81
+ let topDistance = positionRef.current.getBoundingClientRect().top
82
+ let bottomDistance = window.innerHeight - positionRef.current.getBoundingClientRect().bottom
83
+ let leftDistance = positionRef.current.getBoundingClientRect().left
84
+ let rightDistance = window.innerWidth - positionRef.current.getBoundingClientRect().right
85
+
86
+ let totalOverlayWidth = overlayRef.current.clientWidth + arrowRef.current.clientWidth + 48
87
+ let totalOverlayHeight = overlayRef.current.clientHeight + arrowRef.current.clientHeight + 48
88
+ //console.log(autoPositionRef.current, positionRef.current, overlayRef.current, arrowRef.current)
89
+
90
+ if(topDistance >= totalOverlayHeight) {
91
+ return "top"
92
+ } else if(topDistance >= totalOverlayHeight/2) {
93
+ return rightDistance >= totalOverlayWidth ? "right" : "left"
94
+ } else if(bottomDistance >= totalOverlayHeight) {
95
+ return "bottom"
96
+ } else {
97
+ return autoPositionRef.current
98
+ }
99
+ }
100
+
101
+ const Overlay = forwardRef<HTMLDivElement, OverlayType>( ({
102
+ children, overlay, tooltip, show, onToggle,
103
+ position="auto", trigger="click", defaultShow=false,
104
+ tooltipClassname, tooltipStyle, arrowClassname, arrowStyle}, ref
105
+ ) => {
106
+ if(Array.isArray(children)) {
107
+ throw new Error(
108
+ "Overlay can only wrap a single element, either introduce a wrapper or remove all but one trigger element!"
109
+ )
110
+ }
111
+
112
+ const positionRef = useRef<typeof children | null>(null)
113
+ const overlayRef = useRef<HTMLDivElement | null>(null)
114
+ const arrowRef = useRef<HTMLDivElement>(null)
115
+ const [arrowPosition, setArrowPosition] = useState<PositionObject>({top:0, left:0})
116
+ const [overlayPosition, setOverlayPosition] = useState<PositionObject>({top:0, left:0})
117
+ const [internalShow, setInternalShow] = useState(defaultShow)
118
+ const internalShowRef = useRef(internalShow)
119
+ const setInternalShowRef = (updatedValue: boolean) => {
120
+ if(!overlay && !tooltip) return
121
+ internalShowRef.current = updatedValue
122
+ setInternalShow(updatedValue)
123
+ }
124
+ if(show != undefined && show != internalShow) {
125
+ setInternalShowRef(show)
126
+ }
127
+ //const positionsList = ["top", "right", "bottom", "left"]
128
+ const [autoPosition, setAutoPosition] = useState(position === "auto" ? "top" : position)
129
+ const autoPositionRef = useRef(autoPosition)
130
+ const setAutoPositionRef = (updatedValue: any) => {
131
+ autoPositionRef.current = updatedValue
132
+ setAutoPosition(updatedValue)
133
+ }
134
+
135
+ const [isHovering, setIsHovering] = useState(false)
136
+ const [isFocused, setIsFocused] = useState(false)
137
+ const [firstClick, setFirstClick] = useState(true)
138
+ const triggerArray = Array.isArray(trigger) ? trigger : [trigger]
139
+
140
+ const positionSetter = (positionRef:any , overlayRef: any, arrowRef: any) => {
141
+ setOverlayPosition( setPosition(positionRef, overlayRef, autoPositionRef.current, arrowRef) )
142
+ setArrowPosition( setPosition(positionRef, arrowRef, autoPositionRef.current, arrowRef, true) )
143
+ }
144
+ const handleScroll = () => {
145
+ if(!internalShowRef.current) return
146
+
147
+ positionSetter(positionRef, overlayRef, arrowRef)
148
+ if(position === "auto") {
149
+ let updatedPosition = updateAutoPosition(autoPositionRef, positionRef, overlayRef, arrowRef)
150
+ setAutoPositionRef(updatedPosition)
151
+ }
152
+ }
153
+ const resizeHandler = () => {
154
+ if(internalShowRef.current) {
155
+ positionSetter(positionRef, overlayRef, arrowRef)
156
+ }
157
+ if(!internalShowRef.current && position === "auto") {
158
+ //setAutoPosition(detectAutoPostition(overlayRef, autoPositionRef))
159
+ }
160
+ }
161
+ const { onClick, onHover, onFocus, onBlur, onMouseOver, onMouseLeave} = (children as ReactElement)!.props
162
+ //console.log(children)
163
+ /* Event handler funtions */
164
+ const handleClick = (event: MouseEvent) => {
165
+
166
+ if(isFocused && firstClick) {
167
+ //this is needed in case both "focus" and "click" are triggers, otherwise there's weird behaviour
168
+ setFirstClick(false)
169
+ return
170
+ }
171
+ setInternalShowRef(!internalShow)
172
+ if(onToggle) {
173
+ onToggle(!internalShow)
174
+ }
175
+ if(onClick) {
176
+ onClick(event)
177
+ }
178
+ }
179
+ const handleHover = (event: MouseEvent) => {
180
+ setInternalShowRef(true)
181
+ if(!isHovering) {
182
+ setIsHovering(true)
183
+ if(onToggle) {
184
+ onToggle(true)
185
+ }
186
+ }
187
+ if(onHover) {
188
+ onHover(event)
189
+ }
190
+ }
191
+ const handleFocus = (event: MouseEvent) => {
192
+ //console.log("focus")
193
+ setInternalShowRef(true)
194
+ setIsFocused(true)
195
+ if(onToggle) {
196
+ onToggle(true)
197
+ }
198
+ if(onFocus) {
199
+ onFocus(event)
200
+ }
201
+ }
202
+ const handleBlur = (event: MouseEvent) => {
203
+ console.log("blur", isFocused)
204
+ if(isHovering) {
205
+ setIsHovering(false)
206
+ }
207
+ if(isFocused) {
208
+ setIsFocused(false)
209
+ setFirstClick(true)
210
+ }
211
+ setInternalShowRef(false)
212
+ if(onToggle) {
213
+ onToggle(false)
214
+ }
215
+ if(onBlur) {
216
+ onBlur(event)
217
+ }
218
+ }
219
+ useLayoutEffect(() => {
220
+ if(overlayRef.current && arrowRef.current && positionRef.current) {
221
+ positionSetter(positionRef, overlayRef, arrowRef)
222
+ }
223
+ }, [internalShow, overlayRef, positionRef, autoPosition])
224
+
225
+ useEffect(() => {
226
+ const controller = new AbortController()
227
+ const signal = controller.signal
228
+ window.addEventListener("scroll", handleScroll, {signal, capture: true})
229
+ window.addEventListener("resize", resizeHandler, {signal, capture: true})
230
+ return function cleanup() {
231
+ controller.abort()
232
+ setInternalShowRef(false)
233
+ }
234
+ }, [])
235
+
236
+ const checkRefPositionStyle = (positionRef: any) => {
237
+ const posistionElement = positionRef.current
238
+ if(!posistionElement) return
239
+ let elementComputedPositionStyle = getComputedStyle(posistionElement)["position"]
240
+ if(elementComputedPositionStyle === "fixed") {
241
+ return "fixed"
242
+ } else if(elementComputedPositionStyle === "sticky") {
243
+ return "sticky"
244
+ } else {
245
+ return "absolute"
246
+ }
247
+ }
248
+ const tooltipClassnames = mergeClassnames("sg-overlay-wrapper", "sg-tooltip-wrapper", tooltipClassname)
249
+ const arrowClassnames = mergeClassnames(
250
+ "sg-overlay-arrow",
251
+ autoPosition ? " overlay-position-"+autoPosition : "",
252
+ tooltip ? "sg-tooltip-arrow":"",
253
+ arrowClassname
254
+ )
255
+
256
+ return (
257
+ <>
258
+ {
259
+ cloneElement(children as any, {
260
+ ref: mergeRefs([positionRef, (children as any).ref]),
261
+ onClick: triggerArray.find(trigger => trigger === "click") ? handleClick : onClick,
262
+ onMouseOver: triggerArray.find(trigger => trigger === "hover") ? handleHover : onMouseOver,
263
+ onMouseLeave: triggerArray.find(trigger => trigger === "hover") ? handleBlur : onMouseLeave,
264
+ onFocus: triggerArray.find(trigger => trigger === "focus") ? handleFocus : onFocus,
265
+ onBlur: triggerArray.find(trigger => trigger === "focus") ? handleBlur : onBlur,
266
+ })
267
+ }
268
+ {internalShow ? createPortal(
269
+ <>
270
+ {overlay ?
271
+ <>
272
+ <div className="sg-overlay-wrapper"
273
+ ref={mergeRefs([ref,overlayRef])}
274
+ style={{ position:checkRefPositionStyle(positionRef), top:overlayPosition!.top, left:overlayPosition!.left }}
275
+ >{overlay}</div>
276
+ <div
277
+ ref={arrowRef} aria-hidden
278
+ className={arrowClassnames}
279
+ style={{...arrowStyle, position:checkRefPositionStyle(positionRef), top:arrowPosition!.top, left:arrowPosition!.left,}}
280
+ >
281
+ </div>
282
+ </>
283
+ : null}
284
+ {tooltip ?
285
+ <>
286
+ <div className={tooltipClassnames}
287
+ ref={mergeRefs([ref,overlayRef])}
288
+ style={{...tooltipStyle, position:checkRefPositionStyle(positionRef), top:overlayPosition!.top, left:overlayPosition!.left }}
289
+ >{tooltip}</div>
290
+ <div
291
+ ref={arrowRef} aria-hidden
292
+ className={arrowClassnames}
293
+ style={{...arrowStyle, position:checkRefPositionStyle(positionRef), top:arrowPosition!.top, left:arrowPosition!.left,}}>
294
+ </div>
295
+ </>
296
+ :
297
+ null}
298
+ </>
299
+ , document.body) : null}
300
+ </>
301
+ )
302
+ })
303
+ Overlay.displayName = "Overlay"
304
+
305
+ export default Overlay
@@ -0,0 +1,24 @@
1
+ import { ReactNode, CSSProperties } from "react"
2
+ import { BaseDivType } from "../utils/BaseTypes"
3
+
4
+ export type OverlayType = {
5
+ children: ReactNode,
6
+ overlay?: React.JSX.Element,
7
+ tooltip?: React.JSX.Element | string,
8
+ show?: boolean,
9
+ onToggle?: Function,
10
+ position?: "auto" | "top" | "bottom" | "right" | "left",
11
+ trigger?: string | string[],
12
+ defaultShow?: boolean,
13
+ tooltipClassname?: string,
14
+ tooltipStyle?: CSSProperties,
15
+ arrowClassname?: string,
16
+ arrowStyle?: CSSProperties
17
+ } & BaseDivType
18
+
19
+ export type PositionObject = {
20
+ top?: number,
21
+ bottom?: number,
22
+ left?: number,
23
+ right?:number
24
+ }
@@ -1,3 +1,3 @@
1
- import Overlay from "./Overlay";
2
- export default Overlay;
3
- export type { OverlayType, PositionObject } from "./Overlay.types";
1
+ import Overlay from "./Overlay";
2
+ export default Overlay
3
+ export type { OverlayType, PositionObject } from "./Overlay.types"
@@ -0,0 +1,155 @@
1
+ import { createPortal } from "react-dom";
2
+ import React, { forwardRef, useEffect, useRef, useState } from "react";
3
+
4
+ import mergeRefs from "../utils/MergeRefs";
5
+
6
+ import { PopoutType, PopoutBodyType, PopoutFooterType, PopoutHeaderType, PopoutTextType, PopoutTitleType } from "./Popout.types";
7
+ /*
8
+ export const useEventListener = (eventType: keyof HTMLElementEventMap, callback: EventListenerOrEventListenerObject, options: boolean | AddEventListenerOptions | undefined, customOptions: {element: HTMLElement}) => {
9
+ const element = customOptions ? customOptions.element : document.body
10
+ useEffect(() => {
11
+ if(element) {
12
+ element.addEventListener(eventType, callback, options)
13
+ return function cleanup() {
14
+ element.removeEventListener(eventType, callback, options)
15
+ }
16
+ }
17
+ }, [callback, element])
18
+ }
19
+ */
20
+
21
+ const Popout = forwardRef<HTMLDialogElement, PopoutType>(({children, initialPosition={top:0, left:0}, id, resize=false, move=false, className, style, ...restProps}, ref) => {
22
+ const [coordinates, setCoordinates] = useState<{ top?: number, bottom?: number, right?: number, left?: number, offSetTop:number, offSetLeft:number }>({offSetTop:0, offSetLeft:0, ...initialPosition})
23
+ const resizeComputed = resize ? "true":"false"
24
+ const moveComputed = move ? "true":"false"
25
+
26
+ const passedRef = useRef(ref)
27
+ const popupRef = useRef<HTMLDialogElement>(null)
28
+ const [ isMouseDown, setIsMouseDown ] = useState<boolean>(false)
29
+ const isMouseDownRef = useRef(isMouseDown)
30
+ useEffect(() => {
31
+ isMouseDownRef.current = isMouseDown
32
+ }, [isMouseDown])
33
+
34
+ const onMouseDown = (event: React.PointerEvent<HTMLDialogElement>) => {
35
+ const eventTarget = event.target as HTMLElement
36
+ if(move && eventTarget.className.includes("sg-popout-title") || eventTarget.className.includes("sg-popout-header")) {
37
+ const { top, left} = popupRef.current!.getBoundingClientRect();
38
+ setCoordinates(prev => ({
39
+ ...prev,
40
+ offSetTop:event.clientY - top,
41
+ offSetLeft:event.clientX - left
42
+ }))
43
+ popupRef.current!.style.setProperty("user-select", "none")
44
+ popupRef.current!.setPointerCapture(event.pointerId)//event.pointerId)//"moveable-popup-"+id);
45
+ setIsMouseDown(true)
46
+ }
47
+ }
48
+ const onMouseUp = () => {
49
+ if(move) {
50
+ popupRef.current!.style.removeProperty("user-select")
51
+ setIsMouseDown(false)
52
+ }
53
+ }
54
+ const onMouseMove = (event: React.PointerEvent<HTMLDialogElement>) => {
55
+ if( move && isMouseDownRef.current && popupRef.current ) {
56
+ const isTopOver = event.clientY - coordinates.offSetTop < 0
57
+ const isBottomOver = window.innerHeight - (event.clientY - coordinates.offSetTop + popupRef.current.offsetHeight) < 0
58
+ const isLeftOver = event.clientX - coordinates.offSetLeft < 0
59
+ const isRightOver = window.innerWidth - (event.clientX - coordinates.offSetLeft + popupRef.current.offsetWidth) < 0
60
+
61
+ let topCoordinate = isTopOver ? 0 : event.clientY - coordinates.offSetTop
62
+ topCoordinate = isBottomOver ? window.innerHeight - popupRef.current.offsetHeight : topCoordinate
63
+
64
+ let leftCoordinate = isLeftOver ? 0 : event.clientX - coordinates.offSetLeft
65
+ leftCoordinate = isRightOver ? window.innerWidth - popupRef.current.offsetWidth : leftCoordinate
66
+
67
+ //console.log(event.clientX - coordinates.offSetLeft, event.clientY - coordinates.offSetTop)
68
+ setCoordinates(prev => ({
69
+ ...prev,
70
+ top:topCoordinate,
71
+ left:leftCoordinate
72
+ }))
73
+ }
74
+ }
75
+
76
+ useEffect(() => {
77
+ document.body.addEventListener("pointerup", () => onMouseUp(), true)
78
+ return function cleanup() {
79
+ document.body.removeEventListener("pointerup", () => onMouseUp(), true)
80
+ }
81
+ }, [])
82
+ return (
83
+ createPortal(
84
+ <dialog data-resize={resizeComputed} data-move={moveComputed} data-passedref={passedRef}
85
+ ref={mergeRefs([ref,popupRef])} id={id} className={`sg-moveable-popout${className ? " "+className : ""}`}
86
+ style={{...style, top:coordinates.top, left:coordinates.left, bottom:coordinates.bottom, right:coordinates.right}}
87
+ onPointerDown={onMouseDown} onPointerMove={(event) => onMouseMove(event)} {...restProps}
88
+ >
89
+ {children}
90
+ </dialog>
91
+ , document.body
92
+ )
93
+ )
94
+ })
95
+ Popout.displayName = "Popout"
96
+
97
+ const Header = forwardRef<HTMLDivElement | HTMLSpanElement | HTMLHeadingElement, PopoutHeaderType>(
98
+ ({ children, className, as = "div", ...restProps}, ref) =>
99
+ {
100
+ let validAs = ["div", "span", "h1", "h2", "h3", "h4", "h5", "h6"]
101
+ let Component = validAs.find(valid => valid === as) ? as : "div"
102
+ return (
103
+ <Component ref={ref} className={`sg-popout-header ${className}`} {...restProps}>
104
+ {children}
105
+ </Component>
106
+ )
107
+ })
108
+ Header.displayName = "PopoutHeader"
109
+
110
+ const Title = forwardRef<HTMLHeadingElement, PopoutTitleType>( ({as="h4", className, children, ...restProps}, ref) => {
111
+ let validAs = ["h1", "h2", "h3", "h4", "h5", "h6"]
112
+ let Component = validAs.find(valid => valid === as) ? as : "h5"
113
+ return (
114
+ <Component ref={ref} className={`sg-popout-title ${className}`} {...restProps}>
115
+ {children}
116
+ </Component>
117
+ )
118
+ })
119
+ Title.displayName = "PopoutTitle"
120
+
121
+ const Body = forwardRef<HTMLDivElement, PopoutBodyType>( ({children, className, ...restProps}, ref) => {
122
+ return (
123
+ <div ref={ref} className={`sg-popout-body ${className}`} {...restProps}>
124
+ {children}
125
+ </div>
126
+ )
127
+ })
128
+ Body.displayName = "PopoutBody"
129
+
130
+ const Text = forwardRef<HTMLParagraphElement, PopoutTextType>( ({children, className, ...restProps}, ref) => {
131
+ return (
132
+ <p ref={ref} className={`sg-popout-text ${className}`} {...restProps}>
133
+ {children}
134
+ </p>
135
+ )
136
+ })
137
+ Text.displayName = "PopoutText"
138
+
139
+ const Footer = forwardRef<HTMLDivElement, PopoutFooterType>( ({children, className, ...restProps}, ref) => {
140
+ return (
141
+ <div ref={ref} className={`sg-popout-footer ${className}`} {...restProps}>
142
+ {children}
143
+ </div>
144
+ )
145
+ })
146
+ Footer.displayName = "PopoutFooter"
147
+
148
+ export default Object.assign(Popout, {
149
+ Header: Header,
150
+ Title: Title,
151
+ Body: Body,
152
+ Text: Text,
153
+ Footer: Footer
154
+ })
155
+
@@ -0,0 +1,42 @@
1
+ import { ReactNode } from "react"
2
+ import { BaseDialogType, BaseDivType, BaseHeadingType, BaseParagraphType, BaseSpanType } from "../utils/BaseTypes"
3
+
4
+ export type PopoutType = {
5
+ children: ReactNode,
6
+ initialPosition?: {
7
+ top?: number,
8
+ bottom?: number,
9
+ right?: number,
10
+ left?: number
11
+ },
12
+ id?: string,
13
+ resize?: boolean,
14
+ move?: boolean,
15
+ } & BaseDialogType
16
+
17
+ export type PopoutHeaderType = {
18
+ children: ReactNode,
19
+ className?: string,
20
+ as?: React.ElementType
21
+ } & (BaseDivType | BaseHeadingType | BaseSpanType)
22
+
23
+ export type PopoutTitleType = {
24
+ children: ReactNode,
25
+ className?: string,
26
+ as?: React.ElementType
27
+ } & BaseHeadingType
28
+
29
+ export type PopoutBodyType = {
30
+ children: ReactNode,
31
+ className?: string,
32
+ } & BaseDivType
33
+
34
+ export type PopoutTextType = {
35
+ children: ReactNode,
36
+ className?: string,
37
+ } & BaseParagraphType
38
+
39
+ export type PopoutFooterType = {
40
+ children: ReactNode,
41
+ className?: string,
42
+ } & BaseDivType
@@ -0,0 +1,3 @@
1
+ import Popout from "./Popout"
2
+ export default Popout
3
+ export type {PopoutBodyType, PopoutFooterType, PopoutHeaderType, PopoutTextType, PopoutTitleType, PopoutType} from "./Popout.types"
@@ -0,0 +1,15 @@
1
+ import React, { forwardRef } from "react";
2
+
3
+ import { SpinnerType } from "./Spinner.types";
4
+
5
+ const Spinner = forwardRef<HTMLDivElement, SpinnerType>( ({size="1em", color="white", label, className, controlId, ...restProps}, ref) => {
6
+ return (
7
+ <>
8
+ <div aria-labelledby={controlId} role="status" ref={ref} className={`sg-spinner${className ? " "+className : ""}`} style={{width:size, height:size, borderColor:color}} {...restProps}></div>
9
+ <label id={controlId} className="sg-visually-hidden">{label}</label>
10
+ </>
11
+ )
12
+ })
13
+ Spinner.displayName = "Spinner"
14
+
15
+ export default Spinner
@@ -0,0 +1,7 @@
1
+ export type SpinnerType = {
2
+ label: string,
3
+ size?: string,
4
+ color?: string,
5
+ className?: string,
6
+ controlId?: string,
7
+ }
@@ -0,0 +1,3 @@
1
+ import Spinner from "./Spinner"
2
+ export default Spinner
3
+ export type { SpinnerType } from "./Spinner.types"