From 6abb7b064758973a8b25580dbf2de979d87ab916 Mon Sep 17 00:00:00 2001 From: lby Date: Tue, 5 Sep 2023 17:49:16 +0800 Subject: [PATCH] chore(web): add story text block (#653) --- web/package.json | 2 + .../StoryPanel/Block/builtin/Text/Editor.tsx | 31 + .../StoryPanel/Block/builtin/Text/index.tsx | 29 +- .../Block/builtin/common/Wrapper.tsx | 60 +- .../StoryPanel/Block/builtin/common/hooks.ts | 4 +- .../builtin/common/usePropertyValueUpdate.ts | 29 + .../RichTextEditor/images/icons/3-columns.svg | 3 + .../RichTextEditor/images/icons/LICENSE.md | 5 + .../images/icons/arrow-clockwise.svg | 1 + .../images/icons/arrow-counterclockwise.svg | 1 + .../RichTextEditor/images/icons/bg-color.svg | 1 + .../RichTextEditor/images/icons/camera.svg | 1 + .../images/icons/card-checklist.svg | 1 + .../images/icons/caret-right-fill.svg | 1 + .../images/icons/chat-left-text.svg | 1 + .../images/icons/chat-right-dots.svg | 1 + .../images/icons/chat-right-text.svg | 1 + .../images/icons/chat-right.svg | 1 + .../images/icons/chat-square-quote.svg | 1 + .../images/icons/chevron-down.svg | 1 + .../RichTextEditor/images/icons/clipboard.svg | 1 + .../RichTextEditor/images/icons/close.svg | 1 + .../RichTextEditor/images/icons/code.svg | 1 + .../RichTextEditor/images/icons/comments.svg | 1 + .../RichTextEditor/images/icons/copy.svg | 1 + .../RichTextEditor/images/icons/diagram-2.svg | 1 + .../RichTextEditor/images/icons/download.svg | 1 + .../images/icons/draggable-block-menu.svg | 1 + .../images/icons/dropdown-more.svg | 1 + .../images/icons/file-earmark-text.svg | 4 + .../images/icons/file-image.svg | 1 + .../images/icons/filetype-gif.svg | 1 + .../images/icons/font-color.svg | 1 + .../images/icons/font-family.svg | 1 + .../RichTextEditor/images/icons/gear.svg | 1 + .../images/icons/horizontal-rule.svg | 1 + .../RichTextEditor/images/icons/indent.svg | 1 + .../images/icons/journal-code.svg | 1 + .../images/icons/journal-text.svg | 1 + .../RichTextEditor/images/icons/justify.svg | 1 + .../RichTextEditor/images/icons/link.svg | 1 + .../RichTextEditor/images/icons/list-ol.svg | 1 + .../RichTextEditor/images/icons/list-ul.svg | 1 + .../RichTextEditor/images/icons/lock-fill.svg | 1 + .../RichTextEditor/images/icons/lock.svg | 1 + .../RichTextEditor/images/icons/markdown.svg | 1 + .../RichTextEditor/images/icons/mic.svg | 1 + .../RichTextEditor/images/icons/outdent.svg | 1 + .../images/icons/paint-bucket.svg | 1 + .../RichTextEditor/images/icons/palette.svg | 1 + .../images/icons/pencil-fill.svg | 1 + .../RichTextEditor/images/icons/plug-fill.svg | 1 + .../RichTextEditor/images/icons/plug.svg | 1 + .../images/icons/plus-slash-minus.svg | 1 + .../RichTextEditor/images/icons/plus.svg | 1 + .../RichTextEditor/images/icons/scissors.svg | 3 + .../RichTextEditor/images/icons/send.svg | 1 + .../images/icons/square-check.svg | 1 + .../RichTextEditor/images/icons/sticky.svg | 1 + .../images/icons/success-alt.svg | 1 + .../RichTextEditor/images/icons/success.svg | 1 + .../RichTextEditor/images/icons/table.svg | 1 + .../images/icons/text-center.svg | 1 + .../RichTextEditor/images/icons/text-left.svg | 1 + .../images/icons/text-paragraph.svg | 1 + .../images/icons/text-right.svg | 1 + .../RichTextEditor/images/icons/trash.svg | 1 + .../RichTextEditor/images/icons/trash3.svg | 1 + .../RichTextEditor/images/icons/type-bold.svg | 1 + .../RichTextEditor/images/icons/type-h1.svg | 1 + .../RichTextEditor/images/icons/type-h2.svg | 1 + .../RichTextEditor/images/icons/type-h3.svg | 1 + .../RichTextEditor/images/icons/type-h4.svg | 1 + .../RichTextEditor/images/icons/type-h5.svg | 1 + .../RichTextEditor/images/icons/type-h6.svg | 1 + .../images/icons/type-italic.svg | 1 + .../images/icons/type-strikethrough.svg | 1 + .../images/icons/type-subscript.svg | 1 + .../images/icons/type-superscript.svg | 1 + .../images/icons/type-underline.svg | 1 + .../RichTextEditor/images/icons/upload.svg | 1 + .../RichTextEditor/images/icons/user.svg | 1 + .../beta/lib/lexical/RichTextEditor/index.css | 1513 +++++++++++++++++ .../beta/lib/lexical/RichTextEditor/index.tsx | 133 ++ .../lib/lexical/RichTextEditor/nodes/index.ts | 30 + .../RichTextEditor/plugins/AutoLinkPlugin.tsx | 57 + .../FloatingLinkEditorPlugin/index.css | 41 + .../FloatingLinkEditorPlugin/index.tsx | 313 ++++ .../RichTextEditor/plugins/LinkPlugin.tsx | 20 + .../plugins/ListMaxIndentLevelPlugin.tsx | 67 + .../plugins/SwitchEditModePlugin.tsx | 10 + .../RichTextEditor/plugins/ToolbarPlugin.tsx | 825 +++++++++ .../themes/DefaultLexicalEditorTheme.css | 430 +++++ .../themes/DefaultLexicalEditorTheme.ts | 109 ++ .../lexical/RichTextEditor/ui/ColorPicker.css | 80 + .../lexical/RichTextEditor/ui/ColorPicker.tsx | 319 ++++ .../lexical/RichTextEditor/ui/DropDown.tsx | 232 +++ .../RichTextEditor/ui/DropdownColorPicker.tsx | 39 + .../lib/lexical/RichTextEditor/ui/Input.css | 23 + .../lexical/RichTextEditor/ui/TextInput.tsx | 37 + .../RichTextEditor/utils/getSelectedNode.ts | 18 + .../setFloatingElemPositionForLinkEditor.ts | 39 + .../lib/lexical/RichTextEditor/utils/url.ts | 24 + web/src/services/i18n/translations/en.yml | 31 +- web/src/services/i18n/translations/ja.yml | 31 +- web/yarn.lock | 171 ++ 106 files changed, 4789 insertions(+), 45 deletions(-) create mode 100644 web/src/beta/features/Editor/StoryPanel/Block/builtin/Text/Editor.tsx create mode 100644 web/src/beta/features/Editor/StoryPanel/Block/builtin/common/usePropertyValueUpdate.ts create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/3-columns.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/LICENSE.md create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/arrow-clockwise.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/arrow-counterclockwise.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/bg-color.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/camera.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/card-checklist.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/caret-right-fill.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/chat-left-text.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/chat-right-dots.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/chat-right-text.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/chat-right.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/chat-square-quote.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/chevron-down.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/clipboard.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/close.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/code.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/comments.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/copy.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/diagram-2.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/download.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/draggable-block-menu.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/dropdown-more.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/file-earmark-text.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/file-image.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/filetype-gif.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/font-color.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/font-family.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/gear.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/horizontal-rule.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/indent.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/journal-code.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/journal-text.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/justify.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/link.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/list-ol.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/list-ul.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/lock-fill.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/lock.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/markdown.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/mic.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/outdent.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/paint-bucket.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/palette.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/pencil-fill.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/plug-fill.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/plug.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/plus-slash-minus.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/plus.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/scissors.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/send.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/square-check.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/sticky.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/success-alt.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/success.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/table.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/text-center.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/text-left.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/text-paragraph.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/text-right.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/trash.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/trash3.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/type-bold.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/type-h1.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/type-h2.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/type-h3.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/type-h4.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/type-h5.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/type-h6.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/type-italic.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/type-strikethrough.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/type-subscript.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/type-superscript.svg create mode 100755 web/src/beta/lib/lexical/RichTextEditor/images/icons/type-underline.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/upload.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/images/icons/user.svg create mode 100644 web/src/beta/lib/lexical/RichTextEditor/index.css create mode 100644 web/src/beta/lib/lexical/RichTextEditor/index.tsx create mode 100644 web/src/beta/lib/lexical/RichTextEditor/nodes/index.ts create mode 100644 web/src/beta/lib/lexical/RichTextEditor/plugins/AutoLinkPlugin.tsx create mode 100644 web/src/beta/lib/lexical/RichTextEditor/plugins/FloatingLinkEditorPlugin/index.css create mode 100644 web/src/beta/lib/lexical/RichTextEditor/plugins/FloatingLinkEditorPlugin/index.tsx create mode 100644 web/src/beta/lib/lexical/RichTextEditor/plugins/LinkPlugin.tsx create mode 100644 web/src/beta/lib/lexical/RichTextEditor/plugins/ListMaxIndentLevelPlugin.tsx create mode 100644 web/src/beta/lib/lexical/RichTextEditor/plugins/SwitchEditModePlugin.tsx create mode 100644 web/src/beta/lib/lexical/RichTextEditor/plugins/ToolbarPlugin.tsx create mode 100644 web/src/beta/lib/lexical/RichTextEditor/themes/DefaultLexicalEditorTheme.css create mode 100644 web/src/beta/lib/lexical/RichTextEditor/themes/DefaultLexicalEditorTheme.ts create mode 100644 web/src/beta/lib/lexical/RichTextEditor/ui/ColorPicker.css create mode 100644 web/src/beta/lib/lexical/RichTextEditor/ui/ColorPicker.tsx create mode 100644 web/src/beta/lib/lexical/RichTextEditor/ui/DropDown.tsx create mode 100644 web/src/beta/lib/lexical/RichTextEditor/ui/DropdownColorPicker.tsx create mode 100644 web/src/beta/lib/lexical/RichTextEditor/ui/Input.css create mode 100644 web/src/beta/lib/lexical/RichTextEditor/ui/TextInput.tsx create mode 100644 web/src/beta/lib/lexical/RichTextEditor/utils/getSelectedNode.ts create mode 100644 web/src/beta/lib/lexical/RichTextEditor/utils/setFloatingElemPositionForLinkEditor.ts create mode 100644 web/src/beta/lib/lexical/RichTextEditor/utils/url.ts diff --git a/web/package.json b/web/package.json index 2e34ea14aa..13bdd56d82 100644 --- a/web/package.json +++ b/web/package.json @@ -106,6 +106,7 @@ "@emotion/react": "11.11.0", "@emotion/styled": "11.11.0", "@floating-ui/react": "0.24.7", + "@lexical/react": "0.12.0", "@mapbox/vector-tile": "1.3.1", "@monaco-editor/react": "4.5.1", "@popperjs/core": "2.11.7", @@ -144,6 +145,7 @@ "jsonpath-plus": "7.2.0", "jszip": "3.10.1", "leaflet": "1.9.3", + "lexical": "0.12.0", "localforage": "1.10.0", "lodash-es": "4.17.21", "lru-cache": "8.0.4", diff --git a/web/src/beta/features/Editor/StoryPanel/Block/builtin/Text/Editor.tsx b/web/src/beta/features/Editor/StoryPanel/Block/builtin/Text/Editor.tsx new file mode 100644 index 0000000000..919eb496d1 --- /dev/null +++ b/web/src/beta/features/Editor/StoryPanel/Block/builtin/Text/Editor.tsx @@ -0,0 +1,31 @@ +import { debounce } from "lodash-es"; +import { useMemo, useContext } from "react"; + +import RichTextEditor from "@reearth/beta/lib/lexical/RichTextEditor"; + +import { BlockContext } from "../common/Wrapper"; + +export type Props = { + text?: string; + onUpdate?: (text: string) => void; +}; + +const TextBlockEditor: React.FC = ({ text, onUpdate }) => { + const debouncedHandleTextUpdate = useMemo( + () => (onUpdate ? debounce(onUpdate, 1000) : undefined), + [onUpdate], + ); + + const context = useContext(BlockContext); + + return ( + + ); +}; + +export default TextBlockEditor; diff --git a/web/src/beta/features/Editor/StoryPanel/Block/builtin/Text/index.tsx b/web/src/beta/features/Editor/StoryPanel/Block/builtin/Text/index.tsx index 50b3ef25f2..7324fc9e68 100644 --- a/web/src/beta/features/Editor/StoryPanel/Block/builtin/Text/index.tsx +++ b/web/src/beta/features/Editor/StoryPanel/Block/builtin/Text/index.tsx @@ -1,20 +1,38 @@ -import { useMemo } from "react"; +import { useCallback, useMemo } from "react"; -import Text from "@reearth/beta/components/Text"; import { ValueTypes } from "@reearth/beta/utils/value"; import { getFieldValue } from "../../../utils"; import { CommonProps as BlockProps } from "../../types"; +import usePropertyValueUpdate from "../common/usePropertyValueUpdate"; import BlockWrapper from "../common/Wrapper"; +import TextBlockEditor from "./Editor"; + export type Props = BlockProps; +// Text block is very special, it will not edit values with field components +// from the common editor panel, but manage it by itself directly. + const TextBlock: React.FC = ({ block, isSelected, ...props }) => { const text = useMemo( () => getFieldValue(block?.property?.items ?? [], "text") as ValueTypes["string"], [block?.property?.items], ); + const { handlePropertyValueUpdate } = usePropertyValueUpdate(); + + const handleTextUpdate = useCallback( + (text: string) => { + const schemaGroup = block?.property?.items?.find( + i => i.schemaGroup === "default", + )?.schemaGroup; + if (!block?.property?.id || !schemaGroup) return; + handlePropertyValueUpdate(schemaGroup, block?.property?.id, "text", "string")(text); + }, + [block?.property?.id, block?.property?.items, handlePropertyValueUpdate], + ); + return ( = ({ block, isSelected, ...props }) => { isSelected={isSelected} propertyId={block?.property?.id} propertyItems={block?.property?.items} + settingsEnabled={false} {...props}> - {text && ( - - {text} - - )} + ); }; diff --git a/web/src/beta/features/Editor/StoryPanel/Block/builtin/common/Wrapper.tsx b/web/src/beta/features/Editor/StoryPanel/Block/builtin/common/Wrapper.tsx index 6589a2f304..7b1087d7db 100644 --- a/web/src/beta/features/Editor/StoryPanel/Block/builtin/common/Wrapper.tsx +++ b/web/src/beta/features/Editor/StoryPanel/Block/builtin/common/Wrapper.tsx @@ -1,4 +1,4 @@ -import { ReactNode } from "react"; +import { ReactNode, createContext } from "react"; import FieldComponents from "@reearth/beta/components/fields/PropertyFields"; import { stopClickPropagation } from "@reearth/beta/utils/events"; @@ -10,6 +10,8 @@ import Template from "../../Template"; import useHooks from "./hooks"; +export const BlockContext = createContext<{ editMode?: boolean } | undefined>(undefined); + type Spacing = { top: number; bottom: number; @@ -25,6 +27,7 @@ type Props = { propertyId?: string; propertyItems?: Item[]; dndEnabled?: boolean; + settingsEnabled?: boolean; onClick?: () => void; onClickAway?: () => void; onRemove?: () => void; @@ -38,6 +41,7 @@ const BlockWrapper: React.FC = ({ propertyId, propertyItems, dndEnabled = true, + settingsEnabled = true, onClick, onClickAway, onRemove, @@ -58,29 +62,31 @@ const BlockWrapper: React.FC = ({ }); return ( - - - {children ??