# MarkdownEditor

Der MarkdownEditor ist eine Komponente zur Erstellung und Formatierung von Textinhalten mithilfe von Markdown-Syntax. Er unterstützt User bei der schnellen und konsistenten Textformatierung und stellt eine Vorschauansicht zur Verfügung.

## Overview

# Playground

Verwende `<MarkdownEditor />`, um einen MarkdownEditor darzustellen.

```tsx
import { MarkdownEditor } from "@mittwald/flow-react-components";

<MarkdownEditor
  aria-label="Nachricht"
  placeholder="Schreibe eine Nachricht ..."
/>
```

---

# Disabled

Nutze das Property `isDisabled`, um den MarkdownEditor als disabled anzuzeigen.

```tsx
import { MarkdownEditor } from "@mittwald/flow-react-components";

<MarkdownEditor
  isDisabled
  aria-label="Nachricht"
  placeholder="Schreibe eine Nachricht ..."
/>
```

---

# Character Count

Mit der Property `showCharacterCount` wird automatisch eine
`<FieldDescription />` ergänzt, die die aktuelle Zeichenanzahl und – sofern
angegeben – die maximale Zeichenanzahl anzeigt.

```tsx
import { MarkdownEditor } from "@mittwald/flow-react-components";

<MarkdownEditor
  showCharacterCount
  maxLength={100}
  aria-label="Nachricht"
  placeholder="Schreibe eine Nachricht ..."
/>
```

---

# Resize

## Automatisch

Mit der Property `autoResizeMaxRows` lässt sich eine maximale Höhe definieren,
bis zu der sich der MarkdownEditor automatisch an den Inhalt anpasst.

```tsx
import { MarkdownEditor } from "@mittwald/flow-react-components";

<MarkdownEditor
  rows={1}
  autoResizeMaxRows={5}
  aria-label="Nachricht"
  placeholder="Schreibe eine Nachricht ..."
/>
```

## Manuell

Über die Properties `allowResize`, `allowVerticalResize` oder
`allowHorizontalResize` kann die Größe des MarkdownEditors manuell verändert
werden.

```tsx
import { MarkdownEditor } from "@mittwald/flow-react-components";

<MarkdownEditor
  allowResize
  aria-label="Nachricht"
  placeholder="Schreibe eine Nachricht ..."
/>
```

## Kombiniert

Beide Resize-Varianten lassen sich auch miteinander kombinieren. In diesem Fall
passt sich der MarkdownEditor zunächst automatisch an, bis die Größe einmal
manuell geändert wird. Danach bleibt er in der eingestellten Größe bestehen.

```tsx
import { MarkdownEditor } from "@mittwald/flow-react-components";

<MarkdownEditor
  allowResize
  aria-label="Nachricht"
  placeholder="Schreibe eine Nachricht ..."
  rows={1}
  autoResizeMaxRows={5}
/>
```

---

# Kombiniere mit ...

## React Hook Form

Weitere Details zur Formularlogik und -validierung sind in der Component
[Form (React Hook Form)](/04-components/react-hook-form/form/overview) zu
finden.

```tsx
import {
  Label,
  MarkdownEditor,
  Section,
  ActionGroup,
} from "@mittwald/flow-react-components";
import { useForm } from "react-hook-form";
import {
  Field,
  Form,
  SubmitButton,
} from "@mittwald/flow-react-components/react-hook-form";

export default () => {
  const form = useForm({
    defaultValues: { message: "" },
  });
  return (
    <Section>
      <Form
        form={form}
        onSubmit={(v) => console.log(v.message)}
      >
        <Field
          name="message"
          rules={{
            required: "Bitte gib eine Nachricht ein",
          }}
        >
          <MarkdownEditor placeholder="Schreibe eine Nachricht ...">
            <Label>Nachricht</Label>
          </MarkdownEditor>
        </Field>
        <ActionGroup>
          <SubmitButton color="accent">Senden</SubmitButton>
        </ActionGroup>
      </Form>
    </Section>
  );
}
```

## Chat

