@linktr.ee/messaging-react 1.21.2-rc-1771385662 → 1.21.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linktr.ee/messaging-react",
3
- "version": "1.21.2-rc-1771385662",
3
+ "version": "1.21.2",
4
4
  "description": "React messaging components built on messaging-core for web applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,7 +1,7 @@
1
1
  import classNames from "classnames";
2
2
  import React from "react";
3
3
 
4
- interface ActionButtonProps
4
+ export interface ActionButtonProps
5
5
  extends React.ButtonHTMLAttributes<HTMLButtonElement> {
6
6
  variant?: "default" | "danger";
7
7
  }
@@ -244,6 +244,7 @@ const ChannelInfoDialog: React.FC<{
244
244
  onDeleteConversationClick?: () => void
245
245
  onBlockParticipantClick?: () => void
246
246
  onReportParticipantClick?: () => void
247
+ customChannelActions?: React.ReactNode
247
248
  }> = ({
248
249
  dialogRef,
249
250
  onClose,
@@ -256,6 +257,7 @@ const ChannelInfoDialog: React.FC<{
256
257
  onDeleteConversationClick,
257
258
  onBlockParticipantClick,
258
259
  onReportParticipantClick,
260
+ customChannelActions,
259
261
  }) => {
260
262
  const { service, debug } = useMessagingContext()
261
263
  const [isParticipantBlocked, setIsParticipantBlocked] = useState(false)
@@ -505,6 +507,7 @@ const ChannelInfoDialog: React.FC<{
505
507
  <span>Report</span>
506
508
  </ActionButton>
507
509
  </li>
510
+ {customChannelActions}
508
511
  </ul>
509
512
  </div>
510
513
  </div>
@@ -529,6 +532,7 @@ const ChannelViewInner: React.FC<{
529
532
  showStarButton?: boolean
530
533
  chatbotVotingEnabled?: boolean
531
534
  renderChannelBanner?: () => React.ReactNode
535
+ customChannelActions?: React.ReactNode
532
536
  }> = ({
533
537
  onBack,
534
538
  showBackButton,
@@ -542,6 +546,7 @@ const ChannelViewInner: React.FC<{
542
546
  showStarButton = false,
543
547
  chatbotVotingEnabled = false,
544
548
  renderChannelBanner,
549
+ customChannelActions,
545
550
  }) => {
546
551
  const { channel } = useChannelStateContext()
547
552
  const infoDialogRef = useRef<HTMLDialogElement>(null)
@@ -636,6 +641,7 @@ const ChannelViewInner: React.FC<{
636
641
  onDeleteConversationClick={onDeleteConversationClick}
637
642
  onBlockParticipantClick={onBlockParticipantClick}
638
643
  onReportParticipantClick={onReportParticipantClick}
644
+ customChannelActions={customChannelActions}
639
645
  />
640
646
  </>
641
647
  )
@@ -664,6 +670,7 @@ export const ChannelView = React.memo<ChannelViewProps>(
664
670
  showStarButton = false,
665
671
  chatbotVotingEnabled = false,
666
672
  renderChannelBanner,
673
+ customChannelActions,
667
674
  }) => {
668
675
  // Custom send message handler that:
669
676
  // 1. Applies messageMetadata if provided
@@ -738,6 +745,7 @@ export const ChannelView = React.memo<ChannelViewProps>(
738
745
  showStarButton={showStarButton}
739
746
  chatbotVotingEnabled={chatbotVotingEnabled}
740
747
  renderChannelBanner={renderChannelBanner}
748
+ customChannelActions={customChannelActions}
741
749
  />
742
750
  </Channel>
743
751
  </div>
@@ -154,21 +154,6 @@ WithTipTag.args = {
154
154
  ],
155
155
  }
156
156
 
157
- /** Tip message without amount_text (backend may not set it). Tag shows "Delivered with tip". */
158
- export const WithTipTagNoAmount: StoryFn<TemplateProps> = Template.bind({})
159
- WithTipTagNoAmount.args = {
160
- messages: [
161
- { id: 'msg-1', text: 'Love your content!', user: participant },
162
- {
163
- id: 'msg-2',
164
- text: "Here's a tip for you!",
165
- user: participant,
166
- metadata: { custom_type: 'MESSAGE_TIP' },
167
- },
168
- { id: 'msg-3', text: 'Thank you! 🙏', user: mockUser },
169
- ],
170
- }
171
-
172
157
  export const TipOnly: StoryFn<TemplateProps> = Template.bind({})
173
158
  TipOnly.args = {
174
159
  messages: [
@@ -183,21 +168,6 @@ TipOnly.args = {
183
168
  ],
184
169
  }
185
170
 
186
- /** Tip-only bubble without amount_text. Tag shows "Tip". */
187
- export const TipOnlyNoAmount: StoryFn<TemplateProps> = Template.bind({})
188
- TipOnlyNoAmount.args = {
189
- messages: [
190
- { id: 'msg-1', text: 'Hello!', user: participant },
191
- {
192
- id: 'msg-2',
193
- text: '',
194
- user: participant,
195
- metadata: { custom_type: 'MESSAGE_TIP' },
196
- },
197
- { id: 'msg-3', text: 'Thank you for the tip!', user: mockUser },
198
- ],
199
- }
200
-
201
171
  export const MixedTags: StoryFn<TemplateProps> = Template.bind({})
202
172
  MixedTags.args = {
203
173
  messages: [
@@ -226,12 +196,6 @@ MixedTags.args = {
226
196
  user: participant,
227
197
  metadata: { custom_type: 'MESSAGE_PAID', amount_text: '$10.00' },
228
198
  },
229
- {
230
- id: 'msg-6b',
231
- text: 'Another paid message (no amount_text).',
232
- user: participant,
233
- metadata: { custom_type: 'MESSAGE_PAID' },
234
- },
235
199
  { id: 'msg-7', text: 'Got it, thanks!', user: mockUser },
236
200
  {
237
201
  id: 'msg-8',
@@ -48,14 +48,6 @@ Tip.args = {
48
48
  }),
49
49
  }
50
50
 
51
- /** Tip with only custom_type (no amount_text). Matches backend when we don't set amount_text. */
52
- export const TipWithoutAmount: StoryFn<ComponentProps> = Template.bind({})
53
- TipWithoutAmount.args = {
54
- message: createMockMessage({
55
- metadata: { custom_type: 'MESSAGE_TIP' },
56
- }),
57
- }
58
-
59
51
  export const TipStandalone: StoryFn<ComponentProps> = Template.bind({})
60
52
  TipStandalone.args = {
61
53
  message: createMockMessage({
@@ -65,16 +57,6 @@ TipStandalone.args = {
65
57
  standalone: true,
66
58
  }
67
59
 
68
- /** Tip-only bubble with no amount_text (fallback label "Tip"). */
69
- export const TipStandaloneWithoutAmount: StoryFn<ComponentProps> = Template.bind({})
70
- TipStandaloneWithoutAmount.args = {
71
- message: createMockMessage({
72
- text: '',
73
- metadata: { custom_type: 'MESSAGE_TIP' },
74
- }),
75
- standalone: true,
76
- }
77
-
78
60
  export const Paid: StoryFn<ComponentProps> = Template.bind({})
79
61
  Paid.args = {
80
62
  message: createMockMessage({
@@ -82,14 +64,6 @@ Paid.args = {
82
64
  }),
83
65
  }
84
66
 
85
- /** Paid with only custom_type (no amount_text). Fallback label "Delivered with tip". */
86
- export const PaidWithoutAmount: StoryFn<ComponentProps> = Template.bind({})
87
- PaidWithoutAmount.args = {
88
- message: createMockMessage({
89
- metadata: { custom_type: 'MESSAGE_PAID' },
90
- }),
91
- }
92
-
93
67
  export const Chatbot: StoryFn<ComponentProps> = Template.bind({})
94
68
  Chatbot.args = {
95
69
  message: createMockMessage({ metadata: { custom_type: 'MESSAGE_CHATBOT' } }),
@@ -104,7 +78,7 @@ export const AllVariants: StoryFn = () => {
104
78
  return (
105
79
  <div className="p-12 flex flex-col gap-4">
106
80
  <div className="flex items-center gap-4">
107
- <span className="text-sm w-40">Tip (with amount):</span>
81
+ <span className="text-sm w-32">Tip:</span>
108
82
  <MessageTag
109
83
  message={createMockMessage({
110
84
  metadata: { custom_type: 'MESSAGE_TIP', amount_text: '$10.50' },
@@ -112,15 +86,7 @@ export const AllVariants: StoryFn = () => {
112
86
  />
113
87
  </div>
114
88
  <div className="flex items-center gap-4">
115
- <span className="text-sm w-40">Tip (no amount_text):</span>
116
- <MessageTag
117
- message={createMockMessage({
118
- metadata: { custom_type: 'MESSAGE_TIP' },
119
- })}
120
- />
121
- </div>
122
- <div className="flex items-center gap-4">
123
- <span className="text-sm w-40">Paid (with amount):</span>
89
+ <span className="text-sm w-32">Paid:</span>
124
90
  <MessageTag
125
91
  message={createMockMessage({
126
92
  metadata: { custom_type: 'MESSAGE_PAID', amount_text: '$25.00' },
@@ -128,15 +94,7 @@ export const AllVariants: StoryFn = () => {
128
94
  />
129
95
  </div>
130
96
  <div className="flex items-center gap-4">
131
- <span className="text-sm w-40">Paid (no amount_text):</span>
132
- <MessageTag
133
- message={createMockMessage({
134
- metadata: { custom_type: 'MESSAGE_PAID' },
135
- })}
136
- />
137
- </div>
138
- <div className="flex items-center gap-4">
139
- <span className="text-sm w-40">Tip standalone (with amount):</span>
97
+ <span className="text-sm w-32">Tip (standalone):</span>
140
98
  <MessageTag
141
99
  message={createMockMessage({
142
100
  text: '',
@@ -146,23 +104,13 @@ export const AllVariants: StoryFn = () => {
146
104
  />
147
105
  </div>
148
106
  <div className="flex items-center gap-4">
149
- <span className="text-sm w-40">Tip standalone (no amount_text):</span>
150
- <MessageTag
151
- message={createMockMessage({
152
- text: '',
153
- metadata: { custom_type: 'MESSAGE_TIP' },
154
- })}
155
- standalone
156
- />
157
- </div>
158
- <div className="flex items-center gap-4">
159
- <span className="text-sm w-40">Chatbot:</span>
107
+ <span className="text-sm w-32">Chatbot:</span>
160
108
  <MessageTag
161
109
  message={createMockMessage({ metadata: { custom_type: 'MESSAGE_CHATBOT' } })}
162
110
  />
163
111
  </div>
164
112
  <div className="flex items-center gap-4">
165
- <span className="text-sm w-40">No tag:</span>
113
+ <span className="text-sm w-32">No tag:</span>
166
114
  <MessageTag message={createMockMessage()} />
167
115
  <span className="text-xs text-stone">(renders nothing)</span>
168
116
  </div>
@@ -54,17 +54,15 @@ export const MessageTag = ({
54
54
 
55
55
  if (isTipOrPaid) {
56
56
  const amountText = message.metadata?.amount_text
57
+ if (!amountText) return null
58
+
57
59
  const className = standalone
58
60
  ? 'message-tip-standalone'
59
61
  : 'message-tag message-tag--tip'
60
62
 
61
- const label = amountText
62
- ? standalone
63
- ? `${amountText} tip`
64
- : `Delivered with ${amountText} tip`
65
- : standalone
66
- ? 'Tip'
67
- : 'Delivered with tip'
63
+ const label = standalone
64
+ ? `${amountText} tip`
65
+ : `Delivered with ${amountText} tip`
68
66
 
69
67
  return (
70
68
  <div className={className}>
@@ -37,6 +37,7 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
37
37
  chatbotVotingEnabled = false,
38
38
  renderMessagePreview,
39
39
  renderChannelBanner,
40
+ customChannelActions,
40
41
  }) => {
41
42
  const {
42
43
  service,
@@ -495,6 +496,7 @@ export const MessagingShell: React.FC<MessagingShellProps> = ({
495
496
  onMessageSent={onMessageSent}
496
497
  showStarButton={showStarButton}
497
498
  chatbotVotingEnabled={chatbotVotingEnabled}
499
+ customChannelActions={customChannelActions}
498
500
  />
499
501
  </div>
500
502
  ) : initialParticipantFilter ? (
package/src/index.ts CHANGED
@@ -5,6 +5,7 @@ import './styles.css'
5
5
  export { MessagingShell } from './components/MessagingShell'
6
6
  export { ChannelList } from './components/ChannelList'
7
7
  export { ChannelView } from './components/ChannelView'
8
+ export { default as ActionButton } from './components/ActionButton'
8
9
  export { ParticipantPicker } from './components/ParticipantPicker'
9
10
  export { Avatar } from './components/Avatar'
10
11
  export { FaqList } from './components/FaqList'
@@ -36,6 +37,7 @@ export type {
36
37
  } from './types'
37
38
  export type { MessageMetadata } from './stream-custom-data'
38
39
  export type { AvatarProps } from './components/Avatar'
40
+ export type { ActionButtonProps } from './components/ActionButton'
39
41
  export type { Faq, FaqListProps } from './components/FaqList'
40
42
  export type { FaqListItemProps } from './components/FaqList/FaqListItem'
41
43
  export type { VoteSelection } from './hooks/useMessageVote'
package/src/types.ts CHANGED
@@ -154,6 +154,14 @@ export interface ChannelViewProps {
154
154
  * Useful for showing summaries, alerts, or contextual information.
155
155
  */
156
156
  renderChannelBanner?: () => React.ReactNode
157
+
158
+ /**
159
+ * Custom actions rendered at the bottom of the channel info dialog
160
+ * (below Delete Conversation, Block/Unblock, Report).
161
+ * Pass one or more <li> elements so they match the list styling.
162
+ * Use the exported ActionButton for consistent styling.
163
+ */
164
+ customChannelActions?: React.ReactNode
157
165
  }
158
166
 
159
167
  /**
@@ -173,6 +181,7 @@ export type ChannelViewPassthroughProps = Pick<
173
181
  | 'showStarButton'
174
182
  | 'chatbotVotingEnabled'
175
183
  | 'renderChannelBanner'
184
+ | 'customChannelActions'
176
185
  >
177
186
 
178
187
  /**