Skip to content

Commit

Permalink
Merge pull request #56 from reg-viz/refactor/migrate-to-jotai
Browse files Browse the repository at this point in the history
refactor: migrate to jotai from unstated-next
  • Loading branch information
wadackel committed Apr 28, 2024
2 parents a1a70d9 + 0acb04b commit 26e5c21
Show file tree
Hide file tree
Showing 29 changed files with 704 additions and 731 deletions.
3 changes: 2 additions & 1 deletion package.json
Expand Up @@ -55,16 +55,17 @@
"focus-trap": "^7.5.4",
"fuse.js": "^7.0.0",
"history": "^5.3.0",
"jotai": "^2.8.0",
"keycode": "^2.2.0",
"mitt": "^3.0.1",
"mousetrap": "^1.6.5",
"query-string": "^7.0.1",
"rc-slider": "^10.5.0",
"re-resizable": "^6.9.11",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-md-spinner": "^1.0.0",
"react-transition-group": "^4.4.5",
"tinykeys": "^2.1.0",
"unstated-next": "^1.1.0",
"use-intersection": "^0.2.1",
"x-img-diff-js": "^0.3.5"
Expand Down
90 changes: 32 additions & 58 deletions src/App/App.tsx
Expand Up @@ -8,20 +8,19 @@ import { Notification } from '../components/Notification';
import { Sidebar } from '../components/Sidebar';
import { Viewer } from '../components/Viewer';
import { HelpIcon } from '../components/icons/HelpIcon';
import { EntityContainer } from '../containers/entity/EntityContainer';
import { SidebarContainer } from '../containers/sidebar/SidebarContainer';
import { useMousetrap } from '../hooks/useMousetrap';
import { findFirstFocusable } from '../utils/selector';
import { useKey } from '../hooks/useKey';
import { useEntities } from '../states/entity';
import { useSidebarMutators } from '../states/sidebar';
import { Color } from '../styles/variables.css';
import { findFirstFocusable } from '../utils/selector';
import * as styles from './App.css';

export type Props = {};

export const App = () => {
const sidebar = SidebarContainer.useContainer();
const { toggle: toggleSidebar } = useSidebarMutators();

const { newItems, failedItems, deletedItems, passedItems } =
EntityContainer.useContainer();
const { newItems, failedItems, deletedItems, passedItems } = useEntities();

const [helpDialogOpen, setHelpDialogOpen] = useState(false);

Expand All @@ -37,15 +36,15 @@ export const App = () => {
setHelpDialogOpen(false);
}, []);

useMousetrap(['/', 's'], null, (e) => {
useKey(null, ['/', 's'], (e) => {
e.preventDefault();

if (filterRef.current != null) {
filterRef.current.focus();
}
});

useMousetrap('g s', null, () => {
useKey(null, ['g s'], () => {
const { current: list } = listRef;
if (list == null) {
return;
Expand All @@ -59,60 +58,35 @@ export const App = () => {
first.focus();
});

useMousetrap(
'g c',
null,
() => {
if (failedItems.length > 0) {
window.location.hash = 'changed';
}
},
[failedItems],
);
useKey(null, ['g c'], () => {
if (failedItems.length > 0) {
window.location.hash = 'changed';
}
});

useMousetrap(
'g n',
null,
() => {
if (newItems.length > 0) {
window.location.hash = 'new';
}
},
[newItems],
);
useKey(null, ['g n'], () => {
if (newItems.length > 0) {
window.location.hash = 'new';
}
});

useMousetrap(
'g d',
null,
() => {
if (deletedItems.length > 0) {
window.location.hash = 'deleted';
}
},
[deletedItems],
);
useKey(null, ['g d'], () => {
if (deletedItems.length > 0) {
window.location.hash = 'deleted';
}
});

useMousetrap(
'g p',
null,
() => {
if (passedItems.length > 0) {
window.location.hash = 'passed';
}
},
[passedItems],
);
useKey(null, ['g p'], () => {
if (passedItems.length > 0) {
window.location.hash = 'passed';
}
});

useMousetrap(
'f',
null,
() => {
sidebar.toggle();
},
[sidebar],
);
useKey(null, ['f'], () => {
toggleSidebar();
});

useMousetrap('?', null, () => {
useKey(null, ['Shift+?'], () => {
setHelpDialogOpen(true);
});

Expand Down
38 changes: 12 additions & 26 deletions src/App/index.tsx
@@ -1,34 +1,20 @@
import { Provider } from 'jotai';
import React from 'react';
import type { RegData } from '../types/reg';
import { EntityContainer } from '../containers/entity/EntityContainer';
import { ViewerContainer } from '../containers/viewer/ViewerContainer';
import { NotificationContainer } from '../containers/notification/NotificationContainer';
import { HistoryContextProvider } from '../context/HistoryContext';
import { AnchorScrollProvider } from '../context/AnchorScrollContext';
import type { WorkerClient } from '../worker-client';
import { WorkerContext } from '../context/WorkerContext';
import { SidebarContainer } from '../containers/sidebar/SidebarContainer';
import { HistoryContextProvider } from '../context/HistoryContext';
import type { Store } from '../types/store';
import { App as Component } from './App';

export type Props = {
data: RegData;
worker: WorkerClient;
store: Store;
};

export const App = ({ data, worker }: Props) => (
<HistoryContextProvider>
<AnchorScrollProvider>
<WorkerContext.Provider value={worker}>
<NotificationContainer.Provider>
<EntityContainer.Provider initialState={data}>
<SidebarContainer.Provider initialState={data.links}>
<ViewerContainer.Provider>
<Component />
</ViewerContainer.Provider>
</SidebarContainer.Provider>
</EntityContainer.Provider>
</NotificationContainer.Provider>
</WorkerContext.Provider>
</AnchorScrollProvider>
</HistoryContextProvider>
export const App = ({ store }: Props) => (
<Provider store={store}>
<HistoryContextProvider>
<AnchorScrollProvider>
<Component />
</AnchorScrollProvider>
</HistoryContextProvider>
</Provider>
);
52 changes: 21 additions & 31 deletions src/components/ChoiceGroup/ChoiceGroup.tsx
Expand Up @@ -5,7 +5,7 @@ import React, {
useMemo,
useRef,
} from 'react';
import { useMousetrap } from '../../hooks/useMousetrap';
import { useKey } from '../../hooks/useKey';
import type { Modify } from '../../utils/types';
import * as styles from './ChoiceGroup.css';
import { ChoiceButton } from './internal/ChoiceButton';
Expand Down Expand Up @@ -64,41 +64,31 @@ export const ChoiceGroup = ({ value, options, onChange, ...rest }: Props) => {
changedByKey.current = false;
}, [buttonRefList, options, value]);

useMousetrap(
['right', 'l'],
rootRef.current,
(e) => {
e.stopPropagation();
useKey(rootRef, ['right', 'l'], (e) => {
e.stopPropagation();

const current = getValueIndex(options, value);
const next = current + 1;
if (next >= options.length) {
return;
}
const current = getValueIndex(options, value);
const next = current + 1;
if (next >= options.length) {
return;
}

changedByKey.current = true;
onChange(options[next].value, next);
},
[options, value, onChange],
);
changedByKey.current = true;
onChange(options[next].value, next);
});

useMousetrap(
['left', 'h'],
rootRef.current,
(e) => {
e.stopPropagation();
useKey(rootRef, ['left', 'h'], (e) => {
e.stopPropagation();

const current = getValueIndex(options, value);
const previous = current - 1;
if (previous < 0) {
return;
}
const current = getValueIndex(options, value);
const previous = current - 1;
if (previous < 0) {
return;
}

changedByKey.current = true;
onChange(options[previous].value, previous);
},
[options, value, onChange],
);
changedByKey.current = true;
onChange(options[previous].value, previous);
});

return (
<ul {...rest} ref={rootRef} className={styles.wrapper}>
Expand Down
1 change: 1 addition & 0 deletions src/components/Dialog/Dialog.css.ts
Expand Up @@ -71,6 +71,7 @@ export const content = style({
padding: Space * 5,
borderRadius: 4,
boxShadow: tokens.shadow.lv2,
background: tokens.color.white,
transitionProperty: 'opacity, transform',
WebkitTapHighlightColor: 'transparent',
':focus': {
Expand Down
23 changes: 6 additions & 17 deletions src/components/Dialog/Dialog.tsx
@@ -1,14 +1,14 @@
import { disableBodyScroll, enableBodyScroll } from 'body-scroll-lock';
import type { FocusTrap } from 'focus-trap';
import { createFocusTrap } from 'focus-trap';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import React, { useCallback, useEffect, useRef } from 'react';
import { CSSTransition } from 'react-transition-group';
import { useMousetrap } from '../../hooks/useMousetrap';
import { useKey } from '../../hooks/useKey';
import { Color, Duration } from '../../styles/variables.css';
import type { Modify } from '../../utils/types';
import { IconButton } from '../IconButton';
import { CloseIcon } from '../icons/CloseIcon';
import { Portal } from '../internal/Portal';
import { Color, Duration } from '../../styles/variables.css';
import * as styles from './Dialog.css';

const allowOutsideClick = () => true;
Expand All @@ -31,8 +31,6 @@ export const Dialog = ({
onRequestClose,
...rest
}: Props) => {
const [mounted, setMounted] = useState(false);

const bodyRef = useRef<HTMLDivElement>(null);
const innerRef = useRef<HTMLDivElement>(null);
const focusRef = useRef<FocusTrap | null>(null);
Expand All @@ -49,8 +47,6 @@ export const Dialog = ({
focusRef.current.activate();

disableBodyScroll(body);

setMounted(true);
}, []);

const handleExit = useCallback(() => {
Expand All @@ -63,8 +59,6 @@ export const Dialog = ({

focus.deactivate();
enableBodyScroll(body);

setMounted(false);
}, []);

const handleCloseClick = useCallback(
Expand All @@ -90,14 +84,9 @@ export const Dialog = ({
[],
);

useMousetrap(
'esc',
bodyRef.current,
() => {
onRequestClose();
},
[mounted, onRequestClose],
);
useKey(bodyRef, ['Escape'], () => {
onRequestClose();
});

return (
<Portal>
Expand Down
11 changes: 4 additions & 7 deletions src/components/Header/Header.tsx
Expand Up @@ -16,7 +16,7 @@ export type Props = {
max: number;
markersEnabled: boolean;
onRequestClose: () => void;
onMarkersToggle: (enabled: boolean) => void;
onMarkersToggle: () => void;
};

export const Header = ({
Expand All @@ -38,12 +38,9 @@ export const Header = ({
[onRequestClose],
);

const handleToggle = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
onMarkersToggle(e.currentTarget.checked);
},
[onMarkersToggle],
);
const handleToggle = useCallback(() => {
onMarkersToggle();
}, [onMarkersToggle]);

return (
<header className={styles.wrapper}>
Expand Down

0 comments on commit 26e5c21

Please sign in to comment.