mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-30 18:05:55 +01:00 
			
		
		
		
	chore(react/ribbon): integrate expand/collapse button
This commit is contained in:
		| @@ -1,12 +1,13 @@ | |||||||
| interface ActionButtonProps { | interface ActionButtonProps { | ||||||
|     text: string; |     text: string; | ||||||
|     icon: string; |     icon: string; | ||||||
|  |     className?: string; | ||||||
|     onClick?: () => void; |     onClick?: () => void; | ||||||
| } | } | ||||||
|  |  | ||||||
| export default function ActionButton({ text, icon, onClick }: ActionButtonProps) { | export default function ActionButton({ text, icon, className, onClick }: ActionButtonProps) { | ||||||
|     return <button |     return <button | ||||||
|         class={`icon-action ${icon}`} |         class={`icon-action ${icon} ${className ?? ""}`} | ||||||
|         title={text} |         title={text} | ||||||
|         onClick={onClick}         |         onClick={onClick}         | ||||||
|     />; |     />; | ||||||
|   | |||||||
| @@ -11,8 +11,8 @@ import BasicWidget, { ReactWrappedWidget } from "../basic_widget"; | |||||||
| import FNote from "../../entities/fnote"; | import FNote from "../../entities/fnote"; | ||||||
| import attributes from "../../services/attributes"; | import attributes from "../../services/attributes"; | ||||||
| import FBlob from "../../entities/fblob"; | import FBlob from "../../entities/fblob"; | ||||||
| import RawHtml from "./RawHtml"; |  | ||||||
| import NoteContextAwareWidget from "../note_context_aware_widget"; | import NoteContextAwareWidget from "../note_context_aware_widget"; | ||||||
|  | import { VNode } from "preact"; | ||||||
|  |  | ||||||
| type TriliumEventHandler<T extends EventNames> = (data: EventData<T>) => void; | type TriliumEventHandler<T extends EventNames> = (data: EventData<T>) => void; | ||||||
| const registeredHandlers: Map<Component, Map<EventNames, TriliumEventHandler<any>[]>> = new Map(); | const registeredHandlers: Map<Component, Map<EventNames, TriliumEventHandler<any>[]>> = new Map(); | ||||||
| @@ -414,10 +414,10 @@ export function useNoteBlob(note: FNote | null | undefined): [ FBlob | null | un | |||||||
|     return [ blob ] as const; |     return [ blob ] as const; | ||||||
| } | } | ||||||
|  |  | ||||||
| export function useLegacyWidget(widgetFactory: () => BasicWidget, { noteContext, containerClassName }: { | export function useLegacyWidget<T extends BasicWidget>(widgetFactory: () => T, { noteContext, containerClassName }: { | ||||||
|     noteContext?: NoteContext; |     noteContext?: NoteContext; | ||||||
|     containerClassName?: string; |     containerClassName?: string; | ||||||
| } = {}) { | } = {}): [VNode, T] { | ||||||
|     const ref = useRef<HTMLDivElement>(null); |     const ref = useRef<HTMLDivElement>(null); | ||||||
|     const parentComponent = useContext(ParentComponent); |     const parentComponent = useContext(ParentComponent); | ||||||
|  |  | ||||||
| @@ -453,5 +453,5 @@ export function useLegacyWidget(widgetFactory: () => BasicWidget, { noteContext, | |||||||
|         } |         } | ||||||
|     }, [ noteContext ]); |     }, [ noteContext ]); | ||||||
|  |  | ||||||
|     return <div className={containerClassName} ref={ref} /> |     return [ <div className={containerClassName} ref={ref} />, widget ] | ||||||
| } | } | ||||||
| @@ -1,16 +1,55 @@ | |||||||
| import { TabContext } from "./ribbon-interface"; | import { TabContext } from "./ribbon-interface"; | ||||||
| import NoteMapWidget from "../note_map"; | import NoteMapWidget from "../note_map"; | ||||||
| import { useLegacyWidget } from "../react/hooks"; | import { useLegacyWidget } from "../react/hooks"; | ||||||
|  | import ActionButton from "../react/ActionButton"; | ||||||
|  | import { t } from "../../services/i18n"; | ||||||
|  | import { useEffect, useRef, useState } from "preact/hooks"; | ||||||
|  |  | ||||||
|  | const SMALL_SIZE_HEIGHT = "300px"; | ||||||
|  |  | ||||||
| export default function NoteMapTab({ note, noteContext }: TabContext) { | export default function NoteMapTab({ note, noteContext }: TabContext) { | ||||||
|     const noteMapWidget = useLegacyWidget(() => new NoteMapWidget("ribbon"), { |     const [ isExpanded, setExpanded ] = useState(false); | ||||||
|  |     const [ height, setHeight ] = useState(SMALL_SIZE_HEIGHT); | ||||||
|  |     const containerRef = useRef<HTMLDivElement>(null); | ||||||
|  |  | ||||||
|  |     const [ noteMapContainer, noteMapWidget ] = useLegacyWidget(() => new NoteMapWidget("ribbon"), { | ||||||
|         noteContext, |         noteContext, | ||||||
|         containerClassName: "note-map-container" |         containerClassName: "note-map-container" | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|  |     useEffect(() => noteMapWidget.setDimensions(), [ height ]); | ||||||
|  |  | ||||||
|  |     function toggleExpanded(newValue: boolean) { | ||||||
|  |         setExpanded(newValue); | ||||||
|  |  | ||||||
|  |         if (newValue && containerRef.current) { | ||||||
|  |             const { top } = containerRef.current.getBoundingClientRect(); | ||||||
|  |             const height = window.innerHeight - top; | ||||||
|  |             setHeight(height + "px"); | ||||||
|  |         } else { | ||||||
|  |             setHeight(SMALL_SIZE_HEIGHT); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     return ( |     return ( | ||||||
|         <div className="note-map-ribbon-widget"> |         <div className="note-map-ribbon-widget" style={{ height }} ref={containerRef}> | ||||||
|             {noteMapWidget} |             {noteMapContainer} | ||||||
|  |  | ||||||
|  |             {!isExpanded ? ( | ||||||
|  |                 <ActionButton | ||||||
|  |                     icon="bx bx-arrow-to-bottom" | ||||||
|  |                     text={t("note_map.open_full")} | ||||||
|  |                     className="open-full-button" | ||||||
|  |                     onClick={() => toggleExpanded(true)} | ||||||
|  |                 /> | ||||||
|  |             ) : ( | ||||||
|  |                 <ActionButton | ||||||
|  |                     icon="bx bx-arrow-to-top" | ||||||
|  |                     text={t("note_map.collapse")} | ||||||
|  |                     className="collapse-button" | ||||||
|  |                     onClick={() => toggleExpanded(false)} | ||||||
|  |                 /> | ||||||
|  |             )} | ||||||
|         </div> |         </div> | ||||||
|     ); |     ); | ||||||
| } | } | ||||||
| @@ -253,7 +253,7 @@ | |||||||
| } | } | ||||||
|  |  | ||||||
| .note-map-ribbon-widget .note-map-container { | .note-map-ribbon-widget .note-map-container { | ||||||
|     height: 300px; |     height: 100%; | ||||||
| } | } | ||||||
|  |  | ||||||
| .note-map-ribbon-widget .open-full-button, .note-map-ribbon-widget .collapse-button { | .note-map-ribbon-widget .open-full-button, .note-map-ribbon-widget .collapse-button { | ||||||
|   | |||||||
| @@ -2,14 +2,6 @@ import NoteContextAwareWidget from "../note_context_aware_widget.js"; | |||||||
| import NoteMapWidget from "../note_map.js"; | import NoteMapWidget from "../note_map.js"; | ||||||
| import { t } from "../../services/i18n.js"; | import { t } from "../../services/i18n.js"; | ||||||
|  |  | ||||||
| const TPL = /*html*/` |  | ||||||
|  |  | ||||||
|     <button class="bx bx-arrow-to-bottom icon-action open-full-button" title="${t("note_map.open_full")}"></button> |  | ||||||
|     <button class="bx bx-arrow-to-top icon-action collapse-button" style="display: none;" title="${t("note_map.collapse")}"></button> |  | ||||||
|  |  | ||||||
|  |  | ||||||
| </div>`; |  | ||||||
|  |  | ||||||
| export default class NoteMapRibbonWidget extends NoteContextAwareWidget { | export default class NoteMapRibbonWidget extends NoteContextAwareWidget { | ||||||
|  |  | ||||||
|     private openState!: "small" | "full"; |     private openState!: "small" | "full"; | ||||||
| @@ -50,37 +42,7 @@ export default class NoteMapRibbonWidget extends NoteContextAwareWidget { | |||||||
|             this.noteMapWidget.setDimensions(); |             this.noteMapWidget.setDimensions(); | ||||||
|         }); |         }); | ||||||
|  |  | ||||||
|         const handleResize = () => { |  | ||||||
|             if (!this.noteMapWidget.graph) { |  | ||||||
|                 // no graph has been even rendered |  | ||||||
|                 return; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if (this.openState === "full") { |  | ||||||
|                 this.setFullHeight(); |  | ||||||
|             } else if (this.openState === "small") { |  | ||||||
|                 this.setSmallSize(); |  | ||||||
|             } |  | ||||||
|         }; |  | ||||||
|  |  | ||||||
|         new ResizeObserver(handleResize).observe(this.$widget[0]); |         new ResizeObserver(handleResize).observe(this.$widget[0]); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     setSmallSize() { |  | ||||||
|         const SMALL_SIZE_HEIGHT = 300; |  | ||||||
|         const width = this.$widget.width() ?? 0; |  | ||||||
|  |  | ||||||
|         this.$widget.find(".note-map-container").height(SMALL_SIZE_HEIGHT).width(width); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     setFullHeight() { |  | ||||||
|         const { top } = this.$widget[0].getBoundingClientRect(); |  | ||||||
|  |  | ||||||
|         const height = ($(window).height() ?? 0) - top; |  | ||||||
|         const width = this.$widget.width() ?? 0; |  | ||||||
|  |  | ||||||
|         this.$widget.find(".note-map-container") |  | ||||||
|             .height(height) |  | ||||||
|             .width(width); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user