feat(web): integrate localized Lexical editor demo

Register Lexical's English and Simplified Chinese catalogs in the application loader, import its global styles, and add the workspace dependency with its resolved lockfile graph.\n\nReplace the dashboard placeholder with a controlled rich-text editor demo that composes default actions, fixed and bubble toolbars, draggable blocks, generated HTML output, and reset behavior.
This commit is contained in:
Maofeng
2026-07-31 15:09:02 +08:00
parent 0d817537be
commit cbf5ee784f
5 changed files with 166 additions and 42 deletions
+2 -1
View File
@@ -8,7 +8,8 @@
"@workspace/blocks/chats/locales/{locale}",
"@workspace/blocks/layout/locales/{locale}",
"@workspace/blocks/navigation/locales/{locale}",
"@workspace/blocks/notifications/locales/{locale}"
"@workspace/blocks/notifications/locales/{locale}",
"@workspace/lexical/locales/{locale}"
],
"include": ["src", "../../packages/blocks/src", "../../packages/ui/src"],
"exclude": ["**/*.test.{ts,tsx}", "**/node_modules/**"]
+1
View File
@@ -30,6 +30,7 @@
"@tanstack/react-start": "^1.168.32",
"@workspace/blocks": "workspace:*",
"@workspace/i18n": "workspace:*",
"@workspace/lexical": "workspace:*",
"@workspace/ui": "workspace:*",
"country-flag-icons": "^1.6.20",
"lucide-react": "^1.27.0",
+69 -41
View File
@@ -1,48 +1,76 @@
import * as React from "react"
import { formatForDisplay } from "@tanstack/react-hotkeys"
import {
LexicalActions,
LexicalBubbleToolbar,
LexicalContent,
LexicalDraggableBlockPlugin,
LexicalFixedToolbar,
LexicalFooter,
LexicalRoot,
} from "@workspace/lexical"
import { Button } from "@workspace/ui/components/button"
import { Slider } from "@workspace/ui/components/slider"
import { Switch } from "@workspace/ui/components/switch"
const initialEditorHtml = [
"<h2>Welcome to the Lexical editor</h2>",
"<p>This example uses declarative actions to compose reusable editor features.</p>",
"<ul><li>Format text with the toolbar</li><li>Insert links, images, videos, lists, dates, and more</li><li>Read the generated HTML beside the editor</li></ul>",
].join("")
export function DashboardPage() {
return (
<>
<img
className="h-auto w-full"
src="https://pub-c5e31b5cdafb419fb247a8ac2e78df7a.r2.dev/public/assets/background/background-3-blur.webp"
/>
<div className="flex max-w-md min-w-0 flex-col gap-4 text-sm leading-loose">
<div>
<h1 className="font-medium">Project ready!</h1>
<p>You may now add components and start building.</p>
<p>We&apos;ve already added the button component for you.</p>
<Button variant="ghost" className="mt-2">
Button
</Button>
</div>
<div>
<Switch />
<Slider
defaultValue={[75]}
max={100}
step={1}
className="mx-auto w-full max-w-xs"
/>
</div>
<div className="font-mono text-xs text-muted-foreground">
(Press <kbd>Mod+D</kbd> to toggle dark mode)
</div>
const [html, setHtml] = React.useState(initialEditorHtml)
<div>
<span className="mr-2">breakpoint:</span>
<span className="hidden mobile:inline">mobile</span>
<span className="hidden tablet:inline">tablet</span>
<span className="hidden desktop:inline">desktop</span>
</div>
<div>
<span className="mr-2">collapsed:</span>
<span className="hidden collapsed:inline">true</span>
<span className="inline collapsed:hidden">false</span>
</div>
return (
<div className="flex min-w-0 flex-col gap-6 bg-background">
<div>
<h1 className="text-xl font-medium">Lexical editor</h1>
<p className="mt-1 text-sm text-muted-foreground">
Actions declare their controls and editor dependencies in one place.
</p>
</div>
</>
<div className="grid min-w-0 gap-6 xl:grid-cols-[minmax(0,1fr)_minmax(20rem,0.7fr)]">
<section className="min-w-0">
<div className="mb-2 flex items-center justify-between gap-3">
<h2 className="font-medium">Editor</h2>
<code className="text-xs text-muted-foreground">
useDefaults=&quot;full&quot;
</code>
</div>
<LexicalRoot value={html} onChange={setHtml} className="shadow-xs">
<LexicalActions useDefaults="full" />
<LexicalFixedToolbar />
<LexicalContent
className="min-h-72"
placeholder="Write something…"
/>
<LexicalDraggableBlockPlugin />
<LexicalBubbleToolbar aria-label="Selected text formatting" />
<LexicalFooter className="flex items-center justify-between gap-3 text-xs text-muted-foreground">
<span>HTML output updates as you type.</span>
<Button
type="button"
size="sm"
variant="ghost"
onClick={() => setHtml("")}
>
Clear
</Button>
</LexicalFooter>
</LexicalRoot>
</section>
<section className="flex min-w-0 flex-col">
<h2 className="mb-2 font-medium">Generated HTML</h2>
<pre className="min-h-72 flex-1 overflow-auto rounded-lg border bg-muted/30 p-4 text-xs leading-relaxed break-words whitespace-pre-wrap">
{html || "The editor is empty."}
</pre>
</section>
</div>
<p className="font-mono text-xs text-muted-foreground">
Press <kbd>{formatForDisplay("Mod+D")}</kbd> to toggle dark mode.
</p>
</div>
)
}
+1
View File
@@ -1,5 +1,6 @@
@import "@workspace/ui/globals.css";
@import "@workspace/blocks/globals.css";
@import "@workspace/lexical/globals.css";
:root {
--ui-content-top-gap: --spacing(2);