Skip to content

Commit 0cce5aa

Browse files
hejsztynxCopilotkacperzolkiewskiszydlovskyexploIF
authored
docs: core funtionalities section (#715)
# Summary The `Core functionalities` section in the docs - Styling the input - Rendering rich text - Handling events - Web support --------- Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> Co-authored-by: Kacper Żółkiewski <74975508+kacperzolkiewski@users.noreply.github.com> Co-authored-by: Mikołaj Szydłowski <9szydlowski9@gmail.com> Co-authored-by: Igor Furgała <74370735+exploIF@users.noreply.github.com>
1 parent 9b1356e commit 0cce5aa

15 files changed

Lines changed: 842 additions & 29 deletions

docs/docs/core-functionalities/handling-events.md

Lines changed: 0 additions & 7 deletions
This file was deleted.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
sidebar_position: 3
3+
---
4+
5+
# Handling input events
6+
7+
Since the input is [uncontrolled](/fundamentals/core-concepts#the-input-is-uncontrolled),
8+
events are how you observe it. You change content by calling ref methods; you
9+
react to changes by listening to the callbacks below.
10+
11+
Full payload shapes of the available callbacks can be found in the `EnrichedTextInput` reference.
12+
13+
:::note
14+
15+
This page covers `EnrichedTextInput` events. The read-only
16+
[`EnrichedText`](/core-functionalities/rendering-rich-text) component only
17+
exposes `onLinkPress` and `onMentionPress` callbacks.
18+
19+
:::
20+
21+
## Content
22+
23+
- **`onChangeText`** - plain-text content changed.
24+
- **`onChangeHtml`** - the HTML changed.
25+
26+
:::tip
27+
28+
The `onChangeHtml` callback has to parse the content into HTML on every keystroke.
29+
This is a heavy computational operation that might slow down your app's performance. Consider using the `getHTML()` ref method instead if it meets your requirements.
30+
31+
:::
32+
33+
## Selection and style state
34+
35+
- **`onChangeSelection`** - the cursor moved or the selection changed. Gives you
36+
`start`, `end`, and the selected `text`. Useful for range-based methods like
37+
[`setLink`](/rich-text-formatting/links).
38+
- **`onChangeState`** - the active styles at the cursor changed. This is the
39+
event that drives a toolbar by using reported `isActive`, `isBlocking`, and
40+
`isConflicting`, plus the current `alignment`. See the
41+
[style state model](/fundamentals/core-concepts#the-style-state-model).
42+
43+
## Focus
44+
45+
- **`onFocus`** / **`onBlur`** - the input gained or lost focus.
46+
47+
## Mentions
48+
49+
- **`onStartMention`** - a mention started being edited.
50+
- **`onChangeMention`** - the query after the indicator changed.
51+
- **`onEndMention`** - editing a mention stopped.
52+
- **`onMentionDetected`** - the cursor entered or left a mention.
53+
54+
## Links
55+
56+
- **`onLinkDetected`** - the cursor entered or left a link.
57+
58+
## Images
59+
60+
- **`onPasteImages`** - the user pasted one or more images; hands you each
61+
image's data so you can upload and insert them with
62+
[`setImage`](/rich-text-formatting/inline-images).
63+
64+
## Keyboard and submission
65+
66+
- **`onKeyPress`** - a key was pressed.
67+
- **`onSubmitEditing`** - the user pressed return/enter key. Fired when `submitBehavior` is set to either `submit` or `blurAndSubmit`.

docs/docs/core-functionalities/rendering-rich-text.md

Lines changed: 0 additions & 7 deletions
This file was deleted.
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
---
2+
sidebar_position: 2
3+
---
4+
5+
import InteractiveExample from '@site/src/components/InteractiveExample';
6+
import RenderingEditor from '@site/src/examples/RenderingEditor';
7+
import RenderingEditorSrc from '!!raw-loader!@site/src/examples/RenderingEditor';
8+
9+
# Rendering rich text
10+
11+
`EnrichedTextInput` is for editing. To _display_ rich text without an editor -
12+
a chat message, a comment, an article - use its read-only counterpart,
13+
**`EnrichedText`**.
14+
15+
Both components speak the same [HTML format](/fundamentals/html-format-and-supported-tags),
16+
so the typical flow is: edit in `EnrichedTextInput`, persist the
17+
`getHTML` output, and later feed that
18+
string to `EnrichedText`.
19+
20+
## Passing content
21+
22+
`EnrichedText` takes the HTML string as its `children`:
23+
24+
```tsx
25+
import { EnrichedText } from 'react-native-enriched-html';
26+
27+
<EnrichedText>{'<p>Hello <b>world</b></p>'}</EnrichedText>;
28+
```
29+
30+
## Styling
31+
32+
Styling mirrors the input. `style` controls the container and base typography,
33+
and `htmlStyle` controls per-element appearance. `EnrichedText` extends
34+
`htmlStyle` with **press states** for interactive elements, since links and
35+
mentions are pressable here:
36+
37+
```tsx
38+
<EnrichedText
39+
style={{ fontSize: 16, color: '#232736' }}
40+
htmlStyle={{
41+
a: { pressColor: '#1e40af' },
42+
mention: { pressColor: '#16a34a', pressBackgroundColor: '#dcfce7' },
43+
}}>
44+
{html}
45+
</EnrichedText>
46+
```
47+
48+
The added `pressColor` / `pressBackgroundColor` fields on `a` and `mention` are
49+
the only shape difference from the input's `htmlStyle`. See the
50+
[`EnrichedText`](/api-reference/enriched-text) reference for the full type.
51+
52+
## Notable props
53+
54+
- **`selectable`** - allow the user to select and copy the rendered text.
55+
Defaults to `false`.
56+
- **`onLinkPress` / `onMentionPress`** - fire when a link or mention is pressed.
57+
- **`numberOfLines` / `ellipsizeMode`** - truncate long content to a fixed
58+
number of lines with an ellipsis.
59+
- **`useHtmlNormalizer`** - normalize external or messy HTML into the library's canonical
60+
tag subset before rendering. Defaults to `true`. See
61+
[Normalization](/fundamentals/core-concepts#normalization).
62+
- **`allowFontScaling`** - whether to respect the system's accessibility font scaling settings.
63+
64+
:::note
65+
66+
On web, the default behavior of the pressed `<a>` tag is suppressed. To navigate to the link's URL, you need to properly handle the `onLinkPress` event.
67+
68+
:::
69+
70+
## Try it out
71+
72+
Format some text in the editor, then press **Render** - the current HTML is read
73+
with `getHTML()` and handed to an `EnrichedText` below.
74+
75+
<InteractiveExample src={RenderingEditorSrc} component={RenderingEditor} />
76+
77+
:::caution
78+
79+
On iOS and Android, `EnrichedText` does not sanitize HTML for you. Sanitize anything you render that
80+
came from users or other untrusted sources. To know more about the web's built-in sanitization, visit [Web support](/core-functionalities/web-support#sanitization).
81+
82+
:::

docs/docs/core-functionalities/styling-the-input.md

Lines changed: 0 additions & 7 deletions
This file was deleted.
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
---
2+
sidebar_position: 1
3+
---
4+
5+
# Styling the input
6+
7+
`EnrichedTextInput` is styled through two separate props. Together they cover
8+
everything from the container's dimensions down to the color of a bullet point.
9+
10+
- **`style`** - the container's layout behavior and its base typography (`fontSize`, `color`, `fontFamily`, …). It accepts a subset of React Native's `TextStyle`, described by
11+
`EnrichedInputStyle`.
12+
- **`htmlStyle`** - the appearance of individual rich text elements: heading
13+
sizes, blockquote borders, code colors, list markers, mention colors, and so
14+
on.
15+
- **`placeholderTextColor`** - the color of the placeholder text.
16+
- **`selectionColor`** - the color of the text selection highlight.
17+
- **`cursorColor`** - the color of the text cursor.
18+
19+
:::note
20+
21+
`cursorColor` is not supported on iOS. For more platform differences, see [Compatibility](/misc/compatibility).
22+
23+
:::
24+
25+
Here's an interactive live example - edit the `style` and `htmlStyle` values below and the preview updates live.
26+
You can also check the full API reference for `htmlStyle` and `style`, come back and experiment around here.
27+
28+
```jsx live
29+
function StylingExample() {
30+
return (
31+
<EnrichedTextInput
32+
defaultValue="<h1>Heading</h1><ul><li>list with <code>inline code</code></li></ul><blockquote>Blockquote</blockquote><codeblock>codeblock</codeblock>"
33+
style={{
34+
fontSize: 16,
35+
color: '#232736',
36+
padding: 12,
37+
borderRadius: 12,
38+
backgroundColor: '#eef0ff',
39+
}}
40+
htmlStyle={{
41+
h1: { fontSize: 28, bold: true },
42+
ul: { bulletColor: 'cyan', bulletSize: 8 },
43+
code: { color: 'red', backgroundColor: 'yellow' },
44+
blockquote: { borderColor: '#57b495', borderWidth: 3 },
45+
codeblock: { color: 'aquamarine', backgroundColor: '#67c4a5'}
46+
}}
47+
/>
48+
);
49+
}
50+
```
51+
52+
## `style`
53+
54+
`style` accepts a subset of React Native's `TextStyle` - layout, appearance,
55+
and base typography - described by `EnrichedInputStyle`. Most of these map directly
56+
to their React Native `TextStyle` counterparts. Some are platform-limited
57+
(e.g. `shadowColor` is iOS-only, `elevation` is Android-only) - see the
58+
`EnrichedTextInput` reference for the full property list.
59+
60+
## `htmlStyle`
61+
62+
`htmlStyle` maps each supported element to a small config object. Anything you
63+
omit falls back to the built-in default. The available keys are:
64+
65+
| Key | Styles | Notable options |
66+
| ------------ | -------------- | ----------------------------------------------------------- |
67+
| `h1``h6` | Headings | `fontSize`, `bold` |
68+
| `blockquote` | Blockquote | `borderColor`, `borderWidth`, `gapWidth`, `color` |
69+
| `codeblock` | Code block | `color`, `backgroundColor`, `borderRadius` |
70+
| `code` | Inline code | `color`, `backgroundColor` |
71+
| `a` | Links | `color`, `textDecorationLine` |
72+
| `mention` | Mentions | `color`, `backgroundColor`, `textDecorationLine` |
73+
| `ol` | Ordered list | `markerColor`, `markerFontWeight`, `marginLeft`, `gapWidth` |
74+
| `ul` | Unordered list | `bulletColor`, `bulletSize`, `marginLeft`, `gapWidth` |
75+
| `ulCheckbox` | Checkbox list | `boxColor`, `boxSize`, `marginLeft`, `gapWidth` |
76+
77+
The full list of properties, defaults, and platform notes lives in the
78+
`EnrichedTextInput` reference.
79+
80+
### Styling mentions per indicator
81+
82+
`mention` accepts either a single config applied to every mention, or a record
83+
keyed by [indicator](/rich-text-formatting/mentions) so each mention type gets
84+
its own look:
85+
86+
```tsx
87+
htmlStyle={{
88+
mention: {
89+
'@': { color: '#2563eb', backgroundColor: '#dbeafe' },
90+
'#': { color: '#16a34a', backgroundColor: '#dcfce7' },
91+
},
92+
}}
93+
```
94+
95+
:::tip
96+
97+
You can also create a default `mention` style config, by using the `'default'` key.
98+
99+
```tsx
100+
htmlStyle={{
101+
mention: {
102+
'default': { color: '#2563eb', backgroundColor: '#dbeafe' },
103+
'#': { color: '#16a34a', backgroundColor: '#dcfce7' },
104+
},
105+
}}
106+
```
107+
108+
This way you can create a style for any mention indicator to fallback if it doesn't have one fully defined.
109+
110+
:::

docs/docs/core-functionalities/web-support.md

Lines changed: 88 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,91 @@ sidebar_position: 4
44

55
# Web support
66

7-
<!-- TODO: write content for this page -->
7+
Both `EnrichedTextInput` and `EnrichedText` run on the web. On native the editor
8+
is backed by the platform's text engine; on the web it is built on
9+
[Tiptap](https://tiptap.dev/). That implementation
10+
detail stays behind the same public API.
11+
12+
## One API across platforms
13+
14+
The web build exposes the same core API as native - **props, ref methods, and events** -
15+
with one web-only addition - `sanitizationConfig` prop.
16+
Events keep their native shape too - they arrive as
17+
`NativeSyntheticEvent`, read off `e.nativeEvent`, so
18+
[event-handling](/core-functionalities/handling-input-events) code is portable as-is:
19+
20+
```tsx
21+
<EnrichedTextInput
22+
onChangeHtml={e => setHtml(e.nativeEvent.value)}
23+
onChangeState={e => setState(e.nativeEvent)}
24+
/>
25+
```
26+
27+
The interactive examples throughout these docs are the web build running live.
28+
29+
## Keyboard shortcuts
30+
31+
The web editor ships desktop-style formatting shortcuts out of the box, along
32+
with native browser **undo/redo**.
33+
34+
| Action | macOS | Windows / Linux |
35+
| ------------------- | -------------- | --------------------------- |
36+
| Bold | `⌘B` | `Ctrl+B` |
37+
| Italic | `⌘I` | `Ctrl+I` |
38+
| Underline | `⌘U` | `Ctrl+U` |
39+
| Strikethrough | `⌘⇧X` | `Ctrl+Shift+X` |
40+
| Inline code | `⌘⇧C` | `Ctrl+Shift+C` |
41+
| Code block | `⌘⌥⇧C` | `Ctrl+Alt+Shift+C` |
42+
| Normal paragraph | `⌘⌥0` | `Ctrl+Alt+0` |
43+
| Heading 1–6 | `⌘⌥1``⌘⌥6` | `Ctrl+Alt+1``Ctrl+Alt+6` |
44+
| Numbered list | `⌘⇧7` | `Ctrl+Shift+7` |
45+
| Unordered list | `⌘⇧8` | `Ctrl+Shift+8` |
46+
| Checkbox list | `⌘⇧9` | `Ctrl+Shift+9` |
47+
| Paste as plain text | `⌘⇧V` | `Ctrl+Shift+V` |
48+
| Undo | `⌘Z` | `Ctrl+Z` |
49+
| Redo | `⌘⇧Z` | `Ctrl+Shift+Z` |
50+
| Select all | `⌘A` | `Ctrl+A` |
51+
52+
## Platform differences
53+
54+
A few native-only features have no web equivalent and are ignored there:
55+
56+
- **`contextMenuItems`** - the native editing menu isn't available; use your own
57+
UI instead.
58+
- **`returnKeyLabel`** - can't be set inside a browser. `returnKeyType` maps to
59+
the browser's [`enterkeyhint`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/enterkeyhint).
60+
- **RN layout ref methods** - `measure`, `measureInWindow`, `measureLayout`, and
61+
`setNativeProps` are no-ops.
62+
63+
The [`EnrichedTextInput`](/api-reference/enriched-text-input) and
64+
[`EnrichedText`](/api-reference/enriched-text) references note per-prop platform
65+
support.
66+
67+
:::note
68+
69+
On web, `onPasteImages` gives each image a `blob:` URL. If you hold onto those
70+
URIs, call `URL.revokeObjectURL(uri)` once you're done with them (e.g. after an
71+
upload) so the browser can release the memory.
72+
73+
:::
74+
75+
## Sanitization
76+
77+
Unlike the native platforms, the web build sanitizes HTML for you. It runs
78+
[DOMPurify](https://github.com/cure53/DOMPurify) at **every entrypoint** - the
79+
`children` of `EnrichedText`, `defaultValue`, `setValue` and content pasted into `EnrichedTextInput`. Sanitization is also run on the input component's **output** - `getHTML()`.
80+
This ensures untrusted markup can't inject scripts or unsafe attributes into the DOM.
81+
82+
:::note
83+
84+
Sanitization can be customized with the `sanitizationConfig` prop. It allows you to set a `linkRegex` that
85+
will define, which URI-containing attributes will actually be preserved by the sanitizer.
86+
87+
:::
88+
89+
## Server-side rendering
90+
91+
The library does **not** support SSR yet. Normalization and sanitization both need a
92+
DOM to work against, which isn't available during server rendering. In an SSR
93+
framework (Next.js, Remix, …), make sure both `EnrichedTextInput` and
94+
`EnrichedText` render **client-side only**.

docs/docusaurus.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ const config = {
9696
mermaid: true,
9797
},
9898

99-
themes: ['@docusaurus/theme-mermaid'],
99+
themes: ['@docusaurus/theme-mermaid', '@docusaurus/theme-live-codeblock'],
100100

101101
i18n: {
102102
defaultLocale: 'en',

docs/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"@docusaurus/preset-classic": "3.9.2",
2222
"@docusaurus/theme-classic": "3.9.2",
2323
"@docusaurus/theme-common": "3.9.2",
24+
"@docusaurus/theme-live-codeblock": "3.9.2",
2425
"@docusaurus/theme-mermaid": "3.9.2",
2526
"@docusaurus/theme-search-algolia": "3.9.2",
2627
"@emotion/react": "^11.14.0",

0 commit comments

Comments
 (0)