diff --git a/apps/client/src/widgets/attribute_widgets/attribute_editor.ts b/apps/client/src/widgets/attribute_widgets/attribute_editor.ts
index 016bd8776..4baecd691 100644
--- a/apps/client/src/widgets/attribute_widgets/attribute_editor.ts
+++ b/apps/client/src/widgets/attribute_widgets/attribute_editor.ts
@@ -16,12 +16,7 @@ import type { default as FAttribute, AttributeType } from "../../entities/fattri
import type FNote from "../../entities/fnote.js";
import { escapeQuotes } from "../../services/utils.js";
-const HELP_TEXT = `
-
${t("attribute_editor.help_text_body1")}
-${t("attribute_editor.help_text_body2")}
-
-${t("attribute_editor.help_text_body3")}
`;
const TPL = /*html*/`
@@ -229,9 +224,7 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget implem
}
async handleEditorClick(e: JQuery.ClickEvent) {
- const pos = this.textEditor.model.document.selection.getFirstPosition();
-
- if (pos && pos.textNode && pos.textNode.data) {
+ if () {
const clickIndex = this.getClickIndex(pos);
let parsedAttrs;
@@ -267,25 +260,9 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget implem
this.showHelpTooltip();
}
}, 100);
- } else {
- this.showHelpTooltip();
}
}
- showHelpTooltip() {
- this.attributeDetailWidget.hide();
-
- this.$editor.tooltip({
- trigger: "focus",
- html: true,
- title: HELP_TEXT,
- placement: "bottom",
- offset: "0,30"
- });
-
- this.$editor.tooltip("show");
- }
-
getClickIndex(pos: ModelPosition) {
let clickIndex = pos.offset - (pos.textNode?.startOffset ?? 0);
diff --git a/apps/client/src/widgets/react/CKEditor.tsx b/apps/client/src/widgets/react/CKEditor.tsx
index 7b28c30cf..8f521a827 100644
--- a/apps/client/src/widgets/react/CKEditor.tsx
+++ b/apps/client/src/widgets/react/CKEditor.tsx
@@ -1,4 +1,4 @@
-import type { AttributeEditor, EditorConfig } from "@triliumnext/ckeditor5";
+import { CKTextEditor, type AttributeEditor, type EditorConfig, type ModelPosition } from "@triliumnext/ckeditor5";
import { useEffect, useRef } from "preact/compat";
interface CKEditorOpts {
@@ -9,15 +9,19 @@ interface CKEditorOpts {
disableNewlines?: boolean;
disableSpellcheck?: boolean;
onChange?: () => void;
+ onClick?: (pos?: ModelPosition | null) => void;
}
-export default function CKEditor({ className, tabIndex, editor, config, disableNewlines, disableSpellcheck, onChange }: CKEditorOpts) {
+export default function CKEditor({ className, tabIndex, editor, config, disableNewlines, disableSpellcheck, onChange, onClick }: CKEditorOpts) {
const editorContainerRef = useRef(null);
+ const textEditorRef = useRef(null);
useEffect(() => {
if (!editorContainerRef.current) return;
editor.create(editorContainerRef.current, config).then((textEditor) => {
+ textEditorRef.current = textEditor;
+
if (disableNewlines) {
textEditor.editing.view.document.on(
"enter",
@@ -48,6 +52,12 @@ export default function CKEditor({ className, tabIndex, editor, config, disableN
ref={editorContainerRef}
className={className}
tabIndex={tabIndex}
+ onClick={() => {
+ if (onClick) {
+ const pos = textEditorRef.current?.model.document.selection.getFirstPosition();
+ onClick(pos);
+ }
+ }}
/>
)
}
\ No newline at end of file
diff --git a/apps/client/src/widgets/react/hooks.tsx b/apps/client/src/widgets/react/hooks.tsx
index af74c6873..6436b1734 100644
--- a/apps/client/src/widgets/react/hooks.tsx
+++ b/apps/client/src/widgets/react/hooks.tsx
@@ -12,7 +12,8 @@ import FNote from "../../entities/fnote";
import attributes from "../../services/attributes";
import FBlob from "../../entities/fblob";
import NoteContextAwareWidget from "../note_context_aware_widget";
-import { RefObject, VNode } from "preact";
+import { Ref, RefObject, VNode } from "preact";
+import { Tooltip } from "bootstrap";
type TriliumEventHandler = (data: EventData) => void;
const registeredHandlers: Map[]>> = new Map();
@@ -510,4 +511,29 @@ export function useWindowSize() {
});
return size;
+}
+
+export function useTooltip(elRef: RefObject, config: Partial) {
+ useEffect(() => {
+ if (!elRef?.current) return;
+
+ const $el = $(elRef.current);
+ $el.tooltip(config);
+ }, [ elRef, config ]);
+
+ const showTooltip = useCallback(() => {
+ if (!elRef?.current) return;
+
+ const $el = $(elRef.current);
+ $el.tooltip("show");
+ }, [ elRef ]);
+
+ const hideTooltip = useCallback(() => {
+ if (!elRef?.current) return;
+
+ const $el = $(elRef.current);
+ $el.tooltip("hide");
+ }, [ elRef ]);
+
+ return { showTooltip, hideTooltip };
}
\ No newline at end of file
diff --git a/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx b/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx
index 9ae3f2372..d8071f7b9 100644
--- a/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx
+++ b/apps/client/src/widgets/ribbon/components/AttributeEditor.tsx
@@ -1,9 +1,17 @@
-import { useCallback, useEffect, useMemo, useRef, useState } from "preact/hooks"
-import { AttributeEditor as CKEditorAttributeEditor, EditorConfig, MentionFeed } from "@triliumnext/ckeditor5";
+import { useEffect, useRef, useState } from "preact/hooks"
+import { AttributeEditor as CKEditorAttributeEditor, MentionFeed } from "@triliumnext/ckeditor5";
import { t } from "../../../services/i18n";
import server from "../../../services/server";
import note_autocomplete, { Suggestion } from "../../../services/note_autocomplete";
import CKEditor from "../../react/CKEditor";
+import { useTooltip } from "../../react/hooks";
+
+const HELP_TEXT = `
+${t("attribute_editor.help_text_body1")}
+
+${t("attribute_editor.help_text_body2")}
+
+${t("attribute_editor.help_text_body3")}
`;
const mentionSetup: MentionFeed[] = [
{
@@ -51,11 +59,27 @@ const mentionSetup: MentionFeed[] = [
export default function AttributeEditor() {
-
- const [ attributeDetailVisible, setAttributeDetailVisible ] = useState(false);
+ const [ state, setState ] = useState<"normal" | "showHelpTooltip" | "showAttributeDetail">();
+ const wrapperRef = useRef(null);
+ const { showTooltip, hideTooltip } = useTooltip(wrapperRef, {
+ trigger: "focus",
+ html: true,
+ title: HELP_TEXT,
+ placement: "bottom",
+ offset: "0,30"
+ });
+
+ useEffect(() => {
+ if (state === "showHelpTooltip") {
+ showTooltip();
+ } else {
+ hideTooltip();
+ }
+ }, [ state ]);
+
return (
-
+
{
console.log("Data changed!");
}}
+ onClick={(pos) => {
+ if (pos && pos.textNode && pos.textNode.data) {
+ setState("showAttributeDetail")
+ } else {
+ setState("showHelpTooltip");
+ }
+ }}
disableNewlines disableSpellcheck
/>