Skip to content

Commit

Permalink
docs: update README
Browse files Browse the repository at this point in the history
  • Loading branch information
tonai committed Jan 2, 2025
1 parent 28450dd commit ff2b9c8
Show file tree
Hide file tree
Showing 7 changed files with 400 additions and 125 deletions.
331 changes: 305 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,328 @@
# Modèle de ReadMe
# react-dsfr-tiptap

Ci-dessous une proposition de readme pour tout projet
Composant de texte riche React pour le [System de design du gouvernement français (alias DSFR) 🇫🇷](https://www.systeme-de-design.gouv.fr/).

## Description

## Description/Résumé du projet
Ce dépôt contient :

Dans cette section, on décrit la vision générale du projet ainsi que ses objectifs à destination des futurs utilisateurs et des développeurs.
- la documentation (ce fichier Readme)
- la librairie du composant de texte riche dans `packages/react-dsfr-tiptap`
- des examples d'intégration dans `examples`

Pour ce dépôt :
## Installation

Ce dépôt permet de répertorier les différents éléments essentiels dans un dépôt SIDC :
* ce ReadMe
* des modèles de tickets type pour des ajouts de fonctionnalité, réparation de bug, ajout de documentation, maintenance/montée de version...
* des milestones témoins (ex: backlog, sprint1...)
* des exemples de github Actions CI/CD (lancement de test, build d'images...)
* des exemples de label pour les futurs tickets
### Texte Riche

Pour installer ce package dans votre projet React lancez la commande:

## Installation
```bash
npm i react-dsfr-tiptap
```

(ou installez avec le package manager de votre choix)

Vous devez également avoir installé les dépendances suivantes sur votre projet pour que ce package fonctionne:

- `react`
- `react-dom`
- `@codegouvfr/react-dsfr`
- `tss-react`

### Editeur Markdown

Pour utiliser l'éditeur markdown, installez les dépendances supplémentaires avec la commande:

```bash
npm i tiptap-markdown
```

(ou installez avec le package manager de votre choix)

## Utilisation

### Texte Riche

Une fois installée vous pouvez utilisé le composant `RichTextEditor` de cette manière:

```tsx
import { RichTextEditor } from "react-dsfr-tiptap";

function MyComponent() {
const [content, setContent] = useState(`<h2>Content title</h2>`);
return (
<>
<RichTextEditor content={content} onContentUpdate={setContent} />
<div dangerouslySetInnerHTML={{ __html: content }}></div>
</>
);
}
```

### Editeur Markdown

Utilisez l'éditeur markdown en important le composant `MarkdownEditor` depuis `react-dsfr-tiptap/markdown`

```tsx
import { MarkdownEditor } from "react-dsfr-tiptap/markdown";

function MyComponent() {
const [content, setContent] = useState(`## Markdown title`);
return (
<>
<MarkdownEditor content={content} onContentUpdate={setContent} />
<pre>{content}</pre>
</>
);
}
```

### Utilisation avancée

Vous pouvez également utiliser les composants de plus bas niveau pour construire votre composant de texte riche:

```tsx
import StarterKit from "@tiptap/starter-kit";
import { RichTextEditor } from "react-dsfr-tiptap";

function MyComponent() {
const [content, setContent] = useState(`## Markdown title`);

return (
<RichTextEditor.Provider content={content} extensions={[StarterKit]} onUpdate={({ editor }) => editor.getHTML()}>
<RichTextEditor.Menu first>
<RichTextEditor.Group>
<RichTextEditor.Bold />
</RichTextEditor.Group>
<RichTextEditor.Group>
<CustomControl />
</RichTextEditor.Group>
</RichTextEditor.Menu>
<RichTextEditor.Content />
</RichTextEditor.Provider>
);
}
```

Ils vous faudra fournir alors les extensions et configurer le menu par vous même.

## Ajout d'extensions

### Boutons classiques

Les extensions tiptap suivantes sont d'office prise en charge avec le composant `RichTextEditor`.

Il suffit de les installer pour que les boutons apparaissent dans le menu:

- `@tiptap/extension-color`
- `@tiptap/extension-highlight`
- `@tiptap/extension-subscript`
- `@tiptap/extension-superscript`
- `@tiptap/extension-text-align`
- `@tiptap/extension-text-style`
- `@tiptap/extension-underline`

Ces extensions ne fonctionnent qu'avec le composant `RichTextEditor` et pas le composant `MarkdownEditor`.

### Boutons avec modale

Les extensions suivantes sont également prise en charge mais nécessite une configuration supplémentaire:

La procédure d'installation du projet doit être décrite dans cette section ou dans un fichier complémentaire dont le lien est présent ici.
- `@tiptap/extension-image`
- `@tiptap/extension-link`
- `@tiptap/extension-youtube`

Pour utiliser ces extensions installez les packages supplémentaires suivants:

## Documentation développeurs
```bash
npm i react-hook-form @hookform/resolvers yup validator
```

Lien vers la documentation pour les développeurs, à la fois pour maintenir le projet, le déployer et ajouter de nouvelles fonctionnalités. Schémas UML...
et activez les boutons dans le menu via la props `controlMap`:

```tsx
import { RichTextEditor } from "react-dsfr-tiptap";
import { ControlImage, ControlLink, ControlUnlink, ControlYoutube } from "react-dsfr-tiptap/dialog";

function MyComponent() {
const [content, setContent] = useState(`<h2>Content title</h2>`);
return (
<>
<RichTextEditor
content={content}
controlMap={{ Link: ControlLink, Unlink: ControlUnlink, Image: ControlImage, Youtube: ControlYoutube }}
onContentUpdate={setContent}
/>
<div dangerouslySetInnerHTML={{ __html: content }}></div>
</>
);
}
```

Cela fonctionne de la même manière pour le composant `MarkdownEditor` sauf qu'il ne supporte que les liens et les images (et pas les vidéos).

## Configuration

### Props

Les 2 composants `RichTextEditor` et `MarkdownEditor` fonctionne de la même manière et ont les mêmes props:

| Props | Type | Valeur par défaut | Description |
| ----------------- | ------------------------------------------------------------------------------------- | ------------------- | ----------------------------------------------------------------- |
| `content` | `string` | `""` | Contenu de la zone de texte riche |
| `controlMap` | `Partial<Record<Control, (() => ReactNode) \| LazyExoticComponent<() => ReactNode>>>` | `{}` | Permet de configurer les composants des boutons préconfigurés |
| `controls` | `(Control \| (() => ReactNode) \| LazyExoticComponent<() => ReactNode>)[][]` | `defaultControls` | Permet de configurer les boutons du menu |
| `extensions` | `AnyExtension[]` | `defaultExtensions` | Permet d'ajouter des extensions |
| `menu` | `"top" \| "bottom"` | `"top"` | Position du menu |
| `onContentUpdate` | `(content: string) => void` | | Fonction appelé quand le contenu est mis à jour par l'utilisateur |

Les autres props seront passé au hoos `useEditor` de [la librairie `@tiptap/react`](https://tiptap.dev/docs/editor/getting-started/install/react).

Pour le composant `RichTextEditor`:

- `defaultControls` est égal à:
```ts
[
["Bold", "Italic", "Underline", "Strike", "Subscript", "Superscript", "Code", "Highlight", "Color", "ClearFormatting"],
["H1", "H2", "H3", "H4", "H5", "H6", "Paragraph"],
["BulletList", "OrderedList", "CodeBlock", "Blockquote", "HorizontalRule"],
["AlignLeft", "AlignCenter", "AlignRight", "AlignJustify"],
["Undo", "Redo"],
["Link", "Unlink"],
["Image", "Youtube"],
];
```
- `defaultExtensions` est égal à: `[require("@tiptap/starter-kit")]`

Pour le composant `RichTextEditor`:

- `defaultControls` est égal à:
```ts
[
["Bold", "Italic", "Code", "ClearFormatting"],
["H1", "H2", "H3", "H4", "H5", "H6", "Paragraph"],
["BulletList", "OrderedList", "CodeBlock", "Blockquote", "HorizontalRule"],
["Undo", "Redo"],
["Link", "Unlink"],
["Image"],
];
```
- `defaultExtensions` est égal à: `[require("@tiptap/starter-kit"), require("tiptap-markdown")]`

### Ajout de boutons personnalisés

Vous pouvez développer et ajouter vos propres boutons dans le composant de texte riche.

Exemple de bouton:

```tsx
import { Editor, useEditorState } from "@tiptap/react";
import Button from "@codegouvfr/react-dsfr/Button";
import { useEditor } from "react-dsfr-tiptap";
export default function CustomControl() {
const editor = useEditor();
const editorState = useEditorState({
editor,
selector: ({ editor }: { editor: Editor }) => ({
disabled: !editor?.can().chain().focus().insertContent("[custom]").run(),
}),
});
return (
<Button
disabled={editorState.disabled}
onClick={() => editor?.chain().focus().insertContent("[custom]").run()}
priority="tertiary no outline"
size="small"
>
Insérer du contenu
</Button>
);
}
```

Dans ce cas vous pouvez ajoutez votre bouton personnalisé via la props `controls`:

```tsx
import { RichTextEditor } from "react-dsfr-tiptap";
import CustomControl from "./CustomControl";
function MyComponent() {
const [content, setContent] = useState(`<h2>Content title</h2>`);
return (
<>
<RichTextEditor
content={content}
controls={[
["Bold", "Italic", "Underline", "Strike", "Subscript", "Superscript", "Code", "Highlight", "Color", "ClearFormatting"],
["H1", "H2", "H3", "H4", "H5", "H6", "Paragraph"],
["BulletList", "OrderedList", "CodeBlock", "Blockquote", "HorizontalRule"],
["AlignLeft", "AlignCenter", "AlignRight", "AlignJustify"],
["Undo", "Redo"],
["Link", "Unlink"],
["Image", "Youtube"],
[CustomControl],
]}
onContentUpdate={setContent}
/>
<div dangerouslySetInnerHTML={{ __html: content }}></div>
</>
);
}
```

Dans ce cas il vous faudra fournir la liste complète des contrôles.

### Utilitaire de création de boutons personalisés

Vous pouvez aussi utilisez les utilitaires suivants pour faciliter la création de boutons personalisées:

```tsx
import { createControl } from "react-dsfr-tiptap";
export default createControl({
buttonProps: { children: "Insérer du contenu" },
operation: { name: "insertContent", attributes: "[custom]" },
});
```

Cela créera exactement le même contrôle `CustomControl` que celui du chapitre précédent.

De la même manière il suffira ensuite de l'ajouter à la props `controls` du composant `RichTextEditor`.

Il y a également un utilitaire pour créer un bouton qui ouvre une modale:

```tsx
import { createDialogControl } from "react-dsfr-tiptap";
export default createDialogControl({
buttonProps: { children: "Insérer du contenu" },
DialogContent: CustomDialog, // Le composant de modale
onClick: (editor, ref) => ref.current?.open(),
});
```

Pour un example plus complet regardez le fichier `examples/src/TiptapCustomButtons.tsx`.

## L'arborescence du projet

Exemple d'arborescence de projet :

* `.github/` : dossier contenant les modèles d'issues et github actions ;
* `.vscode/` : dossier contenant une configuration vscode pour le projet;
* `doc/` : dossier contenant des fichiers .md de documentation (ex: install.md) ;
* `tests/`: scripts et explications pour lancer les tests ;
* `README.md` : ce fichier
- `.github/` : dossier contenant les modèles d'issues et github actions.
- `.husky/` : dossier contenant des scripts git hooks.
- `.vscode/` : dossier contenant une configuration vscode pour le projet.
- `doc/` : dossier contenant des fichiers .md de documentation (ex: install.md).
- `examples/` : dossier contenant une application avec des examples d'utilisation.
- `packages/` : dossier contenant le code source de la librarie.
- `README.md` : ce fichier.

## Contacts du projets

Ici on met la liste des personnes qui travaillent sur ce projet et le maintiennent à jour.


|Nom|Prénom|mail|fonction|
|---|---|---|---|
| | | | |
| | | | |
| | | | |
| Nom | Prénom | mail | fonction |
| --- | ------ | ---- | -------- |
| | | | |
| | | | |
| | | | |
3 changes: 2 additions & 1 deletion examples/src/Custom.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ControlImage, ControlLink, ControlUnlink, ControlYoutube } from "react-
import StarterKit from "@tiptap/starter-kit";
import Link from "@tiptap/extension-link";

import { CustomControl1, CustomControl2 } from "./TiptapCustomButtons";
import { CustomControl1, CustomControl2, CustomControl3 } from "./TiptapCustomButtons";

const Custom = () => {
const [content, setContent] = useState(`
Expand All @@ -23,6 +23,7 @@ this is a basic example of <strong>Tiptap</strong>. Sure, there are all kind of
<RichTextEditor.Group>
<CustomControl1 />
<CustomControl2 />
<CustomControl3 />
</RichTextEditor.Group>
<RichTextEditor.Group>
<ControlLink />
Expand Down
4 changes: 2 additions & 2 deletions examples/src/Tiptap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useState } from "react";

import { RichTextEditor } from "react-dsfr-tiptap";
import { ControlImage, ControlLink, ControlUnlink, ControlYoutube } from "react-dsfr-tiptap/dialog";
import { CustomControl1, CustomControl2 } from "./TiptapCustomButtons";
import { CustomControl1, CustomControl2, CustomControl3 } from "./TiptapCustomButtons";

const initialContent = `
<h2>
Expand Down Expand Up @@ -51,7 +51,7 @@ const Tiptap = () => {
["Undo", "Redo"],
["Link", "Unlink"],
["Image", "Youtube"],
[CustomControl1, CustomControl2],
[CustomControl1, CustomControl2, CustomControl3],
]}
onContentUpdate={setContent}
/>
Expand Down
Loading

0 comments on commit ff2b9c8

Please sign in to comment.