@koine/react 1.0.26 → 1.0.29

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.
@@ -0,0 +1,35 @@
1
+ import React from "react";
2
+ import { type HTMLMotionProps } from "framer-motion";
3
+ import { useMenu } from "@mui/base/MenuUnstyled";
4
+ import { type PopperChildrenProps } from "react-popper";
5
+ /**
6
+ * Props we control, cannot be overriden from implementers
7
+ */
8
+ declare type MenuButtonOwnProps = {
9
+ "aria-controls"?: string;
10
+ "aria-haspopup": true | "true";
11
+ "aria-expanded"?: true | "true";
12
+ onClick: (event: React.MouseEvent<HTMLButtonElement>) => unknown;
13
+ onKeyDown: (event: React.KeyboardEvent<HTMLButtonElement>) => unknown;
14
+ };
15
+ declare type MenuButtonProps = Omit<React.ComponentPropsWithRef<"button">, keyof MenuButtonOwnProps> & MenuButtonOwnProps;
16
+ export declare type MenuItemsProps = {
17
+ /**
18
+ * Closes the parent menu
19
+ */
20
+ close: () => unknown;
21
+ };
22
+ /**
23
+ * Props we control, cannot be overriden from implementers
24
+ */
25
+ declare type MenuOwnProps = ReturnType<typeof useMenu>["getListboxProps"] & {
26
+ onKeyDown: (event: React.KeyboardEvent) => unknown;
27
+ style: React.StyleHTMLAttributes<HTMLDivElement>;
28
+ };
29
+ export declare type MenuProps = Omit<Omit<HTMLMotionProps<"div">, "children"> & {
30
+ placement?: PopperChildrenProps["placement"];
31
+ Button: (props: MenuButtonProps) => JSX.Element;
32
+ children: (props: MenuItemsProps) => React.ReactNode;
33
+ }, keyof MenuOwnProps>;
34
+ export declare const Menu: React.ForwardRefExoticComponent<MenuProps & React.RefAttributes<unknown>>;
35
+ export default Menu;
@@ -0,0 +1,76 @@
1
+ import { __assign, __rest } from "tslib";
2
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { forwardRef, useId, useMemo, useRef, useState } from "react";
4
+ import { unstable_useEventCallback as useEventCallback } from "@mui/utils";
5
+ import { motion as m, AnimatePresence, } from "framer-motion";
6
+ import { useMenu, MenuUnstyledContext, } from "@mui/base/MenuUnstyled";
7
+ import ModalUnstyled from "@mui/base/ModalUnstyled";
8
+ import ClickAwayListener from "@mui/base/ClickAwayListener";
9
+ import { usePopper } from "react-popper";
10
+ import { clsx } from "@koine/utils/clsx";
11
+ var MenuRoot = m.div;
12
+ var MenuBackdrop = function () { return _jsx("div", { className: "fixed inset-0" }); };
13
+ export var Menu = forwardRef(function Menu(props, ref) {
14
+ var Button = props.Button, placement = props.placement, children = props.children, className = props.className, htmlAttributes = __rest(props, ["Button", "placement", "children", "className"]);
15
+ var id = useId();
16
+ var buttonRef = useRef(null);
17
+ var menuActions = useRef(null);
18
+ var _a = useState(null), popperElement = _a[0], setPopperElement = _a[1];
19
+ var _b = useState(null), anchorEl = _b[0], setAnchorEl = _b[1];
20
+ var open = Boolean(anchorEl);
21
+ var styles = usePopper(anchorEl, popperElement, {
22
+ placement: placement,
23
+ // strategy: "absolute",
24
+ }).styles;
25
+ var _c = useMenu({
26
+ listboxId: id,
27
+ // @ts-expect-error fix if we are going to use all this...
28
+ listboxRef: setPopperElement,
29
+ // these two make the Tab key behaviour correct, closing the menu on Tab
30
+ // press and re-focusing the Button trigger element
31
+ open: open,
32
+ onClose: function () { return setAnchorEl(null); },
33
+ }), registerItem = _c.registerItem, unregisterItem = _c.unregisterItem, getListboxProps = _c.getListboxProps, getItemProps = _c.getItemProps, getItemState = _c.getItemState;
34
+ var contextValue = {
35
+ registerItem: registerItem,
36
+ unregisterItem: unregisterItem,
37
+ getItemState: getItemState,
38
+ getItemProps: getItemProps,
39
+ open: open,
40
+ };
41
+ var handleButtonClick = function (event) {
42
+ if (open) {
43
+ setAnchorEl(null);
44
+ }
45
+ else {
46
+ setAnchorEl(event.currentTarget);
47
+ }
48
+ };
49
+ var handleButtonKeyDown = function (event) {
50
+ var _a;
51
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
52
+ event.preventDefault();
53
+ setAnchorEl(event.currentTarget);
54
+ if (event.key === "ArrowUp") {
55
+ (_a = menuActions.current) === null || _a === void 0 ? void 0 : _a.highlightLastItem();
56
+ }
57
+ }
58
+ };
59
+ var close = useEventCallback(function () {
60
+ var _a;
61
+ setAnchorEl(null);
62
+ (_a = buttonRef.current) === null || _a === void 0 ? void 0 : _a.focus();
63
+ });
64
+ var renderChildren = useMemo(function () {
65
+ var childrenProps = { close: close };
66
+ return children(childrenProps);
67
+ }, [children, close]);
68
+ return (_jsxs(_Fragment, { children: [_jsx(Button, { ref: buttonRef, id: id, "aria-haspopup": "true", "aria-controls": open ? id : undefined, "aria-expanded": open ? "true" : undefined, onClick: handleButtonClick, onKeyDown: handleButtonKeyDown }), _jsx(AnimatePresence, { children: open && (_jsx(ModalUnstyled, __assign({ BackdropComponent: MenuBackdrop, onClose: close, onBackdropClick: close, open: open }, { children: _jsx("div", { children: _jsx(ClickAwayListener, __assign({ onClickAway: close }, { children: _jsx(MenuRoot, __assign({ initial: {
69
+ opacity: 0,
70
+ }, animate: {
71
+ opacity: 1,
72
+ }, exit: {
73
+ opacity: 0,
74
+ }, className: clsx(className), style: styles["popper"] }, htmlAttributes, getListboxProps(), { "aria-labelledby": id }, { children: _jsx(MenuUnstyledContext.Provider, __assign({ value: contextValue }, { children: renderChildren })) })) })) }) }))) })] }));
75
+ });
76
+ export default Menu;
@@ -0,0 +1,6 @@
1
+ import React from "react";
2
+ import { type MenuItemsProps } from "../Menu/MenuMui";
3
+ import { Polymorphic } from "../typings";
4
+ export declare type MenuItemProps = React.PropsWithChildren<Partial<MenuItemsProps>>;
5
+ export declare const MenuItem: Polymorphic.ComponentForwarded<"button", MenuItemProps>;
6
+ export default MenuItem;
@@ -0,0 +1,15 @@
1
+ import { __assign, __rest } from "tslib";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { forwardRef } from "react";
4
+ import { useMenuItem } from "@mui/base/MenuItemUnstyled";
5
+ // import { useMenuItem } from "./useMenuItem";
6
+ import { clsx } from "@koine/utils/clsx";
7
+ export var MenuItem = forwardRef(function MenuItem(props, ref) {
8
+ var _a = props.as, As = _a === void 0 ? "button" : _a, children = props.children, className = props.className, disabledProp = props.disabled, other = __rest(props, ["as", "children", "className", "disabled"]);
9
+ var _b = useMenuItem({
10
+ ref: ref,
11
+ disabled: disabledProp,
12
+ }), getRootProps = _b.getRootProps, disabled = _b.disabled, focusVisible = _b.focusVisible;
13
+ return (_jsx(As, __assign({ className: clsx(focusVisible && "", disabled && "", className) }, getRootProps(other), { children: children })));
14
+ });
15
+ export default MenuItem;
@@ -0,0 +1,11 @@
1
+ import { UseMenuItemParameters } from "@mui/base/MenuItemUnstyled";
2
+ export declare function useMenuItem(props: UseMenuItemParameters): {
3
+ getRootProps: (other?: Record<string, any>) => {
4
+ tabIndex: any;
5
+ id: any;
6
+ role: string;
7
+ };
8
+ disabled: boolean;
9
+ ref: import("react").Ref<any>;
10
+ };
11
+ export default useMenuItem;
@@ -0,0 +1,58 @@
1
+ import { __assign } from "tslib";
2
+ import { useCallback, useContext, useEffect, useId, useRef, useState, } from "react";
3
+ import { unstable_useForkRef as useForkRef } from "@mui/utils";
4
+ import { MenuUnstyledContext } from "@mui/base/MenuUnstyled";
5
+ // import { unstable_useIsFocusVisible as useIsFocusVisible } from "@mui/utils";
6
+ export function useMenuItem(props) {
7
+ var _a;
8
+ var _b = props.disabled, disabled = _b === void 0 ? false : _b, ref = props.ref, label = props.label;
9
+ var id = useId();
10
+ var menuContext = useContext(MenuUnstyledContext);
11
+ var itemRef = useRef(null);
12
+ var handleRef = useForkRef(itemRef, ref);
13
+ if (menuContext === null) {
14
+ throw new Error("MenuItemUnstyled must be used within a MenuUnstyled");
15
+ }
16
+ var registerItem = menuContext.registerItem, unregisterItem = menuContext.unregisterItem, open = menuContext.open;
17
+ useEffect(function () {
18
+ registerItem(id, { disabled: disabled, id: id, ref: itemRef, label: label });
19
+ return function () { return unregisterItem(id); };
20
+ }, [id, registerItem, unregisterItem, disabled, ref, label]);
21
+ // const { getRootProps: getButtonProps, focusVisible } = useButton({
22
+ // disabled,
23
+ // focusableWhenDisabled: true,
24
+ // ref: handleRef,
25
+ // });
26
+ // Ensure the menu item is focused when highlighted
27
+ var _c = useState(false), focusRequested = _c[0], requestFocus = _c[1];
28
+ var focusIfRequested = useCallback(function () {
29
+ if (focusRequested && itemRef.current != null) {
30
+ itemRef.current.focus();
31
+ requestFocus(false);
32
+ }
33
+ }, [focusRequested]);
34
+ useEffect(function () {
35
+ focusIfRequested();
36
+ });
37
+ // useDebugValue({ id, disabled, label });
38
+ var itemState = menuContext.getItemState(id !== null && id !== void 0 ? id : "");
39
+ var highlighted = (itemState !== null && itemState !== void 0 ? itemState : { highlighted: false }).highlighted;
40
+ useEffect(function () {
41
+ requestFocus(highlighted && open);
42
+ }, [highlighted, open]);
43
+ return {
44
+ getRootProps: function (other) {
45
+ var optionProps = menuContext.getItemProps(id, other);
46
+ return __assign(__assign({}, other), {
47
+ // ...getButtonProps(other),
48
+ // @ts-expect-error type from @mui/base is not specific
49
+ tabIndex: optionProps.tabIndex,
50
+ // @ts-expect-error type from @mui/base is not specific
51
+ id: optionProps.id, role: "menuitem" });
52
+ },
53
+ disabled: (_a = itemState === null || itemState === void 0 ? void 0 : itemState.disabled) !== null && _a !== void 0 ? _a : false,
54
+ // focusVisible,
55
+ ref: handleRef,
56
+ };
57
+ }
58
+ export default useMenuItem;
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Menu = void 0;
4
+ var tslib_1 = require("tslib");
5
+ var jsx_runtime_1 = require("react/jsx-runtime");
6
+ var react_1 = require("react");
7
+ var utils_1 = require("@mui/utils");
8
+ var framer_motion_1 = require("framer-motion");
9
+ var MenuUnstyled_1 = require("@mui/base/MenuUnstyled");
10
+ var ModalUnstyled_1 = tslib_1.__importDefault(require("@mui/base/ModalUnstyled"));
11
+ var ClickAwayListener_1 = tslib_1.__importDefault(require("@mui/base/ClickAwayListener"));
12
+ var react_popper_1 = require("react-popper");
13
+ var clsx_1 = require("@koine/utils/clsx");
14
+ var MenuRoot = framer_motion_1.motion.div;
15
+ var MenuBackdrop = function () { return (0, jsx_runtime_1.jsx)("div", { className: "fixed inset-0" }); };
16
+ exports.Menu = (0, react_1.forwardRef)(function Menu(props, ref) {
17
+ var Button = props.Button, placement = props.placement, children = props.children, className = props.className, htmlAttributes = tslib_1.__rest(props, ["Button", "placement", "children", "className"]);
18
+ var id = (0, react_1.useId)();
19
+ var buttonRef = (0, react_1.useRef)(null);
20
+ var menuActions = (0, react_1.useRef)(null);
21
+ var _a = (0, react_1.useState)(null), popperElement = _a[0], setPopperElement = _a[1];
22
+ var _b = (0, react_1.useState)(null), anchorEl = _b[0], setAnchorEl = _b[1];
23
+ var open = Boolean(anchorEl);
24
+ var styles = (0, react_popper_1.usePopper)(anchorEl, popperElement, {
25
+ placement: placement,
26
+ // strategy: "absolute",
27
+ }).styles;
28
+ var _c = (0, MenuUnstyled_1.useMenu)({
29
+ listboxId: id,
30
+ // @ts-expect-error fix if we are going to use all this...
31
+ listboxRef: setPopperElement,
32
+ // these two make the Tab key behaviour correct, closing the menu on Tab
33
+ // press and re-focusing the Button trigger element
34
+ open: open,
35
+ onClose: function () { return setAnchorEl(null); },
36
+ }), registerItem = _c.registerItem, unregisterItem = _c.unregisterItem, getListboxProps = _c.getListboxProps, getItemProps = _c.getItemProps, getItemState = _c.getItemState;
37
+ var contextValue = {
38
+ registerItem: registerItem,
39
+ unregisterItem: unregisterItem,
40
+ getItemState: getItemState,
41
+ getItemProps: getItemProps,
42
+ open: open,
43
+ };
44
+ var handleButtonClick = function (event) {
45
+ if (open) {
46
+ setAnchorEl(null);
47
+ }
48
+ else {
49
+ setAnchorEl(event.currentTarget);
50
+ }
51
+ };
52
+ var handleButtonKeyDown = function (event) {
53
+ var _a;
54
+ if (event.key === "ArrowDown" || event.key === "ArrowUp") {
55
+ event.preventDefault();
56
+ setAnchorEl(event.currentTarget);
57
+ if (event.key === "ArrowUp") {
58
+ (_a = menuActions.current) === null || _a === void 0 ? void 0 : _a.highlightLastItem();
59
+ }
60
+ }
61
+ };
62
+ var close = (0, utils_1.unstable_useEventCallback)(function () {
63
+ var _a;
64
+ setAnchorEl(null);
65
+ (_a = buttonRef.current) === null || _a === void 0 ? void 0 : _a.focus();
66
+ });
67
+ var renderChildren = (0, react_1.useMemo)(function () {
68
+ var childrenProps = { close: close };
69
+ return children(childrenProps);
70
+ }, [children, close]);
71
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Button, { ref: buttonRef, id: id, "aria-haspopup": "true", "aria-controls": open ? id : undefined, "aria-expanded": open ? "true" : undefined, onClick: handleButtonClick, onKeyDown: handleButtonKeyDown }), (0, jsx_runtime_1.jsx)(framer_motion_1.AnimatePresence, { children: open && ((0, jsx_runtime_1.jsx)(ModalUnstyled_1.default, tslib_1.__assign({ BackdropComponent: MenuBackdrop, onClose: close, onBackdropClick: close, open: open }, { children: (0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(ClickAwayListener_1.default, tslib_1.__assign({ onClickAway: close }, { children: (0, jsx_runtime_1.jsx)(MenuRoot, tslib_1.__assign({ initial: {
72
+ opacity: 0,
73
+ }, animate: {
74
+ opacity: 1,
75
+ }, exit: {
76
+ opacity: 0,
77
+ }, className: (0, clsx_1.clsx)(className), style: styles["popper"] }, htmlAttributes, getListboxProps(), { "aria-labelledby": id }, { children: (0, jsx_runtime_1.jsx)(MenuUnstyled_1.MenuUnstyledContext.Provider, tslib_1.__assign({ value: contextValue }, { children: renderChildren })) })) })) }) }))) })] }));
78
+ });
79
+ exports.default = exports.Menu;
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MenuItem = void 0;
4
+ var tslib_1 = require("tslib");
5
+ var jsx_runtime_1 = require("react/jsx-runtime");
6
+ var react_1 = require("react");
7
+ var MenuItemUnstyled_1 = require("@mui/base/MenuItemUnstyled");
8
+ // import { useMenuItem } from "./useMenuItem";
9
+ var clsx_1 = require("@koine/utils/clsx");
10
+ exports.MenuItem = (0, react_1.forwardRef)(function MenuItem(props, ref) {
11
+ var _a = props.as, As = _a === void 0 ? "button" : _a, children = props.children, className = props.className, disabledProp = props.disabled, other = tslib_1.__rest(props, ["as", "children", "className", "disabled"]);
12
+ var _b = (0, MenuItemUnstyled_1.useMenuItem)({
13
+ ref: ref,
14
+ disabled: disabledProp,
15
+ }), getRootProps = _b.getRootProps, disabled = _b.disabled, focusVisible = _b.focusVisible;
16
+ return ((0, jsx_runtime_1.jsx)(As, tslib_1.__assign({ className: (0, clsx_1.clsx)(focusVisible && "", disabled && "", className) }, getRootProps(other), { children: children })));
17
+ });
18
+ exports.default = exports.MenuItem;
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useMenuItem = void 0;
4
+ var tslib_1 = require("tslib");
5
+ var react_1 = require("react");
6
+ var utils_1 = require("@mui/utils");
7
+ var MenuUnstyled_1 = require("@mui/base/MenuUnstyled");
8
+ // import { unstable_useIsFocusVisible as useIsFocusVisible } from "@mui/utils";
9
+ function useMenuItem(props) {
10
+ var _a;
11
+ var _b = props.disabled, disabled = _b === void 0 ? false : _b, ref = props.ref, label = props.label;
12
+ var id = (0, react_1.useId)();
13
+ var menuContext = (0, react_1.useContext)(MenuUnstyled_1.MenuUnstyledContext);
14
+ var itemRef = (0, react_1.useRef)(null);
15
+ var handleRef = (0, utils_1.unstable_useForkRef)(itemRef, ref);
16
+ if (menuContext === null) {
17
+ throw new Error("MenuItemUnstyled must be used within a MenuUnstyled");
18
+ }
19
+ var registerItem = menuContext.registerItem, unregisterItem = menuContext.unregisterItem, open = menuContext.open;
20
+ (0, react_1.useEffect)(function () {
21
+ registerItem(id, { disabled: disabled, id: id, ref: itemRef, label: label });
22
+ return function () { return unregisterItem(id); };
23
+ }, [id, registerItem, unregisterItem, disabled, ref, label]);
24
+ // const { getRootProps: getButtonProps, focusVisible } = useButton({
25
+ // disabled,
26
+ // focusableWhenDisabled: true,
27
+ // ref: handleRef,
28
+ // });
29
+ // Ensure the menu item is focused when highlighted
30
+ var _c = (0, react_1.useState)(false), focusRequested = _c[0], requestFocus = _c[1];
31
+ var focusIfRequested = (0, react_1.useCallback)(function () {
32
+ if (focusRequested && itemRef.current != null) {
33
+ itemRef.current.focus();
34
+ requestFocus(false);
35
+ }
36
+ }, [focusRequested]);
37
+ (0, react_1.useEffect)(function () {
38
+ focusIfRequested();
39
+ });
40
+ // useDebugValue({ id, disabled, label });
41
+ var itemState = menuContext.getItemState(id !== null && id !== void 0 ? id : "");
42
+ var highlighted = (itemState !== null && itemState !== void 0 ? itemState : { highlighted: false }).highlighted;
43
+ (0, react_1.useEffect)(function () {
44
+ requestFocus(highlighted && open);
45
+ }, [highlighted, open]);
46
+ return {
47
+ getRootProps: function (other) {
48
+ var optionProps = menuContext.getItemProps(id, other);
49
+ return tslib_1.__assign(tslib_1.__assign({}, other), {
50
+ // ...getButtonProps(other),
51
+ // @ts-expect-error type from @mui/base is not specific
52
+ tabIndex: optionProps.tabIndex,
53
+ // @ts-expect-error type from @mui/base is not specific
54
+ id: optionProps.id, role: "menuitem" });
55
+ },
56
+ disabled: (_a = itemState === null || itemState === void 0 ? void 0 : itemState.disabled) !== null && _a !== void 0 ? _a : false,
57
+ // focusVisible,
58
+ ref: handleRef,
59
+ };
60
+ }
61
+ exports.useMenuItem = useMenuItem;
62
+ exports.default = useMenuItem;
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "framer-motion": "^6.3.10",
10
10
  "react": "^16.8 || ^17 || ^18",
