@dmsi/wedgekit-react 0.0.2

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 (263) hide show
  1. package/README.md +35 -0
  2. package/dist/chunk-27KIIUAR.js +59 -0
  3. package/dist/chunk-2G2E2JMA.js +123 -0
  4. package/dist/chunk-4C66DLIJ.js +51 -0
  5. package/dist/chunk-4RD5ZF2V.js +55 -0
  6. package/dist/chunk-4RJKB7LC.js +14 -0
  7. package/dist/chunk-4T7F5BZZ.js +26 -0
  8. package/dist/chunk-5GOBP2JS.js +53 -0
  9. package/dist/chunk-6ZY524ID.js +42 -0
  10. package/dist/chunk-AWQSSKCK.js +32 -0
  11. package/dist/chunk-BNHSAFMP.js +93 -0
  12. package/dist/chunk-BWRHL2AG.js +439 -0
  13. package/dist/chunk-DKKYR6DS.js +132 -0
  14. package/dist/chunk-E5ALT5W7.js +182 -0
  15. package/dist/chunk-FY7PTP6E.js +322 -0
  16. package/dist/chunk-GTCSRHPF.js +119 -0
  17. package/dist/chunk-I2UVVKQI.js +12 -0
  18. package/dist/chunk-IGQVA7SC.js +41 -0
  19. package/dist/chunk-K3IKUSZW.js +59 -0
  20. package/dist/chunk-KENSVWOY.js +151 -0
  21. package/dist/chunk-KX3O6GJ6.js +138 -0
  22. package/dist/chunk-L4UM372R.js +253 -0
  23. package/dist/chunk-ORMEWXMH.js +37 -0
  24. package/dist/chunk-Q3FKEKIN.js +23 -0
  25. package/dist/chunk-SEKKGFM6.js +28 -0
  26. package/dist/chunk-SY3HT54E.js +91 -0
  27. package/dist/chunk-TAW5ZZ4Z.js +346 -0
  28. package/dist/chunk-TRUPPHBQ.js +109 -0
  29. package/dist/chunk-TU55CHXU.js +30 -0
  30. package/dist/chunk-TWZZB4WO.js +114 -0
  31. package/dist/chunk-TYI74BSP.js +62 -0
  32. package/dist/chunk-U42SKNR6.js +104 -0
  33. package/dist/chunk-UU3FA6LV.js +72 -0
  34. package/dist/chunk-WVUIIBRR.js +51 -0
  35. package/dist/chunk-XUIPGYP5.js +39 -0
  36. package/dist/chunk-Z4UCFUF7.js +299 -0
  37. package/dist/components/Breadcrumbs.cjs +376 -0
  38. package/dist/components/Breadcrumbs.js +90 -0
  39. package/dist/components/Button.cjs +319 -0
  40. package/dist/components/Button.js +8 -0
  41. package/dist/components/CalendarRange.cjs +520 -0
  42. package/dist/components/CalendarRange.js +13 -0
  43. package/dist/components/Caption.cjs +283 -0
  44. package/dist/components/Caption.js +80 -0
  45. package/dist/components/Checkbox.cjs +378 -0
  46. package/dist/components/Checkbox.js +11 -0
  47. package/dist/components/ContentTab.cjs +382 -0
  48. package/dist/components/ContentTab.js +10 -0
  49. package/dist/components/ContentTabs.cjs +472 -0
  50. package/dist/components/ContentTabs.js +98 -0
  51. package/dist/components/DMSiLogo.cjs +79 -0
  52. package/dist/components/DMSiLogo.js +56 -0
  53. package/dist/components/DataGrid.cjs +3113 -0
  54. package/dist/components/DataGrid.js +758 -0
  55. package/dist/components/DataGridCell.cjs +1907 -0
  56. package/dist/components/DataGridCell.js +24 -0
  57. package/dist/components/DataTable.cjs +791 -0
  58. package/dist/components/DataTable.js +720 -0
  59. package/dist/components/DateInput.cjs +1130 -0
  60. package/dist/components/DateInput.js +170 -0
  61. package/dist/components/DateRangeInput.cjs +1131 -0
  62. package/dist/components/DateRangeInput.js +171 -0
  63. package/dist/components/DebugJson.cjs +50 -0
  64. package/dist/components/DebugJson.js +27 -0
  65. package/dist/components/Display.cjs +234 -0
  66. package/dist/components/Display.js +12 -0
  67. package/dist/components/EditingContext.cjs +73 -0
  68. package/dist/components/EditingContext.js +35 -0
  69. package/dist/components/FilterGroup.cjs +1431 -0
  70. package/dist/components/FilterGroup.js +231 -0
  71. package/dist/components/FullViewportBox.cjs +35 -0
  72. package/dist/components/FullViewportBox.js +12 -0
  73. package/dist/components/Grid.cjs +69 -0
  74. package/dist/components/Grid.js +36 -0
  75. package/dist/components/GridContainer.cjs +125 -0
  76. package/dist/components/GridContainer.js +92 -0
  77. package/dist/components/Heading.cjs +238 -0
  78. package/dist/components/Heading.js +14 -0
  79. package/dist/components/HorizontalDivider.cjs +33 -0
  80. package/dist/components/HorizontalDivider.js +10 -0
  81. package/dist/components/Icon.cjs +98 -0
  82. package/dist/components/Icon.js +7 -0
  83. package/dist/components/Input.cjs +672 -0
  84. package/dist/components/Input.js +21 -0
  85. package/dist/components/InputGroup.cjs +270 -0
  86. package/dist/components/InputGroup.js +60 -0
  87. package/dist/components/Label.cjs +223 -0
  88. package/dist/components/Label.js +8 -0
  89. package/dist/components/Link.cjs +262 -0
  90. package/dist/components/Link.js +8 -0
  91. package/dist/components/List.cjs +37 -0
  92. package/dist/components/List.js +14 -0
  93. package/dist/components/LiveChatComponent.cjs +63 -0
  94. package/dist/components/LiveChatComponent.js +40 -0
  95. package/dist/components/LogoAgilityTopBar.cjs +115 -0
  96. package/dist/components/LogoAgilityTopBar.js +92 -0
  97. package/dist/components/LogoDMSiTopBar.cjs +79 -0
  98. package/dist/components/LogoDMSiTopBar.js +7 -0
  99. package/dist/components/LogoMillworkTopBar.cjs +221 -0
  100. package/dist/components/LogoMillworkTopBar.js +198 -0
  101. package/dist/components/MainBar.cjs +211 -0
  102. package/dist/components/MainBar.js +65 -0
  103. package/dist/components/Menu.cjs +437 -0
  104. package/dist/components/Menu.js +11 -0
  105. package/dist/components/MenuOption.cjs +483 -0
  106. package/dist/components/MenuOption.js +13 -0
  107. package/dist/components/MobileDataGrid.cjs +658 -0
  108. package/dist/components/MobileDataGrid.js +125 -0
  109. package/dist/components/Modal.cjs +783 -0
  110. package/dist/components/Modal.js +245 -0
  111. package/dist/components/ModalButtons.cjs +385 -0
  112. package/dist/components/ModalButtons.js +10 -0
  113. package/dist/components/ModalContent.cjs +57 -0
  114. package/dist/components/ModalContent.js +7 -0
  115. package/dist/components/ModalHeader.cjs +426 -0
  116. package/dist/components/ModalHeader.js +11 -0
  117. package/dist/components/ModalScrim.cjs +64 -0
  118. package/dist/components/ModalScrim.js +7 -0
  119. package/dist/components/NavigationTab.cjs +431 -0
  120. package/dist/components/NavigationTab.js +10 -0
  121. package/dist/components/NavigationTabs.cjs +477 -0
  122. package/dist/components/NavigationTabs.js +56 -0
  123. package/dist/components/Notification.cjs +640 -0
  124. package/dist/components/Notification.js +117 -0
  125. package/dist/components/OptionPill.cjs +478 -0
  126. package/dist/components/OptionPill.js +11 -0
  127. package/dist/components/Paragraph.cjs +231 -0
  128. package/dist/components/Paragraph.js +8 -0
  129. package/dist/components/Password.cjs +700 -0
  130. package/dist/components/Password.js +53 -0
  131. package/dist/components/ProjectBar.cjs +242 -0
  132. package/dist/components/ProjectBar.js +63 -0
  133. package/dist/components/Radio.cjs +349 -0
  134. package/dist/components/Radio.js +131 -0
  135. package/dist/components/Search.cjs +767 -0
  136. package/dist/components/Search.js +12 -0
  137. package/dist/components/Select.cjs +758 -0
  138. package/dist/components/Select.js +12 -0
  139. package/dist/components/SideMenu.cjs +54 -0
  140. package/dist/components/SideMenu.js +21 -0
  141. package/dist/components/SideMenuGroup.cjs +422 -0
  142. package/dist/components/SideMenuGroup.js +83 -0
  143. package/dist/components/SideMenuItem.cjs +388 -0
  144. package/dist/components/SideMenuItem.js +70 -0
  145. package/dist/components/Stack.cjs +138 -0
  146. package/dist/components/Stack.js +7 -0
  147. package/dist/components/StatusPill.cjs +265 -0
  148. package/dist/components/StatusPill.js +52 -0
  149. package/dist/components/Stepper.cjs +885 -0
  150. package/dist/components/Stepper.js +105 -0
  151. package/dist/components/Subheader.cjs +226 -0
  152. package/dist/components/Subheader.js +8 -0
  153. package/dist/components/Surface.cjs +98 -0
  154. package/dist/components/Surface.js +40 -0
  155. package/dist/components/Swatch.cjs +1728 -0
  156. package/dist/components/Swatch.js +1319 -0
  157. package/dist/components/Textarea.cjs +269 -0
  158. package/dist/components/Textarea.js +96 -0
  159. package/dist/components/Theme.cjs +36 -0
  160. package/dist/components/Theme.js +7 -0
  161. package/dist/components/Time.cjs +1118 -0
  162. package/dist/components/Time.js +353 -0
  163. package/dist/components/Toast.cjs +644 -0
  164. package/dist/components/Toast.js +218 -0
  165. package/dist/components/Tooltip.cjs +273 -0
  166. package/dist/components/Tooltip.js +9 -0
  167. package/dist/components/TopBar.cjs +352 -0
  168. package/dist/components/TopBar.js +132 -0
  169. package/dist/components/useInfiniteScroll.cjs +57 -0
  170. package/dist/components/useInfiniteScroll.js +8 -0
  171. package/dist/components/useMatchesMedia.cjs +53 -0
  172. package/dist/components/useMatchesMedia.js +9 -0
  173. package/dist/components/useMenuSystem.cjs +358 -0
  174. package/dist/components/useMenuSystem.js +11 -0
  175. package/dist/components/useMounted.cjs +39 -0
  176. package/dist/components/useMounted.js +8 -0
  177. package/dist/fonts.css +21 -0
  178. package/dist/icons-light[FILL]-PPZXOLWS.woff2 +0 -0
  179. package/dist/icons-normal[FILL]-PPZXOLWS.woff2 +0 -0
  180. package/dist/index.css +4401 -0
  181. package/dist/open-sans-55T6A4JE.woff2 +0 -0
  182. package/dist/types.cjs +18 -0
  183. package/dist/types.js +0 -0
  184. package/package.json +66 -0
  185. package/src/brand.css +125 -0
  186. package/src/classNames.ts +144 -0
  187. package/src/components/Breadcrumbs.tsx +116 -0
  188. package/src/components/Button.tsx +210 -0
  189. package/src/components/CalendarRange.tsx +429 -0
  190. package/src/components/Caption.tsx +101 -0
  191. package/src/components/Checkbox.tsx +196 -0
  192. package/src/components/ContentTab.tsx +66 -0
  193. package/src/components/ContentTabs.tsx +103 -0
  194. package/src/components/DMSiLogo.tsx +32 -0
  195. package/src/components/DataGrid.tsx +948 -0
  196. package/src/components/DataGridCell.tsx +384 -0
  197. package/src/components/DataTable.tsx +835 -0
  198. package/src/components/DateInput.tsx +188 -0
  199. package/src/components/DateRangeInput.tsx +179 -0
  200. package/src/components/DebugJson.tsx +24 -0
  201. package/src/components/Display.tsx +60 -0
  202. package/src/components/EditingContext.tsx +40 -0
  203. package/src/components/FilterGroup.tsx +234 -0
  204. package/src/components/FullViewportBox.tsx +11 -0
  205. package/src/components/Grid.tsx +75 -0
  206. package/src/components/GridContainer.tsx +124 -0
  207. package/src/components/Heading.tsx +66 -0
  208. package/src/components/HorizontalDivider.tsx +3 -0
  209. package/src/components/Icon.tsx +36 -0
  210. package/src/components/Input.tsx +511 -0
  211. package/src/components/InputGroup.tsx +51 -0
  212. package/src/components/Label.tsx +40 -0
  213. package/src/components/Link.tsx +106 -0
  214. package/src/components/List.tsx +10 -0
  215. package/src/components/LiveChatComponent.tsx +56 -0
  216. package/src/components/LogoAgilityTopBar.tsx +53 -0
  217. package/src/components/LogoDMSiTopBar.tsx +32 -0
  218. package/src/components/LogoMillworkTopBar.tsx +118 -0
  219. package/src/components/MainBar.tsx +83 -0
  220. package/src/components/Menu.tsx +286 -0
  221. package/src/components/MenuOption.tsx +275 -0
  222. package/src/components/MobileDataGrid.tsx +135 -0
  223. package/src/components/Modal.tsx +271 -0
  224. package/src/components/ModalButtons.tsx +44 -0
  225. package/src/components/ModalContent.tsx +23 -0
  226. package/src/components/ModalHeader.tsx +41 -0
  227. package/src/components/ModalScrim.tsx +35 -0
  228. package/src/components/NavigationTab.tsx +89 -0
  229. package/src/components/NavigationTabs.tsx +63 -0
  230. package/src/components/Notification.tsx +120 -0
  231. package/src/components/OptionPill.tsx +114 -0
  232. package/src/components/Paragraph.tsx +49 -0
  233. package/src/components/Password.tsx +46 -0
  234. package/src/components/ProjectBar.tsx +76 -0
  235. package/src/components/Radio.tsx +140 -0
  236. package/src/components/Search.tsx +129 -0
  237. package/src/components/Select.tsx +104 -0
  238. package/src/components/SideMenu.tsx +21 -0
  239. package/src/components/SideMenuGroup.tsx +81 -0
  240. package/src/components/SideMenuItem.tsx +90 -0
  241. package/src/components/Stack.tsx +179 -0
  242. package/src/components/StatusPill.tsx +51 -0
  243. package/src/components/Stepper.tsx +91 -0
  244. package/src/components/Subheader.tsx +44 -0
  245. package/src/components/Surface.tsx +34 -0
  246. package/src/components/Swatch.tsx +1066 -0
  247. package/src/components/Textarea.tsx +101 -0
  248. package/src/components/Theme.tsx +13 -0
  249. package/src/components/Time.tsx +438 -0
  250. package/src/components/Toast.tsx +244 -0
  251. package/src/components/Tooltip.tsx +137 -0
  252. package/src/components/TopBar.tsx +124 -0
  253. package/src/components/useInfiniteScroll.tsx +40 -0
  254. package/src/components/useMatchesMedia.tsx +28 -0
  255. package/src/components/useMenuSystem.tsx +367 -0
  256. package/src/components/useMounted.tsx +14 -0
  257. package/src/darkmode.css +140 -0
  258. package/src/fonts.css +23 -0
  259. package/src/index.css +509 -0
  260. package/src/index.tsx +2 -0
  261. package/src/types.ts +149 -0
  262. package/src/utils/formatting.tsx +81 -0
  263. package/src/utils.ts +23 -0
