Просмотр исходного кода

Merge pull request #23082 from overleaf/dp-file-outline-typescript

Convert outline components to typescript

GitOrigin-RevId: 9fd057f70d9de7b9b209697a5d33ea72d5d64daa
David 1 год назад
Родитель
Сommit
f3077599bc

+ 8 - 0
services/web/frontend/js/features/ide-react/types/outline.ts

@@ -0,0 +1,8 @@
+export type OutlineItemData = {
+  line: number
+  title: string
+  level?: number
+  children?: OutlineItemData[]
+  from?: number
+  to?: number
+}

+ 12 - 22
services/web/frontend/js/features/outline/components/outline-item.jsx → services/web/frontend/js/features/outline/components/outline-item.tsx

@@ -1,9 +1,9 @@
 import { useState, useEffect, useRef, memo } from 'react'
 import { useState, useEffect, useRef, memo } from 'react'
-import PropTypes from 'prop-types'
 import scrollIntoViewIfNeeded from 'scroll-into-view-if-needed'
 import scrollIntoViewIfNeeded from 'scroll-into-view-if-needed'
 import classNames from 'classnames'
 import classNames from 'classnames'
 import OutlineList from './outline-list'
 import OutlineList from './outline-list'
 import { OutlineItemToggleButton } from '@/features/outline/components/outline-item-toggle-button'
 import { OutlineItemToggleButton } from '@/features/outline/components/outline-item-toggle-button'
