refactor(react/type_widgets): deduplicate containers

This commit is contained in:
Elian Doran
2025-10-05 16:36:59 +03:00
parent 22069d0aef
commit c209a699ea
21 changed files with 206 additions and 183 deletions

View File

@@ -103,6 +103,7 @@ export default function NoteDetail() {
key={type} key={type}
type={type as ExtendedNoteType} type={type as ExtendedNoteType}
isVisible={activeNoteType === type} isVisible={activeNoteType === type}
isFullHeight={isFullHeight}
props={props} props={props}
/> />
})} })}
@@ -114,7 +115,7 @@ export default function NoteDetail() {
* Wraps a single note type widget, in order to keep it in the DOM even after the user has switched away to another note type. This allows faster loading of the same note type again. The properties are cached, so that they are updated only * Wraps a single note type widget, in order to keep it in the DOM even after the user has switched away to another note type. This allows faster loading of the same note type again. The properties are cached, so that they are updated only
* while the widget is visible, to avoid rendering in the background. When not visible, the DOM element is simply hidden. * while the widget is visible, to avoid rendering in the background. When not visible, the DOM element is simply hidden.
*/ */
function NoteDetailWrapper({ Element, type, isVisible, props }: { Element: (props: TypeWidgetProps) => VNode, type: ExtendedNoteType, isVisible: boolean, props: TypeWidgetProps }) { function NoteDetailWrapper({ Element, type, isVisible, isFullHeight, props }: { Element: (props: TypeWidgetProps) => VNode, type: ExtendedNoteType, isVisible: boolean, isFullHeight: boolean, props: TypeWidgetProps }) {
const [ cachedProps, setCachedProps ] = useState(props); const [ cachedProps, setCachedProps ] = useState(props);
useEffect(() => { useEffect(() => {
@@ -125,10 +126,15 @@ function NoteDetailWrapper({ Element, type, isVisible, props }: { Element: (prop
} }
}, [ isVisible ]); }, [ isVisible ]);
const typeMapping = TYPE_MAPPINGS[type];
return ( return (
<div className={`note-detail-${type}`} style={{ <div
display: !isVisible ? "none" : "" className={`${typeMapping.className} ${typeMapping.printable ? "note-detail-printable" : ""}`}
}}> style={{
display: !isVisible ? "none" : "",
height: isFullHeight ? "100%" : ""
}}
>
{ <Element {...cachedProps} /> } { <Element {...cachedProps} /> }
</div> </div>
); );

View File

@@ -18,73 +18,117 @@ type NoteTypeView = () => Promise<{ default: TypeWidget } | TypeWidget> | ((prop
interface NoteTypeMapping { interface NoteTypeMapping {
view: NoteTypeView; view: NoteTypeView;
printable?: boolean;
/** The class name to assign to the note type wrapper */
className: string;
} }
export const TYPE_MAPPINGS: Record<ExtendedNoteType, NoteTypeMapping> = { export const TYPE_MAPPINGS: Record<ExtendedNoteType, NoteTypeMapping> = {
empty: { empty: {
view: () => import("./type_widgets/Empty"), view: () => import("./type_widgets/Empty"),
className: "note-detail-empty",
printable: true
}, },
doc: { doc: {
view: () => import("./type_widgets/Doc") view: () => import("./type_widgets/Doc"),
className: "note-detail-doc",
printable: true
}, },
search: { search: {
view: () => <div className="note-detail-none note-detail-printable" /> view: () => <></>,
className: "note-detail-none",
printable: true
}, },
protectedSession: { protectedSession: {
view: () => import("./type_widgets/ProtectedSession") view: () => import("./type_widgets/ProtectedSession"),
className: "protected-session-password-component"
}, },
book: { book: {
view: () => import("./type_widgets/Book") view: () => import("./type_widgets/Book"),
className: "note-detail-book",
printable: true,
}, },
contentWidget: { contentWidget: {
view: () => import("./type_widgets/ContentWidget") view: () => import("./type_widgets/ContentWidget"),
className: "note-detail-content-widget",
printable: true
}, },
webView: { webView: {
view: () => import("./type_widgets/WebView") view: () => import("./type_widgets/WebView"),
className: "note-detail-web-view",
printable: true
}, },
file: { file: {
view: () => import("./type_widgets/File") view: () => import("./type_widgets/File"),
className: "note-detail-file",
printable: true
}, },
image: { image: {
view: () => import("./type_widgets/Image") view: () => import("./type_widgets/Image"),
className: "note-detail-image",
printable: true
}, },
readOnlyCode: { readOnlyCode: {
view: async () => (await import("./type_widgets/code/Code")).ReadOnlyCode view: async () => (await import("./type_widgets/code/Code")).ReadOnlyCode,
className: "note-detail-readonly-code",
printable: true
}, },
editableCode: { editableCode: {
view: async () => (await import("./type_widgets/code/Code")).EditableCode view: async () => (await import("./type_widgets/code/Code")).EditableCode,
className: "note-detail-code",
printable: true
}, },
mermaid: { mermaid: {
view: () => import("./type_widgets/Mermaid") view: () => import("./type_widgets/Mermaid"),
className: "note-detail-mermaid",
printable: true
}, },
mindMap: { mindMap: {
view: () => import("./type_widgets/MindMap") view: () => import("./type_widgets/MindMap"),
className: "note-detail-mind-map",
printable: true
}, },
attachmentList: { attachmentList: {
view: async () => (await import("./type_widgets/Attachment")).AttachmentList view: async () => (await import("./type_widgets/Attachment")).AttachmentList,
className: "attachment-list",
printable: true
}, },
attachmentDetail: { attachmentDetail: {
view: async () => (await import("./type_widgets/Attachment")).AttachmentDetail view: async () => (await import("./type_widgets/Attachment")).AttachmentDetail,
className: "attachment-detail",
printable: true
}, },
readOnlyText: { readOnlyText: {
view: () => import("./type_widgets/text/ReadOnlyText") view: () => import("./type_widgets/text/ReadOnlyText"),
className: "note-detail-readonly-text"
}, },
editableText: { editableText: {
view: () => import("./type_widgets/text/EditableText") view: () => import("./type_widgets/text/EditableText"),
className: "note-detail-editable-text",
printable: true
}, },
render: { render: {
view: () => import("./type_widgets/Render") view: () => import("./type_widgets/Render"),
className: "note-detail-render",
printable: true
}, },
canvas: { canvas: {
view: () => import("./type_widgets/Canvas") view: () => import("./type_widgets/Canvas"),
className: "note-detail-canvas",
printable: true
}, },
relationMap: { relationMap: {
view: () => import("./type_widgets/relation_map/RelationMap") view: () => import("./type_widgets/relation_map/RelationMap"),
className: "note-detail-relation-map",
printable: true
}, },
noteMap: { noteMap: {
view: () => import("./type_widgets/NoteMap") view: () => import("./type_widgets/NoteMap"),
className: "note-detail-note-map",
printable: true
}, },
aiChat: { aiChat: {
view: () => import("./type_widgets/AiChat") view: () => import("./type_widgets/AiChat"),
className: "ai-chat-widget-container"
} }
}; };

View File

@@ -31,7 +31,6 @@ export default function AiChat({ note, noteContext }: TypeWidgetProps) {
return llmChatPanel; return llmChatPanel;
}, { }, {
noteContext, noteContext,
containerClassName: "ai-chat-widget-container",
containerStyle: { containerStyle: {
height: "100%" height: "100%"
} }

View File

@@ -46,7 +46,7 @@ export function AttachmentList({ note }: TypeWidgetProps) {
}); });
return ( return (
<div className="attachment-list note-detail-printable"> <>
<AttachmentListHeader noteId={note.noteId} /> <AttachmentListHeader noteId={note.noteId} />
<div className="attachment-list-wrapper"> <div className="attachment-list-wrapper">
@@ -58,7 +58,7 @@ export function AttachmentList({ note }: TypeWidgetProps) {
</Alert> </Alert>
)} )}
</div> </div>
</div> </>
) )
} }
@@ -99,7 +99,7 @@ export function AttachmentDetail({ note, viewScope }: TypeWidgetProps) {
}, [ viewScope ]); }, [ viewScope ]);
return ( return (
<div className="attachment-detail note-detail-printable"> <>
<div className="links-wrapper use-tn-links"> <div className="links-wrapper use-tn-links">
{t("attachment_detail.owning_note")}{" "} {t("attachment_detail.owning_note")}{" "}
<NoteLink notePath={note.noteId} /> <NoteLink notePath={note.noteId} />
@@ -122,7 +122,7 @@ export function AttachmentDetail({ note, viewScope }: TypeWidgetProps) {
<strong>{t("attachment_detail.attachment_deleted")}</strong> <strong>{t("attachment_detail.attachment_deleted")}</strong>
)} )}
</div> </div>
</div> </>
) )
} }

