diff --git a/tsconfig.json b/tsconfig.json index f236fad..5fbc154 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,4 +1,8 @@ { "extends": "@ocavue/tsconfig/dom/root.json", - "references": [{ "path": "./packages/core/tsconfig.json" }] + "references": [ + { "path": "./packages/core/tsconfig.json" }, + { "path": "./packages/react/tsconfig.json" }, + { "path": "./website/tsconfig.json" } + ] } diff --git a/website/src/app.tsx b/website/src/app.tsx index 10f49e1..e4ebae3 100644 --- a/website/src/app.tsx +++ b/website/src/app.tsx @@ -1,7 +1,8 @@ -import { MeowdownEditor, type EditorMode } from '@meowdown/react' +import { MeowdownEditor, type TagItem, type WikilinkItem } from '@meowdown/react' import { type CSSProperties, useLayoutEffect, useState } from 'react' import { uploadFile } from './upload-file.ts' +import { MODES, useEditorMode } from './use-editor-mode.ts' // Confirm, then open the target in a new tab. Shared by the link and image // click handlers below. @@ -19,35 +20,6 @@ function handleImageClick({ src }: { src: string }): void { confirmAndOpen('this image', src) } -interface ModeOption { - value: EditorMode - label: string - description: string -} - -const MODES: ModeOption[] = [ - { - value: 'focus', - label: 'Focus', - description: 'Syntax stays hidden and peeks out only where your cursor rests.', - }, - { - value: 'show', - label: 'Show', - description: 'Every Markdown character stays visible, dimmed in soft grey.', - }, - { - value: 'hide', - label: 'Hide', - description: 'Markdown characters disappear for a clean, fully rendered view.', - }, - { - value: 'source', - label: 'Source', - description: 'Raw Markdown with syntax highlighting, like an IDE.', - }, -] - const INITIAL_CONTENT = ` # Welcome to Meowdown @@ -90,10 +62,10 @@ function greet(name: string): string { const TAGS = ['cats', 'editor', 'ideas', 'markdown', 'meow', 'notes', 'react', 'todo', 'work'] -async function searchTags(query: string): Promise { +async function searchTags(query: string): Promise { // Simulate network latency so the tag menu's loading state shows up. await new Promise((resolve) => setTimeout(resolve, 200)) - return TAGS.filter((tag) => tag.includes(query)) + return TAGS.filter((tag) => tag.includes(query)).map((tag) => ({ tag })) } const NOTES = [ @@ -105,10 +77,12 @@ const NOTES = [ 'Travel plans', ] -async function searchNotes(query: string): Promise { +async function searchNotes(query: string): Promise { // Simulate network latency so the wikilink menu's loading state shows up. await new Promise((resolve) => setTimeout(resolve, 200)) - return NOTES.filter((note) => note.toLowerCase().includes(query)) + return NOTES.filter((note) => note.toLowerCase().includes(query)).map((note) => ({ + target: note, + })) } const ICON_BUTTON_CLASS = @@ -199,8 +173,7 @@ function Brand() { } export function App() { - const [mode, setMode] = useState('focus') - const activeMode = MODES.find((option) => option.value === mode) ?? MODES[0] + const { mode, setMode, activeMode } = useEditorMode() return (
diff --git a/website/src/use-editor-mode.ts b/website/src/use-editor-mode.ts new file mode 100644 index 0000000..410ad95 --- /dev/null +++ b/website/src/use-editor-mode.ts @@ -0,0 +1,61 @@ +import type { EditorMode } from '@meowdown/react' +import { useEffect, useState } from 'react' + +interface ModeOption { + value: EditorMode + label: string + description: string +} + +export const MODES: ModeOption[] = [ + { + value: 'focus', + label: 'Focus', + description: 'Syntax stays hidden and peeks out only where your cursor rests.', + }, + { + value: 'show', + label: 'Show', + description: 'Every Markdown character stays visible, dimmed in soft grey.', + }, + { + value: 'hide', + label: 'Hide', + description: 'Markdown characters disappear for a clean, fully rendered view.', + }, + { + value: 'source', + label: 'Source', + description: 'Raw Markdown with syntax highlighting, like an IDE.', + }, +] + +const MODE_STORAGE_KEY = 'meowdown:mode' + +function readStoredMode(): EditorMode { + const stored = sessionStorage.getItem(MODE_STORAGE_KEY) + if (stored) { + for (const option of MODES) { + if (option.value === stored) { + return option.value + } + } + } + return 'focus' +} + +function writeStoredMode(mode: EditorMode): void { + sessionStorage.setItem(MODE_STORAGE_KEY, mode) +} + +export function useEditorMode() { + const [mode, setMode] = useState(readStoredMode) + + useEffect(() => { + writeStoredMode(mode) + }, [mode]) + + const activeMode = MODES.find((option) => option.value === mode) ?? MODES[0] + + return { mode, setMode, activeMode } +}