Skip to content

Commit

Permalink
refactor: improve types (#2842)
Browse files Browse the repository at this point in the history
  • Loading branch information
atomiks committed Apr 4, 2024
1 parent 3a36db8 commit 29cd8f5
Show file tree
Hide file tree
Showing 9 changed files with 88 additions and 85 deletions.
26 changes: 13 additions & 13 deletions packages/react/src/components/Composite.tsx
Expand Up @@ -42,8 +42,8 @@ const CompositeContext = React.createContext<{
});

type RenderProp =
| JSX.Element
| ((props: React.HTMLAttributes<HTMLElement>) => JSX.Element);
| React.JSX.Element
| ((props: React.HTMLAttributes<HTMLElement>) => React.JSX.Element);

interface CompositeProps {
/**
Expand Down Expand Up @@ -112,8 +112,8 @@ const allKeys = [...horizontalKeys, ...verticalKeys];
export const Composite = React.forwardRef<
HTMLElement,
React.HTMLProps<HTMLElement> & CompositeProps
>(function Composite(
{
>(function Composite(props, forwardedRef) {
const {
render,
orientation = 'both',
loop = true,
Expand All @@ -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(
Expand Down Expand Up @@ -272,12 +271,12 @@ export const Composite = React.forwardRef<
}

const computedProps: React.HTMLAttributes<HTMLElement> = {
...props,
...domProps,
...renderElementProps,
ref: forwardedRef,
'aria-orientation': orientation === 'both' ? undefined : orientation,
onKeyDown(e) {
props.onKeyDown?.(e);
domProps.onKeyDown?.(e);
renderElementProps.onKeyDown?.(e);
handleKeyDown(e);
},
Expand Down Expand Up @@ -310,7 +309,8 @@ interface CompositeItemProps {
export const CompositeItem = React.forwardRef<
HTMLElement,
React.HTMLProps<HTMLElement> & CompositeItemProps
>(function CompositeItem({render, ...props}, forwardedRef) {
>(function CompositeItem(props, forwardedRef) {
const {render, ...domProps} = props;
const renderElementProps =
render && typeof render !== 'function' ? render.props : {};

Expand All @@ -320,13 +320,13 @@ export const CompositeItem = React.forwardRef<
const isActive = activeIndex === index;

const computedProps: React.HTMLAttributes<HTMLElement> = {
...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);
},
Expand Down
38 changes: 18 additions & 20 deletions packages/react/src/components/FloatingArrow.tsx
Expand Up @@ -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<SVGSVGElement> {
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<FloatingContext, 'refs'> & {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.
*/
Expand All @@ -56,7 +49,10 @@ export interface FloatingArrowProps extends React.SVGAttributes<SVGSVGElement> {
* @see https://floating-ui.com/docs/FloatingArrow
*/
export const FloatingArrow = React.forwardRef(function FloatingArrow(
{
props: FloatingArrowProps,
ref: React.ForwardedRef<SVGSVGElement>,
): React.JSX.Element | null {
const {
context: {
placement,
elements: {floating},
Expand All @@ -71,9 +67,8 @@ export const FloatingArrow = React.forwardRef(function FloatingArrow(
d,
style: {transform, ...restStyle} = {},
...rest
}: FloatingArrowProps,
ref: React.Ref<SVGSVGElement>,
): JSX.Element | null {
} = props;

if (__DEV__) {
if (!ref) {
console.warn(
Expand All @@ -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;
Expand Down Expand Up @@ -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={{
Expand All @@ -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 && (
<path
clipPath={`url(#${clipPathId})`}
fill="none"
stroke={stroke}
// Account for the stroke on the fill path rendered below.
strokeWidth={strokeWidth + (d ? 0 : 1)}
strokeWidth={computedStrokeWidth + (d ? 0 : 1)}
d={dValue}
/>
)}
{/* 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. */}
<path stroke={strokeWidth && !d ? rest.fill : 'none'} d={dValue} />
<path
stroke={computedStrokeWidth && !d ? rest.fill : 'none'}
d={dValue}
/>
{/* Assumes the border-width of the floating element matches the
stroke. */}
<clipPath id={clipPathId}>
<rect
x={-halfStrokeWidth}
y={halfStrokeWidth * (isCustomShape ? -1 : 1)}
width={width + strokeWidth}
width={width + computedStrokeWidth}
height={width}
/>
</clipPath>
Expand Down
23 changes: 13 additions & 10 deletions packages/react/src/components/FloatingDelayGroup.tsx
Expand Up @@ -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>): GroupState => ({
...prev,
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -161,4 +164,4 @@ export const useDelayGroup = (
setCurrentId(id);
}
}, [open, setCurrentId, id]);
};
}
6 changes: 3 additions & 3 deletions packages/react/src/components/FloatingFocusManager.tsx
Expand Up @@ -60,7 +60,7 @@ function getPreviouslyFocusedElement() {

const VisuallyHiddenDismiss = React.forwardRef(function VisuallyHiddenDismiss(
props: React.ButtonHTMLAttributes<HTMLButtonElement>,
ref: React.Ref<HTMLButtonElement>,
ref: React.ForwardedRef<HTMLButtonElement>,
) {
return (
<button
Expand All @@ -76,7 +76,7 @@ const VisuallyHiddenDismiss = React.forwardRef(function VisuallyHiddenDismiss(
export interface FloatingFocusManagerProps<
RT extends ReferenceType = ReferenceType,
> {
children: JSX.Element;
children: React.JSX.Element;
/**
* The floating context returned from `useFloating`.
*/
Expand Down Expand Up @@ -145,7 +145,7 @@ export interface FloatingFocusManagerProps<
*/
export function FloatingFocusManager<RT extends ReferenceType = ReferenceType>(
props: FloatingFocusManagerProps<RT>,
): JSX.Element {
): React.JSX.Element {
const {
context,
children,
Expand Down
18 changes: 10 additions & 8 deletions packages/react/src/components/FloatingList.tsx
Expand Up @@ -67,11 +67,9 @@ interface FloatingListProps {
* Provides context for a list of items within the floating element.
* @see https://floating-ui.com/docs/FloatingList
*/
export function FloatingList({
children,
elementsRef,
labelsRef,
}: FloatingListProps): JSX.Element {
export function FloatingList(props: FloatingListProps): React.JSX.Element {
const {children, elementsRef, labelsRef} = props;

const [map, setMap] = React.useState(() => new Map<Node, number | null>());

const register = React.useCallback((node: Node) => {
Expand Down Expand Up @@ -120,15 +118,19 @@ export interface UseListItemProps {
* `FloatingList`.
* @see https://floating-ui.com/docs/FloatingList#uselistitem
*/
export function useListItem({label}: UseListItemProps = {}): {
export function useListItem(props: UseListItemProps = {}): {
ref: (node: HTMLElement | null) => void;
index: number;
} {
const [index, setIndex] = React.useState<number | null>(null);
const componentRef = React.useRef<Node | null>(null);
const {label} = props;

const {register, unregister, map, elementsRef, labelsRef} =
React.useContext(FloatingListContext);

const [index, setIndex] = React.useState<number | null>(null);

const componentRef = React.useRef<Node | null>(null);

const ref = React.useCallback(
(node: HTMLElement | null) => {
componentRef.current = node;
Expand Down
10 changes: 6 additions & 4 deletions packages/react/src/components/FloatingOverlay.tsx
Expand Up @@ -20,10 +20,12 @@ export interface FloatingOverlayProps {
* It's a regular `<div>`, so it can be styled via any CSS solution you prefer.
* @see https://floating-ui.com/docs/FloatingOverlay
*/
export const FloatingOverlay = React.forwardRef<
HTMLDivElement,
React.HTMLProps<HTMLDivElement> & FloatingOverlayProps
>(function FloatingOverlay({lockScroll = false, ...rest}, ref) {
export const FloatingOverlay = React.forwardRef(function FloatingOverlay(
props: React.ComponentPropsWithoutRef<'div'> & FloatingOverlayProps,
ref: React.ForwardedRef<HTMLDivElement>,
) {
const {lockScroll = false, ...rest} = props;

const lockId = useId();

useModernLayoutEffect(() => {
Expand Down
27 changes: 13 additions & 14 deletions packages/react/src/components/FloatingPortal.tsx
Expand Up @@ -38,17 +38,19 @@ const attr = createAttribute('portal');
/**
* @see https://floating-ui.com/docs/FloatingPortal#usefloatingportalnode
*/
export function useFloatingPortalNode({
id,
root,
}: {
id?: string;
root?: HTMLElement | null | React.MutableRefObject<HTMLElement | null>;
} = {}) {
const [portalNode, setPortalNode] = React.useState<HTMLElement | null>(null);
export function useFloatingPortalNode(
props: {
id?: string;
root?: HTMLElement | null | React.MutableRefObject<HTMLElement | null>;
} = {},
) {
const {id, root} = props;

const uniqueId = useId();
const portalContext = usePortalContext();

const [portalNode, setPortalNode] = React.useState<HTMLElement | null>(null);

const portalNodeRef = React.useRef<HTMLDivElement | null>(null);

useModernLayoutEffect(() => {
Expand Down Expand Up @@ -132,12 +134,9 @@ interface FloatingPortalProps {
* while retaining its location in the React tree.
* @see https://floating-ui.com/docs/FloatingPortal
*/
export function FloatingPortal({
children,
id,
root = null,
preserveTabOrder = true,
}: FloatingPortalProps): JSX.Element {
export function FloatingPortal(props: FloatingPortalProps): React.JSX.Element {
const {children, id, root = null, preserveTabOrder = true} = props;

const portalNode = useFloatingPortalNode({id, root});
const [focusManagerState, setFocusManagerState] =
React.useState<FocusManagerState>(null);
Expand Down

0 comments on commit 29cd8f5

Please sign in to comment.