Styling + contenteditable div
This commit is contained in:
parent
6966352d4b
commit
e3321eac89
|
|
@ -0,0 +1,26 @@
|
||||||
|
import { useEffect, useRef } from "preact/hooks";
|
||||||
|
import type { JSX } from "preact";
|
||||||
|
|
||||||
|
type Props = Omit<JSX.HTMLAttributes<HTMLDivElement>, 'value' | 'onInput'> & {
|
||||||
|
value: string;
|
||||||
|
onInput?: JSX.EventHandler<JSX.TargetedInputEvent<HTMLDivElement>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ContentEditable = ({ value, onInput, ...props }: Props) => {
|
||||||
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (ref.current && ref.current.innerHTML !== value) {
|
||||||
|
ref.current.innerHTML = value;
|
||||||
|
}
|
||||||
|
}, [value]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
contentEditable
|
||||||
|
onInput={onInput}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -10,6 +10,8 @@ export const useInputState = (defaultValue = ''): [string, (e: Event | string) =
|
||||||
const { target } = e;
|
const { target } = e;
|
||||||
if (target && 'value' in target && typeof target.value === 'string') {
|
if (target && 'value' in target && typeof target.value === 'string') {
|
||||||
setValue(target.value);
|
setValue(target.value);
|
||||||
|
} else if (target instanceof HTMLElement) {
|
||||||
|
setValue(target.innerHTML);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, []);
|
}, []);
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
background: var(--bg);
|
background: var(--bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
.textarea {
|
.editable {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,10 @@
|
||||||
.sidebar:last-child {
|
.sidebar:last-child {
|
||||||
border-right: none;
|
border-right: none;
|
||||||
border-left: 1px solid var(--border);
|
border-left: 1px solid var(--border);
|
||||||
|
|
||||||
|
& .toggle {
|
||||||
|
align-self: flex-start;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.open {
|
.open {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { Sidebar } from "./sidebar/sidebar";
|
import { Sidebar } from "./sidebar";
|
||||||
import { Editor } from "./editor/editor";
|
import { Editor } from "./editor";
|
||||||
import styles from '../assets/app.module.css';
|
import styles from '../assets/app.module.css';
|
||||||
|
|
||||||
export const App = () => {
|
export const App = () => {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { ContentEditable } from "@common/components/ContentEditable";
|
||||||
|
import { useInputState } from "@common/hooks/useInputState";
|
||||||
|
import styles from '../assets/editor.module.css';
|
||||||
|
|
||||||
|
export const Editor = () => {
|
||||||
|
const [content, handleInput] = useInputState('');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class={styles.editor}>
|
||||||
|
<ContentEditable
|
||||||
|
class={styles.editable}
|
||||||
|
value={content}
|
||||||
|
onInput={handleInput}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -1,9 +0,0 @@
|
||||||
import styles from '../../assets/editor.module.css';
|
|
||||||
|
|
||||||
export const Editor = () => {
|
|
||||||
return (
|
|
||||||
<div class={styles.editor}>
|
|
||||||
<textarea class={styles.textarea} placeholder="Start writing..." />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { useBool } from "@common/hooks/useBool";
|
import { useBool } from "@common/hooks/useBool";
|
||||||
import styles from '../../assets/sidebar.module.css';
|
import styles from '../assets/sidebar.module.css';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
side: 'left' | 'right';
|
side: 'left' | 'right';
|
||||||
Loading…
Reference in New Issue