+import { OutlineItemData } from '@/features/ide-react/types/outline'
 
 
 const OutlineItem = memo(function OutlineItem({
 const OutlineItem = memo(function OutlineItem({
   outlineItem,
   outlineItem,
@@ -11,10 +11,16 @@ const OutlineItem = memo(function OutlineItem({
   highlightedLine,
   highlightedLine,
   matchesHighlightedLine,
   matchesHighlightedLine,
   containsHighlightedLine,
   containsHighlightedLine,
+}: {
+  outlineItem: OutlineItemData
+  jumpToLine: (line: number, syncToPdf: boolean) => void
+  highlightedLine?: number | null
+  matchesHighlightedLine?: boolean
+  containsHighlightedLine?: boolean
 }) {
 }) {
   const [expanded, setExpanded] = useState(true)
   const [expanded, setExpanded] = useState(true)
-  const titleElementRef = useRef()
-  const isHighlightedRef = useRef(false)
+  const titleElementRef = useRef<HTMLButtonElement>(null)
+  const isHighlightedRef = useRef<boolean>(false)
 
 
   const mainItemClasses = classNames('outline-item', {
   const mainItemClasses = classNames('outline-item', {
     'outline-item-no-children': !outlineItem.children,
     'outline-item-no-children': !outlineItem.children,
@@ -27,16 +33,16 @@ const OutlineItem = memo(function OutlineItem({
     'outline-item-link-highlight': isHighlighted,
     'outline-item-link-highlight': isHighlighted,
   })
   })
 
 
-  function handleOutlineItemLinkClick(event) {
+  function handleOutlineItemLinkClick(event: React.MouseEvent) {
     const syncToPdf = event.detail === 2 // double-click = sync to PDF
     const syncToPdf = event.detail === 2 // double-click = sync to PDF
     jumpToLine(outlineItem.line, syncToPdf)
     jumpToLine(outlineItem.line, syncToPdf)
   }
   }
 
 
   useEffect(() => {
   useEffect(() => {
     const wasHighlighted = isHighlightedRef.current
     const wasHighlighted = isHighlightedRef.current
-    isHighlightedRef.current = isHighlighted
+    isHighlightedRef.current = !!isHighlighted
 
 
-    if (!wasHighlighted && isHighlighted) {
+    if (!wasHighlighted && isHighlighted && titleElementRef.current) {
       scrollIntoViewIfNeeded(titleElementRef.current, {
       scrollIntoViewIfNeeded(titleElementRef.current, {
         scrollMode: 'if-needed',
         scrollMode: 'if-needed',
         block: 'center',
         block: 'center',
@@ -89,20 +95,4 @@ const OutlineItem = memo(function OutlineItem({
   )
   )
 })
 })
 
 
-OutlineItem.propTypes = {
-  outlineItem: PropTypes.exact({
-    line: PropTypes.number.isRequired,
-    title: PropTypes.string.isRequired,
-    level: PropTypes.number,
-    children: PropTypes.array,
-    // Used for caching in CM6
-    from: PropTypes.number,
-    to: PropTypes.number,
-  }).isRequired,
-  jumpToLine: PropTypes.func.isRequired,
-  highlightedLine: PropTypes.number,
-  matchesHighlightedLine: PropTypes.bool,
-  containsHighlightedLine: PropTypes.bool,
-}
-
 export default OutlineItem
 export default OutlineItem

+ 10 - 10
services/web/frontend/js/features/outline/components/outline-list.jsx → services/web/frontend/js/features/outline/components/outline-list.tsx

@@ -1,9 +1,9 @@
-import PropTypes from 'prop-types'
 import classNames from 'classnames'
 import classNames from 'classnames'
 import OutlineItem from './outline-item'
 import OutlineItem from './outline-item'
 import { memo } from 'react'
 import { memo } from 'react'
+import { OutlineItemData } from '@/features/ide-react/types/outline'
 
 
-function getChildrenLines(children) {
+function getChildrenLines(children?: OutlineItemData[]): number[] {
   return (children || [])
   return (children || [])
     .map(child => {
     .map(child => {
       return getChildrenLines(child.children).concat(child.line)
       return getChildrenLines(child.children).concat(child.line)
@@ -17,6 +17,12 @@ const OutlineList = memo(function OutlineList({
   isRoot,
   isRoot,
   highlightedLine,
   highlightedLine,
   containsHighlightedLine,
   containsHighlightedLine,
+}: {
+  outline: OutlineItemData[]
+  jumpToLine: (line: number, syncToPdf: boolean) => void
+  isRoot?: boolean
+  highlightedLine?: number | null
+  containsHighlightedLine?: boolean
 }) {
 }) {
   const listClasses = classNames('outline-item-list', {
   const listClasses = classNames('outline-item-list', {
     'outline-item-list-root': isRoot,
     'outline-item-list-root': isRoot,
@@ -27,6 +33,8 @@ const OutlineList = memo(function OutlineList({
         const matchesHighlightedLine =
         const matchesHighlightedLine =
           containsHighlightedLine && highlightedLine === outlineItem.line
           containsHighlightedLine && highlightedLine === outlineItem.line
         const itemContainsHighlightedLine =
         const itemContainsHighlightedLine =
+          highlightedLine !== undefined &&
+          highlightedLine !== null &&
           containsHighlightedLine &&
           containsHighlightedLine &&
           getChildrenLines(outlineItem.children).includes(highlightedLine)
           getChildrenLines(outlineItem.children).includes(highlightedLine)
 
 
@@ -53,12 +61,4 @@ const OutlineList = memo(function OutlineList({
   )
   )
 })
 })
 
 
-OutlineList.propTypes = {
-  outline: PropTypes.array.isRequired,
-  jumpToLine: PropTypes.func.isRequired,
-  isRoot: PropTypes.bool,
-  highlightedLine: PropTypes.number,
-  containsHighlightedLine: PropTypes.bool,
-}
-
 export default OutlineList
 export default OutlineList

+ 2 - 1
services/web/frontend/js/features/outline/components/outline-pane.tsx

@@ -4,10 +4,11 @@ import classNames from 'classnames'
 import OutlineRoot from './outline-root'
 import OutlineRoot from './outline-root'
 import withErrorBoundary from '../../../infrastructure/error-boundary'
 import withErrorBoundary from '../../../infrastructure/error-boundary'
 import { OutlineToggleButton } from '@/features/outline/components/outline-toggle-button'
 import { OutlineToggleButton } from '@/features/outline/components/outline-toggle-button'
+import { OutlineItemData } from '@/features/ide-react/types/outline'
 
 
 const OutlinePane = React.memo<{
 const OutlinePane = React.memo<{
   isTexFile: boolean
   isTexFile: boolean
-  outline: any[]
+  outline: OutlineItemData[]
   jumpToLine(line: number): void
   jumpToLine(line: number): void
   onToggle(value: boolean): void
   onToggle(value: boolean): void
   eventTracking: any
   eventTracking: any

+ 10 - 9
services/web/frontend/js/features/outline/components/outline-root.jsx → services/web/frontend/js/features/outline/components/outline-root.tsx

@@ -1,9 +1,16 @@
-import PropTypes from 'prop-types'
 import { useTranslation } from 'react-i18next'
 import { useTranslation } from 'react-i18next'
-
 import OutlineList from './outline-list'
 import OutlineList from './outline-list'
+import { OutlineItemData } from '@/features/ide-react/types/outline'
 
 
-function OutlineRoot({ outline, jumpToLine, highlightedLine }) {
+function OutlineRoot({
+  outline,
+  jumpToLine,
+  highlightedLine,
+}: {
+  outline: OutlineItemData[]
+  jumpToLine: (line: number, syncToPdf: boolean) => void
+  highlightedLine?: number
+}) {
   const { t } = useTranslation()
   const { t } = useTranslation()
 
 
   return (
   return (
@@ -33,10 +40,4 @@ function OutlineRoot({ outline, jumpToLine, highlightedLine }) {
   )
   )
 }
 }
 
 
-OutlineRoot.propTypes = {
-  outline: PropTypes.array.isRequired,
-  jumpToLine: PropTypes.func.isRequired,
-  highlightedLine: PropTypes.number,
-}
-
 export default OutlineRoot
 export default OutlineRoot