npm package: @sinups/editor-dsd
Description: TextEditor - это текстовой редактор для веб-приложений на JavaScript с акцентом на надежность, доступность и производительность. TextEditorR7 нацелен на предоставление оптимального опыта разработчика, чтобы вы могли легко создавать прототипы и внедрять фу
Latest version: 0.2.58

# TextEditor

TextEditor - это текстовой редактор для веб-приложений на JavaScript с акцентом на надежность, доступность и производительность. TextEditorR7 нацелен на предоставление оптимального опыта разработчика, чтобы вы могли легко создавать прототипы и внедрять функции с уверенностью. Совмещенный с высокорасширяемой архитектурой, TextEditorR7 позволяет разработчикам создавать уникальные текстовые редакторы, масштабирующиеся по размеру и функциональности

## Быстрый старт

```
import { Editor } from '@sinups/editor-dsd';
```

Инициализация текстового редактора.

По умолчанию TextEditorR7 работает с объектом и может возвращать объект или HTML.

Пример с объектом:

```js
const text = 'Hello world';

const json = {
  root: {
    children: [
      {
        children: [
          {
            detail: 0,
            format: 0,
            mode: 'normal',
            style: '',
            text: text,
            type: 'text',
            version: 1
          }
        ],
        direction: 'ltr',
        format: '',
        indent: 0,
        type: 'paragraph',
        version: 1
      }
    ],
    direction: 'ltr',
    format: '',
    indent: 0,
    type: 'root',
    version: 1
  }
};

const onChange = (
  data // json
) => <Editor initialContent={json} onChange={onChange} />;
```

Также в редактор можно передать HTML-строку.

Пример с HTML:

```
const html = `
<h2 dir="ltr" style="text-align: left;">
   <span style="background-color: rgb(248, 231, 28); font-family: &quot;Trebuchet MS&quot;; white-space: pre-wrap;">Hello</span>
</h2>
<h2 dir="ltr">
   <br>
</h2>
<p dir="ltr">
   <br>
</p>
<p dir="ltr">
   <span style="font-size: 21px; white-space: pre-wrap;">world</span>
</p>
`

const onChange = (data) => // json

<Editor initialContent={html} onChange={onChange} />
```

За вывод данных в функции onChange отвечает свойство **outputFormat**. **outputFormat** может быть равен либо "html", либо "json". Пример с **outputFormat**:

```
const html = `
<h2 dir="ltr" style="text-align: left;">
   <span style="background-color: rgb(248, 231, 28); font-family: &quot;Trebuchet MS&quot;; white-space: pre-wrap;">Hello</span>
</h2>
<h2 dir="ltr">
   <br>
</h2>
<p dir="ltr">
   <br>
</p>
<p dir="ltr">
   <span style="font-size: 21px; white-space: pre-wrap;">world</span>
</p>
`

const onChange = (data) => // html

<Editor initialContent={html} outputFormat="html" onChange={onChange} />
```

## DocSpaceStylesProvider

Используйте DocSpaceStylesProvider, чтобы добавить стили оформления к вашему HTML-контенту.

```
  <DocSpaceStylesProvider>
      <div
        dangerouslySetInnerHTML={{ __html: '<p>Your html here</p>' }}
      />
    </DocSpaceStylesProvider>
```

## Загрузка картинок

Чтобы начать работать с загрузкой картинок используйте функцию **fetchUploadImage**, которая принимает три параметра, **file**,**success** и **error**. После успешной загрузки картинок на ваш сервис нужно вызвать функцию **success** и передать два обязательных аргумента,
**URL** изображения и **ID**.

```
  const fetchUploadImage = async (
    file: File,
    success: (url: string, id: string) => void,
    error?: (error?: Error) => void
  ) => {
    const formData = new FormData();
    formData.append('File', file);
    formData.append('FileAccessModifier', '0');

    try {
      const response = await fetch('/api/v1/Files/Upload', {
        method: 'POST',
        body: formData,
        credentials: 'include'
      });

      if (!response.ok) {
        throw new Error('File upload failed');
      }

      const data = await response.json();
      const { Id, Url } = data;

      success(Url, Id);
    } catch (err) {
      if (error) {
        if (err instanceof Error) {
          error(err);
        } else {
          error(new Error('An unknown error occurred'));
        }
      }
    }
  };

<Editor
  ...props
  fetchUploadImage={fetchUploadImage}
/>
```

## Удаление картинок

Чтобы иметь больший контроль над удалением картинки передайте в редактор необязательную функцию **fetchDeleteImage** которая принимает три параметра, **id**, **success** и **error**. После успешного удаления картинки из вашего сервиса нужно вызвать функцию **success**.

