Skip to content

Commit 023b53e

Browse files
committed
chore: updated version of rich text with tiptap
1 parent 868d0fb commit 023b53e

18 files changed

Lines changed: 665 additions & 341 deletions

packages/pluggableWidgets/rich-text-web/src/RichText.xml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -325,9 +325,10 @@
325325
<enumerationValue key="code">Code</enumerationValue>
326326
<enumerationValue key="codeBlock">Code Block</enumerationValue>
327327
<enumerationValue key="viewCode">View Code</enumerationValue>
328-
<enumerationValue key="align">Left Align</enumerationValue>
328+
<enumerationValue key="leftAlign">Left Align</enumerationValue>
329329
<enumerationValue key="centerAlign">Center Align</enumerationValue>
330330
<enumerationValue key="rightAlign">Right Align</enumerationValue>
331+
<enumerationValue key="justifyAlign">Justify Align</enumerationValue>
331332
<enumerationValue key="font">Font Type</enumerationValue>
332333
<enumerationValue key="size">Font Size</enumerationValue>
333334
<enumerationValue key="color">Color</enumerationValue>

packages/pluggableWidgets/rich-text-web/src/components/Editor.tsx

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,43 +9,52 @@ import { TableHeader } from "@tiptap/extension-table-header";
99
import { TableRow } from "@tiptap/extension-table-row";
1010
import { TaskItem } from "@tiptap/extension-task-item";
1111
import { TaskList } from "@tiptap/extension-task-list";
12-
import { TextAlign } from "@tiptap/extension-text-align";
1312
import { TextStyle } from "@tiptap/extension-text-style";
1413
import { Underline } from "@tiptap/extension-underline";
1514
import { Youtube } from "@tiptap/extension-youtube";
1615
import { EditorContent, useEditor } from "@tiptap/react";
1716
import { StarterKit } from "@tiptap/starter-kit";
18-
1917
import { ChangeEvent, forwardRef, ReactElement, ReactNode, useImperativeHandle, useRef } from "react";
2018
import { EditorContextProvider, useCurrentEditor } from "./EditorContext";
21-
// import { DynamicTableStyles } from "./DynamicTableStyles";
22-
// import { DynamicTextColorStyles } from "./DynamicTextColorStyles";
2319
import { Toolbar } from "./toolbars";
20+
import {
21+
PresetEnum,
22+
ToolbarConfigEnum,
23+
AdvancedConfigType,
24+
CustomFontsType,
25+
RichTextContainerProps
26+
} from "../../typings/RichTextProps";
2427
import { FontFamilyClass } from "../extensions/FontFamilyClass";
28+
29+
// import { DynamicTableStyles } from "./DynamicTableStyles";
30+
// import { DynamicTextColorStyles } from "./DynamicTextColorStyles";
2531
import { FontSize } from "../extensions/FontSize";
2632
import { ImageResize } from "../extensions/ImageResize";
2733
import { Indent } from "../extensions/Indent";
2834
import { TableBackgroundColor } from "../extensions/TableBackgroundColor";
2935
import { TableCellBackgroundColor } from "../extensions/TableCellBackgroundColor";
36+
import { TextAlign } from "../extensions/TextAlignClass";
3037
import { TextColorClass } from "../extensions/TextColorClass";
3138
import { TextDirection } from "../extensions/TextDirection";
3239
import { TextHighlightClass } from "../extensions/TextHighlightClass";
3340
import { ConfirmDialog } from "./toolbars/components/ConfirmDialog";
3441
import { ToolbarGroupsConfig } from "./toolbars/ToolbarConfig";
35-
import { PresetEnum, ToolbarConfigEnum, AdvancedConfigType } from "../../typings/RichTextProps";
3642

37-
export interface EditorProps {
43+
export interface EditorProps extends Pick<
44+
RichTextContainerProps,
45+
| "styleDataFormat"
46+
| "imageSourceContent"
47+
| "preset"
48+
| "toolbarConfig"
49+
| "toolbarLocation"
50+
| "advancedConfig"
51+
| "customFonts"
52+
> {
3853
defaultValue?: string;
3954
onUpdate?: (html: string) => void;
4055
readOnly?: boolean;
4156
className?: string;
42-
showToolbar?: boolean;
43-
styleDataFormat?: "inline" | "class";
44-
imageSourceContent?: ReactNode;
45-
preset?: PresetEnum;
46-
toolbarConfig?: ToolbarConfigEnum;
4757
toolbarGroups?: ToolbarGroupsConfig;
48-
advancedConfig?: AdvancedConfigType[];
4958
}
5059

5160
export interface EditorHandle {
@@ -65,6 +74,7 @@ interface EditorInnerProps {
6574
toolbarConfig?: ToolbarConfigEnum;
6675
toolbarGroups?: ToolbarGroupsConfig;
6776
advancedConfig?: AdvancedConfigType[];
77+
customFonts?: CustomFontsType[];
6878
}
6979

7080
function EditorInner({
@@ -75,7 +85,8 @@ function EditorInner({
7585
preset,
7686
toolbarConfig,
7787
toolbarGroups,
78-
advancedConfig
88+
advancedConfig,
89+
customFonts
7990
}: EditorInnerProps): ReactElement {
8091
const { editor, codeViewState, codeViewDispatch } = useCurrentEditor();
8192
const textareaRef = useRef<HTMLTextAreaElement>(null);
@@ -106,6 +117,7 @@ function EditorInner({
106117
toolbarConfig={toolbarConfig}
107118
toolbarGroups={toolbarGroups}
108119
advancedConfig={advancedConfig}
120+
customFonts={customFonts}
109121
/>
110122
)}
111123
{codeViewState.isCodeView ? (
@@ -142,13 +154,14 @@ const Editor = forwardRef<EditorHandle, EditorProps>((props, ref) => {
142154
onUpdate,
143155
readOnly,
144156
className,
145-
showToolbar = true,
146157
styleDataFormat = "inline",
147158
imageSourceContent,
148159
preset,
149160
toolbarConfig,
150161
toolbarGroups,
151-
advancedConfig
162+
toolbarLocation,
163+
advancedConfig,
164+
customFonts
152165
} = props;
153166

154167
const extensions = [
@@ -177,7 +190,8 @@ const Editor = forwardRef<EditorHandle, EditorProps>((props, ref) => {
177190
}),
178191
TextAlign.configure({
179192
types: ["heading", "paragraph"],
180-
alignments: ["left", "center", "right", "justify"]
193+
alignments: ["left", "center", "right", "justify"],
194+
styleDataFormat
181195
}),
182196
Indent.configure({
183197
types: ["paragraph", "heading", "blockquote"],
@@ -236,17 +250,20 @@ const Editor = forwardRef<EditorHandle, EditorProps>((props, ref) => {
236250
return null;
237251
}
238252

253+
const shouldHideToolbar = toolbarLocation === "hide";
254+
239255
return (
240256
<EditorContextProvider editor={editor}>
241257
<EditorInner
242-
showToolbar={showToolbar}
258+
showToolbar={!shouldHideToolbar}
243259
readOnly={!!readOnly}
244260
className={className}
245261
imageSourceContent={imageSourceContent}
246262
preset={preset}
247263
toolbarConfig={toolbarConfig}
248264
toolbarGroups={toolbarGroups}
249265
advancedConfig={advancedConfig}
266+
customFonts={customFonts}
250267
/>
251268
</EditorContextProvider>
252269
);

packages/pluggableWidgets/rich-text-web/src/components/EditorWrapper.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ function EditorWrapper(props: EditorWrapperProps): ReactElement {
3131
tableBetter,
3232
advancedConfig,
3333
enableStatusBar,
34-
statusBarContent
34+
statusBarContent,
35+
customFonts,
36+
toolbarLocation,
37+
readOnlyStyle
3538
} = props;
3639
const editorRef = useRef<EditorHandle>(null);
3740
const [editorText, setEditorText] = useState<string>("");
@@ -76,7 +79,7 @@ function EditorWrapper(props: EditorWrapperProps): ReactElement {
7679
})();
7780

7881
return (
79-
<div className={className}>
82+
<div className={`${className} toolbar-${toolbarLocation}`}>
8083
{stringAttribute.status === "available" && (
8184
<>
8285
<Editor
@@ -105,6 +108,10 @@ function EditorWrapper(props: EditorWrapperProps): ReactElement {
105108
tableBetter
106109
}}
107110
advancedConfig={advancedConfig}
111+
customFonts={customFonts}
112+
toolbarLocation={
113+
stringAttribute.readOnly && readOnlyStyle !== "text" ? "hide" : toolbarLocation
114+
}
108115
/>
109116
{enableStatusBar && (
110117
<StatusBar

packages/pluggableWidgets/rich-text-web/src/components/toolbars/Toolbar.scss

Lines changed: 61 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
1+
.widget-rich-text.toolbar-bottom {
2+
.tiptap-wrapper {
3+
flex-direction: column-reverse;
4+
}
5+
}
6+
17
.tiptap-toolbar {
28
display: flex;
39
flex-direction: column;
410
border: unset;
511
box-shadow: var(--shadow-small, 0 2px 4px 0) var(--shadow-color-border, #00000014);
612

13+
.tiptap-wrapper & {
14+
.toolbar-bottom & {
15+
box-shadow: 2px 0 4px 0 var(--shadow-color-border, #00000014);
16+
}
17+
}
18+
719
.toolbar-row {
820
display: flex;
921
flex-wrap: wrap;
@@ -45,69 +57,63 @@
4557
}
4658
}
4759

48-
.toolbar-dropdown {
49-
position: relative;
50-
51-
.toolbar-dropdown-button {
52-
display: flex;
53-
align-items: center;
54-
gap: 4px;
55-
padding: 6px 10px;
56-
min-width: 120px;
57-
justify-content: space-between;
58-
59-
.dropdown-label {
60-
flex: 1;
61-
text-align: left;
62-
font-size: 13px;
63-
}
60+
.toolbar-dropdown-button {
61+
display: flex;
62+
align-items: center;
63+
gap: 4px;
64+
padding: 6px 10px;
65+
min-width: 120px;
66+
justify-content: space-between;
67+
68+
.dropdown-label {
69+
flex: 1;
70+
text-align: left;
71+
font-size: 13px;
72+
}
6473

65-
.dropdown-arrow {
66-
font-size: 12px;
67-
transition: transform 0.2s;
68-
}
74+
.dropdown-arrow {
75+
font-size: 12px;
76+
transition: transform 0.2s;
6977
}
78+
}
7079

71-
.toolbar-dropdown-menu {
72-
position: absolute;
73-
top: calc(100% + 4px);
74-
left: 0;
80+
.toolbar-dropdown-menu {
81+
// Position is managed by Floating UI (via floatingStyles)
82+
background: white;
83+
border: 1px solid #d0d0d0;
84+
border-radius: 4px;
85+
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
86+
min-width: 160px;
87+
z-index: 1000;
88+
max-height: 300px;
89+
overflow-y: auto;
90+
91+
.toolbar-dropdown-item {
92+
display: block;
93+
width: 100%;
94+
padding: 8px 12px;
95+
text-align: left;
96+
border: none;
7597
background: white;
76-
border: 1px solid #d0d0d0;
77-
border-radius: 4px;
78-
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
79-
min-width: 160px;
80-
z-index: 1000;
81-
max-height: 300px;
82-
overflow-y: auto;
83-
84-
.toolbar-dropdown-item {
85-
display: block;
86-
width: 100%;
87-
padding: 8px 12px;
88-
text-align: left;
89-
border: none;
90-
background: white;
91-
font-size: 14px;
92-
cursor: pointer;
93-
transition: background-color 0.2s;
98+
font-size: 14px;
99+
cursor: pointer;
100+
transition: background-color 0.2s;
94101

95-
&:hover {
96-
background-color: #f0f0f0;
97-
}
102+
&:hover {
103+
background-color: #f0f0f0;
104+
}
98105

99-
&.is-active {
100-
background-color: #264ae5;
101-
color: white;
102-
}
106+
&.is-active {
107+
background-color: #264ae5;
108+
color: white;
109+
}
103110

104-
&:first-child {
105-
border-radius: 4px 4px 0 0;
106-
}
111+
&:first-child {
112+
border-radius: 4px 4px 0 0;
113+
}
107114

108-
&:last-child {
109-
border-radius: 0 0 4px 4px;
110-
}
115+
&:last-child {
116+
border-radius: 0 0 4px 4px;
111117
}
112118
}
113119
}

packages/pluggableWidgets/rich-text-web/src/components/toolbars/Toolbar.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
getFilteredToolbarGroups,
1616
ToolbarGroupsConfig
1717
} from "./ToolbarConfig";
18-
import { PresetEnum, ToolbarConfigEnum, AdvancedConfigType } from "../../../typings/RichTextProps";
18+
import { PresetEnum, ToolbarConfigEnum, AdvancedConfigType, CustomFontsType } from "../../../typings/RichTextProps";
1919
import "./Toolbar.scss";
2020
// eslint-disable-next-line import/order
2121
import { ToolbarDropdown } from "./components/ToolbarDropdown";
@@ -26,6 +26,7 @@ interface ToolbarProps {
2626
toolbarConfig?: ToolbarConfigEnum;
2727
toolbarGroups?: ToolbarGroupsConfig;
2828
advancedConfig?: AdvancedConfigType[];
29+
customFonts?: CustomFontsType[];
2930
}
3031

3132
interface ToolbarGroupProps extends ToolbarProps {
@@ -111,14 +112,14 @@ function ToolbarRow(props: ToolbarRowProps): ReactElement {
111112
}
112113

113114
export default function Toolbar(props: ToolbarProps): ReactElement | null {
114-
const { preset = "basic", toolbarConfig, toolbarGroups, advancedConfig, imageSourceContent } = props;
115+
const { preset = "basic", toolbarConfig, toolbarGroups, advancedConfig, imageSourceContent, customFonts } = props;
115116
const { editor } = useCurrentEditor();
116117
const [activeDropdown, setActiveDropdown] = useState<DropdownCommand | null>(null);
117118

118119
// Filter toolbar groups based on preset and custom configuration
119120
const filteredGroups = useMemo(
120-
() => getFilteredToolbarGroups(preset, toolbarConfig, toolbarGroups, advancedConfig),
121-
[preset, toolbarConfig, toolbarGroups, advancedConfig]
121+
() => getFilteredToolbarGroups(preset, toolbarConfig, toolbarGroups, advancedConfig, customFonts),
122+
[preset, toolbarConfig, toolbarGroups, advancedConfig, customFonts]
122123
);
123124

124125
const filteredSecondaryGroups = useMemo(

0 commit comments

Comments
 (0)