@toptal/picasso-rich-text-editor 100.0.6 → 100.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-package/src/RichTextEditorEmojiPicker/RichTextEditorEmojiPicker.d.ts.map +1 -1
- package/dist-package/src/RichTextEditorEmojiPicker/RichTextEditorEmojiPicker.js +10 -7
- package/dist-package/src/RichTextEditorEmojiPicker/RichTextEditorEmojiPicker.js.map +1 -1
- package/package.json +8 -8
- package/src/RichTextEditorEmojiPicker/RichTextEditorEmojiPicker.test.tsx +38 -0
- package/src/RichTextEditorEmojiPicker/RichTextEditorEmojiPicker.tsx +7 -11
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RichTextEditorEmojiPicker.d.ts","sourceRoot":"","sources":["../../../src/RichTextEditorEmojiPicker/RichTextEditorEmojiPicker.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAErE,UAAU,KAAK;IACb,YAAY,CAAC,EAAE,gBAAgB,EAAE,CAAA;IACjC,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;
|
|
1
|
+
{"version":3,"file":"RichTextEditorEmojiPicker.d.ts","sourceRoot":"","sources":["../../../src/RichTextEditorEmojiPicker/RichTextEditorEmojiPicker.tsx"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAErE,UAAU,KAAK;IACb,YAAY,CAAC,EAAE,gBAAgB,EAAE,CAAA;IACjC,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IACrC,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAaD,eAAO,MAAM,yBAAyB,+CAInC,KAAK,gBA0DP,CAAA"}
|
|
@@ -2,15 +2,10 @@
|
|
|
2
2
|
import React, { useEffect } from 'react';
|
|
3
3
|
import data from '@emoji-mart/data';
|
|
4
4
|
import Picker from '@emoji-mart/react';
|
|
5
|
-
import cx from 'classnames';
|
|
6
5
|
import { Container } from '@toptal/picasso-container';
|
|
6
|
+
import { twMerge } from '@toptal/picasso-tailwind-merge';
|
|
7
7
|
import RichTextEditorButton from '../RichTextEditorButton';
|
|
8
8
|
const TRIGGER_EMOJI_PICKER_ID = 'trigger-emoji-picker';
|
|
9
|
-
const classes = {
|
|
10
|
-
emojiPicker: 'absolute top-[34px] left-0 z-10 opacity-0 pointer-events-none',
|
|
11
|
-
activeOpacity: 'opacity-100',
|
|
12
|
-
activePointers: '[pointer-events:all]',
|
|
13
|
-
};
|
|
14
9
|
const handleEmojiPickerEscBehaviour = (event, setShowEmojiPicker) => {
|
|
15
10
|
if (event.key === 'Escape') {
|
|
16
11
|
setShowEmojiPicker(false);
|
|
@@ -43,7 +38,15 @@ export const RichTextEditorEmojiPicker = ({ customEmojis, onInsertEmoji, disable
|
|
|
43
38
|
}, [showEmojiPicker, setShowEmojiPicker]);
|
|
44
39
|
return (React.createElement(Container, { style: { position: 'relative' } },
|
|
45
40
|
React.createElement(RichTextEditorButton, { onClick: handleEmojiPickerClick, icon: React.createElement(Container, { style: { pointerEvents: 'none' } }, "\uD83D\uDE42"), id: TRIGGER_EMOJI_PICKER_ID, disabled: disabled }),
|
|
46
|
-
React.createElement(Container
|
|
41
|
+
React.createElement(Container
|
|
42
|
+
// twMerge drops the hidden-state classes when open; leaving
|
|
43
|
+
// `pointer-events-none` in place would let stylesheet order decide,
|
|
44
|
+
// and it wins, so clicks fall through the open picker to the editor
|
|
45
|
+
, {
|
|
46
|
+
// twMerge drops the hidden-state classes when open; leaving
|
|
47
|
+
// `pointer-events-none` in place would let stylesheet order decide,
|
|
48
|
+
// and it wins, so clicks fall through the open picker to the editor
|
|
49
|
+
className: twMerge('absolute top-[34px] left-0 z-10 opacity-0 pointer-events-none', showEmojiPicker && 'opacity-100 pointer-events-auto') },
|
|
47
50
|
React.createElement(Picker, { data: data, custom: customEmojis, onEmojiSelect: handleEmojiInsert, onClickOutside: showEmojiPicker && closePicker }))));
|
|
48
51
|
};
|
|
49
52
|
//# sourceMappingURL=RichTextEditorEmojiPicker.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RichTextEditorEmojiPicker.js","sourceRoot":"","sources":["../../../src/RichTextEditorEmojiPicker/RichTextEditorEmojiPicker.tsx"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACxC,OAAO,IAAI,MAAM,kBAAkB,CAAA;AACnC,OAAO,MAAM,MAAM,mBAAmB,CAAA;AACtC,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"RichTextEditorEmojiPicker.js","sourceRoot":"","sources":["../../../src/RichTextEditorEmojiPicker/RichTextEditorEmojiPicker.tsx"],"names":[],"mappings":"AAAA,sDAAsD;AACtD,OAAO,KAAK,EAAE,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACxC,OAAO,IAAI,MAAM,kBAAkB,CAAA;AACnC,OAAO,MAAM,MAAM,mBAAmB,CAAA;AACtC,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAA;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAExD,OAAO,oBAAoB,MAAM,yBAAyB,CAAA;AAS1D,MAAM,uBAAuB,GAAG,sBAAsB,CAAA;AAEtD,MAAM,6BAA6B,GAAG,CACpC,KAAoB,EACpB,kBAAiE,EACjE,EAAE;IACF,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC3B,kBAAkB,CAAC,KAAK,CAAC,CAAA;IAC3B,CAAC;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,EACxC,YAAY,EACZ,aAAa,EACb,QAAQ,GACF,EAAE,EAAE;IACV,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAEnE,MAAM,sBAAsB,GAAG,GAAG,EAAE;QAClC,kBAAkB,CAAC,CAAC,eAAe,CAAC,CAAA;IACtC,CAAC,CAAA;IAED,MAAM,WAAW,GAAG,GAAG,EAAE;QACvB,kBAAkB,CAAC,KAAK,CAAC,CAAA;IAC3B,CAAC,CAAA;IAED,MAAM,iBAAiB,GAAG,CAAC,KAAY,EAAE,EAAE;QACzC,aAAa,CAAC,KAAK,CAAC,CAAA;QACpB,kBAAkB,CAAC,KAAK,CAAC,CAAA;IAC3B,CAAC,CAAA;IAED,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,OAAM;QACR,CAAC;QAED,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE;YAC9C,6BAA6B,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAA;QAC1D,CAAC,CAAC,CAAA;QAEF,OAAO,GAAG,EAAE;YACV,QAAQ,CAAC,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE;gBACjD,6BAA6B,CAAC,KAAK,EAAE,kBAAkB,CAAC,CAAA;YAC1D,CAAC,CAAC,CAAA;QACJ,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,eAAe,EAAE,kBAAkB,CAAC,CAAC,CAAA;IAEzC,OAAO,CACL,oBAAC,SAAS,IAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,UAAU,EAAE;QACxC,oBAAC,oBAAoB,IACnB,OAAO,EAAE,sBAAsB,EAC/B,IAAI,EAAE,oBAAC,SAAS,IAAC,KAAK,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,mBAAgB,EACjE,EAAE,EAAE,uBAAuB,EAC3B,QAAQ,EAAE,QAAQ,GAClB;QACF,oBAAC,SAAS;QACR,4DAA4D;QAC5D,oEAAoE;QACpE,oEAAoE;;YAFpE,4DAA4D;YAC5D,oEAAoE;YACpE,oEAAoE;YACpE,SAAS,EAAE,OAAO,CAChB,+DAA+D,EAC/D,eAAe,IAAI,iCAAiC,CACrD;YAED,oBAAC,MAAM,IACL,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,YAAY,EACpB,aAAa,EAAE,iBAAiB,EAChC,cAAc,EAAE,eAAe,IAAI,WAAW,GAC9C,CACQ,CACF,CACb,CAAA;AACH,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toptal/picasso-rich-text-editor",
|
|
3
|
-
"version": "100.0.
|
|
3
|
+
"version": "100.0.7",
|
|
4
4
|
"description": "Picasso rich text editor",
|
|
5
5
|
"author": "Toptal",
|
|
6
6
|
"homepage": "https://github.com/toptal/picasso/tree/master/packages/picasso-rich-text-editor#readme",
|
|
@@ -28,8 +28,8 @@
|
|
|
28
28
|
"react-dom": ">=17.0.0 < 19.0.0",
|
|
29
29
|
"typescript": "^5.5.0",
|
|
30
30
|
"@toptal/picasso-shared": "^100.1.0",
|
|
31
|
-
"@toptal/picasso-tailwind
|
|
32
|
-
"@toptal/picasso-tailwind": "^100.0.0"
|
|
31
|
+
"@toptal/picasso-tailwind": "^100.0.0",
|
|
32
|
+
"@toptal/picasso-tailwind-merge": "^100.0.0"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@emoji-mart/data": "^1.2.1",
|
|
@@ -45,17 +45,17 @@
|
|
|
45
45
|
"hast-util-to-html": "^7.1.3",
|
|
46
46
|
"lexical": "0.11.3",
|
|
47
47
|
"@toptal/picasso-container": "100.0.1",
|
|
48
|
-
"@toptal/picasso-button": "100.0.2",
|
|
49
48
|
"@toptal/picasso-icons": "100.0.1",
|
|
50
|
-
"@toptal/picasso-
|
|
49
|
+
"@toptal/picasso-button": "100.0.2",
|
|
51
50
|
"@toptal/picasso-image": "100.0.1",
|
|
51
|
+
"@toptal/picasso-file-input": "100.0.3",
|
|
52
52
|
"@toptal/picasso-outlined-input": "100.0.2",
|
|
53
53
|
"@toptal/picasso-list": "100.0.1",
|
|
54
54
|
"@toptal/picasso-link": "100.0.1",
|
|
55
55
|
"@toptal/picasso-select": "100.0.3",
|
|
56
|
-
"@toptal/picasso-input-adornment": "100.0.1",
|
|
57
56
|
"@toptal/picasso-typography": "100.0.1",
|
|
58
57
|
"@toptal/picasso-modal": "100.1.2",
|
|
58
|
+
"@toptal/picasso-input-adornment": "100.0.1",
|
|
59
59
|
"@toptal/picasso-form": "100.0.2",
|
|
60
60
|
"@toptal/picasso-input": "100.0.2",
|
|
61
61
|
"@toptal/picasso-utils": "100.0.1"
|
|
@@ -65,8 +65,8 @@
|
|
|
65
65
|
"jsdom": "^26.1.0",
|
|
66
66
|
"@testing-library/react-hooks": "^8.0.1",
|
|
67
67
|
"@types/classnames": "^2.3.1",
|
|
68
|
-
"@toptal/picasso-
|
|
69
|
-
"@toptal/picasso-
|
|
68
|
+
"@toptal/picasso-tailwind-merge": "100.0.0",
|
|
69
|
+
"@toptal/picasso-test-utils": "100.1.0"
|
|
70
70
|
},
|
|
71
71
|
"sideEffects": false,
|
|
72
72
|
"exports": {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { fireEvent, render, screen } from '@toptal/picasso-test-utils'
|
|
3
|
+
|
|
4
|
+
import { RichTextEditorEmojiPicker } from './RichTextEditorEmojiPicker'
|
|
5
|
+
|
|
6
|
+
const renderEmojiPicker = () =>
|
|
7
|
+
render(<RichTextEditorEmojiPicker onInsertEmoji={jest.fn()} />)
|
|
8
|
+
|
|
9
|
+
// The wrapper that shows and hides the picker sits two levels above the
|
|
10
|
+
// emoji-mart element: wrapper > EmojiMartPicker's div > em-emoji-picker
|
|
11
|
+
const getPickerWrapper = (container: HTMLElement) =>
|
|
12
|
+
container.querySelector('em-emoji-picker')?.parentElement
|
|
13
|
+
?.parentElement as HTMLElement
|
|
14
|
+
|
|
15
|
+
describe('RichTextEditorEmojiPicker', () => {
|
|
16
|
+
it('keeps the picker hidden and click-through until opened', () => {
|
|
17
|
+
const { container } = renderEmojiPicker()
|
|
18
|
+
|
|
19
|
+
const wrapper = getPickerWrapper(container)
|
|
20
|
+
|
|
21
|
+
expect(wrapper).toHaveClass('opacity-0', 'pointer-events-none')
|
|
22
|
+
expect(wrapper).not.toHaveClass('pointer-events-auto')
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('opens the picker with pointer events on, so emoji clicks reach it', () => {
|
|
26
|
+
const { container } = renderEmojiPicker()
|
|
27
|
+
|
|
28
|
+
fireEvent.click(screen.getByRole('button'))
|
|
29
|
+
|
|
30
|
+
const wrapper = getPickerWrapper(container)
|
|
31
|
+
|
|
32
|
+
expect(wrapper).toHaveClass('opacity-100', 'pointer-events-auto')
|
|
33
|
+
// a leftover `pointer-events-none` wins on stylesheet order and swallows
|
|
34
|
+
// every click on the open picker
|
|
35
|
+
expect(wrapper).not.toHaveClass('pointer-events-none')
|
|
36
|
+
expect(wrapper).not.toHaveClass('opacity-0')
|
|
37
|
+
})
|
|
38
|
+
})
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import React, { useEffect } from 'react'
|
|
3
3
|
import data from '@emoji-mart/data'
|
|
4
4
|
import Picker from '@emoji-mart/react'
|
|
5
|
-
import cx from 'classnames'
|
|
6
5
|
import { Container } from '@toptal/picasso-container'
|
|
6
|
+
import { twMerge } from '@toptal/picasso-tailwind-merge'
|
|
7
7
|
|
|
8
8
|
import RichTextEditorButton from '../RichTextEditorButton'
|
|
9
9
|
import type { CustomEmojiGroup, Emoji } from '../plugins/EmojiPlugin'
|
|
@@ -16,12 +16,6 @@ interface Props {
|
|
|
16
16
|
|
|
17
17
|
const TRIGGER_EMOJI_PICKER_ID = 'trigger-emoji-picker'
|
|
18
18
|
|
|
19
|
-
const classes = {
|
|
20
|
-
emojiPicker: 'absolute top-[34px] left-0 z-10 opacity-0 pointer-events-none',
|
|
21
|
-
activeOpacity: 'opacity-100',
|
|
22
|
-
activePointers: '[pointer-events:all]',
|
|
23
|
-
}
|
|
24
|
-
|
|
25
19
|
const handleEmojiPickerEscBehaviour = (
|
|
26
20
|
event: KeyboardEvent,
|
|
27
21
|
setShowEmojiPicker: React.Dispatch<React.SetStateAction<boolean>>
|
|
@@ -76,10 +70,12 @@ export const RichTextEditorEmojiPicker = ({
|
|
|
76
70
|
disabled={disabled}
|
|
77
71
|
/>
|
|
78
72
|
<Container
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
73
|
+
// twMerge drops the hidden-state classes when open; leaving
|
|
74
|
+
// `pointer-events-none` in place would let stylesheet order decide,
|
|
75
|
+
// and it wins, so clicks fall through the open picker to the editor
|
|
76
|
+
className={twMerge(
|
|
77
|
+
'absolute top-[34px] left-0 z-10 opacity-0 pointer-events-none',
|
|
78
|
+
showEmojiPicker && 'opacity-100 pointer-events-auto'
|
|
83
79
|
)}
|
|
84
80
|
>
|
|
85
81
|
<Picker
|