Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion src/features/editor/ui/Editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,6 @@ const PASS_THROUGH_KEYS = new Set([
'fileDeleteButton',
'fileDownloadButton',
'filePreviewButton',
'addTiptapCommentButton',
])

/**
Expand Down Expand Up @@ -216,6 +215,13 @@ export const Editor = forwardRef<EditorHandle, EditorProps>(function Editor(
},
ref
) {
/**
* Tracks whether the editor is still loading initial content.
*
* While `true`, `handleChange` exits early to prevent auto-save from
* firing on programmatic content population (e.g. `replaceBlocks`).
* Set to `false` once the note content has been fully applied.
*/
const loadingRef = useRef(true)
/**
* Whether the editor content has finished loading and is safe to display.
Expand All @@ -226,11 +232,16 @@ export const Editor = forwardRef<EditorHandle, EditorProps>(function Editor(
* to the editor inside the content-loading `useEffect`.
*/
const [contentReady, setContentReady] = useState(false)
/** Resolved theme ("light" or "dark") passed to BlockNoteView. */
const { resolvedTheme } = useTheme()
/** User-configured editor font size in pixels. */
const { fontSize } = useEditorFontSize()
/** User-configured editor font family string. */
const { fontFamily } = useEditorFont()
/** User-configured toolbar item order and visibility from the persistent store. */
const { items: toolbarItemConfigs } = useToolbarConfig()

/** Keeps the cursor vertically centered in the viewport during navigation. */
useCursorCentering()

/**
Expand Down Expand Up @@ -271,17 +282,21 @@ export const Editor = forwardRef<EditorHandle, EditorProps>(function Editor(
return [...passThroughItems, ...configuredItems]
}, [toolbarItemConfigs])

/** Debounced auto-save hook (500 ms delay). Only active when `noteId` is non-null. */
const { scheduleSave, saveStatus } = useAutoSave(
500,
noteId ?? undefined,
onNoteSaved
)
/** Intercepts pasted content to extract and handle embedded links. */
const pasteHandler = useLinkPreview()

/** Propagates the current save status to the parent component. */
useEffect(() => {
onStatusChange?.(saveStatus)
}, [saveStatus, onStatusChange])

/** BlockNote editor instance with custom schema, extensions, and image handling. */
const editor = useCreateBlockNote({
schema,
initialContent: DEFAULT_BLOCKS,
Expand All @@ -300,14 +315,17 @@ export const Editor = forwardRef<EditorHandle, EditorProps>(function Editor(
resolveFileUrl: resolveImageUrl,
})

/** Exposes the editor instance to parent components via the forwarded ref. */
useImperativeHandle(ref, () => ({ editor }), [editor])

// Sync the locked prop to the module-level flag read by the ProseMirror plugin.
useEffect(() => {
setReadOnly(locked)
}, [locked])

/** Intercepts Cmd/Ctrl+Click on links inside the editor to open them in the browser. */
useLinkClickHandler(editor)
/** Shows a toast notification when the user copies content from the editor. */
useCopyToast(editor)
// Rewrite clipboard text/plain so Markdown lists are tight (no blank lines between items).
useClipboardTightenList(editor)
Expand Down Expand Up @@ -414,6 +432,7 @@ export const Editor = forwardRef<EditorHandle, EditorProps>(function Editor(
}
}, [editor, onSuggestionMenuOpen])

/** Search & replace state for the {@link SearchReplacePanel}. */
const search = useSearchReplace(editor)

/**
Expand Down
2 changes: 0 additions & 2 deletions src/features/settings/lib/toolbarConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export const TOOLBAR_ITEM_LABELS: Record<string, string> = {
nestBlockButton: 'Indent',
unnestBlockButton: 'Outdent',
createLinkButton: 'Create Link',
addCommentButton: 'Comment',
}

/** Default toolbar layout — all items visible, in canonical order. */
Expand All @@ -48,7 +47,6 @@ export const DEFAULT_TOOLBAR_CONFIG: ToolbarItemConfig[] = [
{ key: 'nestBlockButton', visible: true },
{ key: 'unnestBlockButton', visible: true },
{ key: 'createLinkButton', visible: true },
{ key: 'addCommentButton', visible: true },
]

/** Store key for persistence via configStore. */
Expand Down
11 changes: 9 additions & 2 deletions src/features/settings/ui/ToolbarOption.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import {
RiAlignLeft,
RiAlignRight,
RiBold,
RiChat3Line,
RiIndentDecrease,
RiIndentIncrease,
RiItalic,
Expand All @@ -51,7 +50,9 @@ import type { ToolbarItemConfig } from '@/features/settings/lib/toolbarConfig'
import { TOOLBAR_ITEM_LABELS } from '@/features/settings/lib/toolbarConfig'
import { cn } from '@/lib/utils'

/** Icon size in pixels used for all toolbar item icons in this settings panel. */
const ICON_SIZE = 14
/** Shared CSS class that prevents icons from shrinking in a flex layout. */
const ICON_CLASS = 'shrink-0'

/** Icons matching the actual BubbleMenu buttons. */
Expand All @@ -76,7 +77,6 @@ const TOOLBAR_ITEM_ICONS: Record<string, ReactNode> = {
<RiIndentDecrease size={ICON_SIZE} className={ICON_CLASS} />
),
createLinkButton: <RiLink size={ICON_SIZE} className={ICON_CLASS} />,
addCommentButton: <RiChat3Line size={ICON_SIZE} className={ICON_CLASS} />,
}

/**
Expand Down Expand Up @@ -160,13 +160,20 @@ export function ToolbarOption() {
const { items, reorder, toggleVisibility, reset, isCustomized } =
useToolbarConfig()

/** DnD sensors: pointer drag (5 px activation distance) and keyboard arrow keys. */
const sensors = useSensors(
useSensor(PointerSensor, { activationConstraint: { distance: 5 } }),
useSensor(KeyboardSensor, {
coordinateGetter: sortableKeyboardCoordinates,
})
)

/**
* Handles the end of a drag event by computing the old and new indices
* and delegating to the `reorder` callback from the toolbar config provider.
*
* @param event - The drag-end event from `@dnd-kit/core`.
*/
const handleDragEnd = useCallback(
(event: DragEndEvent) => {
const { active, over } = event
Expand Down
Loading