import { Header1Small, Header2Small, Header3Small, } from "components/Icons/BlockTextSmall"; import { Props } from "components/Icons/Props"; import { QuoteSmall } from "components/Icons/QuoteSmall"; import { ShortcutKey, Separator } from "components/Layout"; import { ToolbarButton } from "components/Toolbar"; import { getSelectedOrFocusedBlocks } from "components/SelectionManager/selectionState"; import { TextSelection } from "prosemirror-state"; import { useCallback } from "react"; import { useEntity, useReplicache } from "src/replicache"; import { useEditorStates } from "src/state/useEditorState"; import { useUIState } from "src/useUIState"; import { setTextBlockStyle, TextBlockStyle } from "src/utils/blockTypeOperations"; export const TextBlockTypeToolbar = (props: { onClose: () => void; className?: string; }) => { let focusedBlock = useUIState((s) => s.focusedEntity); let blockType = useEntity(focusedBlock?.entityID || null, "block/type"); let headingLevel = useEntity( focusedBlock?.entityID || null, "block/heading-level", ); let textSize = useEntity(focusedBlock?.entityID || null, "block/text-size"); let { rep, undoManager } = useReplicache(); let setStyle = useCallback( async (style: TextBlockStyle) => { if (!rep) return; // Changing block/type remounts the focused block's editor, so stash the // caret and put it back afterwards or the user is dropped out of the doc. let focused = useUIState.getState().focusedEntity; let previousSelection = focused?.entityType === "block" ? useEditorStates.getState().editorStates[focused.entityID]?.editor .selection : undefined; let blocks = await getSelectedOrFocusedBlocks(rep); await setTextBlockStyle(blocks, style, rep, undoManager); // Refocusing would collapse a multi-block selection down to one editor. if (blocks.length !== 1) return; if (!focused || focused.entityType !== "block" || !previousSelection) return; let newEditor = useEditorStates.getState().editorStates[focused.entityID]; if (!newEditor) return; newEditor.view?.dispatch( newEditor.editor.tr.setSelection( TextSelection.create( newEditor.editor.doc, Math.min(previousSelection.anchor, newEditor.editor.doc.content.size), ), ), ); newEditor.view?.focus(); }, [rep, undoManager], ); let setLevel = useCallback( (level: number) => setStyle({ style: "heading", level }), [setStyle], ); return ( // This Toolbar should close once the user starts typing again <> { setLevel(1); }} active={ blockType?.data.value === "heading" && headingLevel?.data.value === 1 } tooltipContent={
Title
start line with #
} >
{ setLevel(2); }} active={ blockType?.data.value === "heading" && headingLevel?.data.value === 2 } tooltipContent={
Heading
start line with ##
} >
{ setLevel(3); }} active={ blockType?.data.value === "heading" && headingLevel?.data.value === 3 } tooltipContent={
Subheading
start line with ###
} >
setStyle({ style: "text", size: "default" })} active={ blockType?.data.value === "text" && textSize?.data.value !== "small" && textSize?.data.value !== "large" } tooltipContent={
Normal Text
} > Text
setStyle({ style: "text", size: "large" })} active={ blockType?.data.value === "text" && textSize?.data.value === "large" } tooltipContent={
Large Text
} >
Large
setStyle({ style: "text", size: "small" })} active={ blockType?.data.value === "text" && textSize?.data.value === "small" } tooltipContent={
Small Text
} >
Small
setStyle( blockType?.data.value === "blockquote" ? { style: "text", size: "default" } : { style: "blockquote" }, ) } active={blockType?.data.value === "blockquote"} tooltipContent={
Block Quote
start line with >
} >
); }; export function TextBlockTypeButton(props: { setToolbarState: (s: "heading") => void; className?: string; }) { return ( Text Style} className={`${props.className}`} onClick={() => { props.setToolbarState("heading"); }} > ); } const TextSizeSmall = (props: Props) => { return ( ); };