feat(lexical): add declarative rich text editor
Introduce @workspace/lexical with composable actions, toolbars, embeds, rich-text nodes, media uploads, selection utilities, HTML serialization, and theme styling.\n\nLocalize built-in controls through MessageDescriptor catalogs for English and Simplified Chinese, while providing an English I18nProvider fallback for standalone editor use. Include focused unit coverage for actions, controls, serialization, plugins, public API, and catalogs.
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
import {
|
||||
Bold,
|
||||
CaseLower,
|
||||
CaseSensitive,
|
||||
CaseUpper,
|
||||
Italic,
|
||||
Strikethrough,
|
||||
Subscript,
|
||||
Superscript,
|
||||
Underline,
|
||||
} from "lucide-react"
|
||||
import { $getSelection, $isRangeSelection, FORMAT_TEXT_COMMAND } from "lexical"
|
||||
import type { TextFormatType } from "lexical"
|
||||
import type { LexicalActionDefinition, LexicalActionName } from "../types"
|
||||
import type { LexicalMessage } from "../i18n"
|
||||
import { lexicalMessages } from "../messages"
|
||||
|
||||
function textFormatAction(
|
||||
name: LexicalActionName,
|
||||
label: LexicalMessage,
|
||||
format: TextFormatType,
|
||||
icon: LexicalActionDefinition["icon"]
|
||||
): LexicalActionDefinition {
|
||||
return {
|
||||
name,
|
||||
label,
|
||||
icon,
|
||||
execute: ({ editor }) => {
|
||||
editor.dispatchCommand(FORMAT_TEXT_COMMAND, format)
|
||||
},
|
||||
isActive: ({ editor }) =>
|
||||
editor.getEditorState().read(() => {
|
||||
const selection = $getSelection()
|
||||
return $isRangeSelection(selection) && selection.hasFormat(format)
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
export const boldAction = textFormatAction(
|
||||
"bold",
|
||||
lexicalMessages.bold,
|
||||
"bold",
|
||||
Bold
|
||||
)
|
||||
export const italicAction = textFormatAction(
|
||||
"italic",
|
||||
lexicalMessages.italic,
|
||||
"italic",
|
||||
Italic
|
||||
)
|
||||
export const underlineAction = textFormatAction(
|
||||
"underline",
|
||||
lexicalMessages.underline,
|
||||
"underline",
|
||||
Underline
|
||||
)
|
||||
export const lowercaseAction = textFormatAction(
|
||||
"lowercase",
|
||||
lexicalMessages.lowercase,
|
||||
"lowercase",
|
||||
CaseLower
|
||||
)
|
||||
export const uppercaseAction = textFormatAction(
|
||||
"uppercase",
|
||||
lexicalMessages.uppercase,
|
||||
"uppercase",
|
||||
CaseUpper
|
||||
)
|
||||
export const capitalizeAction = textFormatAction(
|
||||
"capitalize",
|
||||
lexicalMessages.capitalize,
|
||||
"capitalize",
|
||||
CaseSensitive
|
||||
)
|
||||
export const strikethroughAction = textFormatAction(
|
||||
"strikethrough",
|
||||
lexicalMessages.strikethrough,
|
||||
"strikethrough",
|
||||
Strikethrough
|
||||
)
|
||||
export const subscriptAction = textFormatAction(
|
||||
"subscript",
|
||||
lexicalMessages.subscript,
|
||||
"subscript",
|
||||
Subscript
|
||||
)
|
||||
export const superscriptAction = textFormatAction(
|
||||
"superscript",
|
||||
lexicalMessages.superscript,
|
||||
"superscript",
|
||||
Superscript
|
||||
)
|
||||
Reference in New Issue
Block a user