mirror of
https://github.com/drawdb-io/drawdb.git
synced 2026-06-01 02:00:44 +08:00
Fix rich editor styling
This commit is contained in:
+19
-3
@@ -50,7 +50,16 @@ function SurveyForm({ theme }) {
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const resetForm = () => {
|
||||
setForm({});
|
||||
setForm({
|
||||
satisfaction: 5,
|
||||
ease: 5,
|
||||
wouldRecommend: 5,
|
||||
hadDifficulty: "",
|
||||
difficulty: "",
|
||||
triedOtherApps: "",
|
||||
comparison: "",
|
||||
occupation: "",
|
||||
});
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
@@ -62,9 +71,9 @@ function SurveyForm({ theme }) {
|
||||
await axios
|
||||
.post(`${process.env.REACT_APP_BACKEND_URL}/report_bug`, {
|
||||
subject: `[SURVEY]: ${new Date().toDateString()}`,
|
||||
message: `${Object.keys(questions).map(
|
||||
message: `${Object.keys(form).map(
|
||||
(k) => `<div>${questions[k]}</div><div>${form[k]}</div>`
|
||||
)}<div>Anything else?</div>${$generateHtmlFromNodes(editor)}`,
|
||||
)}<div>How can we make drawDB a better experience for you?</div>${$generateHtmlFromNodes(editor)}`,
|
||||
})
|
||||
.then((res) => {
|
||||
Toast.success("Thanks for the feedback!");
|
||||
@@ -138,6 +147,7 @@ function SurveyForm({ theme }) {
|
||||
<div className="font-semibold ms-1 mb-3">{questions.hadDifficulty}</div>
|
||||
<RadioGroup
|
||||
direction="vertical"
|
||||
value={form.hadDifficulty}
|
||||
onChange={(e) =>
|
||||
setForm((prev) => ({ ...prev, hadDifficulty: e.target.value }))
|
||||
}
|
||||
@@ -151,6 +161,8 @@ function SurveyForm({ theme }) {
|
||||
<div className="font-semibold ms-1 mb-3">{questions.difficulty}</div>
|
||||
<TextArea
|
||||
rows={2}
|
||||
placeholder="Tell us more"
|
||||
value={form.difficulty}
|
||||
onChange={(v) => setForm((prev) => ({ ...prev, difficulty: v }))}
|
||||
/>
|
||||
</div>
|
||||
@@ -161,6 +173,7 @@ function SurveyForm({ theme }) {
|
||||
</div>
|
||||
<RadioGroup
|
||||
direction="vertical"
|
||||
value={form.triedOtherApps}
|
||||
onChange={(e) =>
|
||||
setForm((prev) => ({ ...prev, triedOtherApps: e.target.value }))
|
||||
}
|
||||
@@ -174,6 +187,8 @@ function SurveyForm({ theme }) {
|
||||
<div className="font-semibold ms-1 mb-3">{questions.comparison}</div>
|
||||
<TextArea
|
||||
rows={2}
|
||||
placeholder="Tell us more"
|
||||
value={form.comparison}
|
||||
onChange={(v) => setForm((prev) => ({ ...prev, comparison: v }))}
|
||||
/>
|
||||
</div>
|
||||
@@ -188,6 +203,7 @@ function SurveyForm({ theme }) {
|
||||
]}
|
||||
className="w-full"
|
||||
placeholder="Occupation"
|
||||
value={form.occupation}
|
||||
onSelect={(v) => setForm((prev) => ({ ...prev, occupation: v }))}
|
||||
/>
|
||||
</div>
|
||||
|
||||
+119
-216
@@ -39,30 +39,29 @@ import {
|
||||
getDefaultCodeLanguage,
|
||||
getCodeLanguages,
|
||||
} from "@lexical/code";
|
||||
import { Dropdown } from "@douyinfe/semi-ui";
|
||||
import "../styles/richeditor.css";
|
||||
|
||||
const LowPriority = 1;
|
||||
|
||||
const supportedBlockTypes = new Set([
|
||||
"paragraph",
|
||||
"quote",
|
||||
"code",
|
||||
"h1",
|
||||
"h2",
|
||||
"ul",
|
||||
"ol",
|
||||
]);
|
||||
const blockTypeToIcon = {
|
||||
code: "bi-code-slash",
|
||||
h1: "bi-type-h1",
|
||||
h2: "bi-type-h2",
|
||||
ol: "bi-list-ol",
|
||||
paragraph: "bi-text-paragraph",
|
||||
quote: "bi-chat-square-quote",
|
||||
ul: "bi-list-ul",
|
||||
};
|
||||
|
||||
const blockTypeToBlockName = {
|
||||
code: "Code Block",
|
||||
paragraph: "Paragraph",
|
||||
h1: "Large Heading",
|
||||
h2: "Small Heading",
|
||||
h3: "Heading",
|
||||
h4: "Heading",
|
||||
h5: "Heading",
|
||||
ol: "Numbered List",
|
||||
paragraph: "Paragraph",
|
||||
quote: "Quote",
|
||||
ul: "Bulleted List",
|
||||
ol: "Numbered List",
|
||||
code: "Code Block",
|
||||
quote: "Quote",
|
||||
};
|
||||
|
||||
function Divider() {
|
||||
@@ -252,83 +251,38 @@ function getSelectedNode(selection) {
|
||||
}
|
||||
}
|
||||
|
||||
function BlockOptionsDropdownList({
|
||||
editor,
|
||||
blockType,
|
||||
toolbarRef,
|
||||
setShowBlockOptionsDropDown,
|
||||
theme,
|
||||
}) {
|
||||
const dropDownRef = useRef(null);
|
||||
|
||||
useEffect(() => {
|
||||
const toolbar = toolbarRef.current;
|
||||
const dropDown = dropDownRef.current;
|
||||
|
||||
if (toolbar !== null && dropDown !== null) {
|
||||
const { top, left } = toolbar.getBoundingClientRect();
|
||||
dropDown.style.top = `${top + 40}px`;
|
||||
dropDown.style.left = `${left}px`;
|
||||
}
|
||||
}, [dropDownRef, toolbarRef]);
|
||||
|
||||
useEffect(() => {
|
||||
const dropDown = dropDownRef.current;
|
||||
const toolbar = toolbarRef.current;
|
||||
|
||||
if (dropDown !== null && toolbar !== null) {
|
||||
const handle = (event) => {
|
||||
const target = event.target;
|
||||
|
||||
if (!dropDown.contains(target) && !toolbar.contains(target)) {
|
||||
setShowBlockOptionsDropDown(false);
|
||||
}
|
||||
};
|
||||
document.addEventListener("click", handle);
|
||||
|
||||
return () => {
|
||||
document.removeEventListener("click", handle);
|
||||
};
|
||||
}
|
||||
}, [dropDownRef, setShowBlockOptionsDropDown, toolbarRef]);
|
||||
|
||||
function BlockOptionsDropdownList({ editor, blockType }) {
|
||||
const formatParagraph = () => {
|
||||
if (blockType !== "paragraph") {
|
||||
editor.update(() => {
|
||||
const selection = $getSelection();
|
||||
|
||||
if ($isRangeSelection(selection)) {
|
||||
$wrapNodes(selection, () => $createParagraphNode());
|
||||
}
|
||||
});
|
||||
}
|
||||
setShowBlockOptionsDropDown(false);
|
||||
};
|
||||
|
||||
const formatLargeHeading = () => {
|
||||
if (blockType !== "h1") {
|
||||
editor.update(() => {
|
||||
const selection = $getSelection();
|
||||
|
||||
if ($isRangeSelection(selection)) {
|
||||
$wrapNodes(selection, () => $createHeadingNode("h1"));
|
||||
}
|
||||
});
|
||||
}
|
||||
setShowBlockOptionsDropDown(false);
|
||||
};
|
||||
|
||||
const formatSmallHeading = () => {
|
||||
if (blockType !== "h2") {
|
||||
editor.update(() => {
|
||||
const selection = $getSelection();
|
||||
|
||||
if ($isRangeSelection(selection)) {
|
||||
$wrapNodes(selection, () => $createHeadingNode("h2"));
|
||||
}
|
||||
});
|
||||
}
|
||||
setShowBlockOptionsDropDown(false);
|
||||
};
|
||||
|
||||
const formatBulletList = () => {
|
||||
@@ -337,7 +291,6 @@ function BlockOptionsDropdownList({
|
||||
} else {
|
||||
editor.dispatchCommand(REMOVE_LIST_COMMAND);
|
||||
}
|
||||
setShowBlockOptionsDropDown(false);
|
||||
};
|
||||
|
||||
const formatNumberedList = () => {
|
||||
@@ -346,81 +299,90 @@ function BlockOptionsDropdownList({
|
||||
} else {
|
||||
editor.dispatchCommand(REMOVE_LIST_COMMAND);
|
||||
}
|
||||
setShowBlockOptionsDropDown(false);
|
||||
};
|
||||
|
||||
const formatQuote = () => {
|
||||
if (blockType !== "quote") {
|
||||
editor.update(() => {
|
||||
const selection = $getSelection();
|
||||
|
||||
if ($isRangeSelection(selection)) {
|
||||
$wrapNodes(selection, () => $createQuoteNode());
|
||||
}
|
||||
});
|
||||
}
|
||||
setShowBlockOptionsDropDown(false);
|
||||
};
|
||||
|
||||
const formatCode = () => {
|
||||
if (blockType !== "code") {
|
||||
editor.update(() => {
|
||||
const selection = $getSelection();
|
||||
|
||||
if ($isRangeSelection(selection)) {
|
||||
$wrapNodes(selection, () => $createCodeNode());
|
||||
}
|
||||
});
|
||||
}
|
||||
setShowBlockOptionsDropDown(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="dropdown" ref={dropDownRef}>
|
||||
<button className="item" onClick={formatParagraph}>
|
||||
<span className={`icon paragraph${theme === "dark" ? "-dark" : ""}`} />
|
||||
<span className="text">Paragraph</span>
|
||||
{blockType === "paragraph" && <span className="active" />}
|
||||
<Dropdown
|
||||
trigger="click"
|
||||
clickToHide
|
||||
render={
|
||||
<Dropdown.Menu>
|
||||
<Dropdown.Item
|
||||
onClick={formatParagraph}
|
||||
icon={<i className={`bi ${blockTypeToIcon.paragraph}`} />}
|
||||
>
|
||||
Paragraph
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
onClick={formatLargeHeading}
|
||||
icon={<i className={`bi ${blockTypeToIcon.h1}`} />}
|
||||
>
|
||||
Large Heading
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
onClick={formatSmallHeading}
|
||||
icon={<i className={`bi ${blockTypeToIcon.h2}`} />}
|
||||
>
|
||||
Small Heading
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
onClick={formatBulletList}
|
||||
icon={<i className={`bi ${blockTypeToIcon.ul}`} />}
|
||||
>
|
||||
Bullet List
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
onClick={formatNumberedList}
|
||||
icon={<i className={`bi ${blockTypeToIcon.ol}`} />}
|
||||
>
|
||||
Numbered List
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
onClick={formatQuote}
|
||||
icon={<i className={`bi ${blockTypeToIcon.quote}`} />}
|
||||
>
|
||||
Quote
|
||||
</Dropdown.Item>
|
||||
<Dropdown.Item
|
||||
onClick={formatCode}
|
||||
icon={<i className={`bi ${blockTypeToIcon.code}`} />}
|
||||
>
|
||||
Code Block
|
||||
</Dropdown.Item>
|
||||
</Dropdown.Menu>
|
||||
}
|
||||
>
|
||||
<button
|
||||
className="flex mx-2 justify-center items-center"
|
||||
aria-label="Formatting Options"
|
||||
>
|
||||
<i className={`bi ${blockTypeToIcon[blockType]} me-3`} />
|
||||
<span className="me-3 text-sm">{blockTypeToBlockName[blockType]}</span>
|
||||
<i className="bi bi-chevron-down" />
|
||||
</button>
|
||||
<button className="item" onClick={formatLargeHeading}>
|
||||
<span
|
||||
className={`icon large-heading${theme === "dark" ? "-dark" : ""}`}
|
||||
/>
|
||||
<span className="text">Large Heading</span>
|
||||
{blockType === "h1" && <span className="active" />}
|
||||
</button>
|
||||
<button className="item" onClick={formatSmallHeading}>
|
||||
<span
|
||||
className={`icon small-heading${theme === "dark" ? "-dark" : ""}`}
|
||||
/>
|
||||
<span className="text">Small Heading</span>
|
||||
{blockType === "h2" && <span className="active" />}
|
||||
</button>
|
||||
<button className="item" onClick={formatBulletList}>
|
||||
<span
|
||||
className={`icon bullet-list${theme === "dark" ? "-dark" : ""}`}
|
||||
/>
|
||||
<span className="text">Bullet List</span>
|
||||
{blockType === "ul" && <span className="active" />}
|
||||
</button>
|
||||
<button className="item" onClick={formatNumberedList}>
|
||||
<span
|
||||
className={`icon numbered-list${theme === "dark" ? "-dark" : ""}`}
|
||||
/>
|
||||
<span className="text">Numbered List</span>
|
||||
{blockType === "ol" && <span className="active" />}
|
||||
</button>
|
||||
<button className="item" onClick={formatQuote}>
|
||||
<span className={`icon quote${theme === "dark" ? "-dark" : ""}`} />
|
||||
<span className="text">Quote</span>
|
||||
{blockType === "quote" && <span className="active" />}
|
||||
</button>
|
||||
<button className="item" onClick={formatCode}>
|
||||
<span className={`icon code${theme === "dark" ? "-dark" : ""}`} />
|
||||
<span className="text">Code Block</span>
|
||||
{blockType === "code" && <span className="active" />}
|
||||
</button>
|
||||
</div>
|
||||
</Dropdown>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -432,8 +394,6 @@ export default function ToolbarPlugin(props) {
|
||||
const [canRedo, setCanRedo] = useState(false);
|
||||
const [blockType, setBlockType] = useState("paragraph");
|
||||
const [selectedElementKey, setSelectedElementKey] = useState(null);
|
||||
const [showBlockOptionsDropDown, setShowBlockOptionsDropDown] =
|
||||
useState(false);
|
||||
const [codeLanguage, setCodeLanguage] = useState("");
|
||||
const [, setIsRTL] = useState(false);
|
||||
const [isLink, setIsLink] = useState(false);
|
||||
@@ -469,7 +429,7 @@ export default function ToolbarPlugin(props) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Update text format
|
||||
|
||||
setIsBold(selection.hasFormat("bold"));
|
||||
setIsItalic(selection.hasFormat("italic"));
|
||||
setIsUnderline(selection.hasFormat("underline"));
|
||||
@@ -477,7 +437,6 @@ export default function ToolbarPlugin(props) {
|
||||
setIsCode(selection.hasFormat("code"));
|
||||
setIsRTL($isParentElementRTL(selection));
|
||||
|
||||
// Update links
|
||||
const node = getSelectedNode(selection);
|
||||
const parent = node.getParent();
|
||||
if ($isLinkNode(parent) || $isLinkNode(node)) {
|
||||
@@ -549,131 +508,91 @@ export default function ToolbarPlugin(props) {
|
||||
<div className="toolbar" ref={toolbarRef}>
|
||||
<button
|
||||
disabled={!canUndo}
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(UNDO_COMMAND);
|
||||
}}
|
||||
onClick={() => editor.dispatchCommand(UNDO_COMMAND)}
|
||||
className="toolbar-item spaced"
|
||||
aria-label="Undo"
|
||||
>
|
||||
<i className={`format ${theme === "dark" ? "undo-dark" : "undo"}`} />
|
||||
<i
|
||||
className={`bi bi-arrow-counterclockwise ${
|
||||
canUndo ? "" : "opacity-30"
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
<button
|
||||
disabled={!canRedo}
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(REDO_COMMAND);
|
||||
}}
|
||||
onClick={() => editor.dispatchCommand(REDO_COMMAND)}
|
||||
className="toolbar-item"
|
||||
aria-label="Redo"
|
||||
>
|
||||
<i className={`format ${theme === "dark" ? "redo-dark" : "redo"}`} />
|
||||
<i className={`bi bi-arrow-clockwise ${canRedo ? "" : "opacity-30"}`} />
|
||||
</button>
|
||||
<Divider />
|
||||
{supportedBlockTypes.has(blockType) && (
|
||||
<>
|
||||
<button
|
||||
className="toolbar-item block-controls"
|
||||
onClick={() =>
|
||||
setShowBlockOptionsDropDown(!showBlockOptionsDropDown)
|
||||
}
|
||||
aria-label="Formatting Options"
|
||||
>
|
||||
<span
|
||||
className={
|
||||
"icon block-type " +
|
||||
blockType +
|
||||
(theme === "dark" ? "-dark" : "")
|
||||
}
|
||||
/>
|
||||
<span className="text">{blockTypeToBlockName[blockType]}</span>
|
||||
<i className={`chevron-down${theme === "dark" ? "-dark" : ""}`} />
|
||||
</button>
|
||||
{showBlockOptionsDropDown &&
|
||||
createPortal(
|
||||
<BlockOptionsDropdownList
|
||||
editor={editor}
|
||||
blockType={blockType}
|
||||
toolbarRef={toolbarRef}
|
||||
setShowBlockOptionsDropDown={setShowBlockOptionsDropDown}
|
||||
theme={theme}
|
||||
/>,
|
||||
document.body
|
||||
)}
|
||||
<Divider />
|
||||
</>
|
||||
)}
|
||||
<BlockOptionsDropdownList
|
||||
editor={editor}
|
||||
blockType={blockType}
|
||||
/>
|
||||
<Divider />
|
||||
{blockType === "code" ? (
|
||||
<>
|
||||
<div className="flex items-center">
|
||||
<Select
|
||||
className="toolbar-item code-language"
|
||||
onChange={onCodeLanguageSelect}
|
||||
options={codeLanguges}
|
||||
value={codeLanguage}
|
||||
/>
|
||||
<i
|
||||
className={`chevron-down${theme === "dark" ? "-dark" : ""} inside`}
|
||||
/>
|
||||
</>
|
||||
<i className="bi bi-chevron-down" />
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<button
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(FORMAT_TEXT_COMMAND, "bold");
|
||||
}}
|
||||
onClick={() => editor.dispatchCommand(FORMAT_TEXT_COMMAND, "bold")}
|
||||
className={"toolbar-item spaced " + (isBold ? "active" : "")}
|
||||
aria-label="Format Bold"
|
||||
>
|
||||
<i className={`format bold${theme === "dark" ? "-dark" : ""}`} />
|
||||
<i className="bi bi-type-bold" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(FORMAT_TEXT_COMMAND, "italic");
|
||||
}}
|
||||
onClick={() =>
|
||||
editor.dispatchCommand(FORMAT_TEXT_COMMAND, "italic")
|
||||
}
|
||||
className={"toolbar-item spaced " + (isItalic ? "active" : "")}
|
||||
aria-label="Format Italics"
|
||||
>
|
||||
<i className={`format italic${theme === "dark" ? "-dark" : ""}`} />
|
||||
<i className="bi bi-type-italic" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(FORMAT_TEXT_COMMAND, "underline");
|
||||
}}
|
||||
onClick={() =>
|
||||
editor.dispatchCommand(FORMAT_TEXT_COMMAND, "underline")
|
||||
}
|
||||
className={"toolbar-item spaced " + (isUnderline ? "active" : "")}
|
||||
aria-label="Format Underline"
|
||||
>
|
||||
<i
|
||||
className={`format underline${theme === "dark" ? "-dark" : ""}`}
|
||||
/>
|
||||
<i className="bi bi-type-underline" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(FORMAT_TEXT_COMMAND, "strikethrough");
|
||||
}}
|
||||
onClick={() =>
|
||||
editor.dispatchCommand(FORMAT_TEXT_COMMAND, "strikethrough")
|
||||
}
|
||||
className={
|
||||
"toolbar-item spaced " + (isStrikethrough ? "active" : "")
|
||||
}
|
||||
aria-label="Format Strikethrough"
|
||||
>
|
||||
<i
|
||||
className={`format strikethrough${
|
||||
theme === "dark" ? "-dark" : ""
|
||||
}`}
|
||||
/>
|
||||
<i className="bi bi-type-strikethrough" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(FORMAT_TEXT_COMMAND, "code");
|
||||
}}
|
||||
onClick={() => editor.dispatchCommand(FORMAT_TEXT_COMMAND, "code")}
|
||||
className={"toolbar-item spaced " + (isCode ? "active" : "")}
|
||||
aria-label="Insert Code"
|
||||
>
|
||||
<i className={`format code${theme === "dark" ? "-dark" : ""}`} />
|
||||
<i className="bi bi-code-slash" />
|
||||
</button>
|
||||
<button
|
||||
onClick={insertLink}
|
||||
className={"toolbar-item spaced " + (isLink ? "active" : "")}
|
||||
aria-label="Insert Link"
|
||||
>
|
||||
<i className={`format link${theme === "dark" ? "-dark" : ""}`} />
|
||||
<i className="bi bi-link" />
|
||||
</button>
|
||||
{isLink &&
|
||||
createPortal(
|
||||
@@ -682,30 +601,22 @@ export default function ToolbarPlugin(props) {
|
||||
)}
|
||||
<Divider />
|
||||
<button
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, "left");
|
||||
}}
|
||||
onClick={() =>
|
||||
editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, "left")
|
||||
}
|
||||
className="toolbar-item spaced"
|
||||
aria-label="Left Align"
|
||||
>
|
||||
<i
|
||||
className={`format ${
|
||||
theme === "dark" ? "left-align-dark" : "left-align"
|
||||
}`}
|
||||
/>
|
||||
<i className="bi bi-text-left" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, "center");
|
||||
}}
|
||||
onClick={() =>
|
||||
editor.dispatchCommand(FORMAT_ELEMENT_COMMAND, "center")
|
||||
}
|
||||
className="toolbar-item spaced"
|
||||
aria-label="Center Align"
|
||||
>
|
||||
<i
|
||||
className={`format ${
|
||||
theme === "dark" ? "center-align-dark" : "center-align"
|
||||
}`}
|
||||
/>
|
||||
<i className="bi bi-text-center" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
@@ -714,11 +625,7 @@ export default function ToolbarPlugin(props) {
|
||||
className="toolbar-item spaced"
|
||||
aria-label="Right Align"
|
||||
>
|
||||
<i
|
||||
className={`format ${
|
||||
theme === "dark" ? "right-align-dark" : "right-align"
|
||||
}`}
|
||||
/>
|
||||
<i className="bi bi-text-right" />
|
||||
</button>
|
||||
<button
|
||||
onClick={() => {
|
||||
@@ -727,12 +634,8 @@ export default function ToolbarPlugin(props) {
|
||||
className="toolbar-item"
|
||||
aria-label="Justify Align"
|
||||
>
|
||||
<i
|
||||
className={`format ${
|
||||
theme === "dark" ? "justify-align-dark" : "justify-align"
|
||||
}`}
|
||||
/>
|
||||
</button>{" "}
|
||||
<i className="bi bi-justify" />
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
+1
-326
@@ -319,171 +319,6 @@ pre::-webkit-scrollbar-thumb {
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
.toolbar i.chevron-down {
|
||||
margin-top: 3px;
|
||||
margin-left: 6px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
user-select: none;
|
||||
background-image: url(/public/images/icons/chevron-down.svg);
|
||||
}
|
||||
|
||||
.toolbar i.chevron-down-dark {
|
||||
margin-top: 3px;
|
||||
margin-left: 6px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
user-select: none;
|
||||
background-image: url(/public/images/icons/chevron-down-dark.svg);
|
||||
}
|
||||
|
||||
.toolbar i.chevron-down.inside {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-left: -20px;
|
||||
margin-top: 11px;
|
||||
margin-right: 10px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.toolbar i.chevron-down-dark.inside {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-left: -20px;
|
||||
margin-top: 11px;
|
||||
margin-right: 10px;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#block-controls button:focus-visible {
|
||||
border-color: blue;
|
||||
}
|
||||
|
||||
#block-controls span.block-type {
|
||||
background-size: contain;
|
||||
display: block;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
#block-controls span.block-type.paragraph {
|
||||
background-image: url(/public/images/icons/text-paragraph.svg);
|
||||
}
|
||||
|
||||
#block-controls span.block-type.paragraph-dark {
|
||||
background-image: url(/public/images/icons/text-paragraph-dark.svg);
|
||||
}
|
||||
|
||||
#block-controls span.block-type.h1 {
|
||||
background-image: url(/public/images/icons/type-h1.svg);
|
||||
}
|
||||
|
||||
#block-controls span.block-type.h1-dark {
|
||||
background-image: url(/public/images/icons/type-h1-dark.svg);
|
||||
}
|
||||
|
||||
#block-controls span.block-type.h2 {
|
||||
background-image: url(/public/images/icons/type-h2.svg);
|
||||
}
|
||||
|
||||
#block-controls span.block-type.h2-dark {
|
||||
background-image: url(/public/images/icons/type-h2-dark.svg);
|
||||
}
|
||||
|
||||
#block-controls span.block-type.quote {
|
||||
background-image: url(/public/images/icons/chat-square-quote.svg);
|
||||
}
|
||||
|
||||
#block-controls span.block-type.quote-dark {
|
||||
background-image: url(/public/images/icons/chat-square-quote-dark.svg);
|
||||
}
|
||||
|
||||
#block-controls span.block-type.ul {
|
||||
background-image: url(/public/images/icons/list-ul.svg);
|
||||
}
|
||||
|
||||
#block-controls span.block-type.ul-dark {
|
||||
background-image: url(/public/images/icons/list-ul-dark.svg);
|
||||
}
|
||||
|
||||
#block-controls span.block-type.ol {
|
||||
background-image: url(/public/images/icons/list-ol.svg);
|
||||
}
|
||||
|
||||
#block-controls span.block-type.ol-dark {
|
||||
background-image: url(/public/images/icons/list-ol-dark.svg);
|
||||
}
|
||||
|
||||
#block-controls span.block-type.code {
|
||||
background-image: url(/public/images/icons/code.svg);
|
||||
}
|
||||
|
||||
#block-controls span.block-type.code-dark {
|
||||
background-image: url(/public/images/icons/code-dark.svg);
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
z-index: 5;
|
||||
display: block;
|
||||
position: absolute;
|
||||
box-shadow: 0 12px 28px 0 rgba(0, 0, 0, 0.2), 0 2px 4px 0 rgba(0, 0, 0, 0.1),
|
||||
inset 0 0 0 1px rgba(var(--semi-grey-2), 1);
|
||||
border-radius: 6px;
|
||||
min-width: 240px;
|
||||
min-height: 40px;
|
||||
background-color: rgba(var(--semi-grey-1), 1);
|
||||
}
|
||||
|
||||
.dropdown .item {
|
||||
padding: 6px 16px;
|
||||
width: 100%;
|
||||
color: rgba(var(--semi-text-1), 1);
|
||||
cursor: pointer;
|
||||
line-height: 16px;
|
||||
font-size: 14px;
|
||||
display: flex;
|
||||
align-content: center;
|
||||
flex-direction: row;
|
||||
flex-shrink: 0;
|
||||
justify-content: space-between;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.dropdown .item .active {
|
||||
display: flex;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.dropdown .item:first-child {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.dropdown .item:last-child {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.dropdown .item:hover {
|
||||
background-color: rgba(var(--semi-grey-3), 1);
|
||||
}
|
||||
|
||||
.dropdown .item .text {
|
||||
display: flex;
|
||||
line-height: 20px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.dropdown .item .icon {
|
||||
display: flex;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
user-select: none;
|
||||
margin-right: 12px;
|
||||
line-height: 16px;
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
.link-editor {
|
||||
position: absolute;
|
||||
z-index: 100;
|
||||
@@ -581,164 +416,4 @@ pre::-webkit-scrollbar-thumb {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
vertical-align: -0.25em;
|
||||
}
|
||||
|
||||
i.undo {
|
||||
background-image: url(/public/images/icons/arrow-counterclockwise.svg);
|
||||
}
|
||||
|
||||
i.undo-dark {
|
||||
background-image: url(/public/images/icons/arrow-counterclockwise-dark.svg);
|
||||
}
|
||||
|
||||
i.redo {
|
||||
background-image: url(/public/images/icons/arrow-clockwise.svg);
|
||||
}
|
||||
|
||||
i.redo-dark {
|
||||
background-image: url(/public/images/icons/arrow-clockwise-dark.svg);
|
||||
}
|
||||
|
||||
.icon.paragraph {
|
||||
background-image: url(/public/images/icons/text-paragraph.svg);
|
||||
}
|
||||
|
||||
.icon.paragraph-dark {
|
||||
background-image: url(/public/images/icons/text-paragraph-dark.svg);
|
||||
}
|
||||
|
||||
.icon.large-heading,
|
||||
.icon.h1 {
|
||||
background-image: url(/public/images/icons/type-h1.svg);
|
||||
}
|
||||
|
||||
.icon.large-heading-dark,
|
||||
.icon.h1-dark {
|
||||
background-image: url(/public/images/icons/type-h1-dark.svg);
|
||||
}
|
||||
|
||||
.icon.small-heading,
|
||||
.icon.h2 {
|
||||
background-image: url(/public/images/icons/type-h2.svg);
|
||||
}
|
||||
|
||||
.icon.small-heading-dark,
|
||||
.icon.h2-dark {
|
||||
background-image: url(/public/images/icons/type-h2-dark.svg);
|
||||
}
|
||||
|
||||
.icon.bullet-list,
|
||||
.icon.ul {
|
||||
background-image: url(/public/images/icons/list-ul.svg);
|
||||
}
|
||||
|
||||
.icon.bullet-list-dark,
|
||||
.icon.ul-dark {
|
||||
background-image: url(/public/images/icons/list-ul-dark.svg);
|
||||
}
|
||||
|
||||
.icon.numbered-list,
|
||||
.icon.ol {
|
||||
background-image: url(/public/images/icons/list-ol.svg);
|
||||
}
|
||||
|
||||
.icon.numbered-list-dark,
|
||||
.icon.ol-dark {
|
||||
background-image: url(/public/images/icons/list-ol-dark.svg);
|
||||
}
|
||||
|
||||
.icon.quote {
|
||||
background-image: url(/public/images/icons/chat-square-quote.svg);
|
||||
}
|
||||
|
||||
.icon.quote-dark {
|
||||
background-image: url(/public/images/icons/chat-square-quote-dark.svg);
|
||||
}
|
||||
|
||||
.icon.code {
|
||||
background-image: url(/public/images/icons/code.svg);
|
||||
}
|
||||
|
||||
.icon.code-dark {
|
||||
background-image: url(/public/images/icons/code-dark.svg);
|
||||
}
|
||||
|
||||
i.bold {
|
||||
background-image: url(/public/images/icons/type-bold.svg);
|
||||
}
|
||||
|
||||
i.bold-dark {
|
||||
background-image: url(/public/images/icons/type-bold-dark.svg);
|
||||
}
|
||||
|
||||
i.italic {
|
||||
background-image: url(/public/images/icons/type-italic.svg);
|
||||
}
|
||||
|
||||
i.italic-dark {
|
||||
background-image: url(/public/images/icons/type-italic-dark.svg);
|
||||
}
|
||||
|
||||
i.underline {
|
||||
background-image: url(/public/images/icons/type-underline.svg);
|
||||
}
|
||||
|
||||
i.underline-dark {
|
||||
background-image: url(/public/images/icons/type-underline-dark.svg);
|
||||
}
|
||||
|
||||
i.strikethrough {
|
||||
background-image: url(/public/images/icons/type-strikethrough.svg);
|
||||
}
|
||||
|
||||
i.strikethrough-dark {
|
||||
background-image: url(/public/images/icons/type-strikethrough-dark.svg);
|
||||
}
|
||||
|
||||
i.code {
|
||||
background-image: url(/public/images/icons/code.svg);
|
||||
}
|
||||
|
||||
i.code-dark {
|
||||
background-image: url(/public/images/icons/code-dark.svg);
|
||||
}
|
||||
|
||||
i.link {
|
||||
background-image: url(/public/images/icons/link.svg);
|
||||
}
|
||||
|
||||
i.link-dark {
|
||||
background-image: url(/public/images/icons/link-dark.svg);
|
||||
}
|
||||
|
||||
i.left-align {
|
||||
background-image: url(/public/images/icons/text-left.svg);
|
||||
}
|
||||
|
||||
i.left-align-dark {
|
||||
background-image: url(/public/images/icons/text-left-dark.svg);
|
||||
}
|
||||
|
||||
i.center-align {
|
||||
background-image: url(/public/images/icons/text-center.svg);
|
||||
}
|
||||
|
||||
i.center-align-dark {
|
||||
background-image: url(/public/images/icons/text-center-dark.svg);
|
||||
}
|
||||
|
||||
i.right-align {
|
||||
background-image: url(/public/images/icons/text-right.svg);
|
||||
}
|
||||
|
||||
i.right-align-dark {
|
||||
background-image: url(/public/images/icons/text-right-dark.svg);
|
||||
}
|
||||
|
||||
i.justify-align {
|
||||
background-image: url(/public/images/icons/justify.svg);
|
||||
}
|
||||
|
||||
i.justify-align-dark {
|
||||
background-image: url(/public/images/icons/justify-dark.svg);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user