From baebfdb0bbd14a0fd9d042d0717be8ecba6b5110 Mon Sep 17 00:00:00 2001 From: Timo <16718859+toger5@users.noreply.github.com> Date: Wed, 3 Aug 2022 12:22:07 +0200 Subject: [PATCH] typescript `src/popover` (#488) --- src/popover/{Popover.jsx => Popover.tsx} | 14 +++- src/popover/PopoverMenu.jsx | 84 --------------------- src/popover/PopoverMenu.tsx | 96 ++++++++++++++++++++++++ 3 files changed, 107 insertions(+), 87 deletions(-) rename src/popover/{Popover.jsx => Popover.tsx} (84%) delete mode 100644 src/popover/PopoverMenu.jsx create mode 100644 src/popover/PopoverMenu.tsx diff --git a/src/popover/Popover.jsx b/src/popover/Popover.tsx similarity index 84% rename from src/popover/Popover.jsx rename to src/popover/Popover.tsx index 09c73aa..b02fb58 100644 --- a/src/popover/Popover.jsx +++ b/src/popover/Popover.tsx @@ -14,14 +14,22 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { forwardRef, useRef } from "react"; +import React, { forwardRef, HTMLAttributes } from "react"; import { DismissButton, useOverlay } from "@react-aria/overlays"; import { FocusScope } from "@react-aria/focus"; import classNames from "classnames"; -import styles from "./Popover.module.css"; import { useObjectRef } from "@react-aria/utils"; -export const Popover = forwardRef( +import styles from "./Popover.module.css"; + +interface Props extends HTMLAttributes { + isOpen: boolean; + onClose: () => void; + className?: string; + children?: JSX.Element; +} + +export const Popover = forwardRef( ({ isOpen = true, onClose, className, children, ...rest }, ref) => { const popoverRef = useObjectRef(ref); diff --git a/src/popover/PopoverMenu.jsx b/src/popover/PopoverMenu.jsx deleted file mode 100644 index fe7ee10..0000000 --- a/src/popover/PopoverMenu.jsx +++ /dev/null @@ -1,84 +0,0 @@ -/* -Copyright 2022 Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import React, { forwardRef, useRef } from "react"; -import styles from "./PopoverMenu.module.css"; -import { useMenuTriggerState } from "@react-stately/menu"; -import { useMenuTrigger } from "@react-aria/menu"; -import { OverlayContainer, useOverlayPosition } from "@react-aria/overlays"; -import { mergeProps, useObjectRef } from "@react-aria/utils"; -import classNames from "classnames"; -import { Popover } from "./Popover"; - -export const PopoverMenuTrigger = forwardRef( - ({ children, placement, className, disableOnState, ...rest }, ref) => { - const popoverMenuState = useMenuTriggerState(rest); - const buttonRef = useObjectRef(ref); - const { menuTriggerProps, menuProps } = useMenuTrigger( - {}, - popoverMenuState, - buttonRef - ); - - const popoverRef = useRef(); - - const { overlayProps } = useOverlayPosition({ - targetRef: buttonRef, - overlayRef: popoverRef, - placement: placement || "top", - offset: 5, - isOpen: popoverMenuState.isOpen, - }); - - if ( - !Array.isArray(children) || - children.length > 2 || - typeof children[1] !== "function" - ) { - throw new Error( - "PopoverMenu must have two props. The first being a button and the second being a render prop." - ); - } - - const [popoverTrigger, popoverMenu] = children; - - return ( -
- - {popoverMenuState.isOpen && ( - - - {popoverMenu({ - ...menuProps, - autoFocus: popoverMenuState.focusStrategy, - onClose: popoverMenuState.close, - })} - - - )} -
- ); - } -); diff --git a/src/popover/PopoverMenu.tsx b/src/popover/PopoverMenu.tsx new file mode 100644 index 0000000..2b4555e --- /dev/null +++ b/src/popover/PopoverMenu.tsx @@ -0,0 +1,96 @@ +/* +Copyright 2022 Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React, { forwardRef, useRef } from "react"; +import { useMenuTriggerState } from "@react-stately/menu"; +import { useMenuTrigger } from "@react-aria/menu"; +import { OverlayContainer, useOverlayPosition } from "@react-aria/overlays"; +import { mergeProps, useObjectRef } from "@react-aria/utils"; +import classNames from "classnames"; +import { MenuTriggerProps } from "@react-types/menu"; +import { Placement } from "@react-types/overlays"; + +import styles from "./PopoverMenu.module.css"; +import { Popover } from "./Popover"; + +interface PopoverMenuTriggerProps extends MenuTriggerProps { + children: JSX.Element; + placement: Placement; + className: string; + disableOnState: boolean; + [index: string]: unknown; +} + +export const PopoverMenuTrigger = forwardRef< + HTMLDivElement, + PopoverMenuTriggerProps +>(({ children, placement, className, disableOnState, ...rest }, ref) => { + const popoverMenuState = useMenuTriggerState(rest); + const buttonRef = useObjectRef(ref); + const { menuTriggerProps, menuProps } = useMenuTrigger( + {}, + popoverMenuState, + buttonRef + ); + + const popoverRef = useRef(); + + const { overlayProps } = useOverlayPosition({ + targetRef: buttonRef, + overlayRef: popoverRef, + placement: placement || "top", + offset: 5, + isOpen: popoverMenuState.isOpen, + }); + + if ( + !Array.isArray(children) || + children.length > 2 || + typeof children[1] !== "function" + ) { + throw new Error( + "PopoverMenu must have two props. The first being a button and the second being a render prop." + ); + } + + const [popoverTrigger, popoverMenu] = children; + + return ( +
+ + {popoverMenuState.isOpen && ( + + + {popoverMenu({ + ...menuProps, + autoFocus: popoverMenuState.focusStrategy, + onClose: popoverMenuState.close, + })} + + + )} +
+ ); +});