Skip to content

Commit

Permalink
Merge pull request #477 from VitNode/refactor/editor
Browse files Browse the repository at this point in the history
feat(frontend): Add support for Editor in Auto Form
  • Loading branch information
aXenDeveloper authored Sep 2, 2024
2 parents f460450 + 6f4828b commit 8002596
Show file tree
Hide file tree
Showing 53 changed files with 346 additions and 261 deletions.
1 change: 1 addition & 0 deletions apps/docs/content/docs/ui/forms/auto-form.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ description: Automatically generate form fields based on a schema.
- [Tag Input](/docs/ui/forms/tag-input)
- [Combobox](/docs/ui/forms/combobox)
- [Date Picker](/docs/ui/forms/date-picker)
- [WYSIWYG Editor](/docs/ui/forms/editor)

## Installation

Expand Down
4 changes: 4 additions & 0 deletions apps/docs/content/docs/ui/forms/color-picker.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -74,5 +74,9 @@ import { TypeTable } from 'fumadocs-ui/components/type-table';
description: 'Disable the color picker.',
type: 'boolean',
},
clearOnClick: {
description: 'Action when clear is clicked.',
type: '() => void',
},
}}
/>
80 changes: 49 additions & 31 deletions apps/docs/content/docs/ui/forms/editor.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,53 @@ description: Rich text editor that uses TipTap library.

## Usage

```tsx
import { Editor } from 'vitnode-frontend/editor';
```
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';

```tsx
<Editor onChange={onChange} value={value} />
<Tabs items={['Auto Form', 'Manual']}>
<Tab value="Auto Form">
```ts
import * as z from 'zod';
import { AutoForm } from 'vitnode-frontend/form/auto-form';
import { AutoFormEditor } from 'vitnode-frontend/form/fields/editor';
import { zodLanguageInput } from 'vitnode-frontend/helpers/zod';
```

### With Form

```tsx

```ts
const formSchema = z.object({
content: zodLanguageInput, // [!code highlight]
});
```

### With Upload Files

```tsx

<AutoForm
formSchema={formSchema}
fields={[
{
id: 'content',
component: AutoFormEditor,
},
]}
/>
```

### Form Schema
</Tab>

