An extensible WYSWYG editor based on Lexical.
Kalliope is a ready-to-use editor based on lexical. It is intended to be easy to use and ships with several ready to use plugins.
It does not contain a graphical interface beyond that of the editor itself, and is therefore not tied to any particular UI.
- Built in plugins
- Installation
- Usage
- Configuration
- Utility functions
- Editor commands
- Valid code languages
- Code highlight and code formatting.
- Drag and drop images.
- Emojis (english default).
- Floating link editor.
- Table cell.
- Mentions
- Citation block
- Speech to text
- Text spoiler
- Block spoiler (collapsible)
- Insert tweets
- Insert videos (Youtube, Facebook, Dailymotion, Soundcloud, Twitch).
- Basic formatting (bold, italic, underline, strikethrough, superscript, subscript).
- Text coloring (font and background).
- Different font types
- Different block types (heading, bullet list, numbered list, check list, quote and code block).
yarn add kalliope
import CalliopeEditor from 'kalliope';
The editor component takes three parameters
- config (required) : an object containing configuration options (detailed below).
- containerRef (required): a react ref used to manipulate the editor.
- setFormats (optional): a function used to set the formats applied to the selected text. Useful when building UIs.
<CalliopeEditor
config={config}
containerRef={containerRef}
setFormats={setFormats}
/>
The configuration object (config
parameter) looks like this.
{
placeholderText: t('toolbar.placeholderText'),
initialState: initialState,
isReadOnly: false,
autoFocus: true,
onError: (error) => {
throw error;
},
plugins: [],
imageConfig: {
addCaptionText: t('internal.addCaption'),
defaultCaptionText: t('internal.enterCaption'),
},
twitterConfig: {
loadingComponent: ({ tweetId }) => (
<p>
{t('internal.loadingTweet')}...(ID={tweetId})
</p>
),
},
collapsibleConfig: {
open: true,
},
citation: {
sourceLinkComponent: ({ sourceLink }) => (
<a href={sourceLink} className="source-link-component">
<FontAwesomeIcon icon={sourceIcon} size="lg" />
</a>
) /*,
authorComponent: ({ author }) => (
<a href={author.link} className="author-link-container">
<AccountAvatar
avatar={author.avatar}
username={author.name}
size="5px"
shape="circle"
/>
<span className="author-link-quote">{author.name}</span>
</a>
),*/,
},
mentions: {
onSearchChange: onSearchChange,
onAddMention: (mention) => {
setMentions([...mentions, mention.name]);
},
onRemoveMention: ({ name, link }) => {
const newMentions = mentions.filter((m) => m !== name);
setMentions(newMentions);
},
entryComponent: ({ option: { avatar, name, link } }) => (
<>
<AccountAvatar avatar={avatar} username={name} size="5px" shape="circle" />
<strong className="user-name-mentions">{name}</strong>
</>
),
mentionsData: suggestions,
},
emojiConfig: {
emojiData: emojiData,
},
dragAndDropImage: {
handleDroppedFile: async (file) => {
const resp = await uploadFileToServer(file);
const { src } = resp;
if (src === null) {
notification.error({
message: 'Failed to upload File',
description: "Couldn't upload file to the server (file type not allowed).",
placement: 'topRight',
});
return;
}
const imageSrc = `/static/uploads/${src}`;
containerRef.current.executeCommand('INSERT_IMAGE', {
src: imageSrc,
altText: file.name,
});
},
},
}
Accesible using the containerRef
ref.
Name | Parameters | Description |
---|---|---|
getContent | () => Lexical Editor State | Gets get the current editor content. Returns a Lexical Editor State as JSON. |
clear | () => void | Clears the editor. |
executeCommand | ({commandName: string , commandParams: any }) => void |
Executes and editor command (toggle a block or a font style). |
focus | () => void |
Sets the focus for the editor. |
Name | Parameters | Description |
---|---|---|
UNDO | none | Undo last command |
REDO | none | Redo last undone command |
FORMAT | string . One of bold| italic | underline | strikethrough | superscript | subscript | code |
Apply basic text formatting. |
KEYBOARD | none | Apply keyboard formatting. |
SPOILER | none | Apply text spoiler formatting. |
LINK | string link to insert |
Insert link |
ALIGN | string one of left | center | right | justify |
Insert link |
INDENT | none | Indent text |
OUTDENT | none | Outdent text |
PARAGRAPH | none | Apply paragraph block style to selected text |
BULLET_LIST | none | Apply bullet list formatting to selected text |
NUMBERED_LIST | none | Apply numbered list formatting to selected text |
CHECK | none | Apply check list formatting to selected text |
H1 | none | Apply h1 formatting to selected text |
H2 | none | Apply h2 formatting to selected text |
H3 | none | Apply h3 formatting to selected text |
QUOTE | none | Apply quote block formatting to selected text |
CODE_BLOCK | none | Apply code block formatting (w/format highlighting) to selected text. |
CODE_LANGUAGE_CHANGE | value : string - a code language. See list of valid code languages below |
Change the code language inside a code block. The current block must already be a code block for this method to work. |
CHANGE_FONT | string a valid font family.
Suggested values are (Arial , Courier New , Georgia , Times New Roman , Trebuchet MS , Verdana ) |
Chang the font family type. |
CHANGE_FONT_SIZE | string a valid font size. 'px' (ie: '10px' ) |
Chang the font size. |
CHANGE_FONT_COLOR | string a valid hexadecimal color value. | Change the font color. |
CHANGE_FONT_BG_COLOR | string a valid hexadecimal color value. | Change the background color. |
INSERT_RULE | none | Insert a horizontal rule. |
INSERT_IMAGE | object { altText: string , src: string }. src is the image url. alt text is the alt text for the image. Neither can be null.
|
Insert a resizeable image into the editor. |
INSERT_TWEET | string tweetId. The id in the tweet url (Twitter urls are formatted like this: twitter.com//status/) | Insert a tweet into the editor. |
INSERT_INSTAGRAM_POST | string instagramURL. The instagram URL (Instagram urls are formatted like this: "https://www.instagram.com/p//") | Insert an instagram post into the editor (only works for public instagram links). |
INSERT_TABLE | object {columns: integer , rows: integer }
|
Insert a table into the editor. |
INSERT_EQUATION | object { equation: string , inline: boolean }. The equation must be a valid latex formula. Inline specifies wether the equation is rendered on its own line or not.
|
Insert a LaTeX equation into the editor. Only Valid Katex formulas accepted. |
INSERT_VIDEO | url: string . The URL of the video in question. Look below for accepted video sites.
|
Insert video content into the editor. |
INSERT_EXCALIDRAW | none | Open excalidraw popup. This does not insert anything into the editor, the insertion is done when the user clicks the save button. |
INSERT_BLOCK_SPOILER | open: boolean |
Insert block spoiler (a collapsible container akin to html's summary). |
SPEECH_TO_TEXT | isSpeechToText: boolean - indicates wether speech to text is active or not |
Open the microphone to convert speech to text. When switched off it will insert the captured text into the editor |
INSERT_CITE_QUOTE |
{
author: { name: string , link: string },
source: { content: string , link: string }
}
|
Insert a citation. |
A list of valid code languages is exported from the editor. To obtain the list do
import { getCodeLanguageOptions } from 'kalliope';
const CODE_LANGUAGES = getCodeLanguageOptions();
The following code languages are accepted by the highlighter. The value column indicates the value passed as the parameter of the CHANGE_CODE_LANGUAGE
command.
Value | Language |
---|---|
c | C |
clike | C-Like |
objc | Objective-C |
html | HTML |
xml | XML |
css | CSS |
sql | SQL |
js | JavaScript |
markdown | Markdown |
py | Python |
powershell | Powershell |
rust | Rust |
swift | Swift |
plain | Plain Text |
ts | Typescript |