Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -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" }
]
}
45 changes: 9 additions & 36 deletions website/src/app.tsx
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -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

Expand Down Expand Up @@ -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<string[]> {
async function searchTags(query: string): Promise<TagItem[]> {
// 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 = [
Expand All @@ -105,10 +77,12 @@ const NOTES = [
'Travel plans',
]

async function searchNotes(query: string): Promise<string[]> {
async function searchNotes(query: string): Promise<WikilinkItem[]> {
// 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 =
Expand Down Expand Up @@ -199,8 +173,7 @@ function Brand() {
}

export function App() {
const [mode, setMode] = useState<EditorMode>('focus')
const activeMode = MODES.find((option) => option.value === mode) ?? MODES[0]
const { mode, setMode, activeMode } = useEditorMode()

return (
<main className="relative min-h-dvh overflow-hidden text-stone-600 dark:bg-stone-950">
Expand Down
61 changes: 61 additions & 0 deletions website/src/use-editor-mode.ts
Original file line number Diff line number Diff line change
@@ -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<EditorMode>(readStoredMode)

useEffect(() => {
writeStoredMode(mode)
}, [mode])

const activeMode = MODES.find((option) => option.value === mode) ?? MODES[0]

return { mode, setMode, activeMode }
}
Loading