@mezzanine-ui/react 1.3.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,20 +10,10 @@ import Button from '../Button/Button.js';
10
10
  import { useDocumentEvents } from '../hooks/useDocumentEvents.js';
11
11
  import Translate from '../Transition/Translate.js';
12
12
  import { composeRefs } from '../utils/composeRefs.js';
13
+ import { getElementRef } from '../utils/getElementRef.js';
13
14
  import DropdownItem from './DropdownItem.js';
14
15
  import Popper from '../Popper/Popper.js';
15
16
 
16
- /**
17
- * Extracts ref from a ReactElement, supporting both React 18 and 19.
18
- * In React 18, ref is on the element itself; in React 19, ref is in props.
19
- */
20
- function getElementRef(element) {
21
- var _a;
22
- // React 19: ref is in props
23
- const propsRef = (_a = element.props) === null || _a === void 0 ? void 0 : _a.ref;
24
- // React 18: ref is on the element itself
25
- return propsRef !== null && propsRef !== void 0 ? propsRef : element.ref;
26
- }
27
17
  /**
28
18
  * 下拉選單元件,以 `Button` 或 `Input` 作為觸發元素,點擊後展開選項列表。
29
19
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mezzanine-ui/react",
3
- "version": "1.3.0",
3
+ "version": "1.3.1",
4
4
  "description": "React components for mezzanine-ui",
5
5
  "author": "Mezzanine",
6
6
  "repository": {
@@ -0,0 +1,27 @@
1
+ import { ReactElement, Ref } from 'react';
2
+ /**
3
+ * Helper type to extract ref from a ReactElement.
4
+ * Models `ref` on the element itself, which is compatible with React 18 and 19.
5
+ */
6
+ export type ReactElementWithRef<P, E extends Element = HTMLElement> = ReactElement<P> & {
7
+ ref?: Ref<E>;
8
+ };
9
+ /**
10
+ * Extracts ref from a ReactElement, supporting both React 18 and 19.
11
+ * In React 18, ref is on the element itself; in React 19, ref is in props.
12
+ *
13
+ * Reading the "wrong" location in dev mode triggers React warning getters:
14
+ *
15
+ * - React 18 installs a warning getter on `props.ref` when the element was
16
+ * created with a ref — accessing it logs
17
+ * "`ref` is not a prop. Trying to access it will result in `undefined` being returned."
18
+ * - React 19 installs a deprecation getter on `element.ref` when the element
19
+ * was created with a ref — accessing it logs
20
+ * "Accessing element.ref was removed in React 19."
21
+ *
22
+ * So instead of unconditionally reading `props.ref` first, detect the
23
+ * dev-mode warning getters (marked with `isReactWarning`) and read the ref
24
+ * from the location where it actually lives. Same approach as
25
+ * `getElementRef` in radix-ui/primitives.
26
+ */
27
+ export declare function getElementRef<E extends Element = HTMLElement>(element: ReactElementWithRef<unknown, E>): Ref<E> | undefined;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Whether the given property getter is a React dev-mode warning getter.
3
+ * React marks them with `isReactWarning = true`
4
+ * (see `defineRefPropWarningGetter` in the React source).
5
+ */
6
+ function isReactWarningGetter(getter) {
7
+ return (typeof getter === 'function' &&
8
+ Boolean(getter.isReactWarning));
9
+ }
10
+ /**
11
+ * Extracts ref from a ReactElement, supporting both React 18 and 19.
12
+ * In React 18, ref is on the element itself; in React 19, ref is in props.
13
+ *
14
+ * Reading the "wrong" location in dev mode triggers React warning getters:
15
+ *
16
+ * - React 18 installs a warning getter on `props.ref` when the element was
17
+ * created with a ref — accessing it logs
18
+ * "`ref` is not a prop. Trying to access it will result in `undefined` being returned."
19
+ * - React 19 installs a deprecation getter on `element.ref` when the element
20
+ * was created with a ref — accessing it logs
21
+ * "Accessing element.ref was removed in React 19."
22
+ *
23
+ * So instead of unconditionally reading `props.ref` first, detect the
24
+ * dev-mode warning getters (marked with `isReactWarning`) and read the ref
25
+ * from the location where it actually lives. Same approach as
26
+ * `getElementRef` in radix-ui/primitives.
27
+ */
28
+ function getElementRef(element) {
29
+ var _a, _b, _c;
30
+ const props = element.props;
31
+ // React 18 dev mode: `props.ref` is a warning getter; the actual ref
32
+ // lives on the element itself.
33
+ const propsRefGetter = props
34
+ ? (_a = Object.getOwnPropertyDescriptor(props, 'ref')) === null || _a === void 0 ? void 0 : _a.get
35
+ : undefined;
36
+ if (isReactWarningGetter(propsRefGetter)) {
37
+ return element.ref;
38
+ }
39
+ // React 19 dev mode: `element.ref` may be a deprecation warning getter;
40
+ // the actual ref lives in props as a regular property.
41
+ const elementRefGetter = (_b = Object.getOwnPropertyDescriptor(element, 'ref')) === null || _b === void 0 ? void 0 : _b.get;
42
+ if (isReactWarningGetter(elementRefGetter)) {
43
+ return props === null || props === void 0 ? void 0 : props.ref;
44
+ }
45
+ // No warning getters (production builds, or no ref was given):
46
+ // prefer `props.ref` (React 19), fall back to `element.ref` (React 18).
47
+ // Safe on React 19 dev — its `element.ref` deprecation getter is only
48
+ // installed when a ref exists, in which case `props.ref` is returned here.
49
+ return (_c = props === null || props === void 0 ? void 0 : props.ref) !== null && _c !== void 0 ? _c : element.ref;
50
+ }
51
+
52
+ export { getElementRef };