From 842048b2f29e3e59ae2303e93b71aebc9168176a Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Sat, 9 Dec 2023 17:26:47 +0530 Subject: [PATCH 1/2] style: update the ui of the slash command menu --- .../src/ui/extensions/index.tsx | 13 +- packages/editor/extensions/package.json | 2 +- .../src/extensions/slash-commands.tsx | 303 +++++++++--------- .../src/types/slash-commands-suggestion.ts | 7 +- yarn.lock | 5 + 5 files changed, 175 insertions(+), 155 deletions(-) diff --git a/packages/editor/document-editor/src/ui/extensions/index.tsx b/packages/editor/document-editor/src/ui/extensions/index.tsx index a5b77202f..316abc7b9 100644 --- a/packages/editor/document-editor/src/ui/extensions/index.tsx +++ b/packages/editor/document-editor/src/ui/extensions/index.tsx @@ -15,12 +15,13 @@ export const DocumentEditorExtensions = ( isSubmitting: "submitting" | "submitted" | "saved", ) => void, ) => { - const additonalOptions: ISlashCommandItem[] = [ + const additionalOptions: ISlashCommandItem[] = [ { - title: "Issue Embed", - description: "Embed an issue from the project", - searchTerms: ["Issue", "Iss"], - icon: , + key: "issue_embed", + title: "Issue embed", + description: "Embed an issue from the project.", + searchTerms: ["issue", "link", "embed"], + icon: , command: ({ editor, range }) => { editor .chain() @@ -35,7 +36,7 @@ export const DocumentEditorExtensions = ( ]; return [ - SlashCommand(uploadFile, setIsSubmitting, additonalOptions), + SlashCommand(uploadFile, setIsSubmitting, additionalOptions), DragAndDrop, Placeholder.configure({ placeholder: ({ node }) => { diff --git a/packages/editor/extensions/package.json b/packages/editor/extensions/package.json index 2b1a487bd..29860a1cc 100644 --- a/packages/editor/extensions/package.json +++ b/packages/editor/extensions/package.json @@ -35,7 +35,7 @@ "@plane/editor-core": "*", "eslint": "8.36.0", "eslint-config-next": "13.2.4", - "lucide-react": "^0.244.0", + "lucide-react": "^0.249.0", "tippy.js": "^6.3.7", "@tiptap/pm": "^2.1.7" }, diff --git a/packages/editor/extensions/src/extensions/slash-commands.tsx b/packages/editor/extensions/src/extensions/slash-commands.tsx index 8ca132405..8ea6794dd 100644 --- a/packages/editor/extensions/src/extensions/slash-commands.tsx +++ b/packages/editor/extensions/src/extensions/slash-commands.tsx @@ -10,19 +10,23 @@ import { Editor, Range, Extension } from "@tiptap/core"; import Suggestion from "@tiptap/suggestion"; import { ReactRenderer } from "@tiptap/react"; import tippy from "tippy.js"; -import type { UploadImage, ISlashCommandItem, CommandProps } from "@plane/editor-types"; +import type { + UploadImage, + ISlashCommandItem, + CommandProps, +} from "@plane/editor-types"; import { + CaseSensitive, + Code2, Heading1, Heading2, Heading3, + ImageIcon, List, ListOrdered, - Text, - TextQuote, - Code, + ListTodo, MinusSquare, - CheckSquare, - ImageIcon, + Quote, Table, } from "lucide-react"; import { @@ -39,6 +43,7 @@ import { } from "@plane/editor-core"; interface CommandItemProps { + key: string; title: string; description: string; icon: ReactNode; @@ -83,146 +88,158 @@ const getSuggestionItems = setIsSubmitting?: ( isSubmitting: "submitting" | "submitted" | "saved", ) => void, - additonalOptions?: Array + additionalOptions?: Array, ) => - ({ query }: { query: string }) => { - let slashCommands: ISlashCommandItem[] = [ - { - title: "Text", - description: "Just start typing with plain text.", - searchTerms: ["p", "paragraph"], - icon: , - command: ({ editor, range }: CommandProps) => { - editor - .chain() - .focus() - .deleteRange(range) - .toggleNode("paragraph", "paragraph") - .run(); - }, + ({ query }: { query: string }) => { + let slashCommands: ISlashCommandItem[] = [ + { + key: "text", + title: "Text", + description: "Just start typing with plain text.", + searchTerms: ["p", "paragraph"], + icon: , + command: ({ editor, range }: CommandProps) => { + editor + .chain() + .focus() + .deleteRange(range) + .toggleNode("paragraph", "paragraph") + .run(); }, - { - title: "Heading 1", - description: "Big section heading.", - searchTerms: ["title", "big", "large"], - icon: , - command: ({ editor, range }: CommandProps) => { - toggleHeadingOne(editor, range); - }, + }, + { + key: "heading_1", + title: "Heading 1", + description: "Big section heading.", + searchTerms: ["title", "big", "large"], + icon: , + command: ({ editor, range }: CommandProps) => { + toggleHeadingOne(editor, range); }, - { - title: "Heading 2", - description: "Medium section heading.", - searchTerms: ["subtitle", "medium"], - icon: , - command: ({ editor, range }: CommandProps) => { - toggleHeadingTwo(editor, range); - }, + }, + { + key: "heading_2", + title: "Heading 2", + description: "Medium section heading.", + searchTerms: ["subtitle", "medium"], + icon: , + command: ({ editor, range }: CommandProps) => { + toggleHeadingTwo(editor, range); }, - { - title: "Heading 3", - description: "Small section heading.", - searchTerms: ["subtitle", "small"], - icon: , - command: ({ editor, range }: CommandProps) => { - toggleHeadingThree(editor, range); - }, + }, + { + key: "heading_3", + title: "Heading 3", + description: "Small section heading.", + searchTerms: ["subtitle", "small"], + icon: , + command: ({ editor, range }: CommandProps) => { + toggleHeadingThree(editor, range); }, - { - title: "To-do List", - description: "Track tasks with a to-do list.", - searchTerms: ["todo", "task", "list", "check", "checkbox"], - icon: , - command: ({ editor, range }: CommandProps) => { - toggleTaskList(editor, range); - }, + }, + { + key: "todo_list", + title: "To do", + description: "Track tasks with a to-do list.", + searchTerms: ["todo", "task", "list", "check", "checkbox"], + icon: , + command: ({ editor, range }: CommandProps) => { + toggleTaskList(editor, range); }, - { - title: "Bullet List", - description: "Create a simple bullet list.", - searchTerms: ["unordered", "point"], - icon: , - command: ({ editor, range }: CommandProps) => { - toggleBulletList(editor, range); - }, + }, + { + key: "bullet_list", + title: "Bullet list", + description: "Create a simple bullet list.", + searchTerms: ["unordered", "point"], + icon: , + command: ({ editor, range }: CommandProps) => { + toggleBulletList(editor, range); }, - { - title: "Divider", - description: "Visually divide blocks", - searchTerms: ["line", "divider", "horizontal", "rule", "separate"], - icon: , - command: ({ editor, range }: CommandProps) => { - // @ts-expect-error I have to move this to the core - editor.chain().focus().deleteRange(range).setHorizontalRule().run(); - }, + }, + { + key: "numbered_list", + title: "Numbered list", + description: "Create a list with numbering.", + searchTerms: ["ordered"], + icon: , + command: ({ editor, range }: CommandProps) => { + toggleOrderedList(editor, range); }, - { - title: "Table", - description: "Create a Table", - searchTerms: ["table", "cell", "db", "data", "tabular"], - icon: , - command: ({ editor, range }: CommandProps) => { - insertTableCommand(editor, range); - }, + }, + { + key: "table", + title: "Table", + description: "Create a table", + searchTerms: ["table", "cell", "db", "data", "tabular"], + icon:
, + command: ({ editor, range }: CommandProps) => { + insertTableCommand(editor, range); }, - { - title: "Numbered List", - description: "Create a list with numbering.", - searchTerms: ["ordered"], - icon: , - command: ({ editor, range }: CommandProps) => { - toggleOrderedList(editor, range); - }, + }, + { + key: "quote_block", + title: "Quote", + description: "Capture a quote.", + searchTerms: ["blockquote"], + icon: , + command: ({ editor, range }: CommandProps) => + toggleBlockquote(editor, range), + }, + { + key: "code_block", + title: "Code", + description: "Capture a code snippet.", + searchTerms: ["codeblock"], + icon: , + command: ({ editor, range }: CommandProps) => + // @ts-expect-error I have to move this to the core + editor.chain().focus().deleteRange(range).toggleCodeBlock().run(), + }, + { + key: "image", + title: "Image", + description: "Upload an image from your computer.", + searchTerms: ["photo", "picture", "media"], + icon: , + command: ({ editor, range }: CommandProps) => { + insertImageCommand(editor, uploadFile, setIsSubmitting, range); }, - { - title: "Quote", - description: "Capture a quote.", - searchTerms: ["blockquote"], - icon: , - command: ({ editor, range }: CommandProps) => - toggleBlockquote(editor, range), + }, + { + key: "divider", + title: "Divider", + description: "Visually divide blocks.", + searchTerms: ["line", "divider", "horizontal", "rule", "separate"], + icon: , + command: ({ editor, range }: CommandProps) => { + // @ts-expect-error I have to move this to the core + editor.chain().focus().deleteRange(range).setHorizontalRule().run(); }, - { - title: "Code", - description: "Capture a code snippet.", - searchTerms: ["codeblock"], - icon: , - command: ({ editor, range }: CommandProps) => - // @ts-expect-error I have to move this to the core - editor.chain().focus().deleteRange(range).toggleCodeBlock().run(), - }, - { - title: "Image", - description: "Upload an image from your computer.", - searchTerms: ["photo", "picture", "media"], - icon: , - command: ({ editor, range }: CommandProps) => { - insertImageCommand(editor, uploadFile, setIsSubmitting, range); - }, - }, - ] + }, + ]; - if (additonalOptions) { - additonalOptions.map(item => { - slashCommands.push(item) - }) + if (additionalOptions) { + additionalOptions.map((item) => { + slashCommands.push(item); + }); + } + + slashCommands = slashCommands.filter((item) => { + if (typeof query === "string" && query.length > 0) { + const search = query.toLowerCase(); + return ( + item.title.toLowerCase().includes(search) || + item.description.toLowerCase().includes(search) || + (item.searchTerms && + item.searchTerms.some((term: string) => term.includes(search))) + ); } + return true; + }); - slashCommands = slashCommands.filter((item) => { - if (typeof query === "string" && query.length > 0) { - const search = query.toLowerCase(); - return ( - item.title.toLowerCase().includes(search) || - item.description.toLowerCase().includes(search) || - (item.searchTerms && - item.searchTerms.some((term: string) => term.includes(search))) - ); - } - return true; - }) - - return slashCommands - }; + return slashCommands; + }; export const updateScrollView = (container: HTMLElement, item: HTMLElement) => { const containerHeight = container.offsetHeight; @@ -303,27 +320,23 @@ const CommandList = ({
- {items.map((item: CommandItemProps, index: number) => ( + {items.map((item, index) => ( ))}
@@ -383,11 +396,11 @@ export const SlashCommand = ( setIsSubmitting?: ( isSubmitting: "submitting" | "submitted" | "saved", ) => void, - additonalOptions?: Array, + additionalOptions?: Array, ) => Command.configure({ suggestion: { - items: getSuggestionItems(uploadFile, setIsSubmitting, additonalOptions), + items: getSuggestionItems(uploadFile, setIsSubmitting, additionalOptions), render: renderItems, }, }); diff --git a/packages/editor/types/src/types/slash-commands-suggestion.ts b/packages/editor/types/src/types/slash-commands-suggestion.ts index 327c285cd..34e451098 100644 --- a/packages/editor/types/src/types/slash-commands-suggestion.ts +++ b/packages/editor/types/src/types/slash-commands-suggestion.ts @@ -1,15 +1,16 @@ import { ReactNode } from "react"; -import { Editor, Range } from "@tiptap/core" +import { Editor, Range } from "@tiptap/core"; export type CommandProps = { editor: Editor; range: Range; -} +}; export type ISlashCommandItem = { + key: string; title: string; description: string; searchTerms: string[]; icon: ReactNode; command: ({ editor, range }: CommandProps) => void; -} +}; diff --git a/yarn.lock b/yarn.lock index d6353dc89..1572162ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6078,6 +6078,11 @@ lucide-react@^0.244.0: resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.244.0.tgz#9626f44881830280012dad23afda7ddbcffff24b" integrity sha512-PeDVbx5PlIRrVvdxiuSxPfBo7sK5qrL3LbvvRoGVNiHYRAkBm/48lKqoioxcmp0bgsyJs9lMw7CdtGFvnMJbVg== +lucide-react@^0.249.0: + version "0.249.0" + resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.249.0.tgz#6914c70220d9bdd69015d7b2009fb358a716c909" + integrity sha512-vBvk6aEz7c/v3moYejn3CbIZ9jtn8aDhtT+N9nao71MycQqZB9QtQ0U0WEnB58856A5boKtSUEkjF9NwkM04gA== + lucide-react@^0.293.0: version "0.293.0" resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.293.0.tgz#02703dbcc56bb38779f4e576cc03be8cc0046fcc" From 457ed9bfe6438077cf8d245cd67b24b3f58fd117 Mon Sep 17 00:00:00 2001 From: Aaryan Khandelwal Date: Sun, 10 Dec 2023 01:10:59 +0530 Subject: [PATCH 2/2] chore: update lucide-react package to the latest version --- packages/editor/extensions/package.json | 2 +- yarn.lock | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/editor/extensions/package.json b/packages/editor/extensions/package.json index 29860a1cc..65632e496 100644 --- a/packages/editor/extensions/package.json +++ b/packages/editor/extensions/package.json @@ -35,7 +35,7 @@ "@plane/editor-core": "*", "eslint": "8.36.0", "eslint-config-next": "13.2.4", - "lucide-react": "^0.249.0", + "lucide-react": "^0.293.0", "tippy.js": "^6.3.7", "@tiptap/pm": "^2.1.7" }, diff --git a/yarn.lock b/yarn.lock index 1572162ef..d6353dc89 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6078,11 +6078,6 @@ lucide-react@^0.244.0: resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.244.0.tgz#9626f44881830280012dad23afda7ddbcffff24b" integrity sha512-PeDVbx5PlIRrVvdxiuSxPfBo7sK5qrL3LbvvRoGVNiHYRAkBm/48lKqoioxcmp0bgsyJs9lMw7CdtGFvnMJbVg== -lucide-react@^0.249.0: - version "0.249.0" - resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.249.0.tgz#6914c70220d9bdd69015d7b2009fb358a716c909" - integrity sha512-vBvk6aEz7c/v3moYejn3CbIZ9jtn8aDhtT+N9nao71MycQqZB9QtQ0U0WEnB58856A5boKtSUEkjF9NwkM04gA== - lucide-react@^0.293.0: version "0.293.0" resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.293.0.tgz#02703dbcc56bb38779f4e576cc03be8cc0046fcc"