💄 selection count
This commit is contained in:
@@ -697,7 +697,15 @@ export function MarkdownEditor(): JSX.Element {
|
|||||||
}
|
}
|
||||||
if (update.selectionSet) {
|
if (update.selectionSet) {
|
||||||
const { from, to } = update.state.selection.main
|
const { from, to } = update.state.selection.main
|
||||||
setHasSelection(from !== to)
|
const hasNonEmpty = from !== to
|
||||||
|
setHasSelection(hasNonEmpty)
|
||||||
|
if (hasNonEmpty) {
|
||||||
|
const sel = update.state.sliceDoc(from, to)
|
||||||
|
const words = sel.trim() === '' ? 0 : sel.trim().split(/\s+/).length
|
||||||
|
useEditorStore.getState().setSelectionWordCount(words)
|
||||||
|
} else {
|
||||||
|
useEditorStore.getState().setSelectionWordCount(null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// When the user Cmd+Z's through an Apply, invertedEffects fires a
|
// When the user Cmd+Z's through an Apply, invertedEffects fires a
|
||||||
// setAnnotationsEffect restoring the old list inside CM. Sync that
|
// setAnnotationsEffect restoring the old list inside CM. Sync that
|
||||||
|
|||||||
@@ -79,7 +79,8 @@ export function AnalysisToolbar(): JSX.Element {
|
|||||||
outlineOpen,
|
outlineOpen,
|
||||||
toggleOutline,
|
toggleOutline,
|
||||||
revisionPanelOpen,
|
revisionPanelOpen,
|
||||||
toggleRevisionPanel
|
toggleRevisionPanel,
|
||||||
|
selectionWordCount
|
||||||
} = useEditorStore()
|
} = useEditorStore()
|
||||||
|
|
||||||
const [analyzeOpen, setAnalyzeOpen] = useState(false)
|
const [analyzeOpen, setAnalyzeOpen] = useState(false)
|
||||||
@@ -381,6 +382,11 @@ export function AnalysisToolbar(): JSX.Element {
|
|||||||
A+
|
A+
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
{selectionWordCount !== null && (
|
||||||
|
<span className="toolbar-selection-wordcount" title={`${selectionWordCount} words selected`}>
|
||||||
|
{formatWordCount(selectionWordCount)} sel
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
{activeFilePath && (
|
{activeFilePath && (
|
||||||
<span
|
<span
|
||||||
className="toolbar-wordcount"
|
className="toolbar-wordcount"
|
||||||
|
|||||||
@@ -142,6 +142,17 @@
|
|||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.toolbar-selection-wordcount {
|
||||||
|
color: var(--text-muted);
|
||||||
|
font-size: 11px;
|
||||||
|
font-family: var(--font-sans);
|
||||||
|
white-space: nowrap;
|
||||||
|
flex-shrink: 0;
|
||||||
|
cursor: default;
|
||||||
|
opacity: 0.6;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
|
}
|
||||||
|
|
||||||
/* ── Outline toggle button ───────────────────────────────────────── */
|
/* ── Outline toggle button ───────────────────────────────────────── */
|
||||||
.toolbar-btn-outline {
|
.toolbar-btn-outline {
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ interface EditorState {
|
|||||||
// Word counts
|
// Word counts
|
||||||
projectWordCount: number
|
projectWordCount: number
|
||||||
setProjectWordCount: (count: number) => void
|
setProjectWordCount: (count: number) => void
|
||||||
|
selectionWordCount: number | null
|
||||||
|
setSelectionWordCount: (count: number | null) => void
|
||||||
|
|
||||||
// Editor font size
|
// Editor font size
|
||||||
fontSize: number
|
fontSize: number
|
||||||
@@ -593,6 +595,9 @@ export const useEditorStore = create<EditorState>((set, get) => ({
|
|||||||
projectWordCount: 0,
|
projectWordCount: 0,
|
||||||
setProjectWordCount: (projectWordCount) => set({ projectWordCount }),
|
setProjectWordCount: (projectWordCount) => set({ projectWordCount }),
|
||||||
|
|
||||||
|
selectionWordCount: null as number | null,
|
||||||
|
setSelectionWordCount: (count: number | null) => set({ selectionWordCount: count }),
|
||||||
|
|
||||||
revisionPanelOpen: false,
|
revisionPanelOpen: false,
|
||||||
toggleRevisionPanel: () => set((s) => ({ revisionPanelOpen: !s.revisionPanelOpen })),
|
toggleRevisionPanel: () => set((s) => ({ revisionPanelOpen: !s.revisionPanelOpen })),
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user