@@ -0,0 +1,367 @@
1
+ "use client";
2
+
3
+ import { useState, useRef, useEffect, RefObject, useCallback } from "react";
4
+ import { useMatchesMobile } from "./useMatchesMedia";
5
+
6
+ type MenuPosition = {
7
+ top: number;
8
+ left: number;
9
+ minWidth: number;
10
+ };
11
+
12
+ export function useSubMenuSystem(mobilePositionTo: RefObject<HTMLElement | null>) {
13
+ const [activeMenus, setActiveMenus] = useState<{ [level: number]: string }>(
14
+ {},
15
+ );
16
+ const [activeMenu, setActiveMenu] = useState("");
17
+ const [currentSubMenuLevel, setCurrentSubMenuLevel] = useState<number | null>(null);
18
+ const menuRootRef = useRef<HTMLDivElement>(null);
19
+ const subMenuRefs = useRef<{ [id: string]: HTMLElement | null }>({});
20
+ const hoverTimeoutRef = useRef<NodeJS.Timeout | null>(null);
21
+ const closeTimeoutRef = useRef<NodeJS.Timeout | null>(null);
22
+ const isMobile = useMatchesMobile();
23
+
24
+ const toggleMenu = (menuId: string, level: number) => {
25
+ if (closeTimeoutRef.current) {
26
+ clearTimeout(closeTimeoutRef.current);
27
+ closeTimeoutRef.current = null;
28
+ }
29
+
30
+ setActiveMenu(menuId);
31
+ setCurrentSubMenuLevel(level);
32
+
33
+ setActiveMenus((prev) => {
34
+ const newActiveMenus = { ...prev };
35
+ if (newActiveMenus[level] === menuId) {
36
+ delete newActiveMenus[level];
37
+ } else {
38
+ newActiveMenus[level] = menuId;
39
+ }
40
+
41
+ Object.keys(newActiveMenus).forEach((key) => {
42
+ if (Number(key) > level) {
43
+ delete newActiveMenus[Number(key)];
44
+ }
45
+ });
46
+
47
+ return newActiveMenus;
48
+ });
49
+ };
50
+
51
+ const openMenu = (menuId: string, level: number) => {
52
+ if (closeTimeoutRef.current) {
53
+ clearTimeout(closeTimeoutRef.current);
54
+ closeTimeoutRef.current = null;
55
+ }
56
+
57
+ setActiveMenus((prev) => {
58
+ const newActiveMenus = { ...prev };
59
+ newActiveMenus[level] = menuId;
60
+
61
+ Object.keys(newActiveMenus).forEach((key) => {
62
+ if (Number(key) > level) {
63
+ delete newActiveMenus[Number(key)];
64
+ }
65
+ });
66
+
67
+ return newActiveMenus;
68
+ });
69
+ };
70
+
71
+ const openMenuWithDelay = (menuId: string, level: number, delay = 150) => {
72
+ if (isMobile) {
73
+ return;
74
+ }
75
+
76
+ if (hoverTimeoutRef.current) {
77
+ clearTimeout(hoverTimeoutRef.current);
78
+ }
79
+
80
+ hoverTimeoutRef.current = setTimeout(() => {
81
+ openMenu(menuId, level);
82
+ }, delay);
83
+ };
84
+
85
+ const closeMenuWithDelay = (level: number, delay = 500) => {
86
+ if (isMobile) {
87
+ return;
88
+ }
89
+
90
+ if (hoverTimeoutRef.current) {
91
+ clearTimeout(hoverTimeoutRef.current);
92
+ hoverTimeoutRef.current = null;
93
+ }
94
+
95
+ closeTimeoutRef.current = setTimeout(() => {
96
+ closeSubMenuLevel(level);
97
+ }, delay);
98
+ };
99
+
100
+ const cancelCloseTimeout = () => {
101
+ if (isMobile) {
102
+ return;
103
+ }
104
+
105
+ if (closeTimeoutRef.current) {
106
+ clearTimeout(closeTimeoutRef.current);
107
+ closeTimeoutRef.current = null;
108
+ }
109
+ };
110
+
111
+ const closeSubMenuLevel = (level: number) => {
112
+ setActiveMenus((prev) => {
113
+ const newActiveMenus = { ...prev };
114
+
115
+ delete newActiveMenus[level];
116
+
117
+ Object.keys(newActiveMenus).forEach((key) => {
118
+ if (Number(key) >= level) {
119
+ delete newActiveMenus[Number(key)];
120
+ }
121
+ });
122
+
123
+ if (isMobile) {
124
+ const newSubMenuLevel = level - 1;
125
+ setCurrentSubMenuLevel(newSubMenuLevel);
126
+ const newActiveMenu = newActiveMenus[newSubMenuLevel];
127
+
128
+ if (Object.keys(newActiveMenus).length > 0 && newActiveMenu) {
129
+ setActiveMenu(newActiveMenu);
130
+ }
131
+ }
132
+
133
+ return newActiveMenus;
134
+ });
135
+ };
136
+
137
+ const registerSubMenu = (id: string, element: HTMLElement | null) => {
138
+ subMenuRefs.current[id] = element;
139
+ };
140
+
141
+ const isMenuActive = (menuId: string, level: number) => {
142
+ return activeMenus[level] === menuId;
143
+ };
144
+
145
+ useEffect(() => {
146
+ const handleClickOutside = (event: MouseEvent) => {
147
+ if (Object.keys(activeMenus).length === 0) return;
148
+
149
+ const target = event.target as Node;
150
+
151
+ if (menuRootRef.current?.contains(target)) return;
152
+
153
+ const isInsideActiveSubmenu = Object.values(activeMenus).some((id) => {
154
+ const submenuEl = subMenuRefs.current[id];
155
+ return submenuEl?.contains(target);
156
+ });
157
+
158
+ if (!isInsideActiveSubmenu) {
159
+ setActiveMenus({});
160
+ }
161
+ };
162
+
163
+ document.addEventListener("mousedown", handleClickOutside);
164
+ return () => {
165
+ document.removeEventListener("mousedown", handleClickOutside);
166
+ };
167
+ }, [activeMenus]);
168
+
169
+ useEffect(() => {
170
+ return () => {
171
+ if (hoverTimeoutRef.current) {
172
+ clearTimeout(hoverTimeoutRef.current);
173
+ }
174
+ if (closeTimeoutRef.current) {
175
+ clearTimeout(closeTimeoutRef.current);
176
+ }
177
+ };
178
+ }, []);
179
+
180
+ const getAllFocusableMenuElements = (): HTMLElement[] => {
181
+ const elements: HTMLElement[] = [];
182
+
183
+ if (menuRootRef.current) {
184
+ elements.push(...Array.from(menuRootRef.current.children) as HTMLElement[]);
185
+ }
186
+
187
+ Object.values(activeMenus).forEach((menuId) => {
188
+ const submenuEl = subMenuRefs.current[menuId];
189
+ if (submenuEl) {
190
+ elements.push(...Array.from(submenuEl.children) as HTMLElement[]);
191
+ }
192
+ });
193
+
194
+ return elements;
195
+ };
196
+
197
+ const findCurrentMenuLevel = (element: Element): number => {
198
+ let current = element.parentElement;
199
+ while (current) {
200
+ const level = current.getAttribute("data-menu-level");
201
+ if (level !== null) {
202
+ return parseInt(level, 10);
203
+ }
204
+ current = current.parentElement;
205
+ }
206
+ return 0;
207
+ };
208
+
209
+ const getMenuElementsAtLevel = (level: number): HTMLElement[] => {
210
+ if (level === 0 && menuRootRef.current) {
211
+ return Array.from(menuRootRef.current.children) as HTMLElement[];
212
+ }
213
+
214
+ const menuId = Object.entries(activeMenus).find(([, id]) => {
215
+ const submenuEl = subMenuRefs.current[id];
216
+ return (
217
+ submenuEl &&
218
+ submenuEl.getAttribute("data-menu-level") === level.toString()
219
+ );
220
+ })?.[1];
221
+
222
+ if (menuId) {
223
+ const submenuEl = subMenuRefs.current[menuId];
224
+ if (submenuEl) {
225
+ return Array.from(submenuEl.children) as HTMLElement[];
226
+ }
227
+ }
228
+
229
+ return [];
230
+ };
231
+
232
+ return {
233
+ menuRootRef,
234
+ activeMenus,
235
+ openMenu,
236
+ isMenuActive,
237
+ registerSubMenu,
238
+ closeSubMenuLevel,
239
+ getAllFocusableMenuElements,
240
+ findCurrentMenuLevel,
241
+ getMenuElementsAtLevel,
242
+ mobileHide: isMobile && Object.keys(activeMenus).length > 0,
243
+ listeners: {
244
+ onSubMenuHover: openMenuWithDelay,
245
+ onSubMenuLeave: closeMenuWithDelay,
246
+ onSubMenuEnter: cancelCloseTimeout,
247
+ toggleMenu,
248
+ mobilePositionTo,
249
+ activeMenu,
250
+ currentSubMenuLevel,
251
+ closeSubMenuLevel
252
+ }
253
+ };
254
+ }
255
+
256
+ export function useMenuPosition(
257
+ elementRef: RefObject<HTMLElement | null>,
258
+ position: "right" | "bottom" | "bottom-right" = "bottom",
259
+ options?: {
260
+ isOpen?: boolean;
261
+ setIsOpen?: (isOpen: boolean) => void;
262
+ menuRef?: RefObject<HTMLElement | null>;
263
+ additionalRefs?: RefObject<HTMLElement | null>[];
264
+ topOffset?: number | null;
265
+ },
266
+ ) {
267
+ const [menuPosition, setMenuPosition] = useState<MenuPosition>({
268
+ top: 0,
269
+ left: 0,
270
+ minWidth: 0,
271
+ });
272
+
273
+ const isMobile = useMatchesMobile();
274
+
275
+ const updatePosition = useCallback(() => {
276
+ if (!elementRef?.current) return;
277
+
278
+ const triggerRect = elementRef.current.getBoundingClientRect();
279
+ const menuRect = options?.menuRef?.current?.getBoundingClientRect();
280
+ const viewportWidth = window.innerWidth;
281
+
282
+ const menuWidth = menuRect?.width || triggerRect.width;
283
+ const topOffset = options?.topOffset ?? 4;
284
+
285
+ let top = 0;
286
+ let left = 0;
287
+
288
+ if (position === "bottom" || position === "bottom-right") {
289
+ top = triggerRect.top + triggerRect.height + topOffset;
290
+ } else {
291
+ top = triggerRect.top;
292
+ }
293
+
294
+ if (position === "bottom") {
295
+ left = triggerRect.left + window.scrollX;
296
+ } else if (position === "bottom-right") {
297
+ left = triggerRect.right + window.scrollX - menuWidth;
298
+ } else if (position === "right") {
299
+ left = triggerRect.right + window.scrollX;
300
+ }
301
+
302
+ const overflowsLeftViewport = left + menuWidth > viewportWidth;
303
+
304
+ if (overflowsLeftViewport) {
305
+ left = triggerRect.left - menuWidth
306
+ }
307
+
308
+ if (isMobile) {
309
+ left = triggerRect.left + menuWidth > viewportWidth
310
+ ? Math.max(viewportWidth - menuWidth, 0) - 8
311
+ : triggerRect.left;
312
+ top = (elementRef.current.parentElement?.getBoundingClientRect()?.top ?? 0) + (elementRef.current.parentElement?.getBoundingClientRect()?.height ?? 0) + topOffset;
313
+ }
314
+
315
+ setMenuPosition({
316
+ top,
317
+ left,
318
+ minWidth: triggerRect.width,
319
+ });
320
+ }, [elementRef, position, options?.menuRef, options?.topOffset, isMobile]);
321
+
322
+ useEffect(() => {
323
+ if (!options?.isOpen || !options?.setIsOpen) return;
324
+
325
+ const handleClickOutside = (event: MouseEvent) => {
326
+ const target = event.target as Node;
327
+ if (elementRef.current?.contains(target)) return;
328
+ if (options.menuRef?.current?.contains(target)) return;
329
+ if (options.additionalRefs?.some((ref) => ref.current?.contains(target)))
330
+ return;
331
+
332
+ options.setIsOpen?.(false);
333
+ };
334
+
335
+ document.addEventListener("mousedown", handleClickOutside);
336
+ return () => {
337
+ document.removeEventListener("mousedown", handleClickOutside);
338
+ };
339
+ }, [
340
+ options,
341
+ elementRef,
342
+ options?.isOpen,
343
+ options?.setIsOpen,
344
+ options?.menuRef,
345
+ options?.additionalRefs,
346
+ ]);
347
+
348
+ useEffect(() => {
349
+ updatePosition();
350
+
351
+ const resizeObserver = new ResizeObserver(updatePosition);
352
+ if (elementRef?.current) {
353
+ resizeObserver.observe(elementRef.current);
354
+ }
355
+
356
+ window.addEventListener("scroll", updatePosition);
357
+ window.addEventListener("resize", updatePosition);
358
+
359
+ return () => {
360
+ resizeObserver.disconnect();
361
+ window.removeEventListener("scroll", updatePosition);
362
+ window.removeEventListener("resize", updatePosition);
363
+ };
364
+ }, [elementRef, updatePosition]);
365
+
366
+ return { menuPosition, updatePosition };
367
+ }
@@ -0,0 +1,14 @@
1
+ "use client";
2
+
3
+ import { useEffect, useState } from "react";
4
+
5
+ export const useMounted = () => {
6
+ const [isMounted, setIsMounted] = useState(false);
7
+
8
+ useEffect(() => {
9
+ setIsMounted(true);
10
+ return () => setIsMounted(false);
11
+ }, []);
12
+
13
+ return isMounted;
14
+ };
@@ -0,0 +1,140 @@
1
+
2
+ @media (prefers-color-scheme: dark) {
3
+ :root {
4
+ --color-text-primary-normal: var(--color-neutral-000);
5
+
6
+ --color-text-primary-disabled: var(--color-neutral-400);
7
+ --color-text-primary-error: var(--color-critical-300);
8
+
9
+ --color-text-secondary-normal: var(--color-neutral-300);
10
+ --color-text-secondary-disabled: var(--color-neutral-400);
11
+ --color-text-secondary-error: var(--color-critical-300);
12
+
13
+ --color-text-success-normal: var(--color-success-200);
14
+ --color-text-success-disabled: var(--color-neutral-300);
15
+ --color-text-success-error: var(--color-critical-300);
16
+
17
+ --color-text-warning-normal: var(--color-warning-200);
18
+ --color-text-warning-disabled: var(--color-neutral-300);
19
+ --color-text-warning-error: var(--color-critical-300);
20
+
21
+ --color-text-link-normal: var(--color-link-300);
22
+ --color-text-link-hover: var(--color-link-400);
23
+ --color-text-link-active: var(--color-link-200);
24
+ --color-text-link-disabled: var(--color-neutral-400);
25
+
26
+ --color-border-primary-normal: var(--color-neutral-400);
27
+ --color-border-primary-focus: var(--color-action-300);
28
+ --color-border-primary-error: var(--color-critical-300);
29
+
30
+ --color-icon-primary-normal: var(--color-neutral-300);
31
+ --color-icon-primary-disabled: var(--color-neutral-400);
32
+
33
+ --color-icon-success-normal: var(--color-success-300);
34
+ --color-icon-success-disabled: var(--color-neutral-400);
35
+
36
+ --color-icon-warning-normal: var(--color-warning-300);
37
+ --color-icon-warning-disabled: var(--color-neutral-400);
38
+
39
+ --color-icon-critical-normal: var(--color-critical-300);
40
+ --color-icon-critical-disabled: var(--color-neutral-400);
41
+
42
+ --color-background-primary-normal: var(--color-neutral-600);
43
+ --color-background-grouped-primary-normal: var(--color-neutral-500);
44
+ --color-background-secondary-normal: var(--color-neutral-500);
45
+ --color-background-grouped-secondary-normal: var(--color-neutral-600);
46
+ --color-background-success-normal: var(--color-success-300);
47
+ --color-background-warning-normal: var(--color-warning-300);
48
+ --color-background-critical-normal: var(--color-critical-300);
49
+
50
+ --color-text-action-primary-normal: var(--color-action-300);
51
+ --color-text-action-primary-hover: var(--color-action-400);
52
+ --color-text-action-primary-active: var(--color-action-200);
53
+ --color-text-action-primary-disabled: var(--color-neutral-400);
54
+
55
+ --color-text-on-action-primary-normal: var(--color-neutral-600);
56
+ --color-text-on-action-primary-hover: var(--color-neutral-500);
57
+ --color-text-on-action-primary-active: var(--color-neutral-600);
58
+ --color-text-on-action-primary-disabled: var(--color-neutral-400);
59
+
60
+ --color-text-action-critical-normal: var(--color-critical-300);
61
+ --color-text-action-critical-hover: var(--color-critical-400);
62
+ --color-text-action-critical-active: var(--color-critical-200);
63
+ --color-text-action-critical-disabled: var(--color-neutral-400);
64
+
65
+ --color-border-action-normal: var(--color-action-300);
66
+ --color-border-action-hover: var(--color-action-400);
67
+ --color-border-action-active: var(--color-action-200);
68
+ --color-border-action-disabled: var(--color-neutral-450);
69
+
70
+ --color-text-critical-normal: var(--color-critical-300);
71
+ --color-text-critical-disabled: var(--color-neutral-300);
72
+ --color-text-critical-error: var(--color-critical-300);
73
+
74
+ --color-border-action-critical-normal: var(--color-critical-300);
75
+ --color-border-action-critical-hover: var(--color-critical-400);
76
+ --color-border-action-critical-active: var(--color-critical-200);
77
+ --color-border-action-critical-disabled: var(--color-neutral-450);
78
+
79
+ --color-icon-action-primary-normal: var(--color-neutral-000);
80
+ --color-icon-action-primary-hover: var(--color-action-300);
81
+ --color-icon-action-primary-active: var(--color-action-200);
82
+ --color-icon-action-primary-disabled: var(--color-neutral-400);
83
+
84
+ --color-icon-action-secondary-normal: var(--color-action-300);
85
+ --color-icon-action-secondary-hover: var(--color-action-400);
86
+ --color-icon-action-secondary-active: var(--color-action-200);
87
+ --color-icon-action-secondary-disabled: var(--color-neutral-400);
88
+
89
+ --color-icon-on-action-primary-normal: var(--color-neutral-600);
90
+ --color-icon-on-action-primary-hover: var(--color-neutral-500);
91
+ --color-icon-on-action-primary-active: var(--color-neutral-600);
92
+ --color-icon-on-action-primary-disabled: var(--color-neutral-400);
93
+
94
+ --color-icon-action-critical-normal: var(--color-critical-300);
95
+ --color-icon-action-critical-hover: var(--color-critical-400);
96
+ --color-icon-action-critical-active: var(--color-critical-200);
97
+ --color-icon-action-critical-disabled: var(--color-neutral-400);
98
+
99
+ --color-icon-brand-primary-normal: var(--color-brand-300);
100
+ --color-icon-brand-primary-hover: var(--color-brand-400);
101
+ --color-icon-brand-primary-active: var(--color-brand-200);
102
+ --color-icon-brand-primary-disabled: var(--color-neutral-400);
103
+
104
+ --color-background-action-primary-normal: var(--color-action-300);
105
+ --color-background-action-primary-hover: var(--color-action-400);
106
+ --color-background-action-primary-active: var(--color-action-200);
107
+ --color-background-action-primary-disabled: var(--color-neutral-450);
108
+
109
+ --color-background-action-secondary-normal: var(--color-neutral-600);
110
+ --color-background-action-secondary-hover: var(--color-action-500);
111
+ --color-background-action-secondary-active: var(--color-neutral-600);
112
+ --color-background-action-secondary-disabled: var(--color-neutral-450);
113
+
114
+ --color-background-brand-normal: var(--color-brand-400);
115
+
116
+ --color-background-action-critical-primary-normal: var(
117
+ --color-critical-300
118
+ );
119
+ --color-background-action-critical-primary-hover: var(--color-critical-400);
120
+ --color-background-action-critical-primary-active: var(
121
+ --color-critical-200
122
+ );
123
+ --color-background-action-critical-primary-disabled: var(
124
+ --color-neutral-450
125
+ );
126
+
127
+ --color-background-action-critical-secondary-normal: var(
128
+ --color-neutral-600
129
+ );
130
+ --color-background-action-critical-secondary-hover: var(
131
+ --color-critical-500
132
+ );
133
+ --color-background-action-critical-secondary-active: var(
134
+ --color-neutral-600
135
+ );
136
+ --color-background-action-critical-secondary-disabled: var(
137
+ --color-neutral-450
138
+ );
139
+ }
140
+ }
package/src/fonts.css ADDED
@@ -0,0 +1,23 @@
1
+ @font-face {
2
+ font-family: "Open Sans";
3
+ src: url("../static/open-sans.woff2") format("woff2");
4
+ font-weight: 100 900;
5
+ font-style: normal;
6
+ }
7
+
8
+ @font-face {
9
+ font-family: "Icons";
10
+ src: url("../static/icons-light[FILL].woff2") format("woff2");
11
+ /* src: url("../static/icons-light.woff2") format("woff2"); - We needed icons-light with FILL option */
12
+ font-weight: 300;
13
+ font-style: normal;
14
+ font-display: block;
15
+ }
16
+
17
+ @font-face {
18
+ font-family: "Icons";
19
+ src: url("../static/icons-normal[FILL].woff2") format("woff2");
20
+ font-weight: 400;
21
+ font-style: normal;
22
+ font-display: block;
23
+ }