@react-fabric/core 1.0.0-beta.62 → 1.0.0-beta.63

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 (305) hide show
  1. package/css/components/_animations.css +7 -11
  2. package/css/components/_avatar.css +5 -5
  3. package/css/components/_badge.css +2 -1
  4. package/css/components/_breadcrumbs.css +5 -5
  5. package/css/components/_button.css +48 -14
  6. package/css/components/_card.css +9 -17
  7. package/css/components/_chip.css +0 -4
  8. package/css/components/_dropdown.css +1 -0
  9. package/css/components/_flyout.css +1 -1
  10. package/css/components/_media.css +2 -14
  11. package/css/components/_menu.css +1 -1
  12. package/css/components/_modal.css +1 -1
  13. package/css/components/_progress.css +1 -1
  14. package/css/components/_stepper.css +2 -1
  15. package/css/components/_tabPanel.css +4 -4
  16. package/css/core/_aside.css +3 -3
  17. package/css/core/_errorboundary.css +2 -10
  18. package/css/core/_page.css +1 -1
  19. package/css/core/_responsive.css +8 -0
  20. package/css/core/_viewport.css +1 -5
  21. package/css/reset/_reset.css +36 -41
  22. package/css/reset/_theme.css +214 -201
  23. package/css/styles.css +5 -0
  24. package/css/theme/_colors.css +14 -0
  25. package/css/theme/_utilities.css +103 -225
  26. package/css/theme/index.css +4 -6
  27. package/dist/cjs/components/actionLabel/ActionLabel.js +1 -1
  28. package/dist/cjs/components/animations/Animations.js +7 -7
  29. package/dist/cjs/components/avatar/Avatar.js +1 -1
  30. package/dist/cjs/components/avatar/AvatarGroup.js +1 -1
  31. package/dist/cjs/components/badge/Badge.js +5 -27
  32. package/dist/cjs/components/breadcrumbs/Breadcrumbs.js +1 -1
  33. package/dist/cjs/components/button/Button.js +7 -5
  34. package/dist/cjs/components/button/ButtonGroup.js +1 -1
  35. package/dist/cjs/components/button/ConfirmButton.js +7 -6
  36. package/dist/cjs/components/button/ToggleButtonGroup.js +1 -1
  37. package/dist/cjs/components/callout/Callout.js +8 -7
  38. package/dist/cjs/components/card/Card.js +3 -3
  39. package/dist/cjs/components/card/CardCover.js +1 -1
  40. package/dist/cjs/components/card/FlipContent.js +2 -2
  41. package/dist/cjs/components/chip/Chip.js +8 -7
  42. package/dist/cjs/components/collapsable/Collapsable.js +4 -3
  43. package/dist/cjs/components/divider/Divider.js +2 -2
  44. package/dist/cjs/components/dropdown/Dropdown.js +18 -16
  45. package/dist/cjs/components/empty/EmptyContent.js +1 -1
  46. package/dist/cjs/components/icon/Icon.js +2 -16
  47. package/dist/cjs/components/media/Media.js +13 -13
  48. package/dist/cjs/components/menu/ContextMenu.js +23 -13
  49. package/dist/cjs/components/menu/Menu.js +16 -12
  50. package/dist/cjs/components/menu/MenuItem.js +4 -3
  51. package/dist/cjs/components/meter/Meter.js +1 -1
  52. package/dist/cjs/components/navigator/Navigator.js +5 -5
  53. package/dist/cjs/components/panel/Panel.js +6 -4
  54. package/dist/cjs/components/panel/PanelGroup.js +3 -3
  55. package/dist/cjs/components/panel/PanelStack.js +5 -5
  56. package/dist/cjs/components/progress/ProgressBar.js +2 -2
  57. package/dist/cjs/components/progress/ProgressCircle.js +2 -2
  58. package/dist/cjs/components/tabpanel/Tab.js +6 -4
  59. package/dist/cjs/components/tabpanel/TabPanel.js +4 -4
  60. package/dist/cjs/context/Global.js +2 -55
  61. package/dist/cjs/context/NotificationCenter.js +38 -39
  62. package/dist/cjs/context/context.js +59 -0
  63. package/dist/cjs/core/aside/Aside.js +9 -7
  64. package/dist/cjs/core/boundary/ErrorBoundary.js +2 -4
  65. package/dist/cjs/core/page/Page.js +4 -1
  66. package/dist/cjs/core/responsive/Responsive.js +3 -2
  67. package/dist/cjs/core/theme/ThemeProvider.js +2 -2
  68. package/dist/cjs/core/viewport/Viewport.js +1 -1
  69. package/dist/cjs/hooks/useContextMenu.js +103 -0
  70. package/dist/cjs/hooks/useIsDark.js +6 -4
  71. package/dist/cjs/hooks/useNavigator.js +2 -2
  72. package/dist/cjs/hooks/useOverlayService.js +10 -42
  73. package/dist/cjs/hooks/usePropToggle.js +2 -2
  74. package/dist/cjs/hooks/useResize.js +8 -6
  75. package/dist/cjs/hooks/useResizeObserver.js +5 -5
  76. package/dist/cjs/hooks/useStepper.js +2 -6
  77. package/dist/cjs/hotkeys/HotKey.js +2 -2
  78. package/dist/cjs/hotkeys/HotKeyWrapper.js +8 -13
  79. package/dist/cjs/hotkeys/commons.js +1 -1
  80. package/dist/cjs/hotkeys/context.js +36 -0
  81. package/dist/cjs/index.js +9 -5
  82. package/dist/cjs/overlays/alert/Alert.js +6 -5
  83. package/dist/cjs/overlays/flyout/Flyout.js +8 -6
  84. package/dist/cjs/overlays/message/Message.js +5 -5
  85. package/dist/cjs/overlays/modal/Modal.js +5 -3
  86. package/dist/cjs/overlays/toast/Toast.js +4 -4
  87. package/dist/cjs/overlays/tooltip/Tooltip.js +2 -16
  88. package/dist/cjs/typography/Abbr.js +4 -5
  89. package/dist/cjs/typography/Anchor.js +2 -2
  90. package/dist/cjs/typography/Copy.js +2 -2
  91. package/dist/cjs/typography/Mark.js +2 -4
  92. package/dist/cjs/typography/Text.js +4 -4
  93. package/dist/cjs/typography/Title.js +2 -2
  94. package/dist/cjs/utils/cloneElement.js +4 -4
  95. package/dist/cjs/utils/getBadgeProps.js +51 -0
  96. package/dist/cjs/utils/getIconProps.js +42 -0
  97. package/dist/cjs/utils/getTooltipProps.js +45 -0
  98. package/dist/esm/components/actionLabel/ActionLabel.js +1 -1
  99. package/dist/esm/components/animations/Animations.js +7 -7
  100. package/dist/esm/components/avatar/Avatar.js +1 -1
  101. package/dist/esm/components/avatar/AvatarGroup.js +1 -1
  102. package/dist/esm/components/badge/Badge.js +7 -28
  103. package/dist/esm/components/breadcrumbs/Breadcrumbs.js +1 -1
  104. package/dist/esm/components/button/Button.js +8 -6
  105. package/dist/esm/components/button/ButtonGroup.js +3 -3
  106. package/dist/esm/components/button/ConfirmButton.js +8 -7
  107. package/dist/esm/components/button/ToggleButtonGroup.js +3 -3
  108. package/dist/esm/components/callout/Callout.js +8 -7
  109. package/dist/esm/components/card/Card.js +4 -4
  110. package/dist/esm/components/card/CardCover.js +1 -1
  111. package/dist/esm/components/card/FlipContent.js +2 -2
  112. package/dist/esm/components/chip/Chip.js +9 -8
  113. package/dist/esm/components/collapsable/Collapsable.js +4 -3
  114. package/dist/esm/components/divider/Divider.js +2 -2
  115. package/dist/esm/components/dropdown/Dropdown.js +19 -17
  116. package/dist/esm/components/empty/EmptyContent.js +1 -1
  117. package/dist/esm/components/icon/Icon.js +4 -17
  118. package/dist/esm/components/media/Media.js +13 -13
  119. package/dist/esm/components/menu/ContextMenu.js +24 -14
  120. package/dist/esm/components/menu/Menu.js +19 -15
  121. package/dist/esm/components/menu/MenuItem.js +5 -4
  122. package/dist/esm/components/meter/Meter.js +1 -1
  123. package/dist/esm/components/navigator/Navigator.js +6 -6
  124. package/dist/esm/components/panel/Panel.js +6 -4
  125. package/dist/esm/components/panel/PanelGroup.js +4 -4
  126. package/dist/esm/components/panel/PanelStack.js +6 -6
  127. package/dist/esm/components/progress/ProgressBar.js +2 -2
  128. package/dist/esm/components/progress/ProgressCircle.js +2 -2
  129. package/dist/esm/components/tabpanel/Tab.js +6 -4
  130. package/dist/esm/components/tabpanel/TabPanel.js +5 -5
  131. package/dist/esm/context/Global.js +3 -52
  132. package/dist/esm/context/NotificationCenter.js +38 -39
  133. package/dist/esm/context/context.js +56 -0
  134. package/dist/esm/core/aside/Aside.js +10 -8
  135. package/dist/esm/core/boundary/ErrorBoundary.js +1 -3
  136. package/dist/esm/core/page/Page.js +4 -1
  137. package/dist/esm/core/responsive/Responsive.js +3 -2
  138. package/dist/esm/core/theme/ThemeProvider.js +1 -1
  139. package/dist/esm/core/viewport/Viewport.js +1 -1
  140. package/dist/esm/hooks/useContextMenu.js +103 -0
  141. package/dist/esm/hooks/useIsDark.js +7 -5
  142. package/dist/esm/hooks/useNavigator.js +3 -3
  143. package/dist/esm/hooks/useOverlayService.js +8 -40
  144. package/dist/esm/hooks/usePropToggle.js +3 -3
  145. package/dist/esm/hooks/useResize.js +9 -7
  146. package/dist/esm/hooks/useResizeObserver.js +6 -6
  147. package/dist/esm/hooks/useStepper.js +2 -6
  148. package/dist/esm/hotkeys/HotKey.js +1 -1
  149. package/dist/esm/hotkeys/HotKeyWrapper.js +9 -12
  150. package/dist/esm/hotkeys/commons.js +1 -1
  151. package/dist/esm/hotkeys/context.js +35 -0
  152. package/dist/esm/index.js +7 -3
  153. package/dist/esm/overlays/alert/Alert.js +7 -6
  154. package/dist/esm/overlays/flyout/Flyout.js +9 -7
  155. package/dist/esm/overlays/message/Message.js +6 -6
  156. package/dist/esm/overlays/modal/Modal.js +6 -4
  157. package/dist/esm/overlays/toast/Toast.js +5 -5
  158. package/dist/esm/overlays/tooltip/Tooltip.js +4 -17
  159. package/dist/esm/typography/Abbr.js +4 -5
  160. package/dist/esm/typography/Anchor.js +2 -2
  161. package/dist/esm/typography/Copy.js +3 -3
  162. package/dist/esm/typography/Mark.js +2 -4
  163. package/dist/esm/typography/Text.js +5 -5
  164. package/dist/esm/typography/Title.js +2 -2
  165. package/dist/esm/utils/cloneElement.js +4 -4
  166. package/dist/esm/utils/getBadgeProps.js +51 -0
  167. package/dist/esm/utils/getIconProps.js +42 -0
  168. package/dist/esm/utils/getTooltipProps.js +45 -0
  169. package/dist/types/components/actionLabel/ActionLabel.d.ts +1 -1
  170. package/dist/types/components/animations/Animations.d.ts +6 -6
  171. package/dist/types/components/avatar/Avatar.d.ts +1 -1
  172. package/dist/types/components/avatar/AvatarGroup.d.ts +1 -1
  173. package/dist/types/components/badge/Badge.d.ts +2 -10
  174. package/dist/types/components/breadcrumbs/Breadcrumbs.d.ts +1 -1
  175. package/dist/types/components/button/Button.d.ts +1 -1
  176. package/dist/types/components/button/ButtonGroup.d.ts +1 -1
  177. package/dist/types/components/button/ConfirmButton.d.ts +1 -1
  178. package/dist/types/components/button/ToggleButtonGroup.d.ts +1 -1
  179. package/dist/types/components/callout/Callout.d.ts +7 -3
  180. package/dist/types/components/card/Card.d.ts +2 -2
  181. package/dist/types/components/card/CardCover.d.ts +1 -1
  182. package/dist/types/components/card/FlipContent.d.ts +1 -1
  183. package/dist/types/components/chip/Chip.d.ts +1 -1
  184. package/dist/types/components/collapsable/Collapsable.d.ts +1 -1
  185. package/dist/types/components/divider/Divider.d.ts +1 -1
  186. package/dist/types/components/dropdown/Dropdown.d.ts +7 -3
  187. package/dist/types/components/dropdown/DropdownTool.d.ts +1 -1
  188. package/dist/types/components/empty/EmptyContent.d.ts +3 -3
  189. package/dist/types/components/icon/Icon.d.ts +3 -4
  190. package/dist/types/components/index.d.ts +2 -2
  191. package/dist/types/components/media/Media.d.ts +2 -2
  192. package/dist/types/components/menu/ContextMenu.d.ts +1 -1
  193. package/dist/types/components/menu/Menu.d.ts +1 -1
  194. package/dist/types/components/menu/types.d.ts +1 -1
  195. package/dist/types/components/meter/Meter.d.ts +1 -1
  196. package/dist/types/components/navigator/Navigator.d.ts +1 -1
  197. package/dist/types/components/panel/Panel.d.ts +2 -2
  198. package/dist/types/components/panel/PanelGroup.d.ts +1 -1
  199. package/dist/types/components/panel/PanelStack.d.ts +1 -1
  200. package/dist/types/components/progress/ProgressBar.d.ts +1 -1
  201. package/dist/types/components/progress/ProgressCircle.d.ts +1 -1
  202. package/dist/types/components/tabpanel/Tab.d.ts +1 -1
  203. package/dist/types/components/tabpanel/TabPanel.d.ts +1 -1
  204. package/dist/types/context/Global.d.ts +0 -82
  205. package/dist/types/context/context.d.ts +85 -0
  206. package/dist/types/core/aside/Aside.d.ts +2 -2
  207. package/dist/types/core/responsive/Responsive.d.ts +5 -1
  208. package/dist/types/hooks/useContextMenu.d.ts +10 -0
  209. package/dist/types/hotkeys/HotKeyWrapper.d.ts +0 -9
  210. package/dist/types/hotkeys/context.d.ts +9 -0
  211. package/dist/types/index.d.ts +4 -2
  212. package/dist/types/overlays/alert/Alert.d.ts +2 -2
  213. package/dist/types/overlays/flyout/Flyout.d.ts +2 -2
  214. package/dist/types/overlays/message/Message.d.ts +2 -2
  215. package/dist/types/overlays/modal/Modal.d.ts +2 -2
  216. package/dist/types/overlays/toast/Toast.d.ts +2 -2
  217. package/dist/types/overlays/tooltip/Tooltip.d.ts +0 -3
  218. package/dist/types/types/index.d.ts +2 -2
  219. package/dist/types/typography/Abbr.d.ts +4 -8
  220. package/dist/types/typography/Anchor.d.ts +1 -1
  221. package/dist/types/typography/Copy.d.ts +1 -1
  222. package/dist/types/typography/Mark.d.ts +2 -2
  223. package/dist/types/typography/Text.d.ts +1 -1
  224. package/dist/types/typography/Title.d.ts +1 -1
  225. package/dist/types/utils/getBadgeProps.d.ts +9 -0
  226. package/dist/types/utils/getIconProps.d.ts +2 -0
  227. package/dist/types/utils/getTooltipProps.d.ts +4 -0
  228. package/dist/types/utils/index.d.ts +3 -0
  229. package/package.json +14 -15
  230. package/src/components/actionLabel/ActionLabel.tsx +1 -1
  231. package/src/components/animations/Animations.tsx +6 -6
  232. package/src/components/avatar/Avatar.tsx +1 -1
  233. package/src/components/avatar/AvatarGroup.tsx +1 -1
  234. package/src/components/badge/Badge.tsx +8 -46
  235. package/src/components/breadcrumbs/Breadcrumbs.tsx +1 -1
  236. package/src/components/button/Button.tsx +24 -54
  237. package/src/components/button/ButtonGroup.tsx +1 -1
  238. package/src/components/button/ConfirmButton.tsx +23 -20
  239. package/src/components/button/ToggleButtonGroup.tsx +1 -1
  240. package/src/components/callout/Callout.tsx +14 -19
  241. package/src/components/card/Card.tsx +9 -11
  242. package/src/components/card/CardCover.tsx +1 -1
  243. package/src/components/card/FlipContent.tsx +2 -2
  244. package/src/components/chip/Chip.tsx +16 -33
  245. package/src/components/collapsable/Collapsable.tsx +2 -2
  246. package/src/components/divider/Divider.tsx +1 -1
  247. package/src/components/dropdown/Dropdown.tsx +42 -72
  248. package/src/components/dropdown/DropdownTool.tsx +1 -1
  249. package/src/components/empty/EmptyContent.tsx +3 -3
  250. package/src/components/icon/Icon.tsx +5 -32
  251. package/src/components/index.ts +2 -2
  252. package/src/components/media/Media.tsx +3 -3
  253. package/src/components/menu/ContextMenu.tsx +30 -30
  254. package/src/components/menu/Menu.tsx +32 -61
  255. package/src/components/menu/MenuItem.tsx +9 -28
  256. package/src/components/menu/types.ts +1 -1
  257. package/src/components/meter/Meter.tsx +1 -1
  258. package/src/components/navigator/Navigator.tsx +5 -10
  259. package/src/components/panel/Panel.tsx +13 -54
  260. package/src/components/panel/PanelGroup.tsx +3 -4
  261. package/src/components/panel/PanelStack.tsx +20 -25
  262. package/src/components/progress/ProgressBar.tsx +2 -2
  263. package/src/components/progress/ProgressCircle.tsx +2 -2
  264. package/src/components/tabpanel/Tab.tsx +9 -28
  265. package/src/components/tabpanel/TabPanel.tsx +11 -14
  266. package/src/context/Global.tsx +18 -125
  267. package/src/context/NotificationCenter.tsx +0 -1
  268. package/src/context/context.ts +100 -0
  269. package/src/core/aside/Aside.tsx +18 -55
  270. package/src/core/boundary/ErrorBoundary.tsx +8 -37
  271. package/src/core/page/Page.tsx +3 -5
  272. package/src/core/responsive/Responsive.tsx +10 -34
  273. package/src/core/theme/ThemeProvider.tsx +2 -7
  274. package/src/core/viewport/Viewport.tsx +1 -1
  275. package/src/hooks/useContextMenu.tsx +131 -0
  276. package/src/hooks/useIsDark.ts +7 -5
  277. package/src/hooks/useNavigator.tsx +12 -15
  278. package/src/hooks/useOverlayService.tsx +3 -11
  279. package/src/hooks/usePropToggle.ts +3 -3
  280. package/src/hooks/useResize.ts +14 -17
  281. package/src/hooks/useResizeObserver.ts +21 -21
  282. package/src/hooks/useStepper.tsx +1 -1
  283. package/src/hotkeys/HotKey.tsx +1 -1
  284. package/src/hotkeys/HotKeyWrapper.tsx +81 -105
  285. package/src/hotkeys/commons.ts +2 -0
  286. package/src/hotkeys/context.ts +32 -0
  287. package/src/index.ts +4 -7
  288. package/src/overlays/alert/Alert.tsx +12 -16
  289. package/src/overlays/flyout/Flyout.tsx +32 -69
  290. package/src/overlays/message/Message.tsx +11 -15
  291. package/src/overlays/modal/Modal.tsx +23 -57
  292. package/src/overlays/toast/Toast.tsx +16 -15
  293. package/src/overlays/tooltip/Tooltip.tsx +6 -29
  294. package/src/types/global.d.ts +12 -0
  295. package/src/types/index.ts +2 -2
  296. package/src/typography/Abbr.tsx +11 -39
  297. package/src/typography/Anchor.tsx +1 -1
  298. package/src/typography/Copy.tsx +4 -4
  299. package/src/typography/Mark.tsx +2 -3
  300. package/src/typography/Text.tsx +8 -6
  301. package/src/typography/Title.tsx +1 -1
  302. package/src/utils/getBadgeProps.ts +45 -0
  303. package/src/utils/getIconProps.ts +35 -0
  304. package/src/utils/getTooltipProps.ts +38 -0
  305. package/src/utils/index.ts +3 -0
