markdown editor failing at sync
This commit is contained in:
parent
6f4dcb1bcb
commit
2fc965da28
|
|
@ -15,21 +15,23 @@
|
|||
"author": "Jeff Emmett",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@hackmd/markdown-it": "^12.0.23",
|
||||
"@hackmd/markdown-it-task-lists": "^2.1.4",
|
||||
"@tldraw/assets": "^3.6.0",
|
||||
"@tldraw/sync": "^3.6.0",
|
||||
"@tldraw/sync-core": "^3.6.0",
|
||||
"@tldraw/tldraw": "^3.6.0",
|
||||
"@tldraw/tlschema": "^3.6.0",
|
||||
"@types/markdown-it": "^14.1.1",
|
||||
"@vercel/analytics": "^1.2.2",
|
||||
"cloudflare-workers-unfurl": "^0.0.7",
|
||||
"gray-matter": "^4.0.3",
|
||||
"itty-router": "^5.0.17",
|
||||
"lodash.throttle": "^4.1.1",
|
||||
"markdown-it": "^14.1.0",
|
||||
"markdown-it-task-lists": "^2.1.1",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-markdown-editor-lite": "^1.3.4",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-router-dom": "^7.0.2",
|
||||
"tldraw": "^3.6.0",
|
||||
"vercel": "^39.1.1"
|
||||
|
|
@ -38,8 +40,10 @@
|
|||
"@cloudflare/types": "^6.0.0",
|
||||
"@cloudflare/workers-types": "^4.20240821.1",
|
||||
"@types/lodash.throttle": "^4",
|
||||
"@types/markdown-it": "^14.1.2",
|
||||
"@types/react": "^19.0.1",
|
||||
"@types/react-dom": "^19.0.1",
|
||||
"@types/styled-components": "^5.1.34",
|
||||
"@vitejs/plugin-react": "^4.0.3",
|
||||
"@vitejs/plugin-react-swc": "^3.6.0",
|
||||
"concurrently": "^9.1.0",
|
||||
|
|
|
|||
|
|
@ -326,11 +326,10 @@ p:has(+ ol) {
|
|||
background-color: white;
|
||||
}
|
||||
|
||||
.rc-md-editor {
|
||||
border: none !important;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
||||
.rc-md-editor .editor-container {
|
||||
border-radius: 4px;
|
||||
.mdx-editor {
|
||||
height: 100%;
|
||||
padding: 8px;
|
||||
outline: none;
|
||||
font-family: inherit;
|
||||
}
|
||||
|
|
@ -1,83 +1,163 @@
|
|||
/** TODO: build this */
|
||||
|
||||
import { BaseBoxShapeUtil, TLBaseBoxShape, TLBaseShape } from "tldraw"
|
||||
import MdEditor from "react-markdown-editor-lite"
|
||||
import MarkdownIt from "markdown-it"
|
||||
import "react-markdown-editor-lite/lib/index.css"
|
||||
|
||||
// Initialize markdown parser
|
||||
const mdParser = new MarkdownIt()
|
||||
import ReactMarkdown from "react-markdown"
|
||||
import { useCallback, useState, useEffect } from "react"
|
||||
|
||||
export type IMarkdownShape = TLBaseShape<
|
||||
"MarkdownTool",
|
||||
"markdown",
|
||||
{
|
||||
content: string
|
||||
html: string
|
||||
w: number
|
||||
h: number
|
||||
isEditing: boolean
|
||||
fill: string
|
||||
color: string
|
||||
}
|
||||
>
|
||||
|
||||
export class MarkdownShape extends BaseBoxShapeUtil<
|
||||
IMarkdownShape & TLBaseBoxShape
|
||||
> {
|
||||
static override type = "MarkdownTool"
|
||||
|
||||
indicator(_shape: IMarkdownShape) {
|
||||
return null
|
||||
static override type = "Markdown"
|
||||
static override props = {
|
||||
content: {
|
||||
type: "string",
|
||||
value: "# New Note",
|
||||
validate: (value: unknown) => typeof value === "string",
|
||||
},
|
||||
w: {
|
||||
type: "number",
|
||||
value: 400,
|
||||
validate: (value: unknown) => typeof value === "number",
|
||||
},
|
||||
h: {
|
||||
type: "number",
|
||||
value: 300,
|
||||
validate: (value: unknown) => typeof value === "number",
|
||||
},
|
||||
isEditing: {
|
||||
type: "boolean",
|
||||
value: false,
|
||||
validate: (value: unknown) => typeof value === "boolean",
|
||||
},
|
||||
fill: {
|
||||
type: "string",
|
||||
value: "white",
|
||||
validate: (value: unknown) => typeof value === "string",
|
||||
},
|
||||
color: {
|
||||
type: "string",
|
||||
value: "black",
|
||||
validate: (value: unknown) => typeof value === "string",
|
||||
},
|
||||
}
|
||||
|
||||
getDefaultProps(): IMarkdownShape["props"] & { w: number; h: number } {
|
||||
override getDefaultProps(): IMarkdownShape["props"] &
|
||||
TLBaseBoxShape["props"] {
|
||||
return {
|
||||
content: "# New Note",
|
||||
html: "<h1>New Note</h1>",
|
||||
w: 400,
|
||||
h: 300,
|
||||
content: "# New Note",
|
||||
isEditing: false,
|
||||
fill: "white",
|
||||
color: "black",
|
||||
}
|
||||
}
|
||||
|
||||
getStyleProps(shape: IMarkdownShape) {
|
||||
return {
|
||||
fill: shape.props.fill,
|
||||
color: shape.props.color,
|
||||
}
|
||||
}
|
||||
|
||||
override indicator(shape: IMarkdownShape & TLBaseBoxShape) {
|
||||
return {
|
||||
x: shape.x,
|
||||
y: shape.y,
|
||||
width: shape.props.w,
|
||||
height: shape.props.h,
|
||||
rotation: shape.rotation,
|
||||
}
|
||||
}
|
||||
|
||||
component(shape: IMarkdownShape & TLBaseBoxShape) {
|
||||
const handleEditorChange = ({
|
||||
text,
|
||||
html,
|
||||
}: {
|
||||
text: string
|
||||
html: string
|
||||
}) => {
|
||||
// Update the shape's content
|
||||
const [isEditing, setIsEditing] = useState(shape.props.isEditing)
|
||||
|
||||
const handleChange = useCallback(
|
||||
(e: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||
this.editor?.updateShape({
|
||||
id: shape.id,
|
||||
type: "markdown",
|
||||
props: {
|
||||
...shape.props,
|
||||
content: e.target.value,
|
||||
},
|
||||
})
|
||||
},
|
||||
[shape.id],
|
||||
)
|
||||
|
||||
const toggleEdit = useCallback(() => {
|
||||
setIsEditing(!isEditing)
|
||||
this.editor?.updateShape({
|
||||
id: shape.id,
|
||||
type: "MarkdownTool",
|
||||
type: "markdown",
|
||||
props: {
|
||||
...shape.props,
|
||||
content: text,
|
||||
html: html,
|
||||
isEditing: !isEditing,
|
||||
},
|
||||
})
|
||||
}
|
||||
}, [isEditing, shape.id, shape.props])
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (isEditing) {
|
||||
this.editor?.updateShape({
|
||||
id: shape.id,
|
||||
type: "markdown",
|
||||
props: {
|
||||
...shape.props,
|
||||
isEditing: false,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}, [shape.id, isEditing])
|
||||
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
position: "relative",
|
||||
background: "white",
|
||||
borderRadius: "4px",
|
||||
padding: "8px",
|
||||
overflow: "auto",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
onDoubleClick={toggleEdit}
|
||||
>
|
||||
<MdEditor
|
||||
style={{ height: "100%" }}
|
||||
renderHTML={(text) => mdParser.render(text)}
|
||||
value={shape.props.content}
|
||||
onChange={handleEditorChange}
|
||||
view={{ menu: true, md: true, html: false }}
|
||||
canView={{
|
||||
menu: true,
|
||||
md: true,
|
||||
html: false,
|
||||
both: false,
|
||||
fullScreen: false,
|
||||
hideMenu: false,
|
||||
}}
|
||||
/>
|
||||
{isEditing ? (
|
||||
<textarea
|
||||
value={shape.props.content}
|
||||
onChange={handleChange}
|
||||
style={{
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
border: "none",
|
||||
outline: "none",
|
||||
resize: "none",
|
||||
fontFamily: "inherit",
|
||||
fontSize: "inherit",
|
||||
backgroundColor: "transparent",
|
||||
}}
|
||||
autoFocus
|
||||
onBlur={toggleEdit}
|
||||
/>
|
||||
) : (
|
||||
<ReactMarkdown>{shape.props.content}</ReactMarkdown>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { BaseBoxShapeTool } from "tldraw"
|
||||
|
||||
export class MarkdownTool extends BaseBoxShapeTool {
|
||||
static override id = "MarkdownTool"
|
||||
shapeType = "MarkdownTool"
|
||||
static override id = "markdown"
|
||||
shapeType = "markdown"
|
||||
override initial = "idle"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,12 +99,12 @@ export function CustomContextMenu(props: TLUiContextMenuProps) {
|
|||
/>
|
||||
<TldrawUiMenuItem
|
||||
id="markdown"
|
||||
label="Create Markdown"
|
||||
label="Create Markdown Box"
|
||||
icon="markdown"
|
||||
kbd="alt+m"
|
||||
disabled={hasSelection}
|
||||
onSelect={() => {
|
||||
editor.setCurrentTool("Markdown")
|
||||
editor.setCurrentTool("markdown")
|
||||
}}
|
||||
/>
|
||||
</TldrawUiMenuGroup>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { defineConfig } from "vite";
|
||||
import react from "@vitejs/plugin-react";
|
||||
import { defineConfig } from "vite"
|
||||
import react from "@vitejs/plugin-react"
|
||||
|
||||
export default defineConfig({
|
||||
envPrefix: ["VITE_"],
|
||||
|
|
@ -20,7 +20,7 @@ export default defineConfig({
|
|||
},
|
||||
define: {
|
||||
"import.meta.env.VITE_WORKER_URL": JSON.stringify(
|
||||
process.env.VITE_WORKER_URL
|
||||
process.env.VITE_WORKER_URL,
|
||||
),
|
||||
},
|
||||
});
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in New Issue