```ts {1, 4}
import { zodLanguageInput } from 'vitnode-frontend/helpers/zod';

const formSchema = z.object({
content: zodLanguageInput,
});
<Tab value="Manual">
```ts
import { Editor } from 'vitnode-frontend/components/editor/editor';
```

You can set this field as **required**:

```ts
const formSchema = z.object({
content: zodLanguageInput.min(1),
});
const [value, setValue] = useState<TextLanguage[]>([]);
```

```tsx
<Editor onChange={onChange} value={value} />
```

</Tab>
</Tabs>

## API Reference

import { TypeTable } from 'fumadocs-ui/components/type-table';
Expand Down Expand Up @@ -71,14 +80,18 @@ import { TypeTable } from 'fumadocs-ui/components/type-table';
description: 'Allow upload files.',
type: '{ plugin: string, folder: string }',
},
disabled: {
description: 'Disable editor.',
type: 'boolean',
default: 'false',
},
}}
/>

## Extensions

We have implemented the following extensions:

- [Blockquote](https://tiptap.dev/docs/editor/api/nodes/blockquote),
- [BulletList](https://tiptap.dev/docs/editor/api/nodes/bullet-list),
- [CodeBlock](https://tiptap.dev/docs/editor/api/nodes/code-block),
- [HardBreak](https://tiptap.dev/docs/editor/api/nodes/hard-break),
Expand All @@ -91,28 +104,33 @@ We have implemented the following extensions:
- [Code](https://tiptap.dev/docs/editor/api/marks/code),
- [Italic](https://tiptap.dev/docs/editor/api/marks/italic),
- [Strike](https://tiptap.dev/docs/editor/api/marks/strike),
- [Dropcursor](https://tiptap.dev/docs/editor/api/extensions/dropcursor),
- [Gapcursor](https://tiptap.dev/docs/editor/api/extensions/gapcursor),
- [History](https://tiptap.dev/docs/editor/api/extensions/history),
- [Underline](https://tiptap.dev/docs/editor/api/marks/underline),
- [TextAlign](https://tiptap.dev/docs/editor/api/extensions/text-align),
- [TextStyle](https://tiptap.dev/docs/editor/api/marks/text-style),
- [CodeBlockLowlight](https://tiptap.dev/docs/editor/api/nodes/code-block-lowlight),
- [Color](https://tiptap.dev/docs/editor/api/extensions/color),
- [Link](https://tiptap.dev/docs/editor/api/marks/link),
- [TextStyle](https://tiptap.dev/docs/editor/api/marks/text-style),
- [Color](https://tiptap.dev/docs/editor/api/extensions/color)
- [Blockquote](https://tiptap.dev/docs/editor/api/nodes/blockquote),

To Improve:

- [Dropcursor](https://tiptap.dev/docs/editor/api/extensions/dropcursor),
- [Gapcursor](https://tiptap.dev/docs/editor/api/extensions/gapcursor),

and extra extensions unique to our implementation:

- Remove Formatting,
- Emoji,
- Image,
- Images,
- Files

## Read only mode

To display content form editor you have to use `ReadOnlyEditor` component.

```tsx
import { ReadOnlyEditor } from 'vitnode-frontend/editor/read-only';
import { ReadOnlyEditor } from 'vitnode-frontend/components/editor/read-only';
```

```tsx
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default function DefaultPage() {
</h1>

<p className="text-muted-foreground text-pretty">
Dive in and install or create your first plugin!
Dive in and create install or your first plugin!
</p>

<div className="flex flex-wrap items-center gap-2 md:gap-4">
Expand Down
4 changes: 2 additions & 2 deletions apps/frontend/tailwind.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import vitnodeConfig from 'vitnode-frontend/tailwind.config';
const config = {
presets: [vitnodeConfig],
content: [
'./node_modules/vitnode-frontend/src/components/**/*.tsx',
'./node_modules/vitnode-frontend/src/views/**/*.tsx',
'./node_modules/vitnode-frontend/src/components/**/*.{ts,tsx}',
'./node_modules/vitnode-frontend/src/views/**/*.{ts,tsx}',
'./src/components/**/*.{ts,tsx}',
'./src/app/**/*.{ts,tsx}',
'./src/plugins/**/*.{ts,tsx}',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default function DefaultPage() {
</h1>

<p className="text-muted-foreground text-pretty">
Dive in and install or create your first plugin!
Dive in and create install or your first plugin!
</p>

<div className="flex flex-wrap items-center gap-2 md:gap-4">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import vitnodeConfig from 'vitnode-frontend/tailwind.config';
const config = {
presets: [vitnodeConfig],
content: [
'../../node_modules/vitnode-frontend/src/components/**/*.tsx',
'../../node_modules/vitnode-frontend/src/views/**/*.tsx',
'../../node_modules/vitnode-frontend/src/components/**/*.{ts,tsx}',
'../../node_modules/vitnode-frontend/src/views/**/*.{ts,tsx}',
'./src/components/**/*.{ts,tsx}',
'./src/app/**/*.{ts,tsx}',
'./src/plugins/**/templates/**/*.{ts,tsx}',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { Content, EditorContent, useEditor } from '@tiptap/react';
import { useLocale } from 'next-intl';
import React from 'react';

import { Skeleton } from '../components/ui/skeleton';
import { cn } from '../helpers/classnames';
import { useGlobals } from '../hooks/use-globals';
import { cn } from '../../helpers/classnames';
import { useGlobals } from '../../hooks/use-globals';
import { Skeleton } from '../ui/skeleton';
import { EmojiExtensionEditor } from './extensions/emoji/emoji';
import { extensionsEditor } from './extensions/extensions';
import {
Expand All @@ -21,6 +21,7 @@ import { ToolBarEditor } from './toolbar/toolbar';
interface Props extends Omit<UploadFilesHandlerEditorArgs, 'value'> {
autoFocus?: boolean;
className?: string;
disabled?: boolean;
}

interface WithLanguage extends Props {
Expand All @@ -46,6 +47,7 @@ export const Editor = ({
disableLanguages,
onChange,
value,
disabled,
}: WithLanguage | WithoutLanguage) => {
const { files, setFiles, uploadFiles } = useUploadFilesHandlerEditor({
value,
Expand All @@ -58,6 +60,7 @@ export const Editor = ({
);
const editor = useEditor({
autofocus: autoFocus,
immediatelyRender: false,
extensions: [
...extensionsEditor({
uploadFiles,
Expand Down Expand Up @@ -140,7 +143,9 @@ export const Editor = ({
}}
>
<div
className={cn('border-input rounded-md border shadow-sm', className)}
className={cn('border-input rounded-md border shadow-sm', className, {
'pointer-events-none cursor-not-allowed opacity-50': disabled,
})}
>
<div className="relative">
<ToolBarEditor />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ import { useTranslations } from 'next-intl';
import React from 'react';
import tippy, { Instance } from 'tippy.js';

import { Button } from '../../../components/ui/button';
import { classPopover } from '../../../components/ui/popover';
import { cn } from '../../../helpers/classnames';
import { CONFIG } from '../../../helpers/config-with-env';
import { cn } from '../../../../helpers/classnames';
import { CONFIG } from '../../../../helpers/config-with-env';
import { Button } from '../../../ui/button';
import { classPopover } from '../../../ui/popover';
import {
ComponentListRef,
SuggestionKeyDownProps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,17 @@ export const extensionsEditor = ({
heading: false,
bulletList: {
HTMLAttributes: {
class: 'list-disc',
class: 'pl-5 list-disc',
},
},
listItem: {
HTMLAttributes: {
class:
'ml-[2em] [&>p:first-of-type]:mb-0 [&:not(:first-child)]:mt-[.25em]',
class: 'ml-1 [&>p:first-of-type]:mb-0 [&:not(:first-child)]:mt-1',
},
},
orderedList: {
HTMLAttributes: {
class: 'list-decimal',
class: 'pl-5 list-decimal',
},
},
blockquote: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react';
import { File } from 'lucide-react';
import Image from 'next/image';

import { CONFIG } from '../../../helpers/config-with-env';
import { CONFIG } from '../../../../helpers/config-with-env';
import { acceptMimeTypeImage, FilesHandlerAttributes } from './files';

const FileFromNextWithNode = ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import { useTranslations } from 'next-intl';
import React from 'react';
import tippy, { GetReferenceClientRect, Instance } from 'tippy.js';

import { Button } from '../../../components/ui/button';
import { classPopover } from '../../../components/ui/popover';
import { cn } from '../../../helpers/classnames';
import { cn } from '../../../../helpers/classnames';
import { Button } from '../../../ui/button';
import { classPopover } from '../../../ui/popover';

export interface SuggestionProps<I> {
clientRect?: GetReferenceClientRect;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Paperclip } from 'lucide-react';
import { useTranslations } from 'next-intl';
import React from 'react';

import { Button } from '../../../components/ui/button';
import { Button } from '../../../ui/button';
import { FileStateEditor } from '../../extensions/files/files';
import { useEditorState } from '../../hooks/use-editor-state';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { cn } from '../../../helpers/classnames';
import { cn } from '../../../../helpers/classnames';
import { useEditorState } from '../../hooks/use-editor-state';
import { ItemListFilesFooterEditor } from './item/item';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useGlobals } from '../../hooks/use-globals';
import { useSession } from '../../hooks/use-session';
import { useGlobals } from '../../../hooks/use-globals';
import { useSession } from '../../../hooks/use-session';
import { useEditorState } from '../hooks/use-editor-state';
import { FilesButtonFooterEditor } from './files/button';
import { ListFilesFooterEditor } from './files/list';
Expand All @@ -21,6 +21,10 @@ export const FooterEditor = ({
const { allowUploadFiles, files } = useEditorState();
const { config } = useGlobals();

if (!disableLanguages && !allowUploadFiles) {
return null;
}

return (
<div className="bg-background rounded-b-md p-2">
<div className="flex w-full flex-wrap items-center justify-between gap-2 [&>*]:w-full [&>*]:sm:w-auto">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { useTranslations } from 'next-intl';

import { buttonVariants } from '../../components/ui/button';
import { useGlobals } from '../../../hooks/use-globals';
import { buttonVariants } from '../../ui/button';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '../../components/ui/select';
} from '../../ui/select';
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from '../../components/ui/tooltip';
import { useGlobals } from '../../hooks/use-globals';
} from '../../ui/tooltip';
import { useEditorState } from '../hooks/use-editor-state';

export interface LanguageSelectFooterEditorProps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { generateRandomString } from '@/helpers/generate-random-string';
import { Element } from 'html-react-parser';
import React from 'react';

import { cn } from '../../helpers/classnames';
import { cn } from '../../../helpers/classnames';
import { classNameCodeBlock, lowlight } from '../extensions/code/code';

interface Node {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import { File } from 'lucide-react';
import Image from 'next/image';
import { useTranslations } from 'next-intl';

import { Button } from '../../components/ui/button';
import { CONFIG } from '../../helpers/config-with-env';
import { CONFIG } from '../../../helpers/config-with-env';
import { Button } from '../../ui/button';
import { acceptMimeTypeImage } from '../extensions/files/files';

export const FileDownloadButton = ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import parse, { Element, HTMLReactParserOptions } from 'html-react-parser';
import Image from 'next/image';
import { useLocale } from 'next-intl';

import { cn } from '../../helpers/classnames';
import { cn } from '../../../helpers/classnames';
import { extensionsEditor } from '../extensions/extensions';
import { changeCodeBlock } from './code-block';
import { FileDownloadButton } from './file-download-button';
Expand Down
Loading

0 comments on commit 8002596

Please sign in to comment.