-
Notifications
You must be signed in to change notification settings - Fork 11
Fix: TipTap toolbar cursor-state reactivity #455
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,7 +1,8 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "use client" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useCallback, useEffect, useState } from "react" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useCallback } from "react" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { type Editor } from "@tiptap/react" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { useEditorState } from "@tiptap/react" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { NodeSelection, TextSelection } from "@tiptap/pm/state" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // --- Hooks --- | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -309,25 +310,29 @@ export function useList(config: UseListConfig) { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } = config | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { editor } = useTiptapEditor(providedEditor) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const [isVisible, setIsVisible] = useState<boolean>(true) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const canToggle = canToggleList(editor, type) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const isActive = isListActive(editor, type) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| useEffect(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!editor) return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const handleSelectionUpdate = () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setIsVisible(shouldShowButton({ editor, type, hideWhenUnavailable })) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| handleSelectionUpdate() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| editor.on("selectionUpdate", handleSelectionUpdate) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const toolbarState = useEditorState({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| editor, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| selector: ({ editor: currentEditor }) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!currentEditor) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isVisible: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isActive: false, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| canToggle: false, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return () => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| editor.off("selectionUpdate", handleSelectionUpdate) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, [editor, type, hideWhenUnavailable]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isVisible: shouldShowButton({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| editor: currentEditor, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| type, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hideWhenUnavailable, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isActive: isListActive(currentEditor, type), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| canToggle: canToggleList(currentEditor, type), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| })! | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const { isVisible, isActive, canToggle } = toolbarState | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+313
to
+335
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Find the file and check its basic structure
find . -name "use-list.ts" -type f | head -5Repository: ThinkEx-OSS/thinkex Length of output: 114 🏁 Script executed: #!/bin/bash
# Look for use-list-dropdown-menu.ts as well
find . -name "*use-list-dropdown-menu*" -type fRepository: ThinkEx-OSS/thinkex Length of output: 135 🏁 Script executed: #!/bin/bash
# Check line count to understand file size
wc -l src/components/tiptap-ui/list-button/use-list.ts 2>/dev/null || echo "File not found at that path"Repository: ThinkEx-OSS/thinkex Length of output: 116 🏁 Script executed: #!/bin/bash
# Read the selector code around lines 313-335
sed -n '310,340p' src/components/tiptap-ui/list-button/use-list.tsRepository: ThinkEx-OSS/thinkex Length of output: 826 🏁 Script executed: #!/bin/bash
# Read shouldShowButton function (claimed to be around line 250)
sed -n '240,270p' src/components/tiptap-ui/list-button/use-list.tsRepository: ThinkEx-OSS/thinkex Length of output: 654 🏁 Script executed: #!/bin/bash
# Get the full shouldShowButton function definition
rg -n "shouldShowButton" src/components/tiptap-ui/list-button/use-list.ts -A 20Repository: ThinkEx-OSS/thinkex Length of output: 1198 🏁 Script executed: #!/bin/bash
# Check use-list-dropdown-menu.ts for similar selector pattern
cat -n src/components/tiptap-ui/list-dropdown-menu/use-list-dropdown-menu.ts | head -100Repository: ThinkEx-OSS/thinkex Length of output: 2968 🏁 Script executed: #!/bin/bash
# Search for useEditorState usage in use-list-dropdown-menu.ts
rg -n "useEditorState" src/components/tiptap-ui/list-dropdown-menu/use-list-dropdown-menu.ts -A 25Repository: ThinkEx-OSS/thinkex Length of output: 1492 🏁 Script executed: #!/bin/bash
# Look for any comments or context around the selector in use-list.ts that might explain the design
sed -n '305,325p' src/components/tiptap-ui/list-button/use-list.tsRepository: ThinkEx-OSS/thinkex Length of output: 524 🏁 Script executed: #!/bin/bash
# Check if there's any git history or comments explaining the isVisible: true choice
git log -p --follow -S "isVisible: true" -- src/components/tiptap-ui/list-button/use-list.ts | head -80Repository: ThinkEx-OSS/thinkex Length of output: 45 🏁 Script executed: #!/bin/bash
# Check for any related issue comments or design rationale in the file
sed -n '300,340p' src/components/tiptap-ui/list-button/use-list.tsRepository: ThinkEx-OSS/thinkex Length of output: 996 Align null-editor fallback in selector with The selector returns The same pattern appears in Change the null-editor fallback to Suggested fix const toolbarState = useEditorState({
editor,
selector: ({ editor: currentEditor }) => {
if (!currentEditor) {
return {
- isVisible: true,
+ isVisible: false,
isActive: false,
canToggle: false,
}
}Apply the same fix to 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const handleToggle = useCallback(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (!editor) return false | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor:
canToggle(currentEditor)doesn't reflect the configuredlevels.canTogglefromheading-buttonaccepts a singleleveland is only called here without it, so the result is a generic "can convert to any heading" check rather than scoped to the dropdown's configuredlevels(line 94 default[1..6], but consumers can pass a narrower subset). For a dropdown limited to e.g.[1, 2],canTogglemay reporttrueeven if neither of those specific levels can actually be toggled.If this distinction matters, consider:
Otherwise, this is consistent with prior behavior — flagging for awareness only.
🤖 Prompt for AI Agents