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:
@@ -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
|
||||
+12
@@ -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'
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
import Container from './container'
|
||||
|
||||
function OverviewContainer() {
|
||||
return (
|
||||
<Container>
|
||||
<em>ReviewPanelOverviewContainer</em>
|
||||
</Container>
|
||||
)
|
||||
}
|
||||
|
||||
export default OverviewContainer
|
||||
+35
-1
@@ -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
|
||||
|
||||
+109
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user