import {
Header1Small,
Header2Small,
Header3Small,
} from "components/Icons/BlockTextSmall";
import { Props } from "components/Icons/Props";
import { ShortcutKey, Separator } from "components/Layout";
import { ToolbarButton } from "components/Toolbar";
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";
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 } = useReplicache();
let setLevel = useCallback(
async (level: number) => {
if (!focusedBlock) return;
let entityID = focusedBlock.entityID;
if (
blockType?.data.value !== "text" &&
blockType?.data.value !== "heading"
) {
return;
}
await rep?.mutate.assertFact({
entity: entityID,
attribute: "block/heading-level",
data: { type: "number", value: level },
});
if (blockType.data.value === "text") {
await rep?.mutate.assertFact({
entity: entityID,
attribute: "block/type",
data: { type: "block-type-union", value: "heading" },
});
}
},
[rep, focusedBlock, blockType],
);
return (
// This Toolbar should close once the user starts typing again
<>
{
setLevel(1);
}}
active={
blockType?.data.value === "heading" && headingLevel?.data.value === 1
}
tooltipContent={
}
>
{
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
###
}
>
{
if (headingLevel)
await rep?.mutate.retractFact({ factID: headingLevel.id });
if (textSize) await rep?.mutate.retractFact({ factID: textSize.id });
if (!focusedBlock || !blockType) return;
if (blockType.data.value !== "text") {
let existingEditor =
useEditorStates.getState().editorStates[focusedBlock.entityID];
let selection = existingEditor?.editor.selection;
await rep?.mutate.assertFact({
entity: focusedBlock?.entityID,
attribute: "block/type",
data: { type: "block-type-union", value: "text" },
});
let newEditor =
useEditorStates.getState().editorStates[focusedBlock.entityID];
if (!newEditor || !selection) return;
newEditor.view?.dispatch(
newEditor.editor.tr.setSelection(
TextSelection.create(newEditor.editor.doc, selection.anchor),
),
);
newEditor.view?.focus();
}
}}
active={
blockType?.data.value === "text" &&
textSize?.data.value !== "small" &&
textSize?.data.value !== "large"
}
tooltipContent={Normal Text
}
>
Text
{
if (!focusedBlock || !blockType) return;
if (blockType.data.value !== "text") {
// Convert to text block first if it's a heading
if (headingLevel)
await rep?.mutate.retractFact({ factID: headingLevel.id });
await rep?.mutate.assertFact({
entity: focusedBlock.entityID,
attribute: "block/type",
data: { type: "block-type-union", value: "text" },
});
}
// Set text size to large
await rep?.mutate.assertFact({
entity: focusedBlock.entityID,
attribute: "block/text-size",
data: { type: "text-size-union", value: "large" },
});
}}
active={
blockType?.data.value === "text" && textSize?.data.value === "large"
}
tooltipContent={Large Text
}
>
Large
{
if (!focusedBlock || !blockType) return;
if (blockType.data.value !== "text") {
// Convert to text block first if it's a heading
if (headingLevel)
await rep?.mutate.retractFact({ factID: headingLevel.id });
await rep?.mutate.assertFact({
entity: focusedBlock.entityID,
attribute: "block/type",
data: { type: "block-type-union", value: "text" },
});
}
// Set text size to small
await rep?.mutate.assertFact({
entity: focusedBlock.entityID,
attribute: "block/text-size",
data: { type: "text-size-union", value: "small" },
});
}}
active={
blockType?.data.value === "text" && textSize?.data.value === "small"
}
tooltipContent={Small Text
}
>
Small
>
);
};
export function TextBlockTypeButton(props: {
setToolbarState: (s: "heading") => void;
className?: string;
}) {
return (
Text Size}
className={`${props.className}`}
onClick={() => {
props.setToolbarState("heading");
}}
>
);
}
const TextSizeSmall = (props: Props) => {
return (
);
};