CoastalCommitsPastes/client/components/edit-document/index.tsx

148 lines
5.9 KiB
TypeScript
Raw Normal View History

import { ChangeEvent, memo, useCallback, useMemo, useRef, useState } from "react"
2022-03-06 19:46:59 -05:00
import styles from './document.module.css'
2022-03-21 18:55:21 -04:00
import Trash from '@geist-ui/icons/trash'
import Download from '@geist-ui/icons/download'
import ExternalLink from '@geist-ui/icons/externalLink'
import FormattingIcons from "./formatting-icons"
2022-03-09 20:11:37 -05:00
import Skeleton from "react-loading-skeleton"
import { Button, ButtonGroup, Card, Input, Spacer, Tabs, Textarea, Tooltip } from "@geist-ui/core"
import Preview from "@components/preview"
// import Link from "next/link"
2022-03-06 19:46:59 -05:00
type Props = {
title?: string
content?: string
setTitle?: (title: string) => void
setContent?: (content: string) => void
handleOnContentChange?: (e: ChangeEvent<HTMLTextAreaElement>) => void
2022-03-07 01:16:08 -05:00
initialTab?: "edit" | "preview"
2022-03-09 20:11:37 -05:00
skeleton?: boolean
remove?: () => void
2022-03-06 19:46:59 -05:00
}
const DownloadButton = ({ rawLink }: { rawLink?: string }) => {
return (<div className={styles.actionWrapper}>
<ButtonGroup className={styles.actions}>
<Tooltip text="Download">
<a href={`${rawLink}?download=true`} target="_blank" rel="noopener noreferrer">
<Button
scale={2 / 3} px={0.6}
icon={<Download />}
auto
aria-label="Download"
/>
</a>
</Tooltip>
<Tooltip text="Open raw in new tab">
<a href={rawLink} target="_blank" rel="noopener noreferrer">
<Button
scale={2 / 3} px={0.6}
icon={<ExternalLink />}
auto
aria-label="Open raw file in new tab"
/>
</a>
</Tooltip>
</ButtonGroup>
</div>)
}
const Document = ({ remove, title, content, setTitle, setContent, initialTab = 'edit', skeleton, handleOnContentChange }: Props) => {
2022-03-06 19:46:59 -05:00
const codeEditorRef = useRef<HTMLTextAreaElement>(null)
const [tab, setTab] = useState(initialTab)
// const height = editable ? "500px" : '100%'
const height = "100%";
const handleTabChange = (newTab: string) => {
if (newTab === 'edit') {
codeEditorRef.current?.focus()
}
setTab(newTab as 'edit' | 'preview')
}
2022-03-06 19:46:59 -05:00
const onTitleChange = useCallback((event: ChangeEvent<HTMLInputElement>) => setTitle ? setTitle(event.target.value) : null, [setTitle])
2022-03-23 00:37:27 -04:00
const removeFile = useCallback((remove?: () => void) => {
2022-03-06 19:46:59 -05:00
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-09 20:11:37 -05:00
if (skeleton) {
return <>
<Spacer height={1} />
<Card marginBottom={'var(--gap)'} marginTop={'var(--gap)'} style={{ maxWidth: 980, margin: "0 auto" }}>
<div className={styles.fileNameContainer}>
<Skeleton width={275} height={36} />
{remove && <Skeleton width={36} height={36} />}
2022-03-09 20:11:37 -05:00
</div>
<div className={styles.descriptionContainer}>
<div style={{ flexDirection: 'row', display: 'flex' }}><Skeleton width={125} height={36} /></div>
<Skeleton width={'100%'} height={350} />
</div >
</Card>
</>
}
2022-03-06 19:46:59 -05:00
return (
<>
<Spacer height={1} />
<Card marginBottom={'var(--gap)'} marginTop={'var(--gap)'} style={{ maxWidth: 980, margin: "0 auto" }}>
<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%"}
2022-03-20 23:45:37 -04:00
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)', display: 'flex', flexDirection: 'column' }}>
<Textarea
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">
<Preview height={height} title={title} content={content} />
</Tabs.Item>
</Tabs>
2022-03-08 03:37:18 -05:00
</div >
</Card >
<Spacer height={1} />
</>
2022-03-06 19:46:59 -05:00
)
}
export default memo(Document)