```tsx
import {
  Align,
  Avatar,
  Button,
  Chat,
  Content,
  Header,
  Initials,
  Message,
  MessageSeparator,
  MessageThread,
  Text,
  MarkdownEditor,
} from "@mittwald/flow-react-components";

<Chat height={400}>
  <MessageThread>
    <MessageSeparator>Ticket geöffnet</MessageSeparator>
    <Message>
      <Header>
        <Align>
          <Avatar>
            <Initials>Max Mustermann</Initials>
          </Avatar>
          <Text>
            <strong>Max Mustermann</strong>
          </Text>
        </Align>
      </Header>
      <Content>
        <Text>
          Lorem ipsum dolor sit amet consectetur adipisicing
          elit. Cumque eius quam quas vel voluptas, ullam
          aliquid fugit. Voluptate harum accusantium rerum
          ullam modi blanditiis vitae, laborum ea tempore,
          dolore voluptas. Earum pariatur, similique
          corrupti id officia perferendis. Labore,
          similique. Earum, quas in. At dolorem corrupti
          blanditiis nulla deserunt laborum! Corrupti
          delectus aspernatur nihil nulla obcaecati ipsam
          porro sequi rem? Quam.
        </Text>
      </Content>
    </Message>
    <Message type="sender">
      <Header>
        <Align>
          <Avatar>
            <Initials>John Doe</Initials>
          </Avatar>
          <Text>
            <strong>John Doe</strong>
          </Text>
        </Align>
      </Header>
      <Content>
        <Text>
          Lorem ipsum dolor sit amet consectetur adipisicing
          elit. Cumque eius quam quas vel voluptas, ullam
          aliquid fugit. Voluptate harum accusantium rerum
          ullam modi blanditiis vitae, laborum ea tempore,
          dolore voluptas. Earum pariatur, similique
          corrupti id officia perferendis. Labore,
          similique. Earum, quas in.
        </Text>
      </Content>
    </Message>
  </MessageThread>
  <MarkdownEditor aria-label="Nachricht" />
  <Button color="accent">Senden</Button>
</Chat>
```


## Develop

# Properties

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `markdownComponent` | `ComponentType<MarkdownProps>` | - | Allows replacing the markdown preview renderer implementation. Defaults to the internal `Markdown` component. |
| `showCharacterCount` | `boolean` | - | Whether a character count should be displayed inside the field description. |
| `autoResizeMaxRows` | `number` | - | Whether the text area should grow if its content gets longer than its initial height. |
| `allowResize` | `boolean \| "horizontal" \| "vertical"` | - | Allows the user to manually resize the textArea horizontally. |
| `allowHorizontalResize` _(deprecated)_ | `boolean` | - | @deprecated Use `allowResize` instead. |
| `allowVerticalResize` _(deprecated)_ | `boolean` | - | @deprecated Use `allowResize` instead. |
| `id` | `string` | - | The element's unique identifier. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id). |
| `translate` | `"yes" \| "no"` | - | - |
| `className` | `ClassNameOrFunction<TextFieldRenderProps>` | `'react-aria-TextField'` | The CSS [className](https://developer.mozilla.org/en-US/docs/Web/API/Element/className) for the element. A function may be provided to compute the class based on component state. |
| `style` | `StyleOrFunction<TooltipRenderProps>` | - | The inline [style](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style) for the element. A function may be provided to compute the style based on component state. |
| `render` | `DOMRenderFunction<"div", TooltipRenderProps>` | - | Overrides the default DOM element with a custom render function. This allows rendering existing components with built-in styles and behaviors such as router links, animation libraries, and pre-styled components. Requirements: - You must render the expected element type (e.g. if `<button>` is expected, you cannot render an `<a>`). - Only a single root DOM element can be rendered (no fragments). - You must pass through props and ref to the underlying DOM element, merging with your own prop as appropriate. |
| `dir` | `string` | - | - |
| `lang` | `string` | - | - |
| `hidden` | `boolean` | - | - |
| `inert` | `boolean` | - | - |
| `validationBehavior` | `"native" \| "aria"` | `'native'` | Whether to use native HTML form validation to prevent form submission when the value is missing or invalid, or mark the field as required or invalid via ARIA. |
| `isDisabled` | `boolean` | - | Whether the input is disabled. |
| `isReadOnly` | `boolean` | - | Whether the input can be selected but not changed by the user. |
| `isRequired` | `boolean` | - | Whether user input is required on the input before form submission. |
| `isInvalid` | `boolean` | - | Whether the value is invalid. |
| `validate` | `((value: TimeValue) => true \| ValidationError)` | - | A function that returns an error message if a given value is invalid. Validation errors are displayed to the user when the form is submitted if `validationBehavior="native"`. For realtime validation, use the `isInvalid` prop instead. |
| `autoFocus` | `boolean` | - | Whether the element should receive focus on render. |
| `value` | `TimeValue` | - | The current value (controlled). |
| `defaultValue` | `TimeValue` | - | The default value (uncontrolled). |
| `name` | `string` | - | The name of the input element, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefname). |
| `form` | `string` | - | The `<form>` element to associate the input with. The value of this attribute must be the id of a `<form>` in the same document. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input#form). |
| `slot` | `string` | - | A slot name for the component. Slots allow the component to receive props from a parent component. An explicit `null` value indicates that the local props completely override all props received from a parent. |
| `enterKeyHint` | `"enter" \| "done" \| "go" \| "next" \| "previous" \| "search" \| "send"` | - | An enumerated attribute that defines what action label or icon to preset for the enter key on virtual keyboards. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/enterkeyhint). |
| `excludeFromTabOrder` | `boolean` | - | Whether to exclude the element from the sequential tab order. If true, the element will not be focusable via the keyboard by tabbing. This should be avoided except in rare scenarios where an alternative means of accessing the element or its functionality via the keyboard is available. |
| `autoComplete` | `string` | - | Describes the type of autocomplete functionality the input should provide if any. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefautocomplete). |
| `maxLength` | `number` | - | The maximum number of characters supported by the input. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefmaxlength). |
| `minLength` | `number` | - | The minimum number of characters required by the input. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefminlength). |
| `pattern` | `string` | - | Regex pattern that the value of the input must match to be valid. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefpattern). |
| `type` | `"text" \| "search" \| "url" \| "tel" \| "email" \| "password" \| (string & {})` | `'text'` | The type of input to render. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdeftype). |
| `inputMode` | `"text" \| "none" \| "search" \| "url" \| "tel" \| "email" \| "numeric" \| "decimal"` | - | Hints at the type of data that might be entered by the user while editing the element or its contents. See [MDN](https://html.spec.whatwg.org/multipage/interaction.html#input-modalities:-the-inputmode-attribute). |
| `autoCorrect` | `string` | - | An attribute that takes as its value a space-separated string that describes what, if any, type of autocomplete functionality the input should provide. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#autocomplete). |
| `spellCheck` | `string` | - | An enumerated attribute that defines whether the element may be checked for spelling errors. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/spellcheck). |
| `children` | `ReactNode` | - | - |
| `placeholder` | `string` | - | - |
| `rows` | `number` | - | - |
| `wrapWith` | `ReactElement<unknown, string \| JSXElementConstructor<any>>` | - | - |
| `ref` | `Ref<HTMLSpanElement>` | - | Allows getting a ref to the component instance. Once the component unmounts, React will set `ref.current` to `null` (or call the ref with `null` if you passed a callback ref). @see [React Docs](https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom) |
| `key` | `Key` | - | - |
| `headingOffset` | `number` | `0` | Shifts all heading levels by the given offset. |

