From 29cd8f584eb4467ae6d7c4c3f203ce660adba4a2 Mon Sep 17 00:00:00 2001 From: atomiks Date: Fri, 5 Apr 2024 10:10:33 +1100 Subject: [PATCH] refactor: improve types (#2842) --- packages/react/src/components/Composite.tsx | 26 ++++++------- .../react/src/components/FloatingArrow.tsx | 38 +++++++++---------- .../src/components/FloatingDelayGroup.tsx | 23 ++++++----- .../src/components/FloatingFocusManager.tsx | 6 +-- .../react/src/components/FloatingList.tsx | 18 +++++---- .../react/src/components/FloatingOverlay.tsx | 10 +++-- .../react/src/components/FloatingPortal.tsx | 27 +++++++------ .../react/src/components/FloatingTree.tsx | 17 ++++----- packages/react/src/components/FocusGuard.tsx | 8 ++-- 9 files changed, 88 insertions(+), 85 deletions(-) diff --git a/packages/react/src/components/Composite.tsx b/packages/react/src/components/Composite.tsx index 6eddd717b9..fbd825091a 100644 --- a/packages/react/src/components/Composite.tsx +++ b/packages/react/src/components/Composite.tsx @@ -42,8 +42,8 @@ const CompositeContext = React.createContext<{ }); type RenderProp = - | JSX.Element - | ((props: React.HTMLAttributes) => JSX.Element); + | React.JSX.Element + | ((props: React.HTMLAttributes) => React.JSX.Element); interface CompositeProps { /** @@ -112,8 +112,8 @@ const allKeys = [...horizontalKeys, ...verticalKeys]; export const Composite = React.forwardRef< HTMLElement, React.HTMLProps & CompositeProps ->(function Composite( - { +>(function Composite(props, forwardedRef) { + const { render, orientation = 'both', loop = true, @@ -123,10 +123,9 @@ export const Composite = React.forwardRef< onNavigate: externalSetActiveIndex, itemSizes, dense = false, - ...props - }, - forwardedRef, -) { + ...domProps + } = props; + const [internalActiveIndex, internalSetActiveIndex] = React.useState(0); const activeIndex = externalActiveIndex ?? internalActiveIndex; const onNavigate = useEffectEvent( @@ -272,12 +271,12 @@ export const Composite = React.forwardRef< } const computedProps: React.HTMLAttributes = { - ...props, + ...domProps, ...renderElementProps, ref: forwardedRef, 'aria-orientation': orientation === 'both' ? undefined : orientation, onKeyDown(e) { - props.onKeyDown?.(e); + domProps.onKeyDown?.(e); renderElementProps.onKeyDown?.(e); handleKeyDown(e); }, @@ -310,7 +309,8 @@ interface CompositeItemProps { export const CompositeItem = React.forwardRef< HTMLElement, React.HTMLProps & CompositeItemProps ->(function CompositeItem({render, ...props}, forwardedRef) { +>(function CompositeItem(props, forwardedRef) { + const {render, ...domProps} = props; const renderElementProps = render && typeof render !== 'function' ? render.props : {}; @@ -320,13 +320,13 @@ export const CompositeItem = React.forwardRef< const isActive = activeIndex === index; const computedProps: React.HTMLAttributes = { - ...props, + ...domProps, ...renderElementProps, ref: mergedRef, tabIndex: isActive ? 0 : -1, 'data-active': isActive ? '' : undefined, onFocus(e) { - props.onFocus?.(e); + domProps.onFocus?.(e); renderElementProps.onFocus?.(e); onNavigate(index); }, diff --git a/packages/react/src/components/FloatingArrow.tsx b/packages/react/src/components/FloatingArrow.tsx index 19a4d8b7ec..24bc5ecfc0 100644 --- a/packages/react/src/components/FloatingArrow.tsx +++ b/packages/react/src/components/FloatingArrow.tsx @@ -4,47 +4,40 @@ import * as React from 'react'; import {useId} from '../hooks/useId'; import type {Alignment, FloatingContext, Side} from '../types'; -export interface FloatingArrowProps extends React.SVGAttributes { +export interface FloatingArrowProps extends React.ComponentPropsWithRef<'svg'> { // Omit the original `refs` property from the context to avoid issues with // generics: https://github.com/floating-ui/floating-ui/issues/2483 /** * The floating context. */ context: Omit & {refs: any}; - /** * Width of the arrow. * @default 14 */ width?: number; - /** * Height of the arrow. * @default 7 */ height?: number; - /** * The corner radius (rounding) of the arrow tip. * @default 0 (sharp) */ tipRadius?: number; - /** * Forces a static offset over dynamic positioning under a certain condition. */ staticOffset?: string | number | null; - /** * Custom path string. */ d?: string; - /** * Stroke (border) color of the arrow. */ stroke?: string; - /** * Stroke (border) width of the arrow. */ @@ -56,7 +49,10 @@ export interface FloatingArrowProps extends React.SVGAttributes { * @see https://floating-ui.com/docs/FloatingArrow */ export const FloatingArrow = React.forwardRef(function FloatingArrow( - { + props: FloatingArrowProps, + ref: React.ForwardedRef, +): React.JSX.Element | null { + const { context: { placement, elements: {floating}, @@ -71,9 +67,8 @@ export const FloatingArrow = React.forwardRef(function FloatingArrow( d, style: {transform, ...restStyle} = {}, ...rest - }: FloatingArrowProps, - ref: React.Ref, -): JSX.Element | null { + } = props; + if (__DEV__) { if (!ref) { console.warn( @@ -91,8 +86,8 @@ export const FloatingArrow = React.forwardRef(function FloatingArrow( // Strokes must be double the border width, this ensures the stroke's width // works as you'd expect. - strokeWidth *= 2; - const halfStrokeWidth = strokeWidth / 2; + const computedStrokeWidth = strokeWidth * 2; + const halfStrokeWidth = computedStrokeWidth / 2; const svgX = (width / 2) * (tipRadius / -8 + 1); const svgY = ((height / 2) * tipRadius) / 4; @@ -132,7 +127,7 @@ export const FloatingArrow = React.forwardRef(function FloatingArrow( {...rest} aria-hidden ref={ref} - width={isCustomShape ? width : width + strokeWidth} + width={isCustomShape ? width : width + computedStrokeWidth} height={width} viewBox={`0 0 ${width} ${height > width ? height : width}`} style={{ @@ -143,31 +138,34 @@ export const FloatingArrow = React.forwardRef(function FloatingArrow( [side]: isVerticalSide || isCustomShape ? '100%' - : `calc(100% - ${strokeWidth / 2}px)`, + : `calc(100% - ${computedStrokeWidth / 2}px)`, transform: `${rotation}${transform ?? ''}`, ...restStyle, }} > - {strokeWidth > 0 && ( + {computedStrokeWidth > 0 && ( )} {/* In Firefox, for left/right placements there's a ~0.5px gap where the border can show through. Adding a stroke on the fill removes it. */} - + {/* Assumes the border-width of the floating element matches the stroke. */} diff --git a/packages/react/src/components/FloatingDelayGroup.tsx b/packages/react/src/components/FloatingDelayGroup.tsx index 5064184ddf..2173a96d05 100644 --- a/packages/react/src/components/FloatingDelayGroup.tsx +++ b/packages/react/src/components/FloatingDelayGroup.tsx @@ -57,11 +57,11 @@ interface FloatingDelayGroupProps { * `delay`. * @see https://floating-ui.com/docs/FloatingDelayGroup */ -export const FloatingDelayGroup = ({ - children, - delay, - timeoutMs = 0, -}: FloatingDelayGroupProps): JSX.Element => { +export const FloatingDelayGroup = ( + props: FloatingDelayGroupProps, +): React.JSX.Element => { + const {children, delay, timeoutMs = 0} = props; + const [state, setState] = React.useReducer( (prev: GroupState, next: Partial): GroupState => ({ ...prev, @@ -116,10 +116,13 @@ interface UseGroupOptions { * `FloatingDelayGroup`. * @see https://floating-ui.com/docs/FloatingDelayGroup */ -export const useDelayGroup = ( - {open, onOpenChange}: FloatingContext, - {id}: UseGroupOptions, -) => { +export function useDelayGroup( + context: FloatingContext, + options: UseGroupOptions, +) { + const {open, onOpenChange} = context; + const {id} = options; + const {currentId, setCurrentId, initialDelay, setState, timeoutMs} = useDelayGroupContext(); @@ -161,4 +164,4 @@ export const useDelayGroup = ( setCurrentId(id); } }, [open, setCurrentId, id]); -}; +} diff --git a/packages/react/src/components/FloatingFocusManager.tsx b/packages/react/src/components/FloatingFocusManager.tsx index 2db7c444ef..4c23f9c0e0 100644 --- a/packages/react/src/components/FloatingFocusManager.tsx +++ b/packages/react/src/components/FloatingFocusManager.tsx @@ -60,7 +60,7 @@ function getPreviouslyFocusedElement() { const VisuallyHiddenDismiss = React.forwardRef(function VisuallyHiddenDismiss( props: React.ButtonHTMLAttributes, - ref: React.Ref, + ref: React.ForwardedRef, ) { return (