Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update link editor #1195

Merged
merged 19 commits into from Nov 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions components/form-builder/icons/EditIcon.tsx
@@ -0,0 +1,16 @@
import React from "react";
export const EditIcon = ({ className, title }: { className?: string; title?: string }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
height="48"
width="48"
className={className}
viewBox="0 0 48 48"
focusable="false"
aria-hidden={title ? false : true}
role={title ? "img" : "presentation"}
>
{title && <title>{title}</title>}
<path d="M9 39h2.2l22.15-22.15-2.2-2.2L9 36.8Zm30.7-24.3-6.4-6.4 2.1-2.1q.85-.85 2.1-.85t2.1.85l2.2 2.2q.85.85.85 2.1t-.85 2.1Zm-2.1 2.1L12.4 42H6v-6.4l25.2-25.2Zm-5.35-1.05-1.1-1.1 2.2 2.2Z" />
</svg>
);
29 changes: 26 additions & 3 deletions components/form-builder/lexical-editor/Editor.tsx
@@ -1,4 +1,4 @@
import React from "react";
import React, { useState } from "react";
import PropTypes from "prop-types";
import styled from "styled-components";
import { LexicalComposer } from "@lexical/react/LexicalComposer";
Expand All @@ -17,6 +17,8 @@ import {
TRANSFORMERS,
} from "@lexical/markdown";
import { TabEscape } from "./plugins/TabEscape";
import FloatingLinkEditorPlugin from "./plugins/FloatingLinkEditorPlugin";
import { t } from "i18next";

const RichTextWrapper = styled.div`
height: 100%;
Expand All @@ -39,6 +41,18 @@ export const Editor = ({
onChange: (value: string) => void;
autoFocusEditor?: boolean;
}) => {
const [floatingAnchorElem, setFloatingAnchorElem] = useState<HTMLDivElement | undefined>(
undefined
);

const editorId = "editor-" + Math.random().toString(36).substr(2, 9);

const onRef = (_floatingAnchorElem: HTMLDivElement) => {
if (_floatingAnchorElem !== null) {
setFloatingAnchorElem(_floatingAnchorElem);
}
};

if (typeof content !== "string") {
content = "";
}
Expand All @@ -58,9 +72,17 @@ export const Editor = ({
},
}}
>
<Toolbar />
<Toolbar editorId={editorId} />
<RichTextPlugin
contentEditable={<ContentEditable className="editor-input" />}
contentEditable={
<div className="editor relative" ref={onRef}>
<ContentEditable
className="editor-input"
id={editorId}
ariaLabel={t("RichTextEditor")}
/>
</div>
}
placeholder={""}
/>
<FocusPlugin autoFocusEditor={autoFocusEditor} />
Expand All @@ -74,6 +96,7 @@ export const Editor = ({
}}
/>
<LinkPlugin />
<FloatingLinkEditorPlugin anchorElem={floatingAnchorElem} />
<ListPlugin />
<TabEscape />
</LexicalComposer>
Expand Down
48 changes: 30 additions & 18 deletions components/form-builder/lexical-editor/Toolbar.tsx
Expand Up @@ -2,14 +2,14 @@ import React, { useState, useCallback, useEffect, useRef, KeyboardEvent } from "
import { useLexicalComposerContext } from "@lexical/react/LexicalComposerContext";
import { $isHeadingNode, $createHeadingNode } from "@lexical/rich-text";
import { mergeRegister, $getNearestNodeOfType } from "@lexical/utils";
import { LinkEditor } from "./plugins/LinkEditor";
import { Looks3 } from "@styled-icons/material/Looks3";
import { LooksTwo } from "@styled-icons/material/LooksTwo";
import { FormatBold } from "@styled-icons/material/FormatBold";
import { FormatItalic } from "@styled-icons/material/FormatItalic";
import { Link } from "@styled-icons/material/Link";
import { FormatListBulleted } from "@styled-icons/material/FormatListBulleted";
import { FormatListNumbered } from "@styled-icons/material/FormatListNumbered";
import { TOGGLE_LINK_COMMAND } from "@lexical/link";

import {
$isListNode,
Expand All @@ -29,6 +29,7 @@ import {

import { $wrapNodes } from "@lexical/selection";
import styled from "styled-components";
import { sanitizeUrl } from "./utils/sanitizeUrl";

const blockTypeToBlockName = {
bullet: "Bulleted List",
Expand Down Expand Up @@ -74,14 +75,24 @@ const ToolbarContainer = styled.div`
const LowPriority = 1;
type HeadingTagType = "h2" | "h3" | "h4" | "h5";

export const Toolbar = () => {
export const Toolbar = ({ editorId }: { editorId: string }) => {
const [editor] = useLexicalComposerContext();
const [isBold, setIsBold] = useState(false);
const [isItalic, setIsItalic] = useState(false);
const [isLink] = useState(false);
const [, setSelectedElementKey] = useState("");
const [blockType, setBlockType] = useState("paragraph");

const [isEditable] = useState(() => editor.isEditable());

const insertLink = useCallback(() => {
if (!isLink) {
editor.dispatchCommand(TOGGLE_LINK_COMMAND, sanitizeUrl("https://"));
} else {
editor.dispatchCommand(TOGGLE_LINK_COMMAND, null);
}
}, [editor, isLink]);

const [items] = useState([
{ id: 1, txt: "heading2" },
{ id: 2, txt: "heading3" },
Expand Down Expand Up @@ -229,7 +240,7 @@ export const Toolbar = () => {
<ToolbarContainer
role="toolbar"
aria-label="Text formatting"
aria-controls=""
aria-controls={editorId}
onKeyDown={handleNav}
>
<button
Expand Down Expand Up @@ -330,21 +341,22 @@ export const Toolbar = () => {
<FormatListNumbered size={20} />
</button>

<LinkEditor>
<button
tabIndex={currentFocusIndex == 6 ? 0 : -1}
ref={(el) => {
const index = "button-6" as unknown as number;
if (el && itemsRef.current) {
itemsRef.current[index] = el;
}
}}
className={"toolbar-item " + (isLink ? "active" : "")}
aria-label="Format Link"
>
<Link size={20} />
</button>
</LinkEditor>
<button
tabIndex={currentFocusIndex == 6 ? 0 : -1}
ref={(el) => {
const index = "button-6" as unknown as number;
if (el && itemsRef.current) {
itemsRef.current[index] = el;
}
}}
disabled={!isEditable}
onClick={insertLink}
className={"toolbar-item " + (isLink ? "active" : "")}
aria-label="Insert link"
title="Insert link"
>
<Link size={20} />
</button>
</ToolbarContainer>
</>
);
Expand Down