### Events

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `onClick` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onClickCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onAuxClick` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onAuxClickCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onContextMenu` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onContextMenuCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onDoubleClick` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onDoubleClickCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseDown` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseDownCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseEnter` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseLeave` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseMove` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseMoveCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseOut` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseOutCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseOver` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseOverCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseUp` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onMouseUpCapture` | `MouseEventHandler<HTMLDivElement>` | - | - |
| `onTouchCancel` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onTouchCancelCapture` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onTouchEnd` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onTouchEndCapture` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onTouchMove` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onTouchMoveCapture` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onTouchStart` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onTouchStartCapture` | `TouchEventHandler<HTMLDivElement>` | - | - |
| `onPointerDown` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerDownCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerMove` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerMoveCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerUp` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerUpCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerCancel` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerCancelCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerEnter` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerLeave` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerOver` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerOverCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerOut` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onPointerOutCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onGotPointerCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onGotPointerCaptureCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onLostPointerCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onLostPointerCaptureCapture` | `PointerEventHandler<HTMLDivElement>` | - | - |
| `onScroll` | `UIEventHandler<HTMLDivElement>` | - | - |
| `onScrollCapture` | `UIEventHandler<HTMLDivElement>` | - | - |
| `onWheel` | `WheelEventHandler<HTMLDivElement>` | - | - |
| `onWheelCapture` | `WheelEventHandler<HTMLDivElement>` | - | - |
| `onAnimationStart` | `AnimationEventHandler<HTMLDivElement>` | - | - |
| `onAnimationStartCapture` | `AnimationEventHandler<HTMLDivElement>` | - | - |
| `onAnimationEnd` | `AnimationEventHandler<HTMLDivElement>` | - | - |
| `onAnimationEndCapture` | `AnimationEventHandler<HTMLDivElement>` | - | - |
| `onAnimationIteration` | `AnimationEventHandler<HTMLDivElement>` | - | - |
| `onAnimationIterationCapture` | `AnimationEventHandler<HTMLDivElement>` | - | - |
| `onTransitionCancel` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onTransitionCancelCapture` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onTransitionEnd` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onTransitionEndCapture` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onTransitionRun` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onTransitionRunCapture` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onTransitionStart` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onTransitionStartCapture` | `TransitionEventHandler<HTMLDivElement>` | - | - |
| `onFocus` | `((e: FocusEvent<Element, Element>) => void)` | - | Handler that is called when the element receives focus. |
| `onBlur` | `((e: FocusEvent<Element, Element>) => void)` | - | Handler that is called when the element loses focus. |
| `onFocusChange` | `((isFocused: boolean) => void)` | - | Handler that is called when the element's focus status changes. |
| `onKeyDown` | `((e: KeyboardEvent) => void)` | - | Handler that is called when a key is pressed. |
| `onKeyUp` | `((e: KeyboardEvent) => void)` | - | Handler that is called when a key is released. |
| `onChange` | `((value: TimeValue) => void)` | - | Handler that is called when the value changes. |
| `onCopy` | `ClipboardEventHandler<HTMLInputElement>` | - | Handler that is called when the user copies text. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/oncopy). |
| `onCut` | `ClipboardEventHandler<HTMLInputElement>` | - | Handler that is called when the user cuts text. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/oncut). |
| `onPaste` | `ClipboardEventHandler<HTMLInputElement>` | - | Handler that is called when the user pastes text. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/onpaste). |
| `onCompositionStart` | `CompositionEventHandler<HTMLInputElement>` | - | Handler that is called when a text composition system starts a new text composition session. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Element/compositionstart_event). |
| `onCompositionEnd` | `CompositionEventHandler<HTMLInputElement>` | - | Handler that is called when a text composition system completes or cancels the current text composition session. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Element/compositionend_event). |
| `onCompositionUpdate` | `CompositionEventHandler<HTMLInputElement>` | - | Handler that is called when a new character is received in the current text composition session. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Element/compositionupdate_event). |
| `onSelect` | `ReactEventHandler<HTMLInputElement>` | - | Handler that is called when text in the input is selected. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Element/select_event). |
| `onBeforeInput` | `FormEventHandler<HTMLInputElement>` | - | Handler that is called when the input value is about to be modified. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/beforeinput_event). |
| `onInput` | `FormEventHandler<HTMLInputElement>` | - | Handler that is called when the input value is modified. See [MDN](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event). |

### Accessibility

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| `aria-label` | `string` | - | Defines a string value that labels the current element. |
| `aria-labelledby` | `string` | - | Identifies the element (or elements) that labels the current element. |
| `aria-describedby` | `string` | - | Identifies the element (or elements) that describes the object. |
| `aria-details` | `string` | - | Identifies the element (or elements) that provide a detailed, extended description for the object. |
| `aria-activedescendant` | `string` | - | Identifies the currently active element when DOM focus is on a composite widget, textbox, group, or application. |
| `aria-autocomplete` | `"list" \| "none" \| "inline" \| "both"` | - | Indicates whether inputting text could trigger display of one or more predictions of the user's intended value for an input and specifies how predictions would be presented if they are made. |
| `aria-haspopup` | `boolean \| "false" \| "true" \| "menu" \| "listbox" \| "tree" \| "grid" \| "dialog"` | - | Indicates the availability and type of interactive popup element, such as menu or dialog, that can be triggered by an element. |
| `aria-controls` | `string` | - | Identifies the element (or elements) whose contents or presence are controlled by the current element. |
| `aria-errormessage` | `string` | - | Identifies the element that provides an error message for the object. |
| `aria-hidden` | `Booleanish` | - | Indicates whether the element is exposed to an accessibility API. @see aria-disabled. |


## Guidelines

# Grundlagen

## Best practices

Achte bei der Verwendung eines MarkdownEditors darauf, dass ...

- die Höhe über das Property `rows` so gewählt ist, dass sie der erwarteten
  Textmenge des Users entspricht.
- falls notwendig eine sinnvolle Zeichenbegrenzung definiert ist.
- das [Label](/04-components/content/label/overview) prägnant und leicht
  verständlich ist.
- die FieldDescription genutzt wird, um Beispiele, Formatierungshinweise oder
  Kontext bereitzustellen.
- [Fehlermeldungen](/02-foundations/03-content-guidelines/03-fehlermeldungen)
  klar, hilfreich und lösungsorientiert formuliert sind.

## Verwendung

Verwende einen MarkdownEditor, um Usern die Möglichkeit zu geben, Texte wie
Dokumentationen, Kommentare oder Beschreibungen mithilfe von Markdown-Syntax zu
formatieren.

