@dmsi/wedgekit-react 0.0.550 → 0.0.552

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 (180) hide show
  1. package/dist/{chunk-U3QGZAVS.js → chunk-JADOJNBI.js} +4 -4
  2. package/dist/{chunk-N2KPADIL.js → chunk-WNGFRQ4Y.js} +7 -7
  3. package/dist/{chunk-ZVY3TLXL.js → chunk-ZIPJMN2E.js} +4 -4
  4. package/dist/components/Alert.js +2 -2
  5. package/dist/components/CalendarRange.js +10 -10
  6. package/dist/components/DataGrid/ColumnSelectorHeaderCell/ColumnSelectorMenuOption.js +10 -10
  7. package/dist/components/DataGrid/ColumnSelectorHeaderCell/index.js +10 -10
  8. package/dist/components/DataGrid/PinnedColumns.js +10 -10
  9. package/dist/components/DataGrid/TableBody/LoadingCell.js +10 -10
  10. package/dist/components/DataGrid/TableBody/TableBodyRow.js +10 -10
  11. package/dist/components/DataGrid/TableBody/index.js +10 -10
  12. package/dist/components/DataGrid/index.js +10 -10
  13. package/dist/components/DataGrid/utils.js +10 -10
  14. package/dist/components/DateInput.js +10 -10
  15. package/dist/components/DateRangeInput.js +10 -10
  16. package/dist/components/FilterGroup.js +5 -5
  17. package/dist/components/MobileDataGrid/ColumnSelector/index.js +10 -10
  18. package/dist/components/MobileDataGrid/MobileDataGridHeader.js +10 -10
  19. package/dist/components/MobileDataGrid/RowDetailModalProvider/index.js +5 -5
  20. package/dist/components/MobileDataGrid/index.js +10 -10
  21. package/dist/components/Modal.js +4 -4
  22. package/dist/components/ModalButtons.js +2 -2
  23. package/dist/components/ModalHeader.js +2 -2
  24. package/dist/components/NavigationTab.js +2 -2
  25. package/dist/components/NavigationTabs.js +2 -2
  26. package/dist/components/NestedMenu.js +3 -3
  27. package/dist/components/Notification.js +3 -3
  28. package/dist/components/OptionPill.js +2 -2
  29. package/dist/components/PDFViewer/DownloadIcon.js +2 -2
  30. package/dist/components/PDFViewer/PDFNavigation.js +2 -2
  31. package/dist/components/PDFViewer/index.js +6 -6
  32. package/dist/components/ProductImagePreview/index.js +1 -1
  33. package/dist/components/Stepper.js +3 -3
  34. package/dist/components/Toast.js +3 -3
  35. package/dist/components/Upload.js +3 -3
  36. package/dist/components/index.js +16 -16
  37. package/package.json +8 -9
  38. package/src/brand.css +0 -125
  39. package/src/classNames.ts +0 -174
  40. package/src/components/AccessChangerTabItem.tsx +0 -71
  41. package/src/components/Accordion.tsx +0 -108
  42. package/src/components/Alert.tsx +0 -81
  43. package/src/components/Breadcrumbs.tsx +0 -142
  44. package/src/components/Button.tsx +0 -216
  45. package/src/components/CalendarRange.tsx +0 -628
  46. package/src/components/Caption.tsx +0 -144
  47. package/src/components/Card.tsx +0 -88
  48. package/src/components/Checkbox.tsx +0 -206
  49. package/src/components/CompactImagesPreview.tsx +0 -135
  50. package/src/components/ContentTab.tsx +0 -84
  51. package/src/components/ContentTabs.tsx +0 -136
  52. package/src/components/DMSiLogo.tsx +0 -33
  53. package/src/components/DataGrid/ColumnSelectorHeaderCell/ColumnSelectorMenuOption.tsx +0 -35
  54. package/src/components/DataGrid/ColumnSelectorHeaderCell/index.tsx +0 -74
  55. package/src/components/DataGrid/PinnedColumns.tsx +0 -183
  56. package/src/components/DataGrid/TableBody/LoadingCell.tsx +0 -44
  57. package/src/components/DataGrid/TableBody/TableBodyRow.tsx +0 -157
  58. package/src/components/DataGrid/TableBody/index.tsx +0 -185
  59. package/src/components/DataGrid/index.tsx +0 -756
  60. package/src/components/DataGrid/types.ts +0 -98
  61. package/src/components/DataGrid/utils.tsx +0 -15
  62. package/src/components/DataGridCell.tsx +0 -526
  63. package/src/components/DataTable.tsx +0 -881
  64. package/src/components/DateInput.tsx +0 -306
  65. package/src/components/DateRangeInput.tsx +0 -758
  66. package/src/components/DebugJson.tsx +0 -28
  67. package/src/components/Display.tsx +0 -66
  68. package/src/components/EditingContext.tsx +0 -43
  69. package/src/components/EmptyCartIcon.tsx +0 -18
  70. package/src/components/FilterGroup.tsx +0 -264
  71. package/src/components/FullViewportBox.tsx +0 -19
  72. package/src/components/Grid.tsx +0 -97
  73. package/src/components/Heading.tsx +0 -72
  74. package/src/components/HorizontalDivider.tsx +0 -22
  75. package/src/components/Icon.tsx +0 -39
  76. package/src/components/ImagePlaceholder.tsx +0 -22
  77. package/src/components/Input.tsx +0 -609
  78. package/src/components/InputGroup.tsx +0 -59
  79. package/src/components/Label.tsx +0 -46
  80. package/src/components/Link.tsx +0 -117
  81. package/src/components/List.tsx +0 -18
  82. package/src/components/ListGroup.tsx +0 -82
  83. package/src/components/LiveChatComponent.tsx +0 -56
  84. package/src/components/LoadingScrim.tsx +0 -33
  85. package/src/components/LogoAgilityTopBar.tsx +0 -54
  86. package/src/components/LogoDMSiTopBar.tsx +0 -33
  87. package/src/components/LogoMillworkTopBar.tsx +0 -119
  88. package/src/components/MainBar.tsx +0 -91
  89. package/src/components/MaxViewportBox.tsx +0 -19
  90. package/src/components/Menu.tsx +0 -316
  91. package/src/components/MenuOption.tsx +0 -330
  92. package/src/components/MobileDataGrid/ColumnList.tsx +0 -66
  93. package/src/components/MobileDataGrid/ColumnSelector/index.tsx +0 -97
  94. package/src/components/MobileDataGrid/GridContextProvider/GridContext.tsx +0 -25
  95. package/src/components/MobileDataGrid/GridContextProvider/index.tsx +0 -132
  96. package/src/components/MobileDataGrid/GridContextProvider/useGridContext.ts +0 -10
  97. package/src/components/MobileDataGrid/MobileDataGridCard/MobileDataGridColumn.tsx +0 -27
  98. package/src/components/MobileDataGrid/MobileDataGridCard/index.tsx +0 -138
  99. package/src/components/MobileDataGrid/MobileDataGridHeader.tsx +0 -81
  100. package/src/components/MobileDataGrid/RowDetailModalProvider/ModalContent.tsx +0 -42
  101. package/src/components/MobileDataGrid/RowDetailModalProvider/index.tsx +0 -68
  102. package/src/components/MobileDataGrid/dataGridReducer.ts +0 -55
  103. package/src/components/MobileDataGrid/index.tsx +0 -92
  104. package/src/components/MobileDataGrid/types.ts +0 -4
  105. package/src/components/Modal.tsx +0 -312
  106. package/src/components/ModalButtons.tsx +0 -62
  107. package/src/components/ModalContent.tsx +0 -31
  108. package/src/components/ModalHeader.tsx +0 -78
  109. package/src/components/ModalScrim.tsx +0 -42
  110. package/src/components/NavigationTab.tsx +0 -95
  111. package/src/components/NavigationTabs.tsx +0 -70
  112. package/src/components/NestedMenu.tsx +0 -131
  113. package/src/components/Notification.tsx +0 -128
  114. package/src/components/OptionPill.tsx +0 -139
  115. package/src/components/OrderCheckIcon.tsx +0 -19
  116. package/src/components/PDFViewer/DownloadIcon.tsx +0 -25
  117. package/src/components/PDFViewer/PDFElement.tsx +0 -90
  118. package/src/components/PDFViewer/PDFNavigation.tsx +0 -68
  119. package/src/components/PDFViewer/PDFPage.tsx +0 -34
  120. package/src/components/PDFViewer/index.tsx +0 -128
  121. package/src/components/Pagination.tsx +0 -182
  122. package/src/components/Paragraph.tsx +0 -55
  123. package/src/components/Password.tsx +0 -62
  124. package/src/components/ProductImagePreview/CarouselPagination.tsx +0 -54
  125. package/src/components/ProductImagePreview/MobileImageCarousel.tsx +0 -226
  126. package/src/components/ProductImagePreview/ProductPrimaryImage.tsx +0 -219
  127. package/src/components/ProductImagePreview/Thumbnail.tsx +0 -55
  128. package/src/components/ProductImagePreview/ZoomWindow.tsx +0 -136
  129. package/src/components/ProductImagePreview/index.tsx +0 -182
  130. package/src/components/ProductImagePreview/useProductImagePreview.ts +0 -211
  131. package/src/components/ProjectBar.tsx +0 -82
  132. package/src/components/Radio.tsx +0 -146
  133. package/src/components/Search.tsx +0 -152
  134. package/src/components/SearchResultImage/index.tsx +0 -39
  135. package/src/components/Select.tsx +0 -114
  136. package/src/components/SideMenu.tsx +0 -30
  137. package/src/components/SideMenuGroup.tsx +0 -95
  138. package/src/components/SideMenuItem.tsx +0 -109
  139. package/src/components/SimpleTable.tsx +0 -77
  140. package/src/components/SkeletonParagraph.tsx +0 -31
  141. package/src/components/Spinner.tsx +0 -32
  142. package/src/components/Stack.tsx +0 -347
  143. package/src/components/StatusPill.tsx +0 -59
  144. package/src/components/Stepper.tsx +0 -128
  145. package/src/components/Subheader.tsx +0 -50
  146. package/src/components/Surface.tsx +0 -37
  147. package/src/components/Swatch.tsx +0 -1341
  148. package/src/components/Textarea.tsx +0 -102
  149. package/src/components/Theme.tsx +0 -27
  150. package/src/components/Time.tsx +0 -460
  151. package/src/components/Toast.tsx +0 -268
  152. package/src/components/Tooltip.tsx +0 -159
  153. package/src/components/TopBar.tsx +0 -139
  154. package/src/components/Upload.tsx +0 -107
  155. package/src/components/WorldpayIframe.tsx +0 -7
  156. package/src/components/index.ts +0 -34
  157. package/src/components/useMenuSystem.tsx +0 -456
  158. package/src/components/useMounted.tsx +0 -14
  159. package/src/darkmode.css +0 -278
  160. package/src/fonts.css +0 -23
  161. package/src/hooks/index.ts +0 -4
  162. package/src/hooks/useInfiniteScroll.tsx +0 -40
  163. package/src/hooks/useKeydown.ts +0 -42
  164. package/src/hooks/useMatchesMedia.ts +0 -18
  165. package/src/hooks/useTableLayout.ts +0 -106
  166. package/src/index.css +0 -800
  167. package/src/index.tsx +0 -5
  168. package/src/types.ts +0 -150
  169. package/src/utils/date.ts +0 -236
  170. package/src/utils/formatting.tsx +0 -81
  171. package/src/utils/index.ts +0 -4
  172. package/src/utils/mergeObjectArrays.ts +0 -18
  173. package/src/utils.ts +0 -24
  174. package/dist/{chunk-7FQ7PGUF.js → chunk-7COWXCPA.js} +3 -3
  175. package/dist/{chunk-NKCFYM7A.js → chunk-7SFFUICM.js} +3 -3
  176. package/dist/{chunk-25RZP3VR.js → chunk-AKJUBFJK.js} +3 -3
  177. package/dist/{chunk-TAPYQBQU.js → chunk-CMMQTIVM.js} +3 -3
  178. package/dist/{chunk-GYEXSNFP.js → chunk-FWCVZWE6.js} +3 -3
  179. package/dist/{chunk-MV6W7OMC.js → chunk-QMMPHXVE.js} +3 -3
  180. package/dist/{chunk-GG5OZTI5.js → chunk-XRE52QTN.js} +3 -3
