From 4720f2d36b9e414eb4b17a126c05f2329af1c1d9 Mon Sep 17 00:00:00 2001 From: Tilman Vatteroth Date: Mon, 7 Jun 2021 22:09:13 +0200 Subject: [PATCH] Extract toc button (#1302) * Extract toc button Signed-off-by: Tilman Vatteroth --- .../use-adapted-line-markers-callback.ts | 37 ----------------- .../hooks/use-on-iframe-load.ts | 37 ----------------- .../show-on-prop-change-image-lightbox.tsx | 37 ----------------- .../editor-page/editor-pane/editor-pane.tsx | 2 +- .../table-of-contents/table-of-contents.scss | 12 ------ src/components/intro-page/intro-page.tsx | 1 - .../render-page/markdown-document.tsx | 28 +++---------- .../markdown-toc-button.scss | 17 ++++++++ .../table-of-contents-hovering-button.tsx | 41 +++++++++++++++++++ .../width-based-table-of-contents.tsx | 35 ++++++++++++++++ 10 files changed, 99 insertions(+), 148 deletions(-) delete mode 100644 src/components/editor-page/document-renderer-pane/hooks/use-adapted-line-markers-callback.ts delete mode 100644 src/components/editor-page/document-renderer-pane/hooks/use-on-iframe-load.ts delete mode 100644 src/components/editor-page/document-renderer-pane/show-on-prop-change-image-lightbox.tsx create mode 100644 src/components/render-page/markdown-toc-button/markdown-toc-button.scss create mode 100644 src/components/render-page/markdown-toc-button/table-of-contents-hovering-button.tsx create mode 100644 src/components/render-page/width-based-table-of-contents.tsx diff --git a/src/components/editor-page/document-renderer-pane/hooks/use-adapted-line-markers-callback.ts b/src/components/editor-page/document-renderer-pane/hooks/use-adapted-line-markers-callback.ts deleted file mode 100644 index 03ec762ff..000000000 --- a/src/components/editor-page/document-renderer-pane/hooks/use-adapted-line-markers-callback.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { RefObject, useCallback } from 'react' -import { LineMarkerPosition } from '../../../markdown-renderer/types' - -export const useAdaptedLineMarkerCallback = ( - documentRenderPaneRef: RefObject | undefined, - rendererRef: RefObject, - onLineMarkerPositionChanged: ((lineMarkerPosition: LineMarkerPosition[]) => void) | undefined -): ((lineMarkerPosition: LineMarkerPosition[]) => void) => { - return useCallback( - (linkMarkerPositions) => { - if ( - !onLineMarkerPositionChanged || - !documentRenderPaneRef || - !documentRenderPaneRef.current || - !rendererRef.current - ) { - return - } - const documentRenderPaneTop = documentRenderPaneRef.current.offsetTop ?? 0 - const rendererTop = rendererRef.current.offsetTop ?? 0 - const offset = rendererTop - documentRenderPaneTop - onLineMarkerPositionChanged( - linkMarkerPositions.map((oldMarker) => ({ - line: oldMarker.line, - position: oldMarker.position + offset - })) - ) - }, - [documentRenderPaneRef, onLineMarkerPositionChanged, rendererRef] - ) -} diff --git a/src/components/editor-page/document-renderer-pane/hooks/use-on-iframe-load.ts b/src/components/editor-page/document-renderer-pane/hooks/use-on-iframe-load.ts deleted file mode 100644 index 2af724262..000000000 --- a/src/components/editor-page/document-renderer-pane/hooks/use-on-iframe-load.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { RefObject, useCallback, useRef } from 'react' -import { IframeEditorToRendererCommunicator } from '../../../render-page/iframe-editor-to-renderer-communicator' - -export const useOnIframeLoad = ( - frameReference: RefObject, - iframeCommunicator: IframeEditorToRendererCommunicator, - rendererOrigin: string, - renderPageUrl: string, - onNavigateAway: () => void -): (() => void) => { - const sendToRenderPage = useRef(true) - - return useCallback(() => { - const frame = frameReference.current - if (!frame || !frame.contentWindow) { - iframeCommunicator.unsetOtherSide() - return - } - - if (sendToRenderPage.current) { - iframeCommunicator.setOtherSide(frame.contentWindow, rendererOrigin) - sendToRenderPage.current = false - return - } else { - onNavigateAway() - console.error('Navigated away from unknown URL') - frame.src = renderPageUrl - sendToRenderPage.current = true - } - }, [frameReference, iframeCommunicator, onNavigateAway, renderPageUrl, rendererOrigin]) -} diff --git a/src/components/editor-page/document-renderer-pane/show-on-prop-change-image-lightbox.tsx b/src/components/editor-page/document-renderer-pane/show-on-prop-change-image-lightbox.tsx deleted file mode 100644 index fed0aad82..000000000 --- a/src/components/editor-page/document-renderer-pane/show-on-prop-change-image-lightbox.tsx +++ /dev/null @@ -1,37 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) - * - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import React, { useCallback, useEffect, useState } from 'react' -import { ImageLightboxModal } from '../../markdown-renderer/replace-components/image/image-lightbox-modal' -import { ImageDetails } from '../../render-page/rendering-message' - -export interface ShowOnPropChangeImageLightboxProps { - details?: ImageDetails -} - -export const ShowOnPropChangeImageLightbox: React.FC = ({ details }) => { - const [show, setShow] = useState(false) - - const hideLightbox = useCallback(() => { - setShow(false) - }, []) - - useEffect(() => { - if (details) { - setShow(true) - } - }, [details]) - - return ( - - ) -} diff --git a/src/components/editor-page/editor-pane/editor-pane.tsx b/src/components/editor-page/editor-pane/editor-pane.tsx index 5d4a2b3c0..21b97835a 100644 --- a/src/components/editor-page/editor-pane/editor-pane.tsx +++ b/src/components/editor-page/editor-pane/editor-pane.tsx @@ -164,7 +164,7 @@ export const EditorPane: React.FC = ({ ) const onCursorActivity = useCallback( - (editorWithActivity) => { + (editorWithActivity: Editor) => { setStatusBarInfo(createStatusInfo(editorWithActivity, maxLength)) }, [maxLength] diff --git a/src/components/editor-page/table-of-contents/table-of-contents.scss b/src/components/editor-page/table-of-contents/table-of-contents.scss index cb43eac9b..5c8dc6393 100644 --- a/src/components/editor-page/table-of-contents/table-of-contents.scss +++ b/src/components/editor-page/table-of-contents/table-of-contents.scss @@ -62,15 +62,3 @@ } } } - -.markdown-toc-sidebar-button { - position: fixed; - right: 70px; - bottom: 30px; - - & > .dropup { - position: sticky; - bottom: 20px; - right: 0; - } -} diff --git a/src/components/intro-page/intro-page.tsx b/src/components/intro-page/intro-page.tsx index 178e68b25..874722bb2 100644 --- a/src/components/intro-page/intro-page.tsx +++ b/src/components/intro-page/intro-page.tsx @@ -44,7 +44,6 @@ export const IntroPage: React.FC = () => { void @@ -27,15 +25,15 @@ export interface RendererProps extends ScrollProps { onTaskCheckedChange?: (lineInMarkdown: number, checked: boolean) => void documentRenderPaneRef?: MutableRefObject markdownContent: string - baseUrl?: string onImageClick?: ImageClickHandler onHeightChange?: (height: number) => void - disableToc?: boolean } export interface MarkdownDocumentProps extends RendererProps { additionalOuterContainerClasses?: string additionalRendererClasses?: string + disableToc?: boolean + baseUrl: string } export const MarkdownDocument: React.FC = ({ @@ -105,23 +103,7 @@ export const MarkdownDocument: React.FC = ({
- = 1100}> - - - -
- - - - - -
- -
-
-
-
-
+
diff --git a/src/components/render-page/markdown-toc-button/markdown-toc-button.scss b/src/components/render-page/markdown-toc-button/markdown-toc-button.scss new file mode 100644 index 000000000..7102210a2 --- /dev/null +++ b/src/components/render-page/markdown-toc-button/markdown-toc-button.scss @@ -0,0 +1,17 @@ +/*! + * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +.markdown-toc-sidebar-button { + position: fixed; + right: 70px; + bottom: 30px; + + & > .dropup { + position: sticky; + bottom: 20px; + right: 0; + } +} diff --git a/src/components/render-page/markdown-toc-button/table-of-contents-hovering-button.tsx b/src/components/render-page/markdown-toc-button/table-of-contents-hovering-button.tsx new file mode 100644 index 000000000..9ba2fa225 --- /dev/null +++ b/src/components/render-page/markdown-toc-button/table-of-contents-hovering-button.tsx @@ -0,0 +1,41 @@ +/* + * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import React from 'react' +import { Dropdown } from 'react-bootstrap' +import { TocAst } from 'markdown-it-toc-done-right' +import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon' +import { TableOfContents } from '../../editor-page/table-of-contents/table-of-contents' +import './markdown-toc-button.scss' + +export interface MarkdownTocButtonProps { + tocAst: TocAst + baseUrl: string +} + +/** + * Renders a button that is hovering over the parent and shows a {@link TableOfContents table of contents list} as overlay if clicked. + * + * @param tocAst the {@link TocAst AST} that should be rendered. + * @param baseUrl the base url that will be used to generate the links + * @return the created component + */ +export const TableOfContentsHoveringButton: React.FC = ({ tocAst, baseUrl }) => { + return ( +
+ + + + + +
+ +
+
+
+
+ ) +} diff --git a/src/components/render-page/width-based-table-of-contents.tsx b/src/components/render-page/width-based-table-of-contents.tsx new file mode 100644 index 000000000..84c427bee --- /dev/null +++ b/src/components/render-page/width-based-table-of-contents.tsx @@ -0,0 +1,35 @@ +/* + * SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file) + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import React from 'react' +import { TocAst } from 'markdown-it-toc-done-right' +import { TableOfContents } from '../editor-page/table-of-contents/table-of-contents' +import { TableOfContentsHoveringButton } from './markdown-toc-button/table-of-contents-hovering-button' + +export interface DocumentExternalTocProps { + tocAst: TocAst + width: number + baseUrl: string +} + +const MAX_WIDTH_FOR_BUTTON_VISIBILITY = 1100 + +/** + * Renders the {@link TableOfContents table of contents list} for the given {@link TocAst AST}. + * If the given width is below {@link MAX_WIDTH_FOR_BUTTON_VISIBILITY the width limit} then a {@link TableOfContentsHoveringButton button} with an overlay will be shown instead. + * + * @param tocAst the {@link TocAst AST} that should be rendered. + * @param width the width that should be used to determine if the button should be shown. + * @param baseUrl the base url that will be used to generate the links //TODO: replace with consumer/provider + * @return the created component + */ +export const WidthBasedTableOfContents: React.FC = ({ tocAst, width, baseUrl }) => { + if (width >= MAX_WIDTH_FOR_BUTTON_VISIBILITY) { + return + } else { + return + } +}