@linktr.ee/messaging-react 4.4.1-rc-1787616779 → 4.4.1-rc-1787626707
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/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +20 -29
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/components/MessageBubble/MessageBubble.stories.tsx +21 -13
- package/src/components/MessageBubble/MessageBubble.test.tsx +10 -21
- package/src/components/MessageBubble/components/_shared/BubbleShell.tsx +16 -33
- package/src/components/MessageBubble/types.ts +4 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@linktr.ee/messaging-react",
|
|
3
|
-
"version": "4.4.1-rc-
|
|
3
|
+
"version": "4.4.1-rc-1787626707",
|
|
4
4
|
"description": "React messaging components built on messaging-core for web applications",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
"chromatic:local": "yarn storybook:build && chromatic"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@linktr.ee/messaging-core": "2.6.0-rc-
|
|
54
|
-
"@linktr.ee/messaging-taxonomy": "0.11.0-rc-
|
|
53
|
+
"@linktr.ee/messaging-core": "2.6.0-rc-1787626707",
|
|
54
|
+
"@linktr.ee/messaging-taxonomy": "0.11.0-rc-1787626707",
|
|
55
55
|
"@phosphor-icons/react": "^2.1.10"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
@@ -10,7 +10,7 @@ const meta: Meta = {
|
|
|
10
10
|
export default meta
|
|
11
11
|
|
|
12
12
|
const Canvas = ({ children }: { children: React.ReactNode }) => (
|
|
13
|
-
<div className="
|
|
13
|
+
<div className="min-h-screen w-full space-y-6 bg-[#F9F7F4] p-12">
|
|
14
14
|
{children}
|
|
15
15
|
</div>
|
|
16
16
|
)
|
|
@@ -27,9 +27,7 @@ const Row = ({
|
|
|
27
27
|
<div>
|
|
28
28
|
<p className="mb-2 text-xs font-medium text-black/40">{label}</p>
|
|
29
29
|
<div
|
|
30
|
-
className={`
|
|
31
|
-
align === 'end' ? 'flex justify-end' : 'flex justify-start'
|
|
32
|
-
}`}
|
|
30
|
+
className={`flex ${align === 'end' ? 'justify-end' : 'justify-start'}`}
|
|
33
31
|
>
|
|
34
32
|
{children}
|
|
35
33
|
</div>
|
|
@@ -45,25 +43,29 @@ const MULTILINE = 'Line one\nLine two\nLine three'
|
|
|
45
43
|
export const Gallery: StoryFn = () => (
|
|
46
44
|
<Canvas>
|
|
47
45
|
<Row label="Received — short" align="start">
|
|
48
|
-
<MessageBubble.Received text={SHORT} />
|
|
46
|
+
<MessageBubble.Received text={SHORT} className="w-fit" />
|
|
49
47
|
</Row>
|
|
50
48
|
<Row label="Received — with header (sender name)" align="start">
|
|
51
|
-
<MessageBubble.Received
|
|
49
|
+
<MessageBubble.Received
|
|
50
|
+
header="Brie"
|
|
51
|
+
text={LONG}
|
|
52
|
+
className="w-fit max-w-[520px]"
|
|
53
|
+
/>
|
|
52
54
|
</Row>
|
|
53
55
|
<Row label="Received — no tail" align="start">
|
|
54
|
-
<MessageBubble.Received text={SHORT} tail={false} />
|
|
56
|
+
<MessageBubble.Received text={SHORT} tail={false} className="w-fit" />
|
|
55
57
|
</Row>
|
|
56
58
|
<Row label="Sent — short" align="end">
|
|
57
|
-
<MessageBubble.Sent text={SHORT} />
|
|
59
|
+
<MessageBubble.Sent text={SHORT} className="w-fit" />
|
|
58
60
|
</Row>
|
|
59
61
|
<Row label="Sent — long" align="end">
|
|
60
|
-
<MessageBubble.Sent text={LONG} />
|
|
62
|
+
<MessageBubble.Sent text={LONG} className="w-fit max-w-[520px]" />
|
|
61
63
|
</Row>
|
|
62
64
|
<Row label="Sent — multiline" align="end">
|
|
63
|
-
<MessageBubble.Sent text={MULTILINE} />
|
|
65
|
+
<MessageBubble.Sent text={MULTILINE} className="w-fit" />
|
|
64
66
|
</Row>
|
|
65
67
|
<Row label="Sent — no tail" align="end">
|
|
66
|
-
<MessageBubble.Sent text={SHORT} tail={false} />
|
|
68
|
+
<MessageBubble.Sent text={SHORT} tail={false} className="w-fit" />
|
|
67
69
|
</Row>
|
|
68
70
|
</Canvas>
|
|
69
71
|
)
|
|
@@ -76,7 +78,10 @@ export const Gallery: StoryFn = () => (
|
|
|
76
78
|
export const PreviewToRecipient: StoryFn = () => (
|
|
77
79
|
<Canvas>
|
|
78
80
|
<Row label="How your reply will look to the visitor" align="start">
|
|
79
|
-
<MessageBubble.Received
|
|
81
|
+
<MessageBubble.Received
|
|
82
|
+
text="Thanks so much for the support — I just dropped a new track, hope you love it! 🎶"
|
|
83
|
+
className="w-fit max-w-[520px]"
|
|
84
|
+
/>
|
|
80
85
|
</Row>
|
|
81
86
|
</Canvas>
|
|
82
87
|
)
|
|
@@ -88,7 +93,10 @@ export const PreviewToRecipient: StoryFn = () => (
|
|
|
88
93
|
export const PreviewInChannel: StoryFn = () => (
|
|
89
94
|
<Canvas>
|
|
90
95
|
<Row label="How your reply looks to you in the channel" align="end">
|
|
91
|
-
<MessageBubble.Sent
|
|
96
|
+
<MessageBubble.Sent
|
|
97
|
+
text="Thanks so much for the support — I just dropped a new track, hope you love it! 🎶"
|
|
98
|
+
className="w-fit max-w-[520px]"
|
|
99
|
+
/>
|
|
92
100
|
</Row>
|
|
93
101
|
</Canvas>
|
|
94
102
|
)
|
|
@@ -22,15 +22,12 @@ describe('MessageBubble', () => {
|
|
|
22
22
|
const { rerender } = renderWithProviders(
|
|
23
23
|
<MessageBubble.Sent text="tailed" />
|
|
24
24
|
)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
.closest('.str-chat__message-bubble') as HTMLElement
|
|
25
|
+
// The bubble box wraps the text; its last child is the tail <span>.
|
|
26
|
+
const bubble = screen.getByText('tailed').parentElement as HTMLElement
|
|
28
27
|
expect(bubble.querySelector('span[aria-hidden="true"]')).not.toBeNull()
|
|
29
28
|
|
|
30
29
|
rerender(<MessageBubble.Sent text="tailed" tail={false} />)
|
|
31
|
-
const bubbleNoTail = screen
|
|
32
|
-
.getByText('tailed')
|
|
33
|
-
.closest('.str-chat__message-bubble') as HTMLElement
|
|
30
|
+
const bubbleNoTail = screen.getByText('tailed').parentElement as HTMLElement
|
|
34
31
|
expect(bubbleNoTail.querySelector('span[aria-hidden="true"]')).toBeNull()
|
|
35
32
|
})
|
|
36
33
|
|
|
@@ -50,17 +47,13 @@ describe('MessageBubble', () => {
|
|
|
50
47
|
|
|
51
48
|
it('applies the sent and received surface treatments from theme vars', () => {
|
|
52
49
|
const { rerender } = renderWithProviders(<MessageBubble.Sent text="mine" />)
|
|
53
|
-
const sent = screen
|
|
54
|
-
.getByText('mine')
|
|
55
|
-
.closest('.str-chat__message-bubble') as HTMLElement
|
|
50
|
+
const sent = screen.getByText('mine').parentElement as HTMLElement
|
|
56
51
|
expect(sent.style.backgroundColor).toBe(
|
|
57
52
|
'var(--str-chat__own-message-bubble-background-color, #1e2330)'
|
|
58
53
|
)
|
|
59
54
|
|
|
60
55
|
rerender(<MessageBubble.Received text="theirs" />)
|
|
61
|
-
const received = screen
|
|
62
|
-
.getByText('theirs')
|
|
63
|
-
.closest('.str-chat__message-bubble') as HTMLElement
|
|
56
|
+
const received = screen.getByText('theirs').parentElement as HTMLElement
|
|
64
57
|
expect(received.style.backgroundColor).toBe(
|
|
65
58
|
'var(--str-chat__message-bubble-background-color, #f1f0ee)'
|
|
66
59
|
)
|
|
@@ -68,20 +61,16 @@ describe('MessageBubble', () => {
|
|
|
68
61
|
|
|
69
62
|
it('masks message content from session replay by default', () => {
|
|
70
63
|
renderWithProviders(<MessageBubble.Received header="Brie" text="secret" />)
|
|
71
|
-
const bubble = screen
|
|
72
|
-
.getByText('secret')
|
|
73
|
-
.closest('.str-chat__message-bubble') as HTMLElement
|
|
64
|
+
const bubble = screen.getByText('secret').parentElement as HTMLElement
|
|
74
65
|
expect(bubble.getAttribute('data-dd-privacy')).toBe('mask')
|
|
75
66
|
})
|
|
76
67
|
|
|
77
|
-
it('forwards width/className onto the
|
|
68
|
+
it('forwards width/className onto the bubble box (width is caller-controlled)', () => {
|
|
78
69
|
renderWithProviders(
|
|
79
70
|
<MessageBubble.Sent text="wide" className="w-fit max-w-[520px]" />
|
|
80
71
|
)
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
expect(message.classList.contains('w-fit')).toBe(true)
|
|
85
|
-
expect(message.className).toContain('max-w-[520px]')
|
|
72
|
+
const bubble = screen.getByText('wide').parentElement as HTMLElement
|
|
73
|
+
expect(bubble.classList.contains('w-fit')).toBe(true)
|
|
74
|
+
expect(bubble.className).toContain('max-w-[520px]')
|
|
86
75
|
})
|
|
87
76
|
})
|
|
@@ -15,8 +15,8 @@ export interface BubbleShellProps {
|
|
|
15
15
|
/**
|
|
16
16
|
* Width is caller-controlled — pass a width class in `className`
|
|
17
17
|
* (`w-fit` to hug the text for chat/preview bubbles, `w-full` to fill the
|
|
18
|
-
* container for card-like list rows).
|
|
19
|
-
*
|
|
18
|
+
* container for card-like list rows). With no width class the bubble is a
|
|
19
|
+
* block element and fills its container.
|
|
20
20
|
*/
|
|
21
21
|
className?: string
|
|
22
22
|
}
|
|
@@ -65,42 +65,25 @@ const BubbleShell: React.FC<BubbleShellProps> = ({
|
|
|
65
65
|
className,
|
|
66
66
|
}) => (
|
|
67
67
|
<div
|
|
68
|
+
data-dd-privacy="mask"
|
|
68
69
|
className={classNames(
|
|
69
|
-
'
|
|
70
|
-
|
|
70
|
+
'relative px-4 py-3',
|
|
71
|
+
'text-[0.875rem] leading-[1.3125rem] tracking-[0.14px]',
|
|
71
72
|
className
|
|
72
73
|
)}
|
|
74
|
+
style={{
|
|
75
|
+
...SURFACE_STYLE_BY_VARIANT[variant],
|
|
76
|
+
borderRadius: 'var(--str-chat__message-bubble-border-radius, 1.5rem)',
|
|
77
|
+
isolation: 'isolate',
|
|
78
|
+
}}
|
|
73
79
|
>
|
|
74
|
-
|
|
75
|
-
<div
|
|
76
|
-
|
|
77
|
-
className={classNames(
|
|
78
|
-
'str-chat__message-bubble',
|
|
79
|
-
'relative',
|
|
80
|
-
'text-[0.875rem] leading-[1.3125rem] tracking-[0.14px]'
|
|
81
|
-
)}
|
|
82
|
-
style={{
|
|
83
|
-
...SURFACE_STYLE_BY_VARIANT[variant],
|
|
84
|
-
borderRadius: 'var(--str-chat__message-bubble-border-radius, 1.5rem)',
|
|
85
|
-
isolation: 'isolate',
|
|
86
|
-
}}
|
|
87
|
-
>
|
|
88
|
-
<div className="str-chat__message-text">
|
|
89
|
-
{header != null && (
|
|
90
|
-
<div
|
|
91
|
-
className="mb-1 font-medium"
|
|
92
|
-
data-testid="message-bubble-header"
|
|
93
|
-
>
|
|
94
|
-
{header}
|
|
95
|
-
</div>
|
|
96
|
-
)}
|
|
97
|
-
<p className="m-0 whitespace-pre-wrap break-words hyphens-manual">
|
|
98
|
-
{text}
|
|
99
|
-
</p>
|
|
100
|
-
{tail && <BubbleTail variant={variant} />}
|
|
101
|
-
</div>
|
|
80
|
+
{header != null && (
|
|
81
|
+
<div className="mb-1 font-medium" data-testid="message-bubble-header">
|
|
82
|
+
{header}
|
|
102
83
|
</div>
|
|
103
|
-
|
|
84
|
+
)}
|
|
85
|
+
<p className="m-0 whitespace-pre-wrap break-words hyphens-manual">{text}</p>
|
|
86
|
+
{tail && <BubbleTail variant={variant} />}
|
|
104
87
|
</div>
|
|
105
88
|
)
|
|
106
89
|
|
|
@@ -20,10 +20,10 @@ export interface MessageBubbleBaseProps {
|
|
|
20
20
|
*/
|
|
21
21
|
tail?: boolean
|
|
22
22
|
/**
|
|
23
|
-
* Extra classes on the
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
23
|
+
* Extra classes on the outer bubble. Width is caller-controlled: pass
|
|
24
|
+
* `w-fit` to hug the text (chat/preview) or `w-full` to fill the container
|
|
25
|
+
* (card-like list rows). With no width class the bubble fills its
|
|
26
|
+
* container. Also where you'd set `max-w-[…]`.
|
|
27
27
|
*/
|
|
28
28
|
className?: string
|
|
29
29
|
}
|