Skip to content

Commit 69bdc03

Browse files
committedJan 9, 2025·
chore: use composeRef instead of useImpertativeHandle
1 parent 7bea0ff commit 69bdc03

File tree

14 files changed

+45
-74
lines changed

14 files changed

+45
-74
lines changed
 

‎packages/fern-docs/components/src/FernInput.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export const FernInput = forwardRef<HTMLInputElement, FernInputProps>(
5959
<div className={cn("fern-input-group", className)}>
6060
{leftIcon && <span className="fern-input-icon">{leftIcon}</span>}
6161
<input
62-
ref={composeRefs(forwardedRef, inputRef)}
62+
ref={composeRefs(inputRef, forwardedRef)}
6363
{...props}
6464
className={cn("fern-input", inputClassName)}
6565
onChange={composeEventHandlers(

‎packages/fern-docs/components/src/FernNumericInput.tsx

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { useEventCallback } from "@fern-ui/react-commons";
2+
import { composeRefs } from "@radix-ui/react-compose-refs";
23
import cn from "clsx";
34
import { Minus, Plus } from "iconoir-react";
45
import {
@@ -7,7 +8,6 @@ import {
78
forwardRef,
89
useCallback,
910
useEffect,
10-
useImperativeHandle,
1111
useRef,
1212
useState,
1313
} from "react";
@@ -35,11 +35,9 @@ export const FernNumericInput = forwardRef<
3535
disallowFloat,
3636
...props
3737
},
38-
ref
38+
forwardedRef
3939
) {
4040
const inputRef = useRef<HTMLInputElement>(null);
41-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
42-
useImperativeHandle(ref, () => inputRef.current!);
4341

4442
const [internalValue, setInternalValue] = useState<number>();
4543
const timeout = useRef<ReturnType<typeof setTimeout> | null>(null);
@@ -127,7 +125,7 @@ export const FernNumericInput = forwardRef<
127125
/>
128126
)}
129127
<input
130-
ref={inputRef}
128+
ref={composeRefs(inputRef, forwardedRef)}
131129
type="number"
132130
className={cn("fern-input", inputClassName)}
133131
value={internalValue ?? value}

‎packages/fern-docs/components/src/FernTextarea.tsx

+4-11
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
1+
import { composeRefs } from "@radix-ui/react-compose-refs";
12
import cn from "clsx";
2-
import {
3-
ComponentProps,
4-
forwardRef,
5-
useEffect,
6-
useImperativeHandle,
7-
useRef,
8-
} from "react";
3+
import { ComponentProps, forwardRef, useEffect, useRef } from "react";
94

105
interface FernTextareaProps extends ComponentProps<"textarea"> {
116
onValueChange?: (value: string) => void;
@@ -15,12 +10,10 @@ interface FernTextareaProps extends ComponentProps<"textarea"> {
1510
export const FernTextarea = forwardRef<HTMLTextAreaElement, FernTextareaProps>(
1611
function FernTextarea(
1712
{ className, onValueChange, minLines = 2, ...props },
18-
ref
13+
forwardedRef
1914
) {
2015
const inputRef = useRef<HTMLTextAreaElement>(null);
2116

22-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
23-
useImperativeHandle(ref, () => inputRef.current!);
2417
const handleChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
2518
onValueChange?.(e.target.value);
2619
props.onChange?.(e);
@@ -30,7 +23,7 @@ export const FernTextarea = forwardRef<HTMLTextAreaElement, FernTextareaProps>(
3023
<div className={cn("fern-textarea-group", className)}>
3124
<textarea
3225
{...props}
33-
ref={inputRef}
26+
ref={composeRefs(inputRef, forwardedRef)}
3427
className="fern-textarea"
3528
onChange={handleChange}
3629
/>

‎packages/fern-docs/search-ui/src/components/desktop/desktop-ask-ai.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ export const DesktopCommandWithAskAI = forwardRef<
156156
<DesktopCommandRoot
157157
label={askAI ? "Ask AI" : "Search"}
158158
{...props}
159-
ref={composeRefs(forwardedRef, ref)}
159+
ref={composeRefs(ref, forwardedRef)}
160160
shouldFilter={!askAI}
161161
disableAutoSelection={askAI}
162162
onPopState={
@@ -487,7 +487,7 @@ const AskAIComposer = forwardRef<
487487
>
488488
<DesktopCommandInput asChild>
489489
<TextArea
490-
ref={composeRefs(forwardedRef, inputRef)}
490+
ref={composeRefs(inputRef, forwardedRef)}
491491
autoFocus
492492
placeholder="Ask AI a question..."
493493
minLines={1}

‎packages/fern-docs/search-ui/src/components/desktop/desktop-command-root.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ export const DesktopCommandRoot = forwardRef<
5252
>
5353
<Command.Root
5454
label="Search"
55-
ref={composeRefs(forwardedRef, ref)}
55+
ref={composeRefs(ref, forwardedRef)}
5656
{...props}
5757
id="fern-search-desktop-command"
5858
onKeyDown={composeEventHandlers(

‎packages/fern-docs/search-ui/src/components/desktop/desktop-command.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ const DesktopCommand = forwardRef<
6565
<DesktopCommandRoot
6666
label="Search"
6767
{...props}
68-
ref={composeRefs(forwardedRef, ref)}
68+
ref={composeRefs(ref, forwardedRef)}
6969
onPopState={composeEventHandlers(onPopState, handlePopFilters, {
7070
checkForDefaultPrevented: false,
7171
})}

‎packages/fern-docs/search-ui/src/components/shared/command-link.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export const CommandLink = forwardRef<
7171
return (
7272
<Command.Item {...props} value={href} asChild>
7373
<Comp
74-
ref={composeRefs(forwardedRef, ref)}
74+
ref={composeRefs(ref, forwardedRef)}
7575
href={href}
7676
target={target}
7777
rel={rel}

‎packages/fern-docs/ui/src/api-reference/endpoints/EndpointUrl.tsx

+6-6
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ import visitDiscriminatedUnion from "@fern-api/ui-core-utils/visitDiscriminatedU
44
import { CopyToClipboardButton } from "@fern-docs/components";
55
import { HttpMethodBadge } from "@fern-docs/components/badges";
66
import { useBooleanState } from "@fern-ui/react-commons";
7+
import { composeRefs } from "@radix-ui/react-compose-refs";
78
import cn from "clsx";
89
import React, {
910
PropsWithChildren,
1011
ReactElement,
11-
useImperativeHandle,
1212
useMemo,
1313
useRef,
1414
useState,
@@ -44,13 +44,10 @@ export const EndpointUrl = React.forwardRef<
4444
showEnvironment,
4545
options,
4646
},
47-
parentRef
47+
forwardedRef
4848
) {
4949
const ref = useRef<HTMLDivElement>(null);
5050

51-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
52-
useImperativeHandle(parentRef, () => ref.current!);
53-
5451
const [isHovered, setIsHovered] = useState(false);
5552
const isEditingEnvironment = useBooleanState(false);
5653

@@ -110,7 +107,10 @@ export const EndpointUrl = React.forwardRef<
110107
}, [options, environmentId, baseUrl]);
111108

112109
return (
113-
<div ref={ref} className={cn("flex items-center gap-1 pr-2", className)}>
110+
<div
111+
ref={composeRefs(ref, forwardedRef)}
112+
className={cn("flex items-center gap-1 pr-2", className)}
113+
>
114114
<HttpMethodBadge method={method} />
115115

116116
<div className={cn("flex items-center")}>

‎packages/fern-docs/ui/src/components/HorizontalOverflowMask.tsx

+4-11
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,14 @@
1+
import { composeRefs } from "@radix-ui/react-compose-refs";
12
import cn from "clsx";
23
import fastdom from "fastdom";
3-
import React, {
4-
PropsWithChildren,
5-
useEffect,
6-
useImperativeHandle,
7-
useRef,
8-
useState,
9-
} from "react";
4+
import React, { PropsWithChildren, useEffect, useRef, useState } from "react";
105
import { noop } from "ts-essentials";
116

127
export const HorizontalOverflowMask = React.forwardRef<
138
HTMLDivElement,
149
PropsWithChildren<{ className?: string }>
15-
>(function HorizontalOverflowMask({ children, className }, parentRef) {
10+
>(function HorizontalOverflowMask({ children, className }, forwardedRef) {
1611
const ref = useRef<HTMLDivElement>(null);
17-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
18-
useImperativeHandle(parentRef, () => ref.current!);
1912

2013
const [showLeftMask, setShowLeftMask] = useState(false);
2114
const [hideRightMask, setHideRightMask] = useState(false);
@@ -55,7 +48,7 @@ export const HorizontalOverflowMask = React.forwardRef<
5548

5649
return (
5750
<div
58-
ref={ref}
51+
ref={composeRefs(ref, forwardedRef)}
5952
className={cn(
6053
"fern-x-overflow",
6154
{

‎packages/fern-docs/ui/src/header/Announcement.tsx

+3-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { FernButton } from "@fern-docs/components";
22
import { useResizeObserver } from "@fern-ui/react-commons";
3+
import { composeRefs } from "@radix-ui/react-compose-refs";
34
import clsx from "clsx";
45
import { AnimatePresence, motion } from "framer-motion";
56
import { Xmark } from "iconoir-react";
67
import { useAtom, useAtomValue, useSetAtom } from "jotai";
7-
import { ReactElement, forwardRef, useImperativeHandle, useRef } from "react";
8+
import { ReactElement, forwardRef, useRef } from "react";
89
import {
910
ANNOUNCEMENT_CONFIG_ATOM,
1011
ANNOUNCEMENT_DISMISSED_ATOM,
@@ -32,12 +33,9 @@ const AnnouncementInternal = forwardRef<
3233
}
3334
});
3435

35-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
36-
useImperativeHandle(forwardedRef, () => ref.current!);
37-
3836
return (
3937
<motion.div
40-
ref={ref}
38+
ref={composeRefs(ref, forwardedRef)}
4139
{...props}
4240
className={clsx("overflow-hidden", className)}
4341
>

‎packages/fern-docs/ui/src/mdx/components/iframe/IFrame.tsx

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { FernButton } from "@fern-docs/components";
22
import { usePrevious } from "@fern-ui/react-commons";
3+
import { composeRefs } from "@radix-ui/react-compose-refs";
34
import * as Tooltip from "@radix-ui/react-tooltip";
45
import { Expand } from "iconoir-react";
56
import {
@@ -8,7 +9,6 @@ import {
89
RefObject,
910
forwardRef,
1011
useEffect,
11-
useImperativeHandle,
1212
useRef,
1313
useState,
1414
} from "react";
@@ -29,11 +29,9 @@ export const IFrame = forwardRef<HTMLIFrameElement, IFrame.Props>(
2929
experimental_onReceiveMessage,
3030
...props
3131
},
32-
ref
32+
forwardedRef
3333
): ReactElement => {
3434
const iframeRef = useRef<HTMLIFrameElement>(null);
35-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
36-
useImperativeHandle(ref, () => iframeRef.current!);
3735

3836
useEffect(() => {
3937
const contentWindow = iframeRef.current?.contentWindow;
@@ -65,7 +63,13 @@ export const IFrame = forwardRef<HTMLIFrameElement, IFrame.Props>(
6563
}
6664

6765
// prevent hydration mismatch by setting data-state to closed
68-
return <iframe data-state="closed" ref={ref} {...props} />;
66+
return (
67+
<iframe
68+
data-state="closed"
69+
ref={composeRefs(iframeRef, forwardedRef)}
70+
{...props}
71+
/>
72+
);
6973
}
7074
);
7175

‎packages/fern-docs/ui/src/playground/endpoint/PlaygroundEndpointSelectorContent.tsx

+1-10
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,7 @@ import {
88
} from "@fern-docs/components";
99
import cn, { clsx } from "clsx";
1010
import { Search, Slash, Xmark } from "iconoir-react";
11-
import {
12-
Fragment,
13-
forwardRef,
14-
useEffect,
15-
useImperativeHandle,
16-
useRef,
17-
useState,
18-
} from "react";
11+
import { Fragment, forwardRef, useEffect, useRef, useState } from "react";
1912
import { BuiltWithFern } from "../../sidebar/BuiltWithFern";
2013
import { ApiGroup } from "../utils/flatten-apis";
2114
import { PlaygroundEndpointSelectorLeafNode } from "./PlaygroundEndpointSelectorLeafNode";
@@ -48,8 +41,6 @@ export const PlaygroundEndpointSelectorContent = forwardRef<
4841
PlaygroundEndpointSelectorContentProps
4942
>(({ apiGroups, closeDropdown, selectedEndpoint, className }, ref) => {
5043
const scrollRef = useRef<HTMLDivElement>(null);
51-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
52-
useImperativeHandle(ref, () => scrollRef.current!);
5344

5445
const [filterValue, setFilterValue] = useState<string>("");
5546

‎packages/fern-docs/ui/src/search/algolia/SearchBox.tsx

+5-11
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import { getPlatform } from "@fern-api/ui-core-utils";
22
import { FernButton, FernInput } from "@fern-docs/components";
33
import { useKeyboardCommand, useKeyboardPress } from "@fern-ui/react-commons";
4+
import { composeRefs } from "@radix-ui/react-compose-refs";
45
import { Search, Xmark } from "iconoir-react";
56
import { atom, useSetAtom } from "jotai";
67
import {
78
ReactElement,
89
forwardRef,
910
useCallback,
1011
useEffect,
11-
useImperativeHandle,
1212
useRef,
1313
useState,
1414
} from "react";
@@ -26,7 +26,7 @@ export const SEARCH_BOX_MOUNTED = atom(false);
2626
export const SearchBox = forwardRef<HTMLInputElement, SearchBoxProps>(
2727
function SearchBox(
2828
{ queryHook, className, inputClassName, placeholder },
29-
ref
29+
forwardedRef
3030
): ReactElement {
3131
const { query, refine } = useSearchBox({ queryHook });
3232
const [inputValue, setInputValue] = useState(query);
@@ -42,9 +42,6 @@ export const SearchBox = forwardRef<HTMLInputElement, SearchBoxProps>(
4242
};
4343
}, [setMounted]);
4444

45-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
46-
useImperativeHandle(ref, () => inputRef.current!);
47-
4845
const setQuery = useCallback(
4946
(newQuery: string) => {
5047
setInputValue(newQuery);
@@ -113,7 +110,7 @@ export const SearchBox = forwardRef<HTMLInputElement, SearchBoxProps>(
113110
}}
114111
>
115112
<input
116-
ref={inputRef}
113+
ref={composeRefs(inputRef, forwardedRef)}
117114
className={inputClassName}
118115
autoComplete="off"
119116
autoCorrect="off"
@@ -137,15 +134,12 @@ export const SearchBox = forwardRef<HTMLInputElement, SearchBoxProps>(
137134
export const SearchMobileBox = forwardRef<HTMLInputElement, SearchBoxProps>(
138135
function SearchBox(
139136
{ queryHook, className, inputClassName, placeholder, onFocus },
140-
ref
137+
forwardedRef
141138
): ReactElement {
142139
const { query, refine } = useSearchBox({ queryHook });
143140
const [inputValue, setInputValue] = useState(query);
144141
const inputRef = useRef<HTMLInputElement>(null);
145142

146-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
147-
useImperativeHandle(ref, () => inputRef.current!);
148-
149143
const setQuery = useCallback(
150144
(newQuery: string) => {
151145
setInputValue(newQuery);
@@ -180,7 +174,7 @@ export const SearchMobileBox = forwardRef<HTMLInputElement, SearchBoxProps>(
180174
}}
181175
>
182176
<FernInput
183-
ref={inputRef}
177+
ref={composeRefs(inputRef, forwardedRef)}
184178
className={inputClassName}
185179
autoComplete="off"
186180
autoCorrect="off"

‎packages/fern-docs/ui/src/sidebar/SidebarLink.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ type SidebarLinkProps = PropsWithChildren<
6565
>;
6666

6767
const SidebarLinkInternal = forwardRef<HTMLDivElement, SidebarLinkProps>(
68-
(props, forwardRef) => {
68+
(props, forwardedRef) => {
6969
const {
7070
icon,
7171
className,
@@ -171,7 +171,7 @@ const SidebarLinkInternal = forwardRef<HTMLDivElement, SidebarLinkProps>(
171171

172172
return (
173173
<div
174-
ref={composeRefs(forwardRef, ref)}
174+
ref={composeRefs(ref, forwardedRef)}
175175
className={cn("fern-sidebar-link-container", className)}
176176
data-state={selected ? "active" : "inactive"}
177177
>
@@ -221,7 +221,7 @@ export const SidebarLink = memo(SidebarLinkInternal);
221221
export const SidebarSlugLink = forwardRef<
222222
HTMLDivElement,
223223
PropsWithChildren<SidebarSlugLinkProps>
224-
>((props, forwardRef) => {
224+
>((props, forwardedRef) => {
225225
const { slug, ...innerProps } = props;
226226
const ref = useRef<HTMLDivElement>(null);
227227

@@ -244,7 +244,7 @@ export const SidebarSlugLink = forwardRef<
244244
return (
245245
<SidebarLink
246246
{...innerProps}
247-
ref={composeRefs(forwardRef, ref)}
247+
ref={composeRefs(ref, forwardedRef)}
248248
href={href}
249249
onClick={composeEventHandlers(innerProps.onClick, () => {
250250
if (href) {

0 commit comments

Comments
 (0)
Please sign in to comment.