11
11
  "@mui/base": "^5.0.0-alpha.83",
12
- "@koine/utils": "1.0.26",
12
+ "@koine/utils": "1.0.29",
13
13
  "react-icons": "^4.4.0",
14
14
  "date-fns": "^2.28.0",
15
15
  "react-swipeable": "^7.0.0",
@@ -18,9 +18,10 @@
18
18
  "yup": "^0.32.11",
19
19
  "react-hook-form": "^7.31.3",
20
20
  "type-fest": "^2.13.0",
21
+ "react-popper": "^2.3.0",
21
22
  "tslib": "^2.4.0"
22
23
  },
23
- "version": "1.0.26",
24
+ "version": "1.0.29",
24
25
  "module": "./index.js",
25
26
  "types": "./index.d.ts"
26
27
  }
package/typings.d.ts CHANGED
@@ -19,3 +19,80 @@ declare module "styled-components" {
19
19
  * `ReactSomeFeature` accessible anywhere from `Koine.ReactSomeFeature`
20
20
  */
21
21
  declare namespace Koine {}
22
+
23
+ /**
24
+ * React Polymorphic components type utilities
25
+ *
26
+ * @resources
27
+ * - [Polymorphic types from Radix UI in Wanda System](https://github.com/wonderflow-bv/wanda/blob/main/packages/react-components/src/types/polymorphic/index.ts)
28
+ * - [TypeScript + React: Typing Generic forwardRefs](https://fettblog.eu/typescript-react-generic-forward-refs/)
29
+ * - [React with Typescript -- Generics while using React.forwardRef](https://stackoverflow.com/a/58473012/1938970)
30
+ * - [How to write a generic that extracts the prop types of the component that passed in](https://stackoverflow.com/a/57846897/1938970)
31
+ * - [React TS Generic component to pass generic props to children](https://stackoverflow.com/a/68442669/1938970)
32
+ * - [About custom ref prop](https://gist.github.com/gaearon/1a018a023347fe1c2476073330cc5509)
33
+ * - [forwardRef performance](https://github.com/facebook/react/issues/13456)
34
+ * - [React docs: Exposing DOM Refs to Parent Components](https://github.com/facebook/react/issues/13456)
35
+ */
36
+ declare namespace Polymorphic {
37
+ type AsProp<TComponent extends React.ElementType> = {
38
+ as?: TComponent;
39
+ };
40
+
41
+ type ComponentTypes =
42
+ | React.ComponentClass<any>
43
+ | React.FunctionComponent<any>
44
+ | keyof JSX.IntrinsicElements;
45
+
46
+ type Merge<P1 = {}, P2 = {}> = Omit<P1, keyof P2> & P2;
47
+
48
+ type ForwardRefExoticComponent<TComponent, TOwnProps> =
49
+ React.ForwardRefExoticComponent<
50
+ Merge<
51
+ TComponent extends React.ElementType
52
+ ? React.ComponentPropsWithRef<TComponent>
53
+ : never,
54
+ TOwnProps & { as?: TComponent }
55
+ >
56
+ >;
57
+
58
+ type InferProps<TComponent extends ComponentTypes> =
59
+ TComponent extends React.ComponentClass<infer IProps>
60
+ ? IProps
61
+ : TComponent extends React.FunctionComponent<infer IProps>
62
+ ? IProps
63
+ : TComponent extends React.ForwardRefExoticComponent<infer IProps>
64
+ ? IProps
65
+ : TComponent extends keyof JSX.IntrinsicElements
66
+ ? React.ComponentPropsWithoutRef<TComponent>
67
+ : never;
68
+
69
+ type Ref<TComponent extends React.ElementType> =
70
+ React.ComponentPropsWithRef<TComponent>["ref"];
71
+
72
+ type Props<
73
+ TComponent extends React.ElementType,
74
+ TProps = {}
75
+ > = /* Omit< */ InferProps<TComponent> /* , keyof Props> */ &
76
+ AsProp<TComponent> &
77
+ TProps;
78
+
79
+ type PropsWithRef<TComponent extends React.ElementType, TProps = {}> = Props<
80
+ TComponent,
81
+ TProps
82
+ > & {
83
+ ref?: Ref<TComponent>;
84
+ };
85
+
86
+ interface ComponentForwarded<TComponent, TProps = {}>
87
+ extends ForwardRefExoticComponent<TComponent, TProps> {
88
+ <As = TComponent>(
89
+ props: As extends ""
90
+ ? { as: keyof JSX.IntrinsicElements }
91
+ : As extends React.ComponentType<infer P>
92
+ ? Merge<P, TProps & { as: As }>
93
+ : As extends keyof JSX.IntrinsicElements
94
+ ? Merge<JSX.IntrinsicElements[As], TProps & { as: As }>
95
+ : never
96
+ ): React.ReactElement | null;
97
+ }
98
+ }