@@ -44,16 +44,7 @@ import {
44
44
  } from "@floating-ui/react";
45
45
  import { mergeRefs } from "@react-fabric/utilities";
46
46
  import classNames from "classnames";
47
- import {
48
- Children,
49
- Fragment,
50
- cloneElement,
51
- useCallback,
52
- useEffect,
53
- useMemo,
54
- useRef,
55
- useState,
56
- } from "react";
47
+ import { Children, Fragment, cloneElement, useEffect, useEffectEvent, useMemo, useRef, useState } from "react";
57
48
  import { type ChildProp, type RefProp } from "../../types";
58
49
 
59
50
  export interface DropdownProps extends RefProp {
@@ -87,9 +78,13 @@ export interface DropdownProps extends RefProp {
87
78
  */
88
79
  dropdownClassName?: string;
89
80
  /**
90
- * dropdown event
81
+ * dropdown trigger event, default is click
82
+ */
83
+ trigger?: "click" | "hover";
84
+ /**
85
+ * portal root element
91
86
  */
92
- dropdownEvent?: "click" | "hover";
87
+ root?: HTMLElement;
93
88
  /**
94
89
  * open handler
95
90
  */
@@ -109,9 +104,10 @@ const DropdownElement = ({
109
104
  placement = "bottom",
110
105
  onClose,
111
106
  onOpen,
107
+ root,
112
108
  disabled,
113
109
  plainDropdown,
114
- dropdownEvent,
110
+ trigger = "click",
115
111
  dropdownClassName,
116
112
  }: DropdownProps) => {
117
113
  const arrowRef = useRef(null);
@@ -119,10 +115,7 @@ const DropdownElement = ({
119
115
  const tree = useFloatingTree();
120
116
  const nodeId = useFloatingNodeId();
121
117
 
122
- const [anchor, panel] = useMemo<AnyObject[]>(
123
- () => Children.toArray(children as AnyObject),
124
- [children],
125
- );
118
+ const [anchor, panel] = useMemo<AnyObject[]>(() => Children.toArray(children as AnyObject), [children]);
126
119
 
127
120
  const { refs, floatingStyles, context } = useFloating({
128
121
  nodeId: `dropdown-${nodeId}`,
@@ -146,7 +139,7 @@ const DropdownElement = ({
146
139
  ],
147
140
  });
148
141
 
149
- const handler = dropdownEvent === "hover" ? useHover : useClick;
142
+ const handler = trigger === "hover" ? useHover : useClick;
150
143
  const click = handler(context, {
151
144
  enabled: !disabled,
152
145
  handleClose: safePolygon({ blockPointerEvents: true }),
@@ -156,46 +149,34 @@ const DropdownElement = ({
156
149
  referencePress: true,
157
150
  });
158
151
 
159
- const { getReferenceProps, getFloatingProps } = useInteractions([
160
- dismiss,
161
- click,
162
- ]);
152
+ const { getReferenceProps, getFloatingProps } = useInteractions([dismiss, click]);
163
153
 
164
154
  const minWidth = useMemo(() => {
165
155
  if (fitToParent) {
166
156
  const el: HTMLElement =
167
157
  // @ts-expect-error ignore
168
- refs.reference.current?.closest('[data-ref="buttonGroup"]') ??
169
- refs.reference.current;
158
+ refs.reference.current?.closest('[data-ref="buttonGroup"]') ?? refs.reference.current;
170
159
  return el?.offsetWidth;
171
160
  }
172
161
  return undefined;
173
162
  }, [refs, isOpen, fitToParent]);
174
163
 
175
- const dismissDropdown = useCallback(() => {
164
+ const dismissDropdown = useEffectEvent(() => {
176
165
  setIsOpen(false);
177
166
  onClose?.();
178
- }, []);
167
+ });
179
168
 
180
- const tryClosing = useCallback(
181
- (e: React.MouseEvent) => {
182
- if (
183
- !refs.floating.current?.contains(
184
- (e.target as HTMLElement).closest("[data-dropdown-dismiss='false']"),
185
- ) &&
186
- (!!closeOnClick ||
187
- refs.floating.current?.contains(
188
- (e.target as HTMLElement).closest("[data-dropdown-dismiss='true']"),
189
- ))
190
- ) {
191
- setTimeout(() => {
192
- setIsOpen(false);
193
- onClose?.();
194
- }, 100);
195
- }
196
- },
197
- [closeOnClick, onClose],
198
- );
169
+ const tryClosing = useEffectEvent((e: React.MouseEvent) => {
170
+ if (
171
+ !refs.floating.current?.contains((e.target as HTMLElement).closest("[data-dropdown-dismiss='false']")) &&
172
+ (!!closeOnClick || refs.floating.current?.contains((e.target as HTMLElement).closest("[data-dropdown-dismiss='true']")))
173
+ ) {
174
+ setTimeout(() => {
175
+ setIsOpen(false);
176
+ onClose?.();
177
+ }, 100);
178
+ }
179
+ });
199
180
 
200
181
  const innerRef = useMemo(
201
182
  () => mergeRefs(ref, anchor.props.ref, refs.setReference),
@@ -220,8 +201,7 @@ const DropdownElement = ({
220
201
  };
221
202
  }, [tree]);
222
203
 
223
- if (!anchor || !panel)
224
- throw Error("Dropdown requires two elements [Anchor, Panel]");
204
+ if (!anchor || !panel) throw Error("Dropdown requires two elements [Anchor, Panel]");
225
205
 
226
206
  return (
227
207
  <Fragment>
@@ -238,14 +218,9 @@ const DropdownElement = ({
238
218
  ref: innerRef,
239
219
  })}
240
220
  {isOpen && (
241
- <FloatingPortal
242
- root={
243
- refs.domReference.current?.closest<HTMLElement>(".theme-base") ??
244
- undefined
245
- }
246
- >
221
+ <FloatingPortal root={root ?? refs.domReference.current?.closest<HTMLElement>(".theme-base") ?? undefined}>
247
222
  <FloatingOverlay />
248
- <FloatingFocusManager context={context} modal>
223
+ <FloatingFocusManager context={context} closeOnFocusOut>
249
224
  <div
250
225
  ref={refs.setFloating}
251
226
  style={{
@@ -263,22 +238,22 @@ const DropdownElement = ({
263
238
  className={classNames(
264
239
  "fabric-dropdownBody",
265
240
  dropdownClassName,
266
- !plainDropdown && "shadow-lg bg-base ring-1 ring-tint-100",
267
- "rounded-capped overflow-auto scroll-thin grid max-h-[70vh]",
241
+ !plainDropdown && "shadow-lg bg-default ring-1 ring-tint-100",
242
+ "rounded-capped grid max-h-[70vh]",
268
243
  )}
269
244
  onMouseUpCapture={tryClosing}
270
245
  >
271
- {cloneElement(panel, {
272
- dismiss: dismissDropdown,
273
- })}
246
+ {cloneElement(
247
+ panel,
248
+ typeof panel.type === "string"
249
+ ? {}
250
+ : {
251
+ dismiss: dismissDropdown,
252
+ },
253
+ )}
274
254
  </div>
275
255
  {showArrow && (
276
- <FloatingArrow
277
- ref={arrowRef}
278
- context={context}
279
- strokeWidth={0.5}
280
- className="fill-base stroke-dimmed"
281
- />
256
+ <FloatingArrow ref={arrowRef} context={context} strokeWidth={0.5} className="fill-default stroke-dimmed" />
282
257
  )}
283
258
  </div>
284
259
  </FloatingFocusManager>
@@ -340,10 +315,7 @@ export const Dropdown = (props: DropdownProps) => {
340
315
  * @param dismiss - Whether to dismiss the dropdown on click (default: true).
341
316
  * @returns JSX Element
342
317
  */
343
- export const DropdownDismiss = ({
344
- children,
345
- dismiss = true,
346
- }: ChildProp & { dismiss?: boolean }) => {
318
+ export const DropdownDismiss = ({ children, dismiss = true }: ChildProp & { dismiss?: boolean }) => {
347
319
  const tree = useFloatingTree();
348
320
 
349
321
  return (
@@ -351,9 +323,7 @@ export const DropdownDismiss = ({
351
323
  role="none"
352
324
  className="contents"
353
325
  data-dropdown-dismiss={dismiss}
354
- onMouseUp={() =>
355
- dismiss && setTimeout(() => tree?.events.emit("close"), 50)
356
- }
326
+ onMouseUp={() => dismiss && setTimeout(() => tree?.events.emit("close"), 50)}
357
327
  >
358
328
  {children}
359
329
  </div>
@@ -37,7 +37,7 @@ import { Dropdown, type DropdownProps } from "./Dropdown";
37
37
  * @param {string} icon - The icon to be displayed in the dropdown.
38
38
  * @param {boolean} groupHover - If true, the dropdown will only be visible when the parent group is hovered.
39
39
  * @param {DropdownProps} props - Additional properties for the dropdown.
40
- * @returns {JSX.Element} The rendered DropdownTool component.
40
+ * @returns {React.ReactElement} The rendered DropdownTool component.
41
41
  *
42
42
  * @example
43
43
  * ```jsx
@@ -41,11 +41,11 @@ export interface EmptyContentProps
41
41
  /**
42
42
  * empty title
43
43
  */
44
- title?: string | JSX.Element;
44
+ title?: string | React.ReactElement;
45
45
  /**
46
46
  * empty message
47
47
  */
48
- message: string | JSX.Element;
48
+ message: string | React.ReactElement;
49
49
  /**
50
50
  * content size
51
51
  */
@@ -113,7 +113,7 @@ const DefaultIcon = () => (
113
113
  * such as in empty states of lists, tables, or other content areas.
114
114
  *
115
115
  * @param {EmptyContentProps} props - The properties for the EmptyContent component.
116
- * @returns {JSX.Element} The rendered EmptyContent component.
116
+ * @returns {React.ReactElement} The rendered EmptyContent component.
117
117
  *
118
118
  * @example
119
119
  * ```jsx
@@ -39,7 +39,7 @@ export interface Props extends CssProp, AriaProps, RefProp, TestProps {
39
39
  /**
40
40
  * svg path / webfont className / 1-4 letter text
41
41
  */
42
- icon: string | JSX.Element;
42
+ icon: string | React.ReactElement;
43
43
  /**
44
44
  * icon image source URL, if failed to load then shows icon
45
45
  */
@@ -81,29 +81,8 @@ export interface Props extends CssProp, AriaProps, RefProp, TestProps {
81
81
 
82
82
  export type IconProps =
83
83
  | string
84
- | JSX.Element
85
- | Pick<
86
- Props,
87
- | "icon"
88
- | "iconSrc"
89
- | "bg"
90
- | "color"
91
- | "size"
92
- | "rtlFlip"
93
- | "viewBox"
94
- | "rounded"
95
- | "animate"
96
- >;
97
-
98
- export const getIconProps = (props: IconProps): Props => {
99
- if (typeof props === "string") {
100
- return { icon: props };
101
- }
102
- if (isValidElement(props)) {
103
- return { icon: props };
104
- }
105
- return props as unknown as Props;
106
- };
84
+ | React.ReactElement
85
+ | Pick<Props, "icon" | "iconSrc" | "bg" | "color" | "size" | "rtlFlip" | "viewBox" | "rounded" | "animate">;
107
86
 
108
87
  const SvgTextSize = ["", ".875em", ".525em", ".35em", ".25em"];
109
88
  const SizeMap: KeyValue<string> = {
@@ -123,7 +102,7 @@ const SizeMap: KeyValue<string> = {
123
102
  * These include `bg`, `color`, `size`, `rtlFlip`, `animate`, and `rounded`.
124
103
  *
125
104
  * @param {IconProps} props - The properties for the Icon component.
126
- * @returns {JSX.Element} The rendered Icon component.
105
+ * @returns {React.ReactElement} The rendered Icon component.
127
106
  *
128
107
  * @example
129
108
  * ```jsx
@@ -241,13 +220,7 @@ export const Icon = ({
241
220
  data-clickable={!!onClick}
242
221
  data-inner-clickable={!!onClick}
243
222
  >
244
- {iconSrc && !imageFailed && (
245
- <img
246
- src={iconSrc}
247
- alt="fallback icon"
248
- onError={() => setImageFailed(true)}
249
- />
250
- )}
223
+ {iconSrc && !imageFailed && <img src={iconSrc} alt="fallback icon" onError={() => setImageFailed(true)} />}
251
224
  {(!iconSrc || imageFailed) && iconEl}
252
225
  </dfn>
253
226
  );
@@ -32,7 +32,7 @@ export {
32
32
  } from "./animations/Animations";
33
33
  export { Avatar } from "./avatar/Avatar";
34
34
  export { AvatarGroup } from "./avatar/AvatarGroup";
35
- export { Badge, getBadgeProps } from "./badge/Badge";
35
+ export { Badge } from "./badge/Badge";
36
36
  export { Breadcrumbs } from "./breadcrumbs/Breadcrumbs";
37
37
  export { Button } from "./button/Button";
38
38
  export { ButtonGroup } from "./button/ButtonGroup";
@@ -48,7 +48,7 @@ export { Divider } from "./divider/Divider";
48
48
  export { Dropdown, DropdownDismiss } from "./dropdown/Dropdown";
49
49
  export { DropdownTool } from "./dropdown/DropdownTool";
50
50
  export { EmptyContent } from "./empty/EmptyContent";
51
- export { getIconProps, Icon } from "./icon/Icon";
51
+ export { Icon } from "./icon/Icon";
52
52
  export { Image, Video } from "./media/Media";
53
53
  export { ContextMenu } from "./menu/ContextMenu";
54
54
  export { Menu } from "./menu/Menu";
@@ -89,7 +89,7 @@ const loadIndicator = (
89
89
  * It automatically adjusts the display based on the provided fit property, allowing for different styles such as cover, contain, or fill.
90
90
  *
91
91
  * @param {ImageProps | VideoProps} props - The properties for the Media component.
92
- * @returns {JSX.Element} The rendered Media component.
92
+ * @returns {React.ReactElement} The rendered Media component.
93
93
  *
94
94
  * @example
95
95
  * ```jsx
@@ -174,7 +174,7 @@ export const Image = ({
174
174
  * It also includes a reel decoration for a more engaging visual presentation.
175
175
  *
176
176
  * @param {VideoProps} props - The properties for the Video component.
177
- * @returns {JSX.Element} The rendered Video component.
177
+ * @returns {React.ReactElement} The rendered Video component.
178
178
  *
179
179
  * @example
180
180
  * ```jsx
@@ -264,7 +264,7 @@ export const Video = ({
264
264
  data-inner-clickable
265
265
  className={classNames(
266
266
  "fabric-mediaControls",
267
- "absolute bottom-6 end-6 rounded-full flex flex-col",
267
+ "absolute bottom-6 inset-e-6 rounded-full flex flex-col",
268
268
  )}
269
269
  >
270
270
  <Button
@@ -22,6 +22,8 @@
22
22
  */
23
23
 
24
24
  import {
25
+ FloatingFocusManager,
26
+ FloatingOverlay,
25
27
  FloatingPortal,
26
28
  autoUpdate,
27
29
  flip,
@@ -48,7 +50,7 @@ export interface ContextMenuProps extends ChildrenProp {
48
50
  * This component is useful for creating custom context menus that can be triggered by right-clicking on elements.
49
51
  *
50
52
  * @param {ContextMenuProps} props - The properties for the ContextMenu component.
51
- * @returns {JSX.Element} The rendered ContextMenu component.
53
+ * @returns {React.ReactElement} The rendered ContextMenu component.
52
54
  *
53
55
  * @example
54
56
  * ```jsx
@@ -114,45 +116,43 @@ export const ContextMenu = ({ children, menu, disabled }: ContextMenuProps) => {
114
116
  if (el && !disabled) {
115
117
  el?.parentElement?.addEventListener("contextmenu", handleClick.current);
116
118
  return () => {
117
- el?.parentElement?.removeEventListener(
118
- "contextmenu",
119
- handleClick.current,
120
- );
119
+ el?.parentElement?.removeEventListener("contextmenu", handleClick.current);
121
120
  };
122
121
  }
123
122
  }, [disabled]);
124
123
 
125
124
  const tryClosing = useRef((e: React.MouseEvent) => {
126
- if ((e.target as HTMLElement)?.closest("[data-dropdown-dismiss='true']"))
127
- setTimeout(() => setIsOpen(false), 50);
125
+ if (!(e.target as HTMLElement)?.closest("[data-dropdown-dismiss='false']")) setTimeout(() => setIsOpen(false), 50);
128
126
  });
129
127
 
130
128
  return (
131
- <div
132
- className="contents"
133
- ref={wrapperRef}
134
- onMouseUpCapture={tryClosing.current}
135
- >
129
+ <div className="contents" ref={wrapperRef}>
136
130
  {children}
137
131
  {isOpen && (
138
- <FloatingPortal
139
- root={
140
- refs.domReference.current?.closest<HTMLElement>(".theme-base") ??
141
- undefined
142
- }
143
- >
144
- {cloneElement(menu as AnyObject, {
145
- ...getFloatingProps(),
146
- style: {
147
- ...floatingStyles,
148
- borderRadius: "var(--rounding)",
149
- zIndex: "var(--z-popover)",
150
- fontSize: "0.875rem",
151
- },
152
- className: "bg-base outline rounded-capped shadow-lg",
153
- ref: refs.setFloating,
154
- onMouseUp: tryClosing.current,
155
- })}
132
+ <FloatingPortal root={refs.domReference.current?.closest<HTMLElement>(".theme-base") ?? undefined}>
133
+ <FloatingOverlay
134
+ lockScroll
135
+ style={{
136
+ zIndex: "var(--z-overlay-mask)",
137
+ position: "absolute",
138
+ overflow: "hidden",
139
+ }}
140
+ >
141
+ <FloatingFocusManager context={context}>
142
+ {cloneElement(menu as AnyObject, {
143
+ ...getFloatingProps(),
144
+ style: {
145
+ ...floatingStyles,
146
+ borderRadius: "var(--rounding)",
147
+ zIndex: "var(--z-popover)",
148
+ fontSize: "0.875rem",
149
+ },
150
+ className: "bg-default outline rounded-capped shadow-lg",
151
+ ref: refs.setFloating,
152
+ onMouseUp: tryClosing.current,
153
+ })}
154
+ </FloatingFocusManager>
155
+ </FloatingOverlay>
156
156
  </FloatingPortal>
157
157
  )}
158
158
  </div>
@@ -47,14 +47,7 @@ import {
47
47
  } from "@floating-ui/react";
48
48
  import { mergeRefs } from "@react-fabric/utilities";
49
49
  import classNames from "classnames";
50
- import {
51
- cloneElement,
52
- Fragment,
53
- useCallback,
54
- useEffect,
55
- useRef,
56
- useState,
57
- } from "react";
50
+ import { cloneElement, Fragment, useEffect, useEffectEvent, useRef, useState } from "react";
58
51
  import { HotKeyWrapper } from "../../hotkeys/HotKeyWrapper";
59
52
  import { cloneChildren, nodeCheck } from "../../utils";
60
53
  import { MenuItem } from "./MenuItem";
@@ -71,6 +64,10 @@ const MenuComponent = ({
71
64
  trigger = "hover",
72
65
  // @ts-expect-error ignore
73
66
  ref,
67
+ // @ts-expect-error ignore
68
+ onMouseUp,
69
+ // @ts-expect-error ignore
70
+ onMouseDown,
74
71
  forDropdown,
75
72
  ...rest
76
73
  }: Partial<MenuProps>) => {
@@ -91,15 +88,10 @@ const MenuComponent = ({
91
88
  open: !isNested || isOpen,
92
89
  onOpenChange(open, event, reason) {
93
90
  isNested && setIsOpen(open);
94
- if (reason === "outside-press" && trigger === "click")
95
- tree?.events.emit("close");
91
+ if (reason === "outside-press" && trigger === "click") tree?.events.emit("close");
96
92
  },
97
93
  placement: isNested ? "right-start" : "bottom-start",
98
- middleware: [
99
- offset({ mainAxis: isNested ? 0 : 4, alignmentAxis: isNested ? -4 : 0 }),
100
- flip(),
101
- shift(),
102
- ],
94
+ middleware: [offset({ mainAxis: isNested ? 0 : 4, alignmentAxis: isNested ? -4 : 0 }), flip(), shift()],
103
95
  whileElementsMounted: autoUpdate,
104
96
  });
105
97
 
@@ -127,9 +119,14 @@ const MenuComponent = ({
127
119
  activeIndex,
128
120
  });
129
121
 
130
- const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions(
131
- [click, hover, role, dismiss, listNavigation, typeahead],
132
- );
122
+ const { getReferenceProps, getFloatingProps, getItemProps } = useInteractions([
123
+ click,
124
+ hover,
125
+ role,
126
+ dismiss,
127
+ listNavigation,
128
+ typeahead,
129
+ ]);
133
130
 
134
131
  // Event emitter allows you to communicate across tree components.
135
132
  // This effect closes all menus when an item gets clicked anywhere
@@ -164,33 +161,22 @@ const MenuComponent = ({
164
161
  }
165
162
  }, [tree, isOpen, nodeId, parentId]);
166
163
 
167
- const handleClick = useCallback(
168
- (e: React.MouseEvent) => {
169
- const el = e.target as HTMLElement;
170
- if (el.dataset.id) {
171
- onClick?.(el.dataset.id as AnyObject);
172
- }
173
- },
174
- [onClick],
175
- );
164
+ const handleClick = useEffectEvent((e: React.MouseEvent) => {
165
+ const el = e.target as HTMLElement;
166
+ if (el.dataset.id) {
167
+ onClick?.(el.dataset.id as AnyObject);
168
+ }
169
+ });
176
170
 
177
171
  const Wrapper = isNested ? FloatingPortal : Fragment;
178
172
  const wrapperProps = isNested
179
173
  ? {
180
- root:
181
- refs.domReference.current?.closest<HTMLElement>(".theme-base") ??
182
- undefined,
174
+ root: refs.domReference.current?.closest<HTMLElement>(".theme-base") ?? undefined,
183
175
  }
184
176
  : {};
185
177
 
186
178
  useEffect(() => {
187
- setTimeout(
188
- () =>
189
- refs.floating.current
190
- ?.querySelector(`[data-active="true"]`)
191
- ?.scrollIntoView({ block: "nearest" }),
192
- 100,
193
- );
179
+ setTimeout(() => refs.floating.current?.querySelector(`[data-active="true"]`)?.scrollIntoView({ block: "nearest" }), 100);
194
180
  }, [isOpen]);
195
181
 
196
182
  useEffect(() => {
@@ -227,23 +213,19 @@ const MenuComponent = ({
227
213
  <Wrapper {...wrapperProps}>
228
214
  {isNested && <FloatingOverlay />}
229
215
  <HotKeyWrapper>
230
- <FloatingFocusManager
231
- context={context}
232
- modal={!isNested}
233
- initialFocus={isNested ? -1 : 0}
234
- returnFocus={!isNested}
235
- >
216
+ <FloatingFocusManager context={context} closeOnFocusOut initialFocus={isNested ? -1 : 0} returnFocus={!isNested}>
236
217
  <div
237
218
  className={classNames(
238
219
  menuClassName,
239
- "flex flex-col bg-base p-1 menu-list",
240
- isNested &&
241
- "outline shadow-lg rounded-capped max-h-96 overflow-auto scroll-thin z-(--z-popover)",
220
+ "flex flex-col p-1 menu-list",
221
+ isNested && "outline shadow-lg rounded-capped max-h-96 overflow-auto scroll-thin z-(--z-popover)",
242
222
  )}
243
223
  autoFocus
244
224
  ref={mergeRefs(isNested ? refs.setFloating : ref)}
245
225
  {...getFloatingProps({
246
226
  onClick: isNested ? undefined : handleClick,
227
+ onMouseDown,
228
+ onMouseUp,
247
229
  })}
248
230
  // @ts-expect-error ignore
249
231
  {...{ style: !isNested ? rest.style : floatingStyles }}
@@ -256,8 +238,7 @@ const MenuComponent = ({
256
238
  ? {
257
239
  minimal: !isNested && minimal,
258
240
  "data-focus": activeIndex === index,
259
- ref: (el: HTMLElement) =>
260
- (elementsRef.current[index] = el),
241
+ ref: (el: HTMLElement) => (elementsRef.current[index] = el),
261
242
  ...getItemProps({
262
243
  onClick: child.props.onClick,
263
244
  tabIndex: activeIndex === index ? 0 : -1,
@@ -283,7 +264,7 @@ const MenuComponent = ({
283
264
  * It can be nested within other menus to create complex menu structures.
284
265
  *
285
266
  * @param {MenuProps} props - The properties for the Menu component.
286
- * @returns {JSX.Element} The rendered Menu component.
267
+ * @returns {React.ReactElement} The rendered Menu component.
287
268
  *
288
269
  * @example
289
270
  * ```jsx
@@ -310,23 +291,13 @@ export const Menu = (props: MenuProps) => {
310
291
  const tree = useFloatingTree();
311
292
 
312
293
  if (tree) {
313
- return (
314
- <MenuComponent
315
- {...(props as AnyObject)}
316
- className=""
317
- menuClassName={props.className}
318
- />
319
- );
294
+ return <MenuComponent {...(props as AnyObject)} className="" menuClassName={props.className} />;
320
295
  }
321
296
 
322
297
  if (parentId === null) {
323
298
  return (
324
299
  <FloatingTree>
325
- <MenuComponent
326
- {...(props as AnyObject)}
327
- className=""
328
- menuClassName={props.className}
329
- />
300
+ <MenuComponent {...(props as AnyObject)} className="" menuClassName={props.className} />
330
301
  </FloatingTree>
331
302
  );
332
303
  }