2022-04-09 20:48:19 -04:00
|
|
|
import {
|
|
|
|
ChangeEvent,
|
|
|
|
memo,
|
|
|
|
useCallback,
|
|
|
|
useMemo,
|
|
|
|
useRef,
|
|
|
|
useState
|
|
|
|
} from "react"
|
|
|
|
import styles from "./document.module.css"
|
|
|
|
import Trash from "@geist-ui/icons/trash"
|
2022-03-11 21:48:40 -05:00
|
|
|
import FormattingIcons from "./formatting-icons"
|
2022-03-21 23:43:50 -04:00
|
|
|
|
2022-04-09 20:48:19 -04:00
|
|
|
import {
|
|
|
|
Button,
|
|
|
|
ButtonGroup,
|
|
|
|
Card,
|
|
|
|
Input,
|
|
|
|
Spacer,
|
|
|
|
Tabs,
|
|
|
|
Textarea,
|
|
|
|
Tooltip
|
|
|
|
} from "@geist-ui/core"
|
2022-03-22 23:06:15 -04:00
|
|
|
import Preview from "@components/preview"
|
2022-03-21 23:43:50 -04:00
|
|
|
|
2022-03-11 21:48:40 -05:00
|
|
|
// import Link from "next/link"
|
2022-03-06 19:46:59 -05:00
|
|
|
type Props = {
|
2022-04-09 20:48:19 -04:00
|
|
|
title?: string
|
|
|
|
content?: string
|
|
|
|
setTitle?: (title: string) => void
|
|
|
|
setContent?: (content: string) => void
|
|
|
|
handleOnContentChange?: (e: ChangeEvent<HTMLTextAreaElement>) => void
|
|
|
|
initialTab?: "edit" | "preview"
|
|
|
|
remove?: () => void
|
|
|
|
onPaste?: (e: any) => void
|
2022-03-06 19:46:59 -05:00
|
|
|
}
|
|
|
|
|
2022-04-09 20:48:19 -04:00
|
|
|
const Document = ({
|
|
|
|
onPaste,
|
|
|
|
remove,
|
|
|
|
title,
|
|
|
|
content,
|
|
|
|
setTitle,
|
|
|
|
setContent,
|
|
|
|
initialTab = "edit",
|
|
|
|
handleOnContentChange
|
|
|
|
}: Props) => {
|
|
|
|
const codeEditorRef = useRef<HTMLTextAreaElement>(null)
|
|
|
|
const [tab, setTab] = useState(initialTab)
|
|
|
|
// const height = editable ? "500px" : '100%'
|
|
|
|
const height = "100%"
|
2022-03-08 03:43:18 -05:00
|
|
|
|
2022-04-09 20:48:19 -04:00
|
|
|
const handleTabChange = (newTab: string) => {
|
|
|
|
if (newTab === "edit") {
|
|
|
|
codeEditorRef.current?.focus()
|
|
|
|
}
|
|
|
|
setTab(newTab as "edit" | "preview")
|
|
|
|
}
|
2022-03-06 19:46:59 -05:00
|
|
|
|
2022-04-09 20:48:19 -04:00
|
|
|
const onTitleChange = useCallback(
|
|
|
|
(event: ChangeEvent<HTMLInputElement>) =>
|
|
|
|
setTitle ? setTitle(event.target.value) : null,
|
|
|
|
[setTitle]
|
|
|
|
)
|
2022-03-22 01:50:25 -04:00
|
|
|
|
2022-04-09 20:48:19 -04:00
|
|
|
const removeFile = useCallback(
|
|
|
|
(remove?: () => void) => {
|
|
|
|
if (remove) {
|
|
|
|
if (content && content.trim().length > 0) {
|
|
|
|
const confirmed = window.confirm(
|
|
|
|
"Are you sure you want to remove this file?"
|
|
|
|
)
|
|
|
|
if (confirmed) {
|
|
|
|
remove()
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
remove()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
[content]
|
|
|
|
)
|
2022-03-11 21:48:40 -05:00
|
|
|
|
2022-04-09 20:48:19 -04:00
|
|
|
// if (skeleton) {
|
|
|
|
// return <>
|
|
|
|
// <Spacer height={1} />
|
|
|
|
// <div className={styles.card}>
|
|
|
|
// <div className={styles.fileNameContainer}>
|
|
|
|
// <Skeleton width={275} height={36} />
|
|
|
|
// {remove && <Skeleton width={36} height={36} />}
|
|
|
|
// </div>
|
|
|
|
// <div className={styles.descriptionContainer}>
|
|
|
|
// <div style={{ flexDirection: 'row', display: 'flex' }}><Skeleton width={125} height={36} /></div>
|
|
|
|
// <Skeleton width={'100%'} height={350} />
|
|
|
|
// </div >
|
|
|
|
// </div>
|
|
|
|
// </>
|
|
|
|
// }
|
2022-03-22 01:50:25 -04:00
|
|
|
|
2022-04-09 20:48:19 -04:00
|
|
|
return (
|
|
|
|
<>
|
|
|
|
<Spacer height={1} />
|
|
|
|
<div className={styles.card}>
|
|
|
|
<div className={styles.fileNameContainer}>
|
|
|
|
<Input
|
|
|
|
placeholder="MyFile.md"
|
|
|
|
value={title}
|
|
|
|
onChange={onTitleChange}
|
|
|
|
marginTop="var(--gap-double)"
|
|
|
|
size={1.2}
|
|
|
|
font={1.2}
|
|
|
|
label="Filename"
|
|
|
|
width={"100%"}
|
|
|
|
id={title}
|
|
|
|
/>
|
|
|
|
{remove && (
|
|
|
|
<Button
|
|
|
|
type="abort"
|
|
|
|
ghost
|
|
|
|
icon={<Trash />}
|
|
|
|
auto
|
|
|
|
height={"36px"}
|
|
|
|
width={"36px"}
|
|
|
|
onClick={() => removeFile(remove)}
|
|
|
|
/>
|
|
|
|
)}
|
|
|
|
</div>
|
|
|
|
<div className={styles.descriptionContainer}>
|
|
|
|
{tab === "edit" && (
|
|
|
|
<FormattingIcons setText={setContent} textareaRef={codeEditorRef} />
|
|
|
|
)}
|
|
|
|
<Tabs
|
|
|
|
onChange={handleTabChange}
|
|
|
|
initialValue={initialTab}
|
|
|
|
hideDivider
|
|
|
|
leftSpace={0}
|
|
|
|
>
|
|
|
|
<Tabs.Item label={"Edit"} value="edit">
|
|
|
|
{/* <textarea className={styles.lineCounter} wrap='off' readOnly ref={lineNumberRef}>1.</textarea> */}
|
|
|
|
<div
|
|
|
|
style={{
|
|
|
|
marginTop: "var(--gap-half)",
|
|
|
|
display: "flex",
|
|
|
|
flexDirection: "column"
|
|
|
|
}}
|
|
|
|
>
|
|
|
|
<Textarea
|
|
|
|
onPaste={onPaste ? onPaste : undefined}
|
|
|
|
ref={codeEditorRef}
|
|
|
|
placeholder=""
|
|
|
|
value={content}
|
|
|
|
onChange={handleOnContentChange}
|
|
|
|
width="100%"
|
|
|
|
// TODO: Textarea should grow to fill parent if height == 100%
|
|
|
|
style={{ flex: 1, minHeight: 350 }}
|
|
|
|
resize="vertical"
|
|
|
|
className={styles.textarea}
|
|
|
|
/>
|
|
|
|
</div>
|
|
|
|
</Tabs.Item>
|
|
|
|
<Tabs.Item label="Preview" value="preview">
|
|
|
|
<div style={{ marginTop: "var(--gap-half)" }}>
|
|
|
|
<Preview height={height} title={title} content={content} />
|
|
|
|
</div>
|
|
|
|
</Tabs.Item>
|
|
|
|
</Tabs>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</>
|
|
|
|
)
|
2022-03-06 19:46:59 -05:00
|
|
|
}
|
|
|
|
|
2022-04-09 20:48:19 -04:00
|
|
|
export default memo(Document)
|