@@ -1,316 +0,0 @@
1
- "use client";
2
-
3
- import clsx from "clsx";
4
- import {
5
- ComponentProps,
6
- ReactNode,
7
- RefObject,
8
- useEffect,
9
- useRef,
10
- useState,
11
- } from "react";
12
- import { createPortal } from "react-dom";
13
- import { useMenuPosition } from "./useMenuSystem";
14
- import { findDocumentRoot } from "../utils";
15
- import { useMatchesMobile } from "../hooks";
16
-
17
- export type MenuPosition = "right" | "bottom" | "bottom-right";
18
-
19
- type MenuProps = {
20
- id?: string;
21
- testid?: string;
22
- positionTo?: RefObject<HTMLElement | null>;
23
- mobilePositionTo?: RefObject<HTMLElement | null>;
24
- show?: boolean;
25
- setShow?: (value: boolean) => void;
26
- position?: MenuPosition;
27
- maxHeight?: string;
28
- topOffset?: number | null;
29
- mobileBackMenuOption?: () => ReactNode;
30
- mobileHide?: boolean;
31
- useDefaultMinWidth?: boolean;
32
- autoFocusOff?: boolean;
33
- menuName?: string;
34
- calculateMinMaxHeight?: boolean;
35
- };
36
-
37
- export const Menu = ({
38
- id,
39
- testid,
40
- children,
41
- className,
42
- ref,
43
- positionTo,
44
- mobilePositionTo,
45
- show,
46
- setShow,
47
- position = "bottom",
48
- maxHeight: customMaxHeight,
49
- topOffset,
50
- mobileBackMenuOption,
51
- mobileHide,
52
- useDefaultMinWidth,
53
- autoFocusOff,
54
- menuName,
55
- calculateMinMaxHeight,
56
- ...props
57
- }: ComponentProps<"div"> & MenuProps) => {
58
- const internalRef = useRef<HTMLDivElement>(null);
59
- const actualRef = (ref || internalRef) as RefObject<HTMLDivElement>;
60
- const [maxHeight, setMaxHeight] = useState("180px");
61
- const isMobile = useMatchesMobile();
62
- const { menuPosition, updatePosition } = useMenuPosition(
63
- isMobile && mobilePositionTo ? mobilePositionTo! : positionTo!,
64
- position,
65
- {
66
- isOpen: show,
67
- setIsOpen: setShow,
68
- menuRef: internalRef,
69
- topOffset,
70
- isMobile: !!(isMobile && mobilePositionTo)
71
- },
72
- );
73
-
74
- useEffect(() => {
75
- if (calculateMinMaxHeight) {
76
- return;
77
- }
78
-
79
- const raf = requestAnimationFrame(() => {
80
- if (!actualRef.current || customMaxHeight) {
81
- return;
82
- }
83
-
84
- if (actualRef.current.childElementCount > 4) {
85
- let accumulatedHeight = 0;
86
-
87
- Array.from(actualRef.current.children).forEach((child, index) => {
88
- if (index >= 5) {
89
- return;
90
- }
91
-
92
- accumulatedHeight += child.clientHeight;
93
- });
94
-
95
- accumulatedHeight = (accumulatedHeight / 5) * 4.5; // default max height is set to 4.5 times of the first 5 child height of the menu
96
-
97
- setMaxHeight(`${accumulatedHeight}px`);
98
- }
99
- });
100
-
101
- return () => {
102
- cancelAnimationFrame(raf);
103
- };
104
- }, [actualRef.current, customMaxHeight, calculateMinMaxHeight]);
105
-
106
- useEffect(() => {
107
- if (!calculateMinMaxHeight) {
108
- return;
109
- }
110
-
111
- if (positionTo?.current && actualRef.current) {
112
- const positionToRect = positionTo.current.getBoundingClientRect();
113
- const offsetInPx = 16;
114
-
115
- const calculatedMaxHeight = window.innerHeight - positionToRect.bottom - offsetInPx;
116
-
117
- setMaxHeight(`${calculatedMaxHeight}px`);
118
- }
119
- }, [actualRef.current, positionTo?.current, calculateMinMaxHeight])
120
-
121
- useEffect(() => {
122
- if (!show) {
123
- return;
124
- }
125
-
126
- initializeMenuFocus();
127
- updatePosition();
128
- }, [show, updatePosition]);
129
-
130
- useEffect(() => {
131
- if (!show || !setShow) {
132
- return;
133
- }
134
-
135
- const handleEscapeKey = (event: KeyboardEvent) => {
136
- if (event.key !== "Escape") {
137
- return;
138
- }
139
-
140
- setShow(false);
141
- positionTo?.current?.focus();
142
- };
143
-
144
- document.addEventListener("keydown", handleEscapeKey);
145
-
146
- return () => {
147
- document.removeEventListener("keydown", handleEscapeKey);
148
- };
149
- }, [show, setShow, positionTo]);
150
-
151
- return (
152
- show &&
153
- createPortal(
154
- <div
155
- id={id}
156
- data-testid={testid}
157
- ref={setRefs}
158
- className={clsx(
159
- "shadow-4 rounded-base bg-background-grouped-primary-normal overflow-x-hidden overflow-y-auto flex flex-col outline-0",
160
- "fixed",
161
- "z-50",
162
- "max-w-screen",
163
- mobileHide && "opacity-0 pointer-events-none",
164
- className,
165
- )}
166
- {...props}
167
- style={{
168
- ...props.style,
169
- maxHeight: customMaxHeight || maxHeight,
170
- ...menuPosition,
171
- minWidth: useDefaultMinWidth ? "212px" : menuPosition.minWidth,
172
- }}
173
- onKeyDown={handleKeydown}
174
- onMouseDown={stopPropagation}
175
- onMouseUp={stopPropagation}
176
- onTouchStart={stopPropagation}
177
- onTouchEnd={stopPropagation}
178
- tabIndex={-1}
179
- data-menu={menuName ?? ""}
180
- >
181
- {mobileBackMenuOption?.()}
182
-
183
- {children}
184
- </div>,
185
- findDocumentRoot(internalRef.current),
186
- )
187
- );
188
-
189
- function handleKeydown(e: React.KeyboardEvent<HTMLDivElement>): void {
190
- if (!internalRef.current) {
191
- return;
192
- }
193
-
194
- if (e.key !== "Escape") {
195
- e.stopPropagation();
196
- }
197
-
198
- const menuOptions = Array.from(
199
- internalRef.current.querySelectorAll('[role="menuitem"]'),
200
- ) as HTMLElement[];
201
-
202
- if (menuOptions.length === 0) {
203
- return;
204
- }
205
-
206
- let currentIndex = -1;
207
- const focusedElement = document.activeElement;
208
-
209
- for (let i = 0; i < menuOptions.length; i++) {
210
- if (menuOptions[i] === focusedElement) {
211
- currentIndex = i;
212
- break;
213
- }
214
- }
215
-
216
- switch (e.key) {
217
- case "ArrowDown": {
218
- e.preventDefault();
219
- const nextIndex =
220
- currentIndex < menuOptions.length - 1 ? currentIndex + 1 : 0;
221
- menuOptions[nextIndex].focus();
222
- break;
223
- }
224
-
225
- case "ArrowUp": {
226
- e.preventDefault();
227
- const prevIndex =
228
- currentIndex > 0 ? currentIndex - 1 : menuOptions.length - 1;
229
- menuOptions[prevIndex].focus();
230
- break;
231
- }
232
-
233
- case "Home":
234
- e.preventDefault();
235
- menuOptions[0].focus();
236
- break;
237
-
238
- case "End":
239
- e.preventDefault();
240
- menuOptions[menuOptions.length - 1].focus();
241
- break;
242
-
243
- case "Enter":
244
- case " ":
245
- case "ArrowRight":
246
- e.preventDefault();
247
-
248
- if (currentIndex >= 0) {
249
- menuOptions[currentIndex].click();
250
- }
251
-
252
- break;
253
-
254
- case "ArrowLeft":
255
- e.preventDefault();
256
- positionTo?.current?.click();
257
- positionTo?.current?.focus();
258
-
259
- break;
260
- }
261
- }
262
-
263
- function initializeMenuFocus() {
264
- if (!autoFocusOff) {
265
- internalRef.current?.focus();
266
- }
267
-
268
- const selectedOption = internalRef.current?.querySelector(
269
- "[data-selected]",
270
- ) as HTMLElement | null;
271
-
272
- // Get the first menu item (not submenu wrapper)
273
- const firstMenuItem = internalRef.current?.querySelector(
274
- '[role="menuitem"]',
275
- ) as HTMLElement | null;
276
-
277
- const targetElement = selectedOption || firstMenuItem;
278
-
279
- if (!targetElement) {
280
- return;
281
- }
282
-
283
- targetElement.scrollIntoView({
284
- block: "nearest",
285
- behavior: "instant",
286
- });
287
-
288
- if (autoFocusOff) {
289
- return;
290
- }
291
-
292
- requestAnimationFrame(() => {
293
- targetElement.focus();
294
- });
295
- }
296
-
297
- function setRefs(node: HTMLDivElement | null) {
298
- internalRef.current = node;
299
-
300
- if (ref) {
301
- if (typeof ref === "function") {
302
- ref(node);
303
- } else {
304
- ref.current = node;
305
- }
306
- }
307
- }
308
-
309
- function stopPropagation(
310
- e: React.MouseEvent<HTMLDivElement> | React.TouchEvent<HTMLDivElement>,
311
- ) {
312
- e.stopPropagation();
313
- }
314
- };
315
-
316
- Menu.displayName = "Menu";
@@ -1,330 +0,0 @@
1
- "use client";
2
-
3
- import clsx from "clsx";
4
- import { PropsWithChildren, ReactNode, RefObject, useId, useRef, useState } from "react";
5
- import { baseTransition, componentGap, componentPadding, layoutGroupGap } from "../classNames";
6
- import { AsProps } from "../types";
7
- import { Label, Tags } from "./Label";
8
- import { Paragraph } from "./Paragraph";
9
- import { Icon } from "./Icon";
10
- import { MenuPosition } from "./Menu";
11
- import { useMatchesMobile } from "../hooks";
12
- import { Caption } from "./Caption";
13
-
14
- type BaseProps = PropsWithChildren<{
15
- id?: string;
16
- testid?: string;
17
- disabled?: boolean;
18
- value?: string;
19
- before?: ReactNode;
20
- after?: ReactNode;
21
- onClick?: (id: string, value?: string) => void;
22
- ref?: React.Ref<HTMLDivElement> | undefined;
23
- mobilePositionTo?: RefObject<HTMLElement | null>;
24
- selected?: boolean;
25
- currentSubMenuLevel?: number | null;
26
- small?: boolean;
27
- }> &
28
- (
29
- | {
30
- subMenu: (props: {
31
- menuId: string;
32
- positionTo?: RefObject<HTMLDivElement>;
33
- mobilePositionTo?: RefObject<HTMLElement | null>;
34
- position?: MenuPosition;
35
- subMenuLevel: number;
36
- mobileBackMenuOption?: () => ReactNode;
37
- mobileHide?: boolean;
38
- autoFocusOff?: boolean;
39
- }) => ReactNode;
40
- subMenuLevel?: number;
41
- onSubMenuHover: (menuId: string, level: number) => void;
42
- onSubMenuLeave: (level: number) => void;
43
- onSubMenuEnter: () => void;
44
- onMouseMove: () => void;
45
- toggleMenu: (id: string, level: number) => void;
46
- activeMenu: string;
47
- closeSubMenuLevel: (level: number) => void;
48
- }
49
- | {
50
- subMenu?: undefined;
51
- subMenuLevel?: number;
52
- onSubMenuHover?: (menuId: string, level: number) => void;
53
- onSubMenuLeave?: (level: number) => void;
54
- onSubMenuEnter?: () => void;
55
- onMouseMove?: () => void;
56
- toggleMenu?: (id: string, level: number) => void;
57
- closeSubMenuLevel?: (level: number) => void;
58
- activeMenu?: string;
59
- }
60
- ) &
61
- (
62
- | {
63
- highlightMatchingText: true;
64
- menuValue: string;
65
- }
66
- | {
67
- highlightMatchingText?: false | undefined;
68
- menuValue?: string;
69
- }
70
- );
71
-
72
- type ActionProps = BaseProps & {
73
- variant: "action";
74
- } & AsProps<Tags>;
75
-
76
- type NormalProps = BaseProps & {
77
- variant?: "normal";
78
- };
79
-
80
- type MenuOptionProps = ActionProps | NormalProps;
81
-
82
- export const MenuOption = ({
83
- id,
84
- testid,
85
- children,
86
- disabled = false,
87
- variant = "normal",
88
- value,
89
- before,
90
- after,
91
- subMenu,
92
- onClick,
93
- selected,
94
- ref,
95
- onSubMenuHover,
96
- onSubMenuLeave,
97
- onSubMenuEnter,
98
- toggleMenu,
99
- subMenuLevel = 1,
100
- currentSubMenuLevel,
101
- closeSubMenuLevel,
102
- activeMenu,
103
- mobilePositionTo,
104
- highlightMatchingText = false,
105
- menuValue,
106
- onMouseMove,
107
- small = false,
108
- }: MenuOptionProps) => {
109
- const uniqueId = useId();
110
- const internalRef = useRef(null);
111
- const actualRef = (ref || internalRef) as RefObject<HTMLDivElement>;
112
- const menuId = useRef(`menu-${uniqueId}`);
113
- const isMobile = useMatchesMobile();
114
- const [isSubMenuHovered, setIsSubMenuHovered] = useState(false);
115
-
116
- const handleMouseEnter = () => {
117
- if (subMenu && onSubMenuHover && !disabled) {
118
- onSubMenuHover(menuId.current, subMenuLevel);
119
- }
120
- };
121
-
122
- const handleMouseLeave = () => {
123
- if (subMenu && onSubMenuLeave && !disabled) {
124
- onSubMenuLeave(subMenuLevel);
125
- }
126
-
127
- setIsSubMenuHovered(false);
128
- };
129
-
130
- const handleMouseMove = () => {
131
- if (subMenu && onMouseMove && !disabled) {
132
- onMouseMove();
133
- }
134
- }
135
-
136
- const handleSubMenuEnter = () => {
137
- if (onSubMenuEnter) {
138
- onSubMenuEnter();
139
- }
140
- setIsSubMenuHovered(true);
141
- };
142
-
143
- const additionalAttributes = {
144
- "data-selected": selected || null,
145
- "data-submenu-hovered": isSubMenuHovered || null,
146
- };
147
-
148
- const svgStyles = clsx(
149
- "[&>svg]:shrink-0 [&>svg]:fill-icon-action-primary-normal",
150
- );
151
-
152
- const textLabelStyles = clsx("w-full whitespace-nowrap !leading-6");
153
-
154
- const normalStyles =
155
- variant === "normal" &&
156
- !disabled &&
157
- clsx(
158
- "bg-transparent text-text-primary-normal",
159
- "hover:bg-background-action-secondary-hover",
160
- "focus-visible:bg-background-action-secondary-hover",
161
- "data-selected:bg-background-action-secondary-hover",
162
- "data-submenu-hovered:bg-background-action-secondary-hover",
163
- "active:bg-background-action-secondary-active",
164
- );
165
-
166
- const normalDisabledStyles =
167
- variant === "normal" && disabled && clsx("text-text-primary-disabled");
168
-
169
- const actionStyles =
170
- variant === "action" &&
171
- !disabled &&
172
- clsx(
173
- "text-action-400 bg-transparent",
174
- "hover:bg-background-action-secondary-hover hover:text-text-action-hover",
175
- "focus-visible:bg-background-action-secondary-hover focus-visible:text-text-action-hover",
176
- "data-selected:bg-background-action-secondary-active data-selected:text-text-action-active",
177
- "data-submenu-hovered:bg-background-action-secondary-active data-submenu-hovered:text-text-action-active",
178
- "active:bg-background-action-secondary-active active:text-text-action-active",
179
- );
180
-
181
- const actionDisabledStyles =
182
- variant === "action" && disabled && clsx("text-text-action-disabled");
183
-
184
- const disabledStyles =
185
- disabled && clsx("bg-transparent cursor-default pointer-events-none");
186
-
187
- const processChildren =
188
- typeof children === "string" && highlightMatchingText
189
- ? highlightMatch(children, menuValue)
190
- : children;
191
-
192
- const renderChildren =
193
- typeof children === "object" ? (
194
- children
195
- ) : variant === "action" ? (
196
- <Label padded className={textLabelStyles}>
197
- {processChildren}
198
- </Label>
199
- ) : (
200
- !small ? (
201
- <Paragraph padded className={textLabelStyles}>
202
- {processChildren}
203
- </Paragraph>
204
- ) : (
205
- <Caption padded className={textLabelStyles}>
206
- {processChildren}
207
- </Caption>
208
- )
209
- );
210
-
211
- return (
212
- <>
213
- <div
214
- id={id}
215
- data-testid={testid}
216
- ref={actualRef}
217
- className={clsx(
218
- "flex cursor-pointer w-full text-left relative outline-none",
219
- svgStyles,
220
- small ? layoutGroupGap : componentGap,
221
- componentPadding,
222
- baseTransition,
223
- normalStyles,
224
- normalDisabledStyles,
225
- actionStyles,
226
- actionDisabledStyles,
227
- disabledStyles,
228
- { "items-center": !small },
229
- )}
230
- data-value={value || children}
231
- onClick={() => {
232
- onClick?.(menuId.current, (value || children) as string);
233
- if (subMenu) {
234
- toggleMenu(menuId.current, subMenuLevel);
235
- }
236
- }}
237
- onMouseEnter={handleMouseEnter}
238
- onMouseLeave={handleMouseLeave}
239
- onMouseMove={handleMouseMove}
240
- {...additionalAttributes}
241
- tabIndex={-1}
242
- role="menuitem"
243
- aria-haspopup={subMenu ? "menu" : undefined}
244
- >
245
- {before && <div className={clsx("shrink-0", { "items-center flex": !small })}>{before}</div>}
246
-
247
- {renderChildren}
248
-
249
- {renderAfterProp()}
250
- </div>
251
-
252
- {subMenu && (
253
- <div
254
- onMouseEnter={handleSubMenuEnter}
255
- onMouseLeave={() => {
256
- handleMouseLeave();
257
- setIsSubMenuHovered(false);
258
- }}
259
- data-submenu-parent={menuId.current}
260
- data-menu-level={subMenuLevel + 1}
261
- >
262
- {subMenu({
263
- menuId: menuId.current,
264
- positionTo: actualRef,
265
- mobilePositionTo,
266
- position: "right",
267
- subMenuLevel,
268
- mobileBackMenuOption,
269
- mobileHide: isMobile && activeMenu !== menuId.current,
270
- autoFocusOff: true,
271
- })}
272
- </div>
273
- )}
274
- </>
275
- );
276
-
277
- function renderAfterProp() {
278
- if (after) {
279
- return after;
280
- }
281
-
282
- if (subMenu && after !== null) {
283
- return <Icon name="chevron_right" />;
284
- }
285
- }
286
-
287
- function mobileBackMenuOption() {
288
- if (!isMobile) {
289
- return;
290
- }
291
-
292
- return (
293
- <MenuOption
294
- id={id ? `${id}-back` : undefined}
295
- testid={testid ? `${testid}-back` : undefined}
296
- onClick={() => {
297
- closeSubMenuLevel?.(currentSubMenuLevel ?? 0);
298
- }}
299
- variant="action"
300
- before={<Icon name="chevron_left" />}
301
- >
302
- Back
303
- </MenuOption>
304
- );
305
- }
306
- };
307
-
308
- MenuOption.displayName = "MenuOption";
309
-
310
- function highlightMatch(text: string, searchValue?: string): React.ReactNode {
311
- if (!searchValue || !searchValue.trim()) {
312
- return text;
313
- }
314
-
315
- const regex = new RegExp(
316
- `(${searchValue.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")})`,
317
- "gi",
318
- );
319
- const parts = text.split(regex);
320
-
321
- return parts.map((part, index) =>
322
- regex.test(part) ? (
323
- <span key={index} className="font-bold">
324
- {part}
325
- </span>
326
- ) : (
327
- part
328
- ),
329
- );
330
- }
@@ -1,66 +0,0 @@
1
- import clsx from "clsx";
2
- import { useGridContext } from "./GridContextProvider/useGridContext";
3
- import { MobileDataGridCard } from "./MobileDataGridCard";
4
- import { GridContextType } from "./GridContextProvider/GridContext";
5
- import { RowActions } from "./types";
6
-
7
- type ColumnListProps<T> = {
8
- withBorder?: boolean;
9
- renderLink?: (data: T) => React.ReactNode;
10
- renderChevron?: boolean;
11
- enableRowSelection?: boolean;
12
- footer?: (ctx: GridContextType<T>) => React.ReactNode;
13
- rowActions?: RowActions<T>;
14
- };
15
- export function ColumnList<T extends Record<string, unknown>>(
16
- props: ColumnListProps<T>,
17
- ) {
18
- const {
19
- withBorder,
20
- renderLink,
21
- renderChevron,
22
- footer: Footer,
23
- enableRowSelection,
24
- rowActions,
25
- } = props;
26
- const ctx = useGridContext<T>();
27
- const { id, testid, data, getId, selectedRowIds } = ctx;
28
- return (
29
- <div
30
- className={clsx(
31
- "flex flex-col flex-1 relative overflow-y-auto overflow-x-hidden",
32
- !!Footer && "mb-20",
33
- )}
34
- >
35
- <ul
36
- id={id}
37
- data-testid={testid}
38
- className={clsx(
39
- "rounded absolute top-0 left-0 w-full flex-1",
40
- "divide-y divide-border-primary-normal",
41
- withBorder && "border border-border-primary-normal",
42
- )}
43
- >
44
- {data.map((item) => {
45
- const id = getId(item);
46
- return (
47
- <MobileDataGridCard
48
- data={item}
49
- key={id}
50
- renderLink={renderLink}
51
- enableRowSelection={enableRowSelection}
52
- selected={!!id && selectedRowIds.includes(id)}
53
- renderChevron={renderChevron}
54
- rowActions={rowActions}
55
- />
56
- );
57
- })}
58
- {!!Footer && (
59
- <div className="fixed left-0 right-0 bottom-0 flex flex-col w-full min-h-20">
60
- <Footer {...ctx} />
61
- </div>
62
- )}
63
- </ul>
64
- </div>
65
- );
66
- }