Skip to content
Merged
1 change: 1 addition & 0 deletions packages/pluggableWidgets/rich-text-web/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

### Added

- We added support to add custom font families to Rich Text.
- We added table support to Rich Text, now it is possible to add tables and configure their layout.

### Fixed
Expand Down
16 changes: 16 additions & 0 deletions packages/pluggableWidgets/rich-text-web/src/RichText.xml
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,22 @@
<caption>Enable spell checking</caption>
<description />
</property>
<property key="customFonts" type="object" isList="true" required="false">
<caption>Custom fonts</caption>
<description />
<properties>
<property key="fontName" type="string" required="false">
<caption>Font name</caption>
<category>Item</category>
<description>A title for this font combination (e.g., Arial).</description>
</property>
<property key="fontStyle" type="string" required="false">
<caption>Font style</caption>
<category>Item</category>
<description>The full CSS font-family declaration that will be applied (e.g., arial, helvetica, sans-serif).</description>
</property>
</properties>
</property>
</propertyGroup>
</propertyGroup>
<propertyGroup caption="Custom toolbar">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ describe("Rich Text", () => {
maxHeightUnit: "none",
maxHeight: 0,
minHeight: 75,
OverflowY: "auto"
OverflowY: "auto",
customFonts: []
};
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,15 @@ import {
useLayoutEffect,
useRef
} from "react";
import QuillTableBetter from "../utils/formats/quill-table-better/quill-table-better";
import "../utils/formats/quill-table-better/assets/css/quill-table-better.scss";
import { CustomFontsType } from "../../typings/RichTextProps";
import { EditorDispatchContext } from "../store/EditorProvider";
import { SET_FULLSCREEN_ACTION } from "../store/store";
import "../utils/customPluginRegisters";
import { FontStyleAttributor, formatCustomFonts } from "../utils/formats/fonts";
import "../utils/formats/quill-table-better/assets/css/quill-table-better.scss";
import QuillTableBetter from "../utils/formats/quill-table-better/quill-table-better";
import { RESIZE_MODULE_CONFIG } from "../utils/formats/resizeModuleConfig";
import { ACTION_DISPATCHER } from "../utils/helpers";
import MxQuill from "../utils/MxQuill";
import {
enterKeyKeyboardHandler,
Expand All @@ -24,12 +30,9 @@ import {
} from "./CustomToolbars/toolbarHandlers";
import { useEmbedModal } from "./CustomToolbars/useEmbedModal";
import Dialog from "./ModalDialog/Dialog";
import { RESIZE_MODULE_CONFIG } from "../utils/formats/resizeModuleConfig";
import { ACTION_DISPATCHER } from "../utils/helpers";
import { EditorDispatchContext } from "../store/EditorProvider";
import { SET_FULLSCREEN_ACTION } from "../store/store";

export interface EditorProps {
customFonts: CustomFontsType[];
defaultValue?: string;
onTextChange?: (...args: [delta: Delta, oldContent: Delta, source: EmitterSource]) => void;
onSelectionChange?: (...args: [range: Range, oldRange: Range, source: EmitterSource]) => void;
Expand All @@ -42,6 +45,9 @@ export interface EditorProps {

// Editor is an uncontrolled React component
const Editor = forwardRef((props: EditorProps, ref: MutableRefObject<Quill | null>) => {
const fonts = formatCustomFonts(props.customFonts);
const FontStyle = new FontStyleAttributor(fonts);
Quill.register(FontStyle, true);
const { theme, defaultValue, style, className, toolbarId, onTextChange, onSelectionChange, readOnly } = props;
const containerRef = useRef<HTMLDivElement>(null);
const modalRef = useRef<HTMLDivElement>(null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ function EditorWrapperInner(props: EditorWrapperProps): ReactElement {
preset={preset}
quill={quillRef.current}
toolbarContent={toolbarPreset}
customFonts={props.customFonts}
/>
</If>
<Editor
Expand All @@ -207,6 +208,7 @@ function EditorWrapperInner(props: EditorWrapperProps): ReactElement {
className={"widget-rich-text-container"}
readOnly={stringAttribute.readOnly}
key={`${toolbarId}_${stringAttribute.readOnly}`}
customFonts={props.customFonts}
/>
</div>
{enableStatusBar && (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import classNames from "classnames";
import Quill from "quill";
import { CSSProperties, ReactElement, RefObject, createElement, forwardRef } from "react";
import { PresetEnum } from "typings/RichTextProps";
import { CustomFontsType, PresetEnum } from "../../typings/RichTextProps";
import { formatCustomFonts } from "../utils/formats/fonts";
import { FormatsContainer, ToolbarContext, presetToNumberConverter } from "./CustomToolbars/ToolbarWrapper";
import { TOOLBAR_MAPPING, toolbarContentType } from "./CustomToolbars/constants";

export interface ToolbarProps {
customFonts?: CustomFontsType[];
id: string;
preset: PresetEnum;
style?: CSSProperties;
quill?: Quill | null;
style?: CSSProperties;
toolbarContent: toolbarContentType[];
}

Expand Down Expand Up @@ -65,6 +67,16 @@ const Toolbar = forwardRef((props: ToolbarProps, ref: RefObject<HTMLDivElement>)
{toolbarGroup.children.map((toolbar, idx) => {
const currentToolbar = TOOLBAR_MAPPING[toolbar];
const key = `toolbar_${id}_${index}_${idx}`;
let value = currentToolbar.value;

if (currentToolbar.title === "Font type") {
type FontListType = Array<{ value: string; description: string; style: string }>;
value = [
...(currentToolbar.value as FontListType),
...formatCustomFonts(props.customFonts ?? [])
].sort((a, b) => (a.value ?? "").localeCompare(b.value ?? ""));
}

return currentToolbar.custom
? createElement(currentToolbar.component, {
key,
Expand All @@ -77,7 +89,7 @@ const Toolbar = forwardRef((props: ToolbarProps, ref: RefObject<HTMLDivElement>)
key,
className: classNames(currentToolbar.className),
presetValue: currentToolbar.presetValue,
value: currentToolbar.value,
value,
title: currentToolbar.title
},
currentToolbar.children && createElement(currentToolbar.children)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Scope, StyleAttributor } from "parchment";
import Quill from "quill";
import { CustomFontsType } from "../../../typings/RichTextProps";
import "./fonts.scss";

export const FONT_LIST = [
Expand All @@ -22,13 +22,21 @@ const config = {
scope: Scope.INLINE
};

class FontStyleAttributor extends StyleAttributor {
export class FontStyleAttributor extends StyleAttributor {
private fontList: typeof FONT_LIST = [];

constructor(fontList: typeof FONT_LIST) {
super("font", "font-family", config);
this.fontList = fontList;
}

add(node: HTMLElement, value: any): boolean {
if (!this.canAdd(node, value)) {
return false;
}
node.dataset.value = value;
const style = FONT_LIST.find(x => x.value === value)?.style;
const allFonts = [...FONT_LIST, ...this.fontList];
const style = allFonts.find(x => x.value === value)?.style;
if (style) {
super.add(node, style);
} else {
Expand All @@ -46,6 +54,10 @@ class FontStyleAttributor extends StyleAttributor {
}
}

const FontStyle = new FontStyleAttributor("font", "font-family", config);

Quill.register(FontStyle, true);
export function formatCustomFonts(fonts: CustomFontsType[] = []): typeof FONT_LIST {
return fonts.map(font => ({
value: font.fontName?.toLowerCase().split(" ").join("-") ?? "",
description: font.fontName ?? "",
style: font.fontStyle ?? ""
}));
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ export type OverflowYEnum = "auto" | "scroll" | "hidden";

export type OnChangeTypeEnum = "onLeave" | "onDataChange";

export interface CustomFontsType {
fontName: string;
fontStyle: string;
}

export type ToolbarConfigEnum = "basic" | "advanced";

export type CtItemTypeEnum = "separator" | "undo" | "redo" | "bold" | "italic" | "underline" | "strike" | "superScript" | "subScript" | "orderedList" | "bulletList" | "lowerAlphaList" | "checkList" | "minIndent" | "plusIndent" | "direction" | "link" | "image" | "video" | "formula" | "blockquote" | "code" | "codeBlock" | "viewCode" | "align" | "centerAlign" | "rightAlign" | "font" | "size" | "color" | "background" | "header" | "fullscreen" | "clean" | "tableBetter";
Expand All @@ -31,6 +36,11 @@ export interface AdvancedConfigType {
ctItemType: CtItemTypeEnum;
}

export interface CustomFontsPreviewType {
fontName: string;
fontStyle: string;
}

export interface AdvancedConfigPreviewType {
ctItemType: CtItemTypeEnum;
}
Expand Down Expand Up @@ -59,6 +69,7 @@ export interface RichTextContainerProps {
onLoad?: ActionValue;
onChangeType: OnChangeTypeEnum;
spellCheck: boolean;
customFonts: CustomFontsType[];
toolbarConfig: ToolbarConfigEnum;
history: boolean;
fontStyle: boolean;
Expand Down Expand Up @@ -100,6 +111,7 @@ export interface RichTextPreviewProps {
onLoad: {} | null;
onChangeType: OnChangeTypeEnum;
spellCheck: boolean;
customFonts: CustomFontsPreviewType[];
toolbarConfig: ToolbarConfigEnum;
history: boolean;
fontStyle: boolean;
Expand Down
Loading