@linktr.ee/messaging-react 4.0.0-rc-1786390369 → 4.0.0

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.d.ts CHANGED
@@ -393,10 +393,11 @@ export declare interface ChannelViewProps {
393
393
  */
394
394
  onOutboundClick?: OutboundClickHandler;
395
395
  /**
396
- * Resolves an outbound record id to the current automation id and name. The
397
- * host must provide a new resolver reference when a returned outbound
398
- * changes so ChannelView re-renders and publishes the new value to memoized
399
- * rows. Missing records stay unresolved and render no label.
396
+ * Resolves `metadata.outbound_id` (an outbound record id) to the current
397
+ * automation id and name. The host must provide a new resolver reference
398
+ * when a returned outbound changes so ChannelView re-renders and publishes
399
+ * the new value to memoized rows. Missing records stay unresolved and render
400
+ * no label.
400
401
  */
401
402
  resolveOutbound?: OutboundResolver;
402
403
  /**
@@ -1403,8 +1404,8 @@ export declare interface MessageMetadata {
1403
1404
  */
1404
1405
  sent_from?: 'stack_detail';
1405
1406
  /**
1406
- * Opaque Outbound Record id on automation messages. Hosts resolve this
1407
- * server-side to the current automation id and name.
1407
+ * Opaque outbound record id on automation messages. The Stream wire field is
1408
+ * `outbound_id`; resolver APIs name this value `outboundRecordId` explicitly.
1408
1409
  */
1409
1410
  outbound_id?: string;
1410
1411
  }
@@ -1549,7 +1550,7 @@ export declare function optimizeMessagingAttachmentUrl(url: string | undefined |
1549
1550
 
1550
1551
  export declare type OutboundClickHandler = (outbound: ResolvedOutbound) => void;
1551
1552
 
1552
- export declare type OutboundResolver = (outboundId: string) => ResolvedOutbound | undefined;
1553
+ export declare type OutboundResolver = (outboundRecordId: string) => ResolvedOutbound | undefined;
1553
1554
 
1554
1555
  /**
1555
1556
  * Generic participant interface for different host environments
@@ -1636,6 +1637,7 @@ export declare interface ReceivedBubbleProps extends MessageBubbleBaseProps {
1636
1637
  export declare function resolveConversationParticipant(members: ChannelMembers | undefined, currentUserId: string | undefined, channelType: string | undefined): ChannelMember | undefined;
1637
1638
 
1638
1639
  export declare type ResolvedOutbound = {
1640
+ /** Automation id referenced by the outbound record. */
1639
1641
  id: string;
1640
1642
  name?: string;
1641
1643
  };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { a as e, b as t, C as i, c as n, d as o, e as m, F as r, f as l, L as g, h as c, M, i as h, j as L, k as u, l as d, R as p, m as C, n as v, p as A, q as k, s as F, t as b, u as P, v as f, w as x, o as y, x as z, y as S, z as q, B, D, E, G as R } from "./index-CB548cbP.js";
