a tool for shared writing and social publishing
1import { useEntity, useReplicache } from "src/replicache";
2import "katex/dist/katex.min.css";
3import { BlockProps } from "./Block";
4import Katex from "katex";
5import { useMemo } from "react";
6import { useUIState } from "src/useUIState";
7import { theme } from "tailwind.config";
8import { BaseTextareaBlock } from "./BaseTextareaBlock";
9import { elementId } from "src/utils/elementId";
10
11export function MathBlock(props: BlockProps) {
12 let content = useEntity(props.entityID, "block/math");
13 let focusedBlock = useUIState(
14 (s) => s.focusedEntity?.entityID === props.entityID,
15 );
16 let { rep } = useReplicache();
17 const { html, error } = useMemo(() => {
18 try {
19 const html = Katex.renderToString(content?.data.value || "", {
20 displayMode: true,
21 throwOnError: false,
22 errorColor: theme.colors["accent-contrast"],
23 });
24
25 return { html, error: undefined };
26 } catch (error) {
27 if (error instanceof Katex.ParseError || error instanceof TypeError) {
28 return { error };
29 }
30
31 throw error;
32 }
33 }, [content?.data.value]);
34 return focusedBlock ? (
35 <BaseTextareaBlock
36 id={elementId.block(props.entityID).input}
37 block={props}
38 className="bg-border-light rounded-md p-2 w-full min-h-[48px] whitespace-nowrap overflow-auto! border-border-light outline-border-light selected-outline"
39 placeholder="write some Tex here..."
40 value={content?.data.value}
41 onChange={async (e) => {
42 // Update the entity with the new value
43 await rep?.mutate.assertFact({
44 attribute: "block/math",
45 entity: props.entityID,
46 data: { type: "string", value: e.target.value },
47 });
48 }}
49 />
50 ) : html && content?.data.value ? (
51 <div
52 className="text-lg min-h-[66px] w-full border border-transparent"
53 dangerouslySetInnerHTML={{ __html: html }}
54 />
55 ) : (
56 <div className="text-tertiary italic rounded-md p-2 w-full min-h-16">
57 write some Tex here...
58 </div>
59 );
60}