Skip to content

Commit d04d1df

Browse files
hejsztynxszydlovskyCopilot
authored
feat(web): EnrichedText selectable, useHtmlNormalizer, ref, onFocus, onBlur (#677)
# Summary Implemented following props: - `selectable` - `useHtmlNormalizer` - native `ref` methods, where only `focus` and `blur` are functional, the rest of them are no-op - `onFocus` and `onBlur` callback props Added `EnrichedTextInstance` to the exported API. Refactored the web example app. ## Compatibility | OS | Implemented | | ------- | :---------: | | iOS | ❌ | | Android | ❌ | | Web | ✅ | ## Checklist - [x] E2E tests are passing - [ ] Required E2E tests have been added (if applicable) --------- Co-authored-by: Mikołaj Szydłowski <9szydlowski9@gmail.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
1 parent 4bc6307 commit d04d1df

27 files changed

Lines changed: 210 additions & 81 deletions
-111 Bytes
Loading
150 Bytes
Loading

.playwright/tests/enrichedTextVisual.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ test.describe('visual: images', () => {
227227
{
228228
name: 'image placeholder inside lists',
229229
snapshot: 'enriched-text-images-placeholder-list.png',
230-
html: '<html><ol><li>List with a broken image <img src="" width="20" height="20" /> inside.</li></ol></html>',
230+
html: '<html><ol><li>List with a broken image <img src="/pw-e2e-broken.png" width="20" height="20" /> inside.</li></ol></html>',
231231
},
232232
];
233233

.playwright/tests/images.spec.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ test.describe('images', () => {
3333
const snapshotName = 'images-placeholder-empty-src.png';
3434
await setEditorHtml(
3535
page,
36-
'<html><p>Hi <img src="" width="40" height="40" /> bye</p></html>'
36+
'<html><p>Hi <img src="/pw-e2e-broken.png" width="40" height="40" /> bye</p></html>'
3737
);
3838

3939
await expect(page.locator('[data-eti-image-placeholder]')).toBeVisible({
@@ -102,22 +102,22 @@ test.describe('images', () => {
102102
{
103103
name: 'paragraph with placeholder image',
104104
snapshot: 'images-paragraph-placeholder.png',
105-
html: '<html><p>Before <img src="" width="40" height="40" /> after</p></html>',
105+
html: '<html><p>Before <img src="/pw-e2e-broken.png" width="40" height="40" /> after</p></html>',
106106
},
107107
{
108108
name: 'blockquote with placeholder image',
109109
snapshot: 'images-blockquote-placeholder.png',
110-
html: '<html><blockquote><p>Before <img src="" width="40" height="40" /> after</p></blockquote></html>',
110+
html: '<html><blockquote><p>Before <img src="/pw-e2e-broken.png" width="40" height="40" /> after</p></blockquote></html>',
111111
},
112112
{
113113
name: 'unordered list item with placeholder image',
114114
snapshot: 'images-ul-placeholder.png',
115-
html: '<html><ul><li><p>Item <img src="" width="40" height="40" /> end</p></li></ul></html>',
115+
html: '<html><ul><li><p>Item <img src="/pw-e2e-broken.png" width="40" height="40" /> end</p></li></ul></html>',
116116
},
117117
{
118118
name: 'ordered list item with placeholder image',
119119
snapshot: 'images-ol-placeholder.png',
120-
html: '<html><ol><li><p>Step <img src="" width="40" height="40" /> done</p></li></ol></html>',
120+
html: '<html><ol><li><p>Step <img src="/pw-e2e-broken.png" width="40" height="40" /> done</p></li></ol></html>',
121121
},
122122
{
123123
name: 'loaded image inside list (routed PNG)',
@@ -127,7 +127,7 @@ test.describe('images', () => {
127127
{
128128
name: 'placeholder image inside checkbox list',
129129
snapshot: 'images-checkbox-list-placeholder.png',
130-
html: '<html><ul data-type="checkbox"><li checked>Before <img src="" width="40" height="40" /> after</li></ul></html>',
130+
html: '<html><ul data-type="checkbox"><li checked>Before <img src="/pw-e2e-broken.png" width="40" height="40" /> after</li></ul></html>',
131131
},
132132
] as const;
133133

@@ -148,7 +148,7 @@ test.describe('images', () => {
148148
page,
149149
}) => {
150150
const expectedHtml =
151-
'<html><p><code><b><i><u><s>Alpha </s></u></i></b></code><img src="" width="48" height="48"/><code><b><i><u><s> Beta</s></u></i></b></code></p></html>';
151+
'<html><p><code><b><i><u><s>Alpha </s></u></i></b></code><img src="/pw-e2e-broken.png" width="48" height="48"/><code><b><i><u><s> Beta</s></u></i></b></code></p></html>';
152152
const toolbarOrder = [
153153
'bold',
154154
'italic',
@@ -159,7 +159,7 @@ test.describe('images', () => {
159159

160160
await setEditorHtml(
161161
page,
162-
'<html><p>Alpha <img src="" width="48" height="48"/> Beta</p></html>'
162+
'<html><p>Alpha <img src="/pw-e2e-broken.png" width="48" height="48"/> Beta</p></html>'
163163
);
164164

165165
await expect(page.locator('.eti-inline-image')).toBeVisible({

.playwright/tests/links.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,13 +172,13 @@ test.describe('test-links setLink table', () => {
172172
},
173173
{
174174
name: 'setLink wraps link text before inline image - keeps the image',
175-
html: '<html><p>abc<img width="80" height="80" src=""></p></html>',
175+
html: '<html><p>abc<img width="80" height="80" src="/pw-e2e-broken.png"></p></html>',
176176
start: '0',
177177
end: '3',
178178
text: 'abc',
179179
url: 'https://example.com',
180180
expectContains:
181-
'<p><a href="https://example.com">abc</a><img src="" width="80" height="80"/></p>',
181+
'<p><a href="https://example.com">abc</a><img src="/pw-e2e-broken.png" width="80" height="80"/></p>',
182182
},
183183
{
184184
name: 'wraps bold italic list item text with link',

.playwright/tests/strictMarks.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,7 @@ test.describe('strict marks', () => {
343343
}) => {
344344
await setEditorHtml(
345345
page,
346-
'<html><p><mention text="@Jane" indicator="@" id="1" type="user">@Jane</mention></p></html>'
346+
'<html><p><mention text="@Jane" indicator="@" id="1">@Jane</mention></p></html>'
347347
);
348348

349349
const editor = editorLocator(page);
@@ -356,7 +356,7 @@ test.describe('strict marks', () => {
356356
const html = await getSerializedHtml(page);
357357
return (
358358
html.includes(
359-
'<mention text="@Jane" indicator="@" id="1" type="user">@Jane</mention>'
359+
'<mention text="@Jane" indicator="@" id="1">@Jane</mention>'
360360
) && !html.includes('@Jane after</mention>')
361361
);
362362
})

apps/example-web/src/App.tsx

Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,9 @@ import {
1414
type OnSubmitEditing,
1515
type OnChangeMentionEvent,
1616
type OnMentionDetected,
17-
EnrichedText,
18-
type OnLinkPressEvent,
19-
type OnMentionPressEvent,
2017
} from 'react-native-enriched-html';
2118
import { WEB_DEFAULT_HTML_STYLE } from './defaultHtmlStyle';
22-
import type { NativeSyntheticEvent, TextStyle } from 'react-native';
19+
import type { NativeSyntheticEvent } from 'react-native';
2320
import { EditorActions } from './components/EditorActions';
2421
import { SetValueModal } from './components/SetValueModal';
2522
import { ImageModal } from './components/ImageModal';
@@ -30,6 +27,7 @@ import { Toolbar } from './components/Toolbar';
3027
import { MentionPopup, type MentionItem } from './components/MentionPopup';
3128
import { useUserMention } from './hooks/useUserMention';
3229
import { useChannelMention } from './hooks/useChannelMention';
30+
import { TextRenderer } from './components/TextRenderer';
3331

3432
const DEFAULT_LINK_STATE: OnLinkDetected = {
3533
text: '',
@@ -173,14 +171,6 @@ function App() {
173171
setSelection(e.nativeEvent);
174172
};
175173

176-
const handleLinkPress = (e: OnLinkPressEvent) => {
177-
console.log('[EnrichedText] link press event', e);
178-
};
179-
180-
const handleMentionPress = (e: OnMentionPressEvent) => {
181-
console.log('[EnrichedText] mention press event', e);
182-
};
183-
184174
const openLinkModal = () => {
185175
setIsLinkModalOpen(true);
186176
};
@@ -288,7 +278,6 @@ function App() {
288278
mentionIndicators={['@', '#']}
289279
htmlStyle={WEB_DEFAULT_HTML_STYLE}
290280
linkRegex={LINK_REGEX}
291-
useHtmlNormalizer
292281
/>
293282
<MentionPopup
294283
variant="user"
@@ -340,17 +329,7 @@ function App() {
340329

341330
{showHtmlOutput && <HtmlOutputPanel html={currentHtml} />}
342331

343-
<div className="container enriched-text-container">
344-
<h1 className="app-title">Enriched Text</h1>
345-
<EnrichedText
346-
style={enrichedTextStyle}
347-
htmlStyle={WEB_DEFAULT_HTML_STYLE}
348-
onLinkPress={handleLinkPress}
349-
onMentionPress={handleMentionPress}
350-
>
351-
{enrichedTextValue}
352-
</EnrichedText>
353-
</div>
332+
<TextRenderer htmlValue={enrichedTextValue} />
354333

355334
{isSetValueModalOpen && (
356335
<SetValueModal
@@ -392,14 +371,4 @@ const enrichedInputStyle: EnrichedInputStyle = {
392371
fontSize: 18,
393372
};
394373

395-
const enrichedTextStyle: TextStyle = {
396-
backgroundColor: 'gainsboro',
397-
width: '100%',
398-
marginVertical: 12,
399-
paddingVertical: 12,
400-
paddingHorizontal: 14,
401-
borderRadius: 8,
402-
fontSize: 18,
403-
};
404-
405374
export default App;
File renamed without changes.

apps/example-web/src/components/EditorActions.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import './EditorActions.css';
1+
import './Actions.css';
22

33
interface EditorActionsProps {
44
showHtmlOutput: boolean;
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import './Actions.css';
2+
3+
interface TextActionsProps {
4+
onFocus: () => void;
5+
onBlur: () => void;
6+
}
7+
8+
export function TextActions({ onFocus, onBlur }: TextActionsProps) {
9+
return (
10+
<div className="btn-row" data-testid="text-actions-row">
11+
<button className="btn" data-testid="text-focus-button" onClick={onFocus}>
12+
Focus
13+
</button>
14+
<button className="btn" data-testid="text-blur-button" onClick={onBlur}>
15+
Blur
16+
</button>
17+
</div>
18+
);
19+
}

0 commit comments

Comments
 (0)