```
  const fetchDeleteImage = async (
    id: string,
    success: () => void,
    error?: (error?: Error) => void
  ) => {
    const body = { Ids: [id] };

    try {
      const response = await fetch('/api/v1/Documents/Delete', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify(body),
        credentials: 'include'
      });

      await response.json();
      success();
    } catch (err) {
      if (error) {
        if (err instanceof Error) {
          error(err);
        } else {
          error(new Error('An unknown error occurred'));
        }
      }
    }
  };

<Editor
  ...props
   fetchUploadImage={fetchUploadImage}
   fetchDeleteImage={fetchUploadImage}
/>
```

## Дополнительные опции для работы с закгрузкой картинки

```
import { Editor, Dropzone } from "@sinups/editor-dsd";

const Content = () => (
      <Group justify="center" gap="xl" mih={220} style={{ pointerEvents: 'none' }}>
           {/*
           Компоненты Dropzone.Accept, Dropzone.Reject и Dropzone.Idle видны только тогда, когда пользователь выполняет
           определенное действие:

          Dropzone.Accept отображается только тогда, когда пользователь перетаскивает файл, который можно принять, в зону сброса.
          Dropzone.Reject отображается только тогда, когда пользователь перетаскивает файл, который не может быть принят, в зону сброса.
         Dropzone.Idle виден, когда пользователь ничего не перетаскивает в зону сброса.
          */}
            <Dropzone.Accept>
              <IconUpload
                style={{ width: rem(52), height: rem(52), color: 'var(--mantine-color-blue-6)' }}
                stroke={1.5}
              />
            </Dropzone.Accept>
            <Dropzone.Reject>
              <IconX
                style={{ width: rem(52), height: rem(52), color: 'var(--mantine-color-red-6)' }}
                stroke={1.5}
              />
            </Dropzone.Reject>
            <Dropzone.Idle>
              <IconPhoto
                style={{ width: rem(52), height: rem(52), color: 'var(--mantine-color-dimmed)' }}
                stroke={1.5}
              />
            </Dropzone.Idle>

            <div>
              <Text size="xl" inline>
                Перетащите изображения сюда или нажмите, чтобы выбрать файлы
              </Text>
              <Text size="sm" c="dimmed" inline mt={7}>
                Прикрепляйте столько файлов, сколько хотите, каждый файл не должен превышать{' '}
                {maxImageSize} МБ.
              </Text>
            </div>
          </Group>
  );

<Editor
  ...props
   fetchUploadImage={fetchUploadImage}
   contentModalUploadImage={Content}
   maxImageSize={5}
   maxImageSizeError={() => {}}
/>
```

## Коллаборация

```
<Editor
...props
ws={{
       url: 'https://wss.dudoc.io/', //cсылка на websocket
       id: '322323', // уникальный id документа
       user: userProfile, // текущий пользователь
       getActiveUsers: (users) => { / возвращает активных пользователей редактирующий документ
          setActiveUsers(users);
        }
      }}
/>
```

## Сброс содержимого редактора

```

import {  CLEAR_EDITOR_COMMAND } from './EditorLexical';

<>
   <button
      onClick={() => {
        if (editorRef.current) {
          editorRef.current.update(() => {
            editorRef.current?.dispatchCommand(CLEAR_EDITOR_COMMAND, undefined);
          });
        }
      }}
    >
      Reset
    </button>
    <Editor
    ...props
     editorRef={editorRef}
    />
<>
```

## Свойства

```
onChange: (value: string | object) => undefined - функция, срабатывает при каждом изменении редактора и возвращает HTML-строку или объект в зависимости от свойства outputFormat.
debounce?: number -  Как часто вызывается функция onChange в ms.
onBlur: (value: string | object) => undefined - функция, срабатывает при расфокусировки редактора и возвращает HTML-строку или объект в зависимости от свойства outputFormat.
outputFormat?: 'html' | 'json' - свойство outputFormat передается, если мы хотим на выходе получать HTML-строку, по умолчанию json.
initialContent: string | object - изначальные данные для редактора.
maxHeight?: number - задает высоту редактора, по умолчанию 100%.
mode?: 'simple' | 'default' | 'full' | 'editor' - режим редактора: в зависимости от выбранного режима урезается или добавляется новый функционал. По умолчанию default.
fetchUploadImage?: (file: File, success: (url: string, id: string, error?: (error?: Error) => void) => void - Функция для загрузки картинки на ваш сервис.
fetchDeleteImage?: (id: string, success: () => void, error?: (error?: Error) => void - Вспомогательная функция для удаления картинки
maxImageSize?: number - Максимальный размер картинки в мегабайтах
contentModalUploadImage?: React.FunctionComponent - React компонент для замены контента в DropZone
maxImageSizeError?: () => void - Функция вызывается если картинка превышает размер maxImageSize
disable?: boolean - Переключает в режим чтения
ws?:{{
      url: string - //cсылка на websocket
      id: string // уникальный id документа
      user: {color: string, name: string}, // текущий пользователь
      getActiveUsers: (users) => void / возвращает активных пользователей редактирующий документ
    }}
editorRef?: {current: EditorType | null} // ссылка на редактор
```