View File

@@ -23,13 +23,9 @@ export default function Book({ note }: TypeWidgetProps) {
} }
}); });
return ( return (shouldDisplayNoChildrenWarning &&
<div className="note-detail-book note-detail-printable">
{(shouldDisplayNoChildrenWarning && (
<Alert type="warning" className="note-detail-book-empty-help"> <Alert type="warning" className="note-detail-book-empty-help">
<RawHtml html={t("book.no_children_help")} /> <RawHtml html={t("book.no_children_help")} />
</Alert> </Alert>
))}
</div>
) )
} }

View File

@@ -60,8 +60,7 @@ export default function Canvas({ note }: TypeWidgetProps) {
}, []); }, []);
return ( return (
<div className="canvas-widget note-detail-canvas note-detail-printable note-detail full-height" onWheel={onWheel}> <div className="canvas-render" onWheel={onWheel}>
<div className="canvas-render">
<div className="excalidraw-wrapper"> <div className="excalidraw-wrapper">
<Excalidraw <Excalidraw
excalidrawAPI={api => apiRef.current = api} excalidrawAPI={api => apiRef.current = api}
@@ -83,7 +82,6 @@ export default function Canvas({ note }: TypeWidgetProps) {
/> />
</div> </div>
</div> </div>
</div>
) )
} }

