Skip to content

Commit c543d9d

Browse files
committed
Upgrade Databrowser to React 19 #1026
1 parent 3a43928 commit c543d9d

21 files changed

Lines changed: 427 additions & 460 deletions

browser/data-browser/package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,16 @@
3131
"prismjs": "^1.29.0",
3232
"query-string": "^7.1.3",
3333
"quick-score": "^0.2.0",
34-
"react": "^18.3.1",
34+
"react": "^19.0.0",
3535
"react-colorful": "^5.6.1",
36-
"react-dom": "^18.3.1",
36+
"react-dom": "^19.0.0",
3737
"react-dropzone": "^11.7.1",
3838
"react-helmet-async": "^1.3.0",
3939
"react-hot-toast": "^2.4.1",
4040
"react-hotkeys-hook": "^3.4.7",
4141
"react-icons": "^4.12.0",
4242
"react-intersection-observer": "^9.13.1",
43-
"react-is": "^18.3.1",
43+
"react-is": "^19.0.0",
4444
"react-markdown": "^8.0.7",
4545
"react-pdf": "^9.1.1",
4646
"react-router": "^6.27.0",
@@ -57,8 +57,8 @@
5757
"devDependencies": {
5858
"@swc/plugin-styled-components": "^2.0.12",
5959
"@types/prismjs": "^1.26.5",
60-
"@types/react": "^18.3.12",
61-
"@types/react-dom": "^18.3.1",
60+
"@types/react": "^19.0.0",
61+
"@types/react-dom": "^19.0.0",
6262
"@types/react-pdf": "^7.0.0",
6363
"@types/react-router-dom": "^5.3.3",
6464
"@types/react-window": "^1.8.8",

browser/data-browser/src/components/Dialog/DialogGlobalContextProvider.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,14 @@ import { styled } from 'styled-components';
1616
interface DialogGlobalContext {
1717
openDialogs: string[];
1818
setDialogOpen: (id: string, open: boolean) => void;
19-
portal: RefObject<HTMLDivElement>;
19+
portal: RefObject<HTMLDivElement | null>;
2020
}
2121

22-
export const DialogContext = createContext<DialogGlobalContext>(null!);
22+
export const DialogContext = createContext<DialogGlobalContext>({
23+
openDialogs: [],
24+
setDialogOpen: () => {},
25+
portal: { current: null },
26+
});
2327

2428
export const DialogGlobalContextProvider: FC<PropsWithChildren> = ({
2529
children,

browser/data-browser/src/components/Dialog/useDialog.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export type UseDialogOptions<E extends HTMLElement> = {
1616
bindShow?: React.Dispatch<boolean>;
1717
onCancel?: () => void;
1818
onSuccess?: () => void;
19-
triggerRef?: React.RefObject<E>;
19+
triggerRef?: React.RefObject<E | null>;
2020
};
2121

2222
/** Sets up state, and functions to use with a {@link Dialog} */

browser/data-browser/src/components/Dropdown/DefaultTrigger.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export const buildDefaultTrigger = (
1515
): DropdownTriggerRenderFunction => {
1616
const Comp = (
1717
{ onClick, menuId, isActive }: DropdownTriggerProps,
18-
ref: React.Ref<HTMLButtonElement>,
18+
ref: React.Ref<HTMLButtonElement | null>,
1919
) => {
2020
const id = useId();
2121

browser/data-browser/src/components/Dropdown/DropdownContainer.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ export const DropdownContainer: React.FC<React.PropsWithChildren<unknown>> = ({
88
const portalRef = useRef<HTMLDivElement>(null);
99

1010
return (
11-
<DropdownPortalContext.Provider value={portalRef}>
11+
<DropdownPortalContext value={portalRef}>
1212
{children}
1313
<DropdownContainerDiv ref={portalRef}></DropdownContainerDiv>
14-
</DropdownPortalContext.Provider>
14+
</DropdownPortalContext>
1515
);
1616
};
1717

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import { createContext } from 'react';
22

33
export const DropdownPortalContext = createContext<
4-
React.RefObject<HTMLDivElement>
5-
>(null!);
4+
React.RefObject<HTMLDivElement | null>
5+
>({
6+
current: null,
7+
});

browser/data-browser/src/components/EditableTitle.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { UnsavedIndicator } from './UnsavedIndicator';
1313
export interface EditableTitleProps {
1414
resource: Resource;
1515
/** Uses `name` by default */
16-
parentRef?: React.RefObject<HTMLInputElement>;
16+
parentRef?: React.RefObject<HTMLInputElement | null>;
1717
id?: string;
1818
className?: string;
1919
}

browser/data-browser/src/components/IconButton/IconButton.tsx

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import {
22
ComponentType,
33
ButtonHTMLAttributes,
4-
forwardRef,
5-
PropsWithChildren,
64
AnchorHTMLAttributes,
75
} from 'react';
86
import { styled, DefaultTheme } from 'styled-components';
@@ -30,52 +28,51 @@ type BaseProps = {
3028
};
3129

3230
export type IconButtonProps = BaseProps &
33-
ButtonHTMLAttributes<HTMLButtonElement>;
31+
ButtonHTMLAttributes<HTMLButtonElement> & {
32+
ref?: React.Ref<HTMLButtonElement | null>;
33+
};
3434

35-
export const IconButton = forwardRef<
36-
HTMLButtonElement,
37-
PropsWithChildren<IconButtonProps>
38-
>(({ variant, children, color, ...props }, ref) => {
35+
export const IconButton: React.FC<React.PropsWithChildren<IconButtonProps>> = ({
36+
variant = IconButtonVariant.Simple,
37+
color = 'inherit',
38+
size = '1em',
39+
children,
40+
ref,
41+
...props
42+
}) => {
3943
const Comp = ComponentMap.get(variant!) ?? SimpleIconButton;
4044

4145
return (
42-
<Comp ref={ref} color={color!} {...props}>
46+
<Comp ref={ref} color={color} size={size} {...props}>
4347
{children}
4448
</Comp>
4549
);
46-
});
47-
48-
IconButton.displayName = 'IconButton';
49-
50-
const defaultProps = {
51-
variant: IconButtonVariant.Simple,
52-
color: 'inherit',
53-
size: '1em',
54-
} as IconButtonProps;
55-
56-
IconButton.defaultProps = defaultProps;
50+
};
5751

5852
export type IconButtonLinkProps = BaseProps &
5953
AnchorHTMLAttributes<HTMLAnchorElement> & {
6054
href: string;
55+
ref?: React.Ref<HTMLAnchorElement | null>;
6156
};
6257

63-
export const IconButtonLink = forwardRef<
64-
HTMLAnchorElement,
65-
PropsWithChildren<IconButtonLinkProps>
66-
>(({ variant, children, color, ...props }, ref) => {
58+
export const IconButtonLink: React.FC<
59+
React.PropsWithChildren<IconButtonLinkProps>
60+
> = ({
61+
variant = IconButtonVariant.Simple,
62+
color = 'inherit',
63+
size = '1em',
64+
ref,
65+
children,
66+
...props
67+
}) => {
6768
const Comp = ComponentMap.get(variant ?? IconButtonVariant.Simple)!;
6869

6970
return (
70-
<Comp ref={ref} color={color!} as='a' {...props}>
71+
<Comp ref={ref} color={color!} size={size} as='a' {...props}>
7172
{children}
7273
</Comp>
7374
);
74-
});
75-
76-
IconButtonLink.displayName = 'IconButtonLink';
77-
78-
IconButtonLink.defaultProps = defaultProps as IconButtonLinkProps;
75+
};
7976

8077
interface ButtonBaseProps {
8178
size?: string;

browser/data-browser/src/components/Popover.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,11 @@ const fadeIn = keyframes`
8787
`;
8888

8989
const Content = styled(RadixPopover.Content)`
90-
--popover-close-offset: ${p => p.theme.margin}rem;
90+
--popover-close-offset: ${p => p.theme.size()};
9191
--popover-close-size: 25px;
9292
--popover-close-safe-area: calc(
9393
var(--popover-close-size) + (var(--popover-close-offset) * 2) -
94-
${p => p.theme.margin}rem
94+
${p => p.theme.size()}
9595
);
9696
background-color: ${p => transparentize(0.2, p.theme.colors.bgBody)};
9797
backdrop-filter: blur(10px);
@@ -110,16 +110,16 @@ const Arrow = styled(RadixPopover.Arrow)`
110110
`;
111111

112112
const PopoverContainerContext =
113-
createContext<RefObject<HTMLDivElement>>(createRef());
113+
createContext<RefObject<HTMLDivElement | null>>(createRef());
114114

115115
export const PopoverContainer: FC<PropsWithChildren> = ({ children }) => {
116116
const popoverContainerRef = useRef<HTMLDivElement>(null);
117117

118118
return (
119119
<ContainerDiv ref={popoverContainerRef}>
120-
<PopoverContainerContext.Provider value={popoverContainerRef}>
120+
<PopoverContainerContext value={popoverContainerRef}>
121121
{children}
122-
</PopoverContainerContext.Provider>
122+
</PopoverContainerContext>
123123
</ContainerDiv>
124124
);
125125
};

browser/data-browser/src/components/TableEditor/ActiveCellIndicator.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ type OnScrollCallbackOptions = {
1717

1818
export interface ActiveCellIndicatorProps {
1919
sizeStr: string;
20-
scrollerRef: React.RefObject<HTMLDivElement>;
20+
scrollerRef: React.RefObject<HTMLDivElement | null>;
2121
setOnScroll: (
2222
onScroll: ({ scrollUpdateWasRequested }: OnScrollCallbackOptions) => void,
2323
) => void;
@@ -29,7 +29,7 @@ const cursorGoesOffscreen = (parentRect: DOMRect, childRect: DOMRect) => {
2929

3030
const getCornerIfMultiSelect = (
3131
cursorMode: CursorMode,
32-
ref: React.MutableRefObject<HTMLDivElement | null>,
32+
ref: React.RefObject<HTMLDivElement | null>,
3333
) => {
3434
if (cursorMode === CursorMode.MultiSelect && ref.current) {
3535
return ref.current.getBoundingClientRect();
@@ -68,7 +68,7 @@ export function ActiveCellIndicator({
6868

6969
/** Measure the size and position of the current active cell and morph the indicator to the same values. */
7070
const updatePosition = useCallback(
71-
(followHorizontaly = true) => {
71+
(followHorizontally = true) => {
7272
if (!activeCellRef.current || !scrollerRef.current) {
7373
setVisible(false);
7474

@@ -83,7 +83,7 @@ export function ActiveCellIndicator({
8383
multiSelectCornerCellRef,
8484
);
8585

86-
if (followHorizontaly && cursorGoesOffscreen(scrollerRect, cellRect)) {
86+
if (followHorizontally && cursorGoesOffscreen(scrollerRect, cellRect)) {
8787
setTransitioningOffscreen(true);
8888

8989
scrollIntoView(scrollerRef.current, scrollerRect, cellRect);

0 commit comments

Comments
 (0)