1
+ import { a as e, b as t, C as i, c as n, d as o, e as m, F as r, f as l, L as g, h as c, M, i as h, j as L, k as u, l as d, R as p, m as C, n as v, p as A, q as k, s as F, t as b, u as P, v as f, w as x, o as y, x as z, y as S, z as q, B, D, E, G as R } from "./index-Dyxu8r07.js";
2
2
  export {
3
3
  e as ActionButton,
4
4
  t as Avatar,
package/dist/testing.d.ts CHANGED
@@ -57,8 +57,8 @@ export declare interface MessageMetadata {
57
57
  */
58
58
  sent_from?: 'stack_detail';
59
59
  /**
60
- * Opaque Outbound Record id on automation messages. Hosts resolve this
61
- * server-side to the current automation id and name.
60
+ * Opaque outbound record id on automation messages. The Stream wire field is
61
+ * `outbound_id`; resolver APIs name this value `outboundRecordId` explicitly.
62
62
  */
63
63
  outbound_id?: string;
64
64
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linktr.ee/messaging-react",
3
- "version": "4.0.0-rc-1786390369",
3
+ "version": "4.0.0",
4
4
  "description": "React messaging components built on messaging-core for web applications",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -50,7 +50,7 @@
50
50
  "chromatic:local": "yarn storybook:build && chromatic"
51
51
  },
52
52
  "dependencies": {
53
- "@linktr.ee/messaging-core": "2.4.0-rc-1786390369",
53
+ "@linktr.ee/messaging-core": "^2.4.0",
54
54
  "@linktr.ee/messaging-taxonomy": "^0.9.0",
55
55
  "@phosphor-icons/react": "^2.1.10"
56
56
  },
@@ -54,7 +54,7 @@ const createChannel = () => {
54
54
  }
55
55
 
56
56
  describe('ChannelView outbound resolution', () => {
57
- it('updates an existing Stream message row when its outbound lookup resolves', async () => {
57
+ it('updates an existing Stream message row when its outbound record lookup resolves', async () => {
58
58
  const { channel, client } = createChannel()
59
59
  const firstResolver = () => undefined
60
60
  const secondResolver = () => ({
@@ -19,7 +19,7 @@ import { CustomMessage } from './CustomMessage'
19
19
  import { CustomMessageActions } from './CustomMessage/CustomMessageActions'
20
20
  import {
21
21
  OutboundContext,
22
- useOutboundsById,
22
+ useOutboundsByRecordId,
23
23
  } from './CustomMessage/OutboundContext'
24
24
  import { CustomMessageInput } from './CustomMessageInput'
25
25
  import { CustomSystemMessage } from './CustomSystemMessage'
@@ -105,7 +105,7 @@ const ChannelViewInner: React.FC<{
105
105
  : undefined
106
106
  // Resolve outside memoized Stream rows so current automation details publish
107
107
  // without remounting the rows.
108
- const outboundsById = useOutboundsById(messages, resolveOutbound)
108
+ const outboundsByRecordId = useOutboundsByRecordId(messages, resolveOutbound)
109
109
 
110
110
  const hasVisibleMessages = channel.state.messages.some(
111
111
  (message) => message.type !== 'deleted'
@@ -159,7 +159,7 @@ const ChannelViewInner: React.FC<{
159
159
  )
160
160
 
161
161
  return (
162
- <OutboundContext.Provider value={outboundsById}>
162
+ <OutboundContext.Provider value={outboundsByRecordId}>
163
163
  <WithComponents
164
164
  overrides={{
165
165
  Message: MessageOverride,
@@ -27,7 +27,7 @@ import type { OutboundResolver } from '../../types'
27
27
  import CustomTypingIndicator from '../CustomTypingIndicator'
28
28
 
29
29
  import { CustomMessageActions } from './CustomMessageActions'
30
- import { OutboundContext, buildOutboundsById } from './OutboundContext'
30
+ import { OutboundContext, buildOutboundsByRecordId } from './OutboundContext'
31
31
 
32
32
  import { CustomMessage } from './index'
33
33
 
@@ -167,8 +167,8 @@ const TemplateInner: React.FC<{
167
167
  return () => clearTimeout(timer)
168
168
  }, [channel, client, typingUser])
169
169
 
170
- const outboundsById = React.useMemo(
171
- () => buildOutboundsById(messages, resolveOutbound),
170
+ const outboundsByRecordId = React.useMemo(
171
+ () => buildOutboundsByRecordId(messages, resolveOutbound),
172
172
  [messages, resolveOutbound]
173
173
  )
174
174
 
@@ -183,7 +183,7 @@ const TemplateInner: React.FC<{
183
183
  }
184
184
 
185
185
  return (
186
- <OutboundContext.Provider value={outboundsById}>
186
+ <OutboundContext.Provider value={outboundsByRecordId}>
187
187
  <Chat client={client}>
188
188
  <div className="h-screen w-full bg-white">
189
189
  <Channel
@@ -3,12 +3,15 @@ import { describe, expect, it, vi } from 'vitest'
3
3
  import { renderHook } from '../../test/utils'
4
4
  import type { OutboundResolver } from '../../types'
5
5
 
6
- import { buildOutboundsById, useOutboundsById } from './OutboundContext'
6
+ import {
7
+ buildOutboundsByRecordId,
8
+ useOutboundsByRecordId,
9
+ } from './OutboundContext'
7
10
 
8
- describe('buildOutboundsById', () => {
11
+ describe('buildOutboundsByRecordId', () => {
9
12
  it('returns undefined when no resolver is provided', () => {
10
13
  expect(
11
- buildOutboundsById(
14
+ buildOutboundsByRecordId(
12
15
  [{ metadata: { outbound_id: 'outbound-1' } }],
13
16
  undefined
14
17
  )
@@ -18,19 +21,19 @@ describe('buildOutboundsById', () => {
18
21
  it('returns undefined without invoking the resolver when there are no messages', () => {
19
22
  const resolveOutbound = vi.fn()
20
23
 
21
- expect(buildOutboundsById(undefined, resolveOutbound)).toBeUndefined()
22
- expect(buildOutboundsById([], resolveOutbound)).toBeUndefined()
24
+ expect(buildOutboundsByRecordId(undefined, resolveOutbound)).toBeUndefined()
25
+ expect(buildOutboundsByRecordId([], resolveOutbound)).toBeUndefined()
23
26
  expect(resolveOutbound).not.toHaveBeenCalled()
24
27
  })
25
28
 
26
- it('resolves each unique outbound id once', () => {
27
- const resolveOutbound = vi.fn((outboundId: string) => ({
28
- id: `automation-for-${outboundId}`,
29
- name: `name-for-${outboundId}`,
29
+ it('resolves each unique outbound record id once', () => {
30
+ const resolveOutbound = vi.fn((outboundRecordId: string) => ({
31
+ id: `automation-for-${outboundRecordId}`,
32
+ name: `name-for-${outboundRecordId}`,
30
33
  }))
31
34
 
32
35
  expect(
33
- buildOutboundsById(
36
+ buildOutboundsByRecordId(
34
37
  [
35
38
  { metadata: { outbound_id: 'outbound-1' } },
36
39
  { metadata: { outbound_id: 'outbound-1' } },
@@ -54,7 +57,7 @@ describe('buildOutboundsById', () => {
54
57
 
55
58
  it('omits outbound records the resolver cannot resolve', () => {
56
59
  expect(
57
- buildOutboundsById(
60
+ buildOutboundsByRecordId(
58
61
  [{ metadata: { outbound_id: 'outbound-1' } }],
59
62
  () => undefined
60
63
  )
@@ -62,17 +65,17 @@ describe('buildOutboundsById', () => {
62
65
  })
63
66
  })
64
67
 
65
- describe('useOutboundsById', () => {
68
+ describe('useOutboundsByRecordId', () => {
66
69
  const messages = [{ metadata: { outbound_id: 'outbound-1' } }]
67
70
 
68
71
  const renderWithResolver = (resolver: OutboundResolver) =>
69
72
  renderHook(
70
73
  ({ resolveOutbound }: { resolveOutbound: OutboundResolver }) =>
71
- useOutboundsById(messages, resolveOutbound),
74
+ useOutboundsByRecordId(messages, resolveOutbound),
72
75
  { initialProps: { resolveOutbound: resolver } }
73
76
  )
74
77
 
75
- it('publishes a renamed automation under the same outbound id', () => {
78
+ it('publishes a renamed automation under the same outbound record id', () => {
76
79
  const { result, rerender } = renderWithResolver(() => ({
77
80
  id: 'automation-1',
78
81
  name: 'July 9th Class absentee',
@@ -2,18 +2,18 @@ import { createContext, useState } from 'react'
2
2
 
3
3
  import type { OutboundResolver, ResolvedOutbound } from '../../types'
4
4
 
5
- /** Current outbound sources keyed by the record id stored on each message. */
6
- export type OutboundsById = Readonly<Record<string, ResolvedOutbound>>
5
+ /** Current outbound sources keyed by the outbound record id stored on each message. */
6
+ export type OutboundsByRecordId = Readonly<Record<string, ResolvedOutbound>>
7
7
 
8
- export const OutboundContext = createContext<OutboundsById | undefined>(
8
+ export const OutboundContext = createContext<OutboundsByRecordId | undefined>(
9
9
  undefined
10
10
  )
11
11
 
12
- const outboundIdFromMessage = (message: {
12
+ const outboundRecordIdFromMessage = (message: {
13
13
  metadata?: { outbound_id?: unknown }
14
14
  }): string | undefined => {
15
- const outboundId = message.metadata?.outbound_id
16
- return typeof outboundId === 'string' ? outboundId : undefined
15
+ const outboundRecordId = message.metadata?.outbound_id
16
+ return typeof outboundRecordId === 'string' ? outboundRecordId : undefined
17
17
  }
18
18
 
19
19
  /**
@@ -22,10 +22,10 @@ const outboundIdFromMessage = (message: {
22
22
  * Built outside memoized Stream rows so a new resolver reference can publish
23
23
  * current automation details without remounting the Stream message rows.
24
24
  */
25
- export const buildOutboundsById = (
25
+ export const buildOutboundsByRecordId = (
26
26
  messages: readonly { metadata?: { outbound_id?: unknown } }[] | undefined,
27
27
  resolveOutbound: OutboundResolver | undefined
28
- ): OutboundsById | undefined => {
28
+ ): OutboundsByRecordId | undefined => {
29
29
  if (!resolveOutbound || !messages?.length) {
30
30
  return undefined
31
31
  }
@@ -34,13 +34,13 @@ export const buildOutboundsById = (
34
34
  let outbounds: Record<string, ResolvedOutbound> | undefined
35
35
 
36
36
  for (const message of messages) {
37
- const outboundId = outboundIdFromMessage(message)
38
- if (!outboundId || seen.has(outboundId)) {
37
+ const outboundRecordId = outboundRecordIdFromMessage(message)
38
+ if (!outboundRecordId || seen.has(outboundRecordId)) {
39
39
  continue
40
40
  }
41
- seen.add(outboundId)
41
+ seen.add(outboundRecordId)
42
42
 
43
- const resolved = resolveOutbound(outboundId)
43
+ const resolved = resolveOutbound(outboundRecordId)
44
44
  if (!resolved) {
45
45
  continue
46
46
  }
@@ -48,7 +48,7 @@ export const buildOutboundsById = (
48
48
  outbounds ??= {}
49
49
  // Snapshot resolver-owned values so a host that mutates and reuses its
50
50
  // cached object cannot also mutate the previously published context map.
51
- outbounds[outboundId] = {
51
+ outbounds[outboundRecordId] = {
52
52
  id: resolved.id,
53
53
  ...(resolved.name !== undefined ? { name: resolved.name } : {}),
54
54
  }
@@ -58,8 +58,8 @@ export const buildOutboundsById = (
58
58
  }
59
59
 
60
60
  const areOutboundsEqual = (
61
- previous: OutboundsById | undefined,
62
- next: OutboundsById | undefined
61
+ previous: OutboundsByRecordId | undefined,
62
+ next: OutboundsByRecordId | undefined
63
63
  ): boolean => {
64
64
  if (previous === next) {
65
65
  return true
@@ -75,9 +75,9 @@ const areOutboundsEqual = (
75
75
  }
76
76
 
77
77
  return previousIds.every(
78
- (outboundId) =>
79
- previous[outboundId].id === next[outboundId]?.id &&
80
- previous[outboundId].name === next[outboundId]?.name
78
+ (outboundRecordId) =>
79
+ previous[outboundRecordId].id === next[outboundRecordId]?.id &&
80
+ previous[outboundRecordId].name === next[outboundRecordId]?.name
81
81
  )
82
82
  }
83
83
 
@@ -86,13 +86,13 @@ const areOutboundsEqual = (
86
86
  * the resolved id/name pairs actually change — so context consumers update for
87
87
  * late-arriving outbounds without thrashing on unrelated renders.
88
88
  */
89
- export const useOutboundsById = (
89
+ export const useOutboundsByRecordId = (
90
90
  messages: readonly { metadata?: { outbound_id?: unknown } }[] | undefined,
91
91
  resolveOutbound: OutboundResolver | undefined
92
- ): OutboundsById | undefined => {
93
- const outbounds = buildOutboundsById(messages, resolveOutbound)
92
+ ): OutboundsByRecordId | undefined => {
93
+ const outbounds = buildOutboundsByRecordId(messages, resolveOutbound)
94
94
  const [publishedOutbounds, setPublishedOutbounds] = useState<
95
- OutboundsById | undefined
95
+ OutboundsByRecordId | undefined
96
96
  >(outbounds)
97
97
 
98
98
  if (!areOutboundsEqual(publishedOutbounds, outbounds)) {
@@ -187,11 +187,11 @@ export const SentMessageDeliveryStatus = ({
187
187
  return null
188
188
  }
189
189
 
190
- const outboundId = message.metadata?.outbound_id
190
+ const outboundRecordId = message.metadata?.outbound_id
191
191
  const outboundStatus =
192
192
  message.status !== 'sending' &&
193
193
  message.status !== 'failed' &&
194
- outboundId &&
194
+ outboundRecordId &&
195
195
  resolvedOutbound ? (
196
196
  <OutboundStatus
197
197
  outbound={resolvedOutbound}
@@ -468,10 +468,12 @@ const MemoizedCustomMessage = React.memo(
468
468
 
469
469
  export const CustomMessage = (props: CustomMessageUIComponentProps) => {
470
470
  const messageContext = useMessageContext('CustomMessage')
471
- const outboundsById = useContext(OutboundContext)
472
- const outboundId = messageContext.message.metadata?.outbound_id
471
+ const outboundsByRecordId = useContext(OutboundContext)
472
+ const outboundRecordId = messageContext.message.metadata?.outbound_id
473
473
  const resolvedOutbound =
474
- typeof outboundId === 'string' ? outboundsById?.[outboundId] : undefined
474
+ typeof outboundRecordId === 'string'
475
+ ? outboundsByRecordId?.[outboundRecordId]
476
+ : undefined
475
477
 
476
478
  return (
477
479
  <MemoizedCustomMessage
@@ -67,8 +67,8 @@ export interface MessageMetadata {
67
67
  */
68
68
  sent_from?: 'stack_detail'
69
69
  /**
70
- * Opaque Outbound Record id on automation messages. Hosts resolve this
71
- * server-side to the current automation id and name.
70
+ * Opaque outbound record id on automation messages. The Stream wire field is
71
+ * `outbound_id`; resolver APIs name this value `outboundRecordId` explicitly.
72
72
  */
73
73
  outbound_id?: string
74
74
  }
package/src/types.ts CHANGED
@@ -37,6 +37,7 @@ export type MessageLinkClickHandler = (
37
37
  ) => void
38
38
 
39
39
  export type ResolvedOutbound = {
40
+ /** Automation id referenced by the outbound record. */
40
41
  id: string
41
42
  name?: string
42
43
  }
@@ -44,7 +45,7 @@ export type ResolvedOutbound = {
44
45
  export type OutboundClickHandler = (outbound: ResolvedOutbound) => void
45
46
 
46
47
  export type OutboundResolver = (
47
- outboundId: string
48
+ outboundRecordId: string
48
49
  ) => ResolvedOutbound | undefined
49
50
 
50
51
  export type ChannelPreviewProps = ChannelPreviewUIComponentProps & {
@@ -373,10 +374,11 @@ export interface ChannelViewProps {
373
374
  onOutboundClick?: OutboundClickHandler
374
375
 
375
376
  /**
376
- * Resolves an outbound record id to the current automation id and name. The
377
- * host must provide a new resolver reference when a returned outbound
378
- * changes so ChannelView re-renders and publishes the new value to memoized
379
- * rows. Missing records stay unresolved and render no label.
377
+ * Resolves `metadata.outbound_id` (an outbound record id) to the current
378
+ * automation id and name. The host must provide a new resolver reference
379
+ * when a returned outbound changes so ChannelView re-renders and publishes
380
+ * the new value to memoized rows. Missing records stay unresolved and render
381
+ * no label.
380
382
  */
381
383
  resolveOutbound?: OutboundResolver
382
384