View File

@@ -50,12 +50,10 @@ const CONTENT_WIDGETS: Record<OptionPages | "_backendLog", (props: TypeWidgetPro
export default function ContentWidget({ note, ...restProps }: TypeWidgetProps) { export default function ContentWidget({ note, ...restProps }: TypeWidgetProps) {
const Content = CONTENT_WIDGETS[note.noteId]; const Content = CONTENT_WIDGETS[note.noteId];
return ( return (
<div className="note-detail-content-widget note-detail-printable">
<div className={`note-detail-content-widget-content ${note.noteId.startsWith("_options") ? "options" : ""}`}> <div className={`note-detail-content-widget-content ${note.noteId.startsWith("_options") ? "options" : ""}`}>
{Content {Content
? <Content note={note} {...restProps} /> ? <Content note={note} {...restProps} />
: (t("content_widget.unknown_widget", { id: note.noteId }))} : (t("content_widget.unknown_widget", { id: note.noteId }))}
</div> </div>
</div>
) )
} }

View File

@@ -18,15 +18,15 @@
border: 1px solid var(--main-border-color); border: 1px solid var(--main-border-color);
} }
.note-detail-doc.contextual-help { .note-detail-doc-content.contextual-help {
padding-bottom: 0; padding-bottom: 0;
} }
.note-detail-doc.contextual-help h2, .note-detail-doc-content.contextual-help h2,
.note-detail-doc.contextual-help h3, .note-detail-doc-content.contextual-help h3,
.note-detail-doc.contextual-help h4, .note-detail-doc-content.contextual-help h4,
.note-detail-doc.contextual-help h5, .note-detail-doc-content.contextual-help h5,
.note-detail-doc.contextual-help h6 { .note-detail-doc-content.contextual-help h6 {
font-size: 1.25rem; font-size: 1.25rem;
background-color: var(--main-background-color); background-color: var(--main-background-color);
position: sticky; position: sticky;

View File

@@ -27,12 +27,10 @@ export default function Doc({ note, viewScope, ntxId }: TypeWidgetProps) {
}); });
return ( return (
<div className={`note-detail-doc note-detail-printable ${viewScope?.viewMode === "contextual-help" ? "contextual-help" : ""}`}>
<RawHtmlBlock <RawHtmlBlock
containerRef={containerRef} containerRef={containerRef}
className="note-detail-doc-content ck-content" className={`note-detail-doc-content ck-content ${viewScope?.viewMode === "contextual-help" ? "contextual-help" : ""}`}
html={html} html={html}
/> />
</div>
); );
} }

View File

@@ -12,10 +12,10 @@ import { TypeWidgetProps } from "./type_widget";
export default function Empty({ }: TypeWidgetProps) { export default function Empty({ }: TypeWidgetProps) {
return ( return (
<div class="note-detail-empty note-detail-printable"> <>
<WorkspaceSwitcher /> <WorkspaceSwitcher />
<NoteSearch /> <NoteSearch />
</div> </>
) )
} }

View File

@@ -12,24 +12,17 @@ const TEXT_MAX_NUM_CHARS = 5000;
export default function File({ note }: TypeWidgetProps) { export default function File({ note }: TypeWidgetProps) {
const blob = useNoteBlob(note); const blob = useNoteBlob(note);
let preview: VNode | null = null;
if (blob?.content) { if (blob?.content) {
preview = <TextPreview content={blob.content} /> return <TextPreview content={blob.content} />
} else if (note.mime === "application/pdf") { } else if (note.mime === "application/pdf") {
preview = <PdfPreview note={note} /> return <PdfPreview note={note} />
} else if (note.mime.startsWith("video/")) { } else if (note.mime.startsWith("video/")) {
preview = <VideoPreview note={note} /> return <VideoPreview note={note} />
} else if (note.mime.startsWith("audio/")) { } else if (note.mime.startsWith("audio/")) {
preview = <AudioPreview note={note} /> return <AudioPreview note={note} />
} else { } else {
preview = <NoPreview /> return <NoPreview />
} }
return (
<div className="note-detail-file note-detail-printable">
{preview}
</div>
);
} }
function TextPreview({ content }: { content: string }) { function TextPreview({ content }: { content: string }) {

View File

@@ -41,7 +41,6 @@ export default function Image({ note, ntxId }: TypeWidgetProps) {
}); });
return ( return (
<div className="note-detail-image note-detail-printable">
<div ref={containerRef} className="note-detail-image-wrapper"> <div ref={containerRef} className="note-detail-image-wrapper">
<img <img
id={uniqueId} id={uniqueId}
@@ -49,6 +48,5 @@ export default function Image({ note, ntxId }: TypeWidgetProps) {
src={createImageSrcUrl(note)} src={createImageSrcUrl(note)}
/> />
</div> </div>
</div>
) )
} }

View File

@@ -7,7 +7,7 @@ import nodeMenu from "@mind-elixir/node-menu";
import "mind-elixir/style"; import "mind-elixir/style";
import "@mind-elixir/node-menu/dist/style.css"; import "@mind-elixir/node-menu/dist/style.css";
import "./MindMap.css"; import "./MindMap.css";
import { useEditorSpacedUpdate, useNoteLabelBoolean, useTriliumEvent, useTriliumEvents, useTriliumOptionBool } from "../react/hooks"; import { useEditorSpacedUpdate, useNoteLabelBoolean, useSyncedRef, useTriliumEvent, useTriliumEvents, useTriliumOptionBool } from "../react/hooks";
import { refToJQuerySelector } from "../react/react_utils"; import { refToJQuerySelector } from "../react/react_utils";
import utils from "../../services/utils"; import utils from "../../services/utils";
@@ -16,6 +16,7 @@ const NEW_TOPIC_NAME = "";
interface MindElixirProps { interface MindElixirProps {
apiRef?: RefObject<MindElixirInstance>; apiRef?: RefObject<MindElixirInstance>;
containerProps?: Omit<HTMLAttributes<HTMLDivElement>, "ref">; containerProps?: Omit<HTMLAttributes<HTMLDivElement>, "ref">;
containerRef?: RefObject<HTMLDivElement>;
editable: boolean; editable: boolean;
content: MindElixirData; content: MindElixirData;
onChange?: () => void; onChange?: () => void;
@@ -94,8 +95,8 @@ export default function MindMap({ note, ntxId }: TypeWidgetProps) {
}, []); }, []);
return ( return (
<div ref={containerRef} className="note-detail-mind-map note-detail-printable">
<MindElixir <MindElixir
containerRef={containerRef}
apiRef={apiRef} apiRef={apiRef}
content={content} content={content}
onChange={() => spacedUpdate.scheduleUpdate()} onChange={() => spacedUpdate.scheduleUpdate()}
@@ -105,12 +106,11 @@ export default function MindMap({ note, ntxId }: TypeWidgetProps) {
onKeyDown onKeyDown
}} }}
/> />
</div>
) )
} }
function MindElixir({ content, containerProps, apiRef: externalApiRef, onChange, editable }: MindElixirProps) { function MindElixir({ content, containerRef: externalContainerRef, containerProps, apiRef: externalApiRef, onChange, editable }: MindElixirProps) {
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useSyncedRef<HTMLDivElement>(externalContainerRef, null);
const apiRef = useRef<MindElixirInstance>(null); const apiRef = useRef<MindElixirInstance>(null);
useEffect(() => { useEffect(() => {

View File

@@ -6,7 +6,7 @@ export default function NoteMap({ note }: TypeWidgetProps) {
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
return ( return (
<div ref={containerRef} className="note-detail-note-map note-detail-printable"> <div ref={containerRef}>
<NoteMapEl parentRef={containerRef} note={note} widgetMode="type" /> <NoteMapEl parentRef={containerRef} note={note} widgetMode="type" />
</div> </div>
); );

View File

@@ -20,7 +20,6 @@ export default function ProtectedSession() {
}, [ passwordRef ]); }, [ passwordRef ]);
return ( return (
<div className="protected-session-password-component note-detail-printable">
<form class="protected-session-password-form" onSubmit={submitCallback}> <form class="protected-session-password-form" onSubmit={submitCallback}>
<FormGroup name="protected-session-password-in-detail" label={t("protected_session.enter_password_instruction")}> <FormGroup name="protected-session-password-in-detail" label={t("protected_session.enter_password_instruction")}>
<FormTextBox <FormTextBox
@@ -37,6 +36,5 @@ export default function ProtectedSession() {
keyboardShortcut="Enter" keyboardShortcut="Enter"
/> />
</form> </form>
</div>
) )
} }

View File

@@ -38,7 +38,7 @@ export default function Render({ note, noteContext, ntxId }: TypeWidgetProps) {
}); });
return ( return (
<div className="note-detail-render note-detail-printable"> <>
{!renderNotesFound && ( {!renderNotesFound && (
<Alert className="note-detail-render-help" type="warning"> <Alert className="note-detail-render-help" type="warning">
<p><strong>{t("render.note_detail_render_help_1")}</strong></p> <p><strong>{t("render.note_detail_render_help_1")}</strong></p>
@@ -47,6 +47,6 @@ export default function Render({ note, noteContext, ntxId }: TypeWidgetProps) {
)} )}
<div ref={contentRef} className="note-detail-render-content" /> <div ref={contentRef} className="note-detail-render-content" />
</div> </>
); );
} }

View File

@@ -10,13 +10,10 @@ const isElectron = utils.isElectron();
export default function WebView({ note }: TypeWidgetProps) { export default function WebView({ note }: TypeWidgetProps) {
const [ webViewSrc ] = useNoteLabel(note, "webViewSrc"); const [ webViewSrc ] = useNoteLabel(note, "webViewSrc");
return ( return (webViewSrc
<div className="note-detail-web-view note-detail-printable">
{webViewSrc
? <WebViewContent src={webViewSrc} /> ? <WebViewContent src={webViewSrc} />
: <WebViewHelp />} : <WebViewHelp />
</div> );
)
} }
function WebViewContent({ src }: { src: string }) { function WebViewContent({ src }: { src: string }) {

View File

@@ -44,7 +44,6 @@ export function ReadOnlyCode({ note, viewScope, ntxId, parentComponent }: TypeWi
}, [ blob ]); }, [ blob ]);
return ( return (
<div className="note-detail-readonly-code note-detail-printable">
<CodeEditor <CodeEditor
ntxId={ntxId} parentComponent={parentComponent} ntxId={ntxId} parentComponent={parentComponent}
className="note-detail-readonly-code-content" className="note-detail-readonly-code-content"
@@ -52,7 +51,6 @@ export function ReadOnlyCode({ note, viewScope, ntxId, parentComponent }: TypeWi
mime={note.mime} mime={note.mime}
readOnly readOnly
/> />
</div>
) )
} }
@@ -93,7 +91,7 @@ export function EditableCode({ note, ntxId, debounceUpdate, parentComponent, upd
useKeyboardShortcuts("code-detail", containerRef, parentComponent); useKeyboardShortcuts("code-detail", containerRef, parentComponent);
return ( return (
<div className="note-detail-code note-detail-printable"> <>
<CodeEditor <CodeEditor
ntxId={ntxId} parentComponent={parentComponent} ntxId={ntxId} parentComponent={parentComponent}
editorRef={editorRef} containerRef={containerRef} editorRef={editorRef} containerRef={containerRef}
@@ -119,7 +117,7 @@ export function EditableCode({ note, ntxId, debounceUpdate, parentComponent, upd
<TouchBarButton icon="NSImageNameTouchBarPlayTemplate" click={() => appContext.triggerCommand("runActiveNote")} /> <TouchBarButton icon="NSImageNameTouchBarPlayTemplate" click={() => appContext.triggerCommand("runActiveNote")} />
)} )}
</TouchBar> </TouchBar>
</div> </>
) )
} }

View File

@@ -133,7 +133,6 @@ export default function RelationMap({ note, ntxId }: TypeWidgetProps) {
useRelationData(note.noteId, data, mapApiRef, pbApiRef); useRelationData(note.noteId, data, mapApiRef, pbApiRef);
return ( return (
<div className="note-detail-relation-map note-detail-printable">
<div <div
className="relation-map-wrapper" className="relation-map-wrapper"
onClick={clickCallback} onClick={clickCallback}
@@ -157,7 +156,6 @@ export default function RelationMap({ note, ntxId }: TypeWidgetProps) {
))} ))}
</JsPlumb> </JsPlumb>
</div> </div>
</div>
) )
} }

View File

@@ -1,7 +1,7 @@
import { HTMLProps, RefObject, useEffect, useImperativeHandle, useRef, useState } from "preact/compat"; import { HTMLProps, RefObject, useEffect, useImperativeHandle, useRef, useState } from "preact/compat";
import { PopupEditor, ClassicEditor, EditorWatchdog, type WatchdogConfig, CKTextEditor, TemplateDefinition } from "@triliumnext/ckeditor5"; import { PopupEditor, ClassicEditor, EditorWatchdog, type WatchdogConfig, CKTextEditor, TemplateDefinition } from "@triliumnext/ckeditor5";
import { buildConfig, BuildEditorOptions } from "./config"; import { buildConfig, BuildEditorOptions } from "./config";
import { useLegacyImperativeHandlers } from "../../react/hooks"; import { useLegacyImperativeHandlers, useSyncedRef } from "../../react/hooks";
import link from "../../../services/link"; import link from "../../../services/link";
import froca from "../../../services/froca"; import froca from "../../../services/froca";
@@ -30,10 +30,11 @@ interface CKEditorWithWatchdogProps extends Pick<HTMLProps<HTMLDivElement>, "cla
onEditorInitialized?: (editor: CKTextEditor) => void; onEditorInitialized?: (editor: CKTextEditor) => void;
editorApi: RefObject<CKEditorApi>; editorApi: RefObject<CKEditorApi>;
templates: TemplateDefinition[]; templates: TemplateDefinition[];
containerRef?: RefObject<HTMLDivElement>;
} }
export default function CKEditorWithWatchdog({ content, contentLanguage, className, tabIndex, isClassicEditor, watchdogRef: externalWatchdogRef, watchdogConfig, onNotificationWarning, onWatchdogStateChange, onChange, onEditorInitialized, editorApi, templates }: CKEditorWithWatchdogProps) { export default function CKEditorWithWatchdog({ containerRef: externalContainerRef, content, contentLanguage, className, tabIndex, isClassicEditor, watchdogRef: externalWatchdogRef, watchdogConfig, onNotificationWarning, onWatchdogStateChange, onChange, onEditorInitialized, editorApi, templates }: CKEditorWithWatchdogProps) {
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useSyncedRef<HTMLDivElement>(externalContainerRef, null);
const watchdogRef = useRef<EditorWatchdog>(null); const watchdogRef = useRef<EditorWatchdog>(null);
const [ editor, setEditor ] = useState<CKTextEditor>(); const [ editor, setEditor ] = useState<CKTextEditor>();

View File

@@ -185,9 +185,10 @@ export default function EditableText({ note, parentComponent, ntxId, noteContext
}); });
return ( return (
<div ref={containerRef} class={`note-detail-editable-text note-detail-printable ${codeBlockWordWrap ? "word-wrap" : ""}`}> <>
{note && !!templates && <CKEditorWithWatchdog {note && !!templates && <CKEditorWithWatchdog
className="note-detail-editable-text-editor use-tn-links" containerRef={containerRef}
className={`note-detail-editable-text-editor use-tn-links ${codeBlockWordWrap ? "word-wrap" : ""}`}
tabIndex={300} tabIndex={300}
content={content} content={content}
contentLanguage={language} contentLanguage={language}
@@ -229,7 +230,7 @@ export default function EditableText({ note, parentComponent, ntxId, noteContext
/>} />}
<EditableTextTouchBar watchdogRef={watchdogRef} refreshTouchBarRef={refreshTouchBarRef} /> <EditableTextTouchBar watchdogRef={watchdogRef} refreshTouchBarRef={refreshTouchBarRef} />
</div> </>
) )
} }