Skip to content

Commit

Permalink
feat: custom labels
Browse files Browse the repository at this point in the history
  • Loading branch information
tiavina-mika committed Jun 23, 2024
1 parent 5e5f06c commit 2cebc25
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 87 deletions.
69 changes: 32 additions & 37 deletions src/components/Heading.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { Editor } from "@tiptap/react";
import { Menu, MenuItem, Fade, Theme, Button } from "@mui/material";
import { Level } from "@tiptap/extension-heading";
import { MouseEvent, useState } from "react";
import { MouseEvent, useMemo, useState } from "react";
import ChevronDown from "../icons/ChevronDown";
import Icon from "../icons/Icon";
import { ITextEditorOption } from "./TextEditor";
import { ILabels } from "../types";

const isActive = (editor: Editor) => {
return (
Expand All @@ -17,34 +17,7 @@ const isActive = (editor: Editor) => {
);
}

type IOption = ITextEditorOption<Level>;

const options: IOption[] = [
{
value: 1,
label: "Heading 1"
},
{
value: 2,
label: "Heading 2"
},
{
value: 3,
label: "Heading 3"
},
{
value: 4,
label: "Heading 4"
},
{
value: 5,
label: "Heading 5"
},
{
value: 6,
label: "Heading 6"
}
];
const options: Level[] = [1, 2, 3, 4, 5, 6];

const classes = {
button: (isActive: boolean) => (theme: Theme) => ({
Expand All @@ -70,15 +43,34 @@ const classes = {
fontSize
})
}

type Props = {
editor: Editor;
headingLabels?: ILabels["headings"];
};
const Heading = ({ editor }: Props) => {
const Heading = ({ editor, headingLabels }: Props) => {
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(
null
);
const [selected, setSelected] = useState(0);

// get label for selected heading
const selectedLabel = useMemo(() => {
const heading = options.find(option => option === selected);

if (heading) {
if (headingLabels && headingLabels[`h${heading}`]) {
return headingLabels[`h${heading}`];
}
return `Heading ${heading}`;
}

if (headingLabels && headingLabels.normalText) {
return headingLabels.normalText;
}
return 'Normal text';
}, [selected, headingLabels]);

const handleOpenHeadingMenu = (event: MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
};
Expand Down Expand Up @@ -111,7 +103,7 @@ const Heading = ({ editor }: Props) => {
color="inherit"
>
<span>
{options.find(option => option.value === selected)?.label || "Normal text"}
{selectedLabel}
</span>
{/* chevron icon */}
<Icon>
Expand All @@ -129,19 +121,22 @@ const Heading = ({ editor }: Props) => {
onClose={handleClose}
TransitionComponent={Fade}
>
{/* normal text option */}
<MenuItem onClick={handleSelectNormalText}>
Normal text
{headingLabels?.normalText || "Normal text"}
</MenuItem>
{/* heading options */}
{options.map((option, index) => (
<MenuItem
key={index}
onClick={() => handleSelectHeading(option.value)}
onClick={() => handleSelectHeading(option)}
css={classes.menuItem(
editor.isActive("heading", { level: option.value }), // isActive
(10 - index) * 3 // fontSize
editor.isActive("heading", { level: option }), // isActive
(10 - index) * 3 // fontSize is decreasing
)}
>
{option.label}
{/* override labels or default ones */}
{headingLabels?.[`h${option}`] || `Heading ${option}`}
</MenuItem>
))}
</Menu>
Expand Down
10 changes: 6 additions & 4 deletions src/components/LinkDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ import { useState, ChangeEvent } from 'react';
import { TextField } from '@mui/material';
import Dialog from './Dialog';
import { checkIsValidUrl } from '../utils/app.utils';
import { ILabels } from '../types';

type Props = {
editor: Editor;
open: boolean;
onClose: () => void;
labels?: ILabels['link'];
};
const LinkDialog = ({ editor, open, onClose }: Props) => {
const LinkDialog = ({ editor, open, onClose, labels }: Props) => {
const [link, setLink] = useState<string>('');
const [error, setError] = useState<string>('');

Expand All @@ -25,12 +27,12 @@ const LinkDialog = ({ editor, open, onClose }: Props) => {

const handleConfirm = () => {
if (!link) {
setError('Please enter a link');
setError(labels?.enter || 'Please enter a link');
return;
}
const isValidUrl = checkIsValidUrl(link);
if (!isValidUrl) {
setError('Invalid URL');
setError(labels?.invalid || 'Invalid URL');
return;
}

Expand Down Expand Up @@ -65,7 +67,7 @@ const LinkDialog = ({ editor, open, onClose }: Props) => {
>
<TextField
label="Link"
placeholder="Entrer le lien"
placeholder={labels?.insert || 'Insert link'}
type="url"
fullWidth
onChange={handleChangeLink}
Expand Down
36 changes: 19 additions & 17 deletions src/components/TableMenuDialog.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { Editor } from "@tiptap/react";
import { Menu, MenuItem, Fade } from "@mui/material";
import { ILabels } from "../types";

type IOption = {
label: string;
action: () => void;
};
const getTableMenus = (editor: Editor): IOption[] => [
const getTableMenus = (editor: Editor, labels?: ILabels['table']): IOption[] => [
{
label: "Insert table",
label: labels?.insertTable || "Insert table",
action: () =>
editor
.chain()
Expand All @@ -16,55 +17,55 @@ const getTableMenus = (editor: Editor): IOption[] => [
.run()
},
{
label: "Add column before",
label: labels?.addColumnBefore || "Add column before",
action: () => editor.chain().focus().addColumnBefore().run()
},
{
label: "Add column after",
label: labels?.addColumnAfter || "Add column after",
action: () => editor.chain().focus().addColumnAfter().run()
},
{
label: "Delete Column",
label: labels?.deleteColumn || "Delete Column",
action: () => editor.chain().focus().deleteColumn().run()
},
{
label: "Add row before",
label: labels?.addRowBefore || "Add row before",
action: () => editor.chain().focus().addRowBefore().run()
},
{
label: "Add row after",
label: labels?.addRowAfter || "Add row after",
action: () => editor.chain().focus().addRowAfter().run()
},
{
label: "Delete row",
label: labels?.deleteRow || "Delete row",
action: () => editor.chain().focus().deleteRow().run()
},
{
label: "Delete table",
label: labels?.deleteTable || "Delete table",
action: () => editor.chain().focus().deleteTable().run()
},
{
label: "Merge cells",
label: labels?.mergeCells || "Merge cells",
action: () => editor.chain().focus().mergeCells().run()
},
{
label: "Toggle header column",
label: labels?.toggleHeaderColumn || "Toggle header column",
action: () => editor.chain().focus().toggleHeaderColumn().run()
},
{
label: "Toggle header row",
label: labels?.toggleHeaderRow || "Toggle header row",
action: () => editor.chain().focus().toggleHeaderRow().run()
},
{
label: "Toggle header cell",
label: labels?.toggleHeaderCell || "Toggle header cell",
action: () => editor.chain().focus().toggleHeaderCell().run()
},
{
label: "Merge or split",
label: labels?.mergeOrSplit || "Merge or split",
action: () => editor.chain().focus().mergeOrSplit().run()
},
{
label: "Set cell attribute",
label: labels?.setCellAttribute || "Set cell attribute",
action: () => editor.chain().focus().setCellAttribute("colspan", 2).run()
}
];
Expand All @@ -73,8 +74,9 @@ type Props = {
editor: Editor;
anchorEl: null | HTMLElement;
onClose: () => void;
labels?: ILabels["table"];
};
const TableMenuDialog = ({ editor, anchorEl, onClose }: Props) => {
const TableMenuDialog = ({ editor, anchorEl, onClose, labels }: Props) => {
const handleClick = (menu: IOption) => {
menu.action();
onClose();
Expand All @@ -91,7 +93,7 @@ const TableMenuDialog = ({ editor, anchorEl, onClose }: Props) => {
onClose={onClose}
TransitionComponent={Fade}
>
{getTableMenus(editor).map((menu, index) => (
{getTableMenus(editor, labels).map((menu, index) => (
<MenuItem value={index} key={index} onClick={() => handleClick(menu)}>
{menu.label}
</MenuItem>
Expand Down
11 changes: 8 additions & 3 deletions src/components/TextEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { useState, SyntheticEvent, ReactNode } from 'react';
import { useTextEditor } from "../hooks/useTextEditor";

import Toolbar from './Toolbar';
import { IEditorToolbar } from "../types";
import { IEditorToolbar, ILabels } from "../types";

const defaultMenuToolbar: IEditorToolbar[] = ['heading', 'bold', 'italic', 'underline', 'link', 'bulletList'];

Expand Down Expand Up @@ -215,6 +215,7 @@ export type TextEditorProps = {
* the final element is something like: <a href="/profile/some_user_id">{mentioned_user}</a>
*/
userPathname?: string;
labels?: ILabels;
} & Partial<EditorOptions>;

const TextEditor = ({
Expand All @@ -236,6 +237,7 @@ const TextEditor = ({
user,
mentions,
userPathname,
labels,
editable = true,
withFloatingMenu = false,
withBubbleMenu = true,
Expand Down Expand Up @@ -283,9 +285,10 @@ const TextEditor = ({
css={classes.tabs}
className={tabsClassName}
>
<Tab css={classes.tab} label="Editor" value="editor" className={tabClassName} />
<Tab css={classes.tab} label="Preview" value="preview" className={tabClassName} />
<Tab css={classes.tab} label={labels?.editor?.editor || 'Editor'} value="editor" className={tabClassName} />
<Tab css={classes.tab} label={labels?.editor?.preview || 'Preview'} className={tabClassName} />
</Tabs>

{/* ---------------------------- */}
{/* ----------- editor --------- */}
{/* ---------------------------- */}
Expand All @@ -299,6 +302,7 @@ const TextEditor = ({
editor={editor}
toolbar={floatingMenuToolbar || defaultMenuToolbar}
css={[classes.menu, classes.bubbleMenu]}
labels={labels}
/>
</FloatingMenu>
)}
Expand All @@ -323,6 +327,7 @@ const TextEditor = ({
editor={editor}
className={cx('stretchSelf', toolbarClassName)}
toolbar={toolbar}
labels={labels}
/>
)}
</div>
Expand Down
Loading

0 comments on commit 2cebc25

Please sign in to comment.