Merge pull request #13378 from overleaf/ii-review-panel-migration-create-context-api

[web] Create context api for review panel

GitOrigin-RevId: 3d550e2f3c14ecd0586d088f4ecb75acd44aa782
This commit is contained in:
ilkin-overleaf
2023-07-17 10:29:53 +00:00
committed by Copybot
parent 7ac4b7571f
commit 1918ef3767
8 changed files with 429 additions and 112 deletions
@@ -0,0 +1,19 @@
import classnames from 'classnames'
const reviewPanelClasses = ['ol-cm-review-panel']
type ContainerProps = {
children?: React.ReactNode
classNames?: Record<string, boolean>
style?: React.CSSProperties
}
function Container({ children, classNames, ...rest }: ContainerProps) {
return (
<div className={classnames(...reviewPanelClasses, classNames)} {...rest}>
{children}
</div>
)
}
export default Container
@@ -0,0 +1,12 @@
import Container from './container'
function CurrentFileContainer() {
return (
<Container>
<em>ReviewPanelCurrentFileContainer</em>
<div className="review-panel-tools">Tools</div>
</Container>
)
}
export default CurrentFileContainer
@@ -0,0 +1 @@
export type SubView = 'cur_file' | 'overview'
@@ -0,0 +1,11 @@
import Container from './container'
function OverviewContainer() {
return (
<Container>
<em>ReviewPanelOverviewContainer</em>
</Container>
)
}
export default OverviewContainer
@@ -1,5 +1,39 @@
import ReactDOM from 'react-dom'
import { useCodeMirrorViewContext } from '../codemirror-editor'
import {
ReviewPanelStateProvider,
useReviewPanelStateValueContext,
} from '../../context/review-panel-state-context'
import CurrentFileContainer from './current-file-container'
import OverviewContainer from './overview-container'
type ReviewPanelViewProps = {
parentDomNode: Element
}
function ReviewPanelView({ parentDomNode }: ReviewPanelViewProps) {
const { subView } = useReviewPanelStateValueContext()
return ReactDOM.createPortal(
<>
{subView === 'cur_file' ? (
<CurrentFileContainer />
) : (
<OverviewContainer />
)}
</>,
parentDomNode
)
}
function ReviewPanel() {
return <div>Content to be added.</div>
const view = useCodeMirrorViewContext()
return (
<ReviewPanelStateProvider>
<ReviewPanelView parentDomNode={view.scrollDOM} />
</ReviewPanelStateProvider>
)
}
export default ReviewPanel
@@ -0,0 +1,109 @@
import { createContext, useContext, useMemo } from 'react'
import useScopeValue from '../../../shared/hooks/use-scope-value'
import { SubView } from '../components/review-panel/nav'
interface ReviewPanelState {
values: {
subView: SubView
collapsed: Record<string, boolean>
}
updaterFns: {
setSubView: React.Dispatch<
React.SetStateAction<ReviewPanelState['values']['subView']>
>
setCollapsed: React.Dispatch<
React.SetStateAction<ReviewPanelState['values']['collapsed']>
>
}
}
function useAngularReviewPanelState(): ReviewPanelState {
const [subView, setSubView] = useScopeValue<SubView>('reviewPanel.subView')
const [collapsed, setCollapsed] = useScopeValue<Record<string, boolean>>(
'reviewPanel.overview.docsCollapsedState'
)
const values = useMemo<ReviewPanelState['values']>(
() => ({
subView,
collapsed,
}),
[subView, collapsed]
)
const updaterFns = useMemo<ReviewPanelState['updaterFns']>(
() => ({
setSubView,
setCollapsed,
}),
[setSubView, setCollapsed]
)
return { values, updaterFns }
}
const ReviewPanelStateValueContext = createContext<
ReviewPanelState['values'] | undefined
>(undefined)
type ReviewPanelStateValueProps = {
children?: React.ReactNode
value: ReviewPanelState['values']
}
function ReviewPanelStateValueProvider(props: ReviewPanelStateValueProps) {
return <ReviewPanelStateValueContext.Provider {...props} />
}
const ReviewPanelStateUpdaterFnsContext = createContext<
ReviewPanelState['updaterFns'] | undefined
>(undefined)
type ReviewPanelStateUpdaterFnsProviderProps = {
children?: React.ReactNode
value: ReviewPanelState['updaterFns']
}
function ReviewPanelStateUpdaterFnsProvider(
props: ReviewPanelStateUpdaterFnsProviderProps
) {
return <ReviewPanelStateUpdaterFnsContext.Provider {...props} />
}
type ReviewPanelStateProviderProps = {
children?: React.ReactNode
}
export function ReviewPanelStateProvider({
children,
}: ReviewPanelStateProviderProps) {
const { values, updaterFns } = useAngularReviewPanelState()
return (
<ReviewPanelStateValueProvider value={values}>
<ReviewPanelStateUpdaterFnsProvider value={updaterFns}>
{children}
</ReviewPanelStateUpdaterFnsProvider>
</ReviewPanelStateValueProvider>
)
}
export function useReviewPanelStateValueContext() {
const context = useContext(ReviewPanelStateValueContext)
if (!context) {
throw new Error(
'ReviewPanelStateValueContext is only available inside ReviewPanelStateProvider'
)
}
return context
}
export function useReviewPanelStateUpdaterFnsContext() {
const context = useContext(ReviewPanelStateUpdaterFnsContext)
if (!context) {
throw new Error(
'ReviewPanelStateUpdaterFnsContext is only available inside ReviewPanelStateProvider'
)
}
return context
}