From f3077599bc2433e67a2f8ef38ae6515b41693b63 Mon Sep 17 00:00:00 2001 From: David <33458145+davidmcpowell@users.noreply.github.com> Date: Mon, 27 Jan 2025 10:02:39 +0000 Subject: [PATCH] Merge pull request #23082 from overleaf/dp-file-outline-typescript Convert outline components to typescript GitOrigin-RevId: 9fd057f70d9de7b9b209697a5d33ea72d5d64daa --- .../js/features/ide-react/types/outline.ts | 8 +++++ .../{outline-item.jsx => outline-item.tsx} | 34 +++++++------------ .../{outline-list.jsx => outline-list.tsx} | 20 +++++------ .../outline/components/outline-pane.tsx | 3 +- .../{outline-root.jsx => outline-root.tsx} | 19 ++++++----- 5 files changed, 42 insertions(+), 42 deletions(-) create mode 100644 services/web/frontend/js/features/ide-react/types/outline.ts rename services/web/frontend/js/features/outline/components/{outline-item.jsx => outline-item.tsx} (79%) rename services/web/frontend/js/features/outline/components/{outline-list.jsx => outline-list.tsx} (80%) rename services/web/frontend/js/features/outline/components/{outline-root.jsx => outline-root.tsx} (76%) diff --git a/services/web/frontend/js/features/ide-react/types/outline.ts b/services/web/frontend/js/features/ide-react/types/outline.ts new file mode 100644 index 0000000000..d75d2b709c --- /dev/null +++ b/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 +} diff --git a/services/web/frontend/js/features/outline/components/outline-item.jsx b/services/web/frontend/js/features/outline/components/outline-item.tsx similarity index 79% rename from services/web/frontend/js/features/outline/components/outline-item.jsx rename to services/web/frontend/js/features/outline/components/outline-item.tsx index 7b7c51e5e7..08a6b0f942 100644 --- a/services/web/frontend/js/features/outline/components/outline-item.jsx +++ b/services/web/frontend/js/features/outline/components/outline-item.tsx @@ -1,9 +1,9 @@ import { useState, useEffect, useRef, memo } from 'react' -import PropTypes from 'prop-types' import scrollIntoViewIfNeeded from 'scroll-into-view-if-needed' import classNames from 'classnames' import OutlineList from './outline-list' import { OutlineItemToggleButton } from '@/features/outline/components/outline-item-toggle-button' +import { OutlineItemData } from '@/features/ide-react/types/outline' const OutlineItem = memo(function OutlineItem({ outlineItem, @@ -11,10 +11,16 @@ const OutlineItem = memo(function OutlineItem({ highlightedLine, matchesHighlightedLine, containsHighlightedLine, +}: { + outlineItem: OutlineItemData + jumpToLine: (line: number, syncToPdf: boolean) => void + highlightedLine?: number | null + matchesHighlightedLine?: boolean + containsHighlightedLine?: boolean }) { const [expanded, setExpanded] = useState(true) - const titleElementRef = useRef() - const isHighlightedRef = useRef(false) + const titleElementRef = useRef(null) + const isHighlightedRef = useRef(false) const mainItemClasses = classNames('outline-item', { 'outline-item-no-children': !outlineItem.children, @@ -27,16 +33,16 @@ const OutlineItem = memo(function OutlineItem({ 'outline-item-link-highlight': isHighlighted, }) - function handleOutlineItemLinkClick(event) { + function handleOutlineItemLinkClick(event: React.MouseEvent) { const syncToPdf = event.detail === 2 // double-click = sync to PDF jumpToLine(outlineItem.line, syncToPdf) } useEffect(() => { const wasHighlighted = isHighlightedRef.current - isHighlightedRef.current = isHighlighted + isHighlightedRef.current = !!isHighlighted - if (!wasHighlighted && isHighlighted) { + if (!wasHighlighted && isHighlighted && titleElementRef.current) { scrollIntoViewIfNeeded(titleElementRef.current, { scrollMode: 'if-needed', 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 diff --git a/services/web/frontend/js/features/outline/components/outline-list.jsx b/services/web/frontend/js/features/outline/components/outline-list.tsx similarity index 80% rename from services/web/frontend/js/features/outline/components/outline-list.jsx rename to services/web/frontend/js/features/outline/components/outline-list.tsx index d7930a01a1..fc8117c5ca 100644 --- a/services/web/frontend/js/features/outline/components/outline-list.jsx +++ b/services/web/frontend/js/features/outline/components/outline-list.tsx @@ -1,9 +1,9 @@ -import PropTypes from 'prop-types' import classNames from 'classnames' import OutlineItem from './outline-item' import { memo } from 'react' +import { OutlineItemData } from '@/features/ide-react/types/outline' -function getChildrenLines(children) { +function getChildrenLines(children?: OutlineItemData[]): number[] { return (children || []) .map(child => { return getChildrenLines(child.children).concat(child.line) @@ -17,6 +17,12 @@ const OutlineList = memo(function OutlineList({ isRoot, highlightedLine, containsHighlightedLine, +}: { + outline: OutlineItemData[] + jumpToLine: (line: number, syncToPdf: boolean) => void + isRoot?: boolean + highlightedLine?: number | null + containsHighlightedLine?: boolean }) { const listClasses = classNames('outline-item-list', { 'outline-item-list-root': isRoot, @@ -27,6 +33,8 @@ const OutlineList = memo(function OutlineList({ const matchesHighlightedLine = containsHighlightedLine && highlightedLine === outlineItem.line const itemContainsHighlightedLine = + highlightedLine !== undefined && + highlightedLine !== null && containsHighlightedLine && 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 diff --git a/services/web/frontend/js/features/outline/components/outline-pane.tsx b/services/web/frontend/js/features/outline/components/outline-pane.tsx index 764239ba8c..a52b06859e 100644 --- a/services/web/frontend/js/features/outline/components/outline-pane.tsx +++ b/services/web/frontend/js/features/outline/components/outline-pane.tsx @@ -4,10 +4,11 @@ import classNames from 'classnames' import OutlineRoot from './outline-root' import withErrorBoundary from '../../../infrastructure/error-boundary' import { OutlineToggleButton } from '@/features/outline/components/outline-toggle-button' +import { OutlineItemData } from '@/features/ide-react/types/outline' const OutlinePane = React.memo<{ isTexFile: boolean - outline: any[] + outline: OutlineItemData[] jumpToLine(line: number): void onToggle(value: boolean): void eventTracking: any diff --git a/services/web/frontend/js/features/outline/components/outline-root.jsx b/services/web/frontend/js/features/outline/components/outline-root.tsx similarity index 76% rename from services/web/frontend/js/features/outline/components/outline-root.jsx rename to services/web/frontend/js/features/outline/components/outline-root.tsx index 665a38e06a..c295617c3d 100644 --- a/services/web/frontend/js/features/outline/components/outline-root.jsx +++ b/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 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() 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