|
1 | 1 | import React from 'react'; |
2 | | -import { Image } from 'react-native'; |
| 2 | +import { Image, ImageProps, TextInputProps } from 'react-native'; |
| 3 | + |
| 4 | +import type { LocalMessage, UserResponse } from 'stream-chat'; |
3 | 5 |
|
4 | 6 | import { Attachment } from '../../components/Attachment/Attachment'; |
5 | 7 | import { AudioAttachment } from '../../components/Attachment/Audio'; |
@@ -64,6 +66,7 @@ import { MessageReplies } from '../../components/Message/MessageItemView/Message |
64 | 66 | import { MessageRepliesAvatars } from '../../components/Message/MessageItemView/MessageRepliesAvatars'; |
65 | 67 | import { MessageStatus } from '../../components/Message/MessageItemView/MessageStatus'; |
66 | 68 | import { MessageSwipeContent } from '../../components/Message/MessageItemView/MessageSwipeContent'; |
| 69 | +import type { MessageTextProps } from '../../components/Message/MessageItemView/MessageTextContainer'; |
67 | 70 | import { MessageTimestamp } from '../../components/Message/MessageItemView/MessageTimestamp'; |
68 | 71 | import { ReactionListBottom } from '../../components/Message/MessageItemView/ReactionList/ReactionListBottom'; |
69 | 72 | import { ReactionListClustered } from '../../components/Message/MessageItemView/ReactionList/ReactionListClustered'; |
@@ -147,10 +150,16 @@ import { DefaultMessageOverlayBackground } from '../../contexts/overlayContext/M |
147 | 150 | import type { MessageActionsProps } from '../../contexts/overlayContext/MessageOverlayHostLayer'; |
148 | 151 |
|
149 | 152 | /** |
150 | | - * All default component implementations used across the SDK. |
151 | | - * These are the components used when no overrides are provided via WithComponents. |
| 153 | + * Normalizes each component entry to React.ComponentType<P>, stripping |
| 154 | + * extra inferred properties (like `displayName: string` from runtime |
| 155 | + * assignments) that would otherwise leak into the override types and |
| 156 | + * force integrators to match them. |
152 | 157 | */ |
153 | | -export const DEFAULT_COMPONENTS = { |
| 158 | +type NormalizeComponents<T> = { |
| 159 | + [K in keyof T]: T[K] extends React.ComponentType<infer P> ? React.ComponentType<P> : T[K]; |
| 160 | +}; |
| 161 | + |
| 162 | +const components = { |
154 | 163 | Attachment, |
155 | 164 | AttachButton, |
156 | 165 | AttachmentPickerContent, |
@@ -300,35 +309,38 @@ export const DEFAULT_COMPONENTS = { |
300 | 309 | MessageOverlayBackground: DefaultMessageOverlayBackground, |
301 | 310 |
|
302 | 311 | // Image |
303 | | - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
304 | | - ImageComponent: Image as React.ComponentType<any>, |
305 | | - |
306 | | - // Optional overrides (no defaults — undefined unless user provides via WithComponents) |
307 | | - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
308 | | - AttachmentPickerIOSSelectMorePhotos: undefined as React.ComponentType<any> | undefined, |
309 | | - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
310 | | - ChatLoadingIndicator: undefined as React.ComponentType<any> | null | undefined, |
311 | | - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
312 | | - CreatePollContent: undefined as React.ComponentType<any> | undefined, |
313 | | - MessageActions: undefined as React.ComponentType<MessageActionsProps> | undefined, |
314 | | - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
315 | | - Input: undefined as React.ComponentType<any> | undefined, |
316 | | - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
317 | | - ListHeaderComponent: undefined as React.ComponentType<any> | undefined, |
318 | | - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
319 | | - MessageContentBottomView: undefined as React.ComponentType<any> | undefined, |
320 | | - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
321 | | - MessageContentLeadingView: undefined as React.ComponentType<any> | undefined, |
322 | | - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
323 | | - MessageContentTopView: undefined as React.ComponentType<any> | undefined, |
324 | | - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
325 | | - MessageContentTrailingView: undefined as React.ComponentType<any> | undefined, |
326 | | - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
327 | | - MessageLocation: undefined as React.ComponentType<any> | undefined, |
328 | | - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
329 | | - MessageSpacer: undefined as React.ComponentType<any> | undefined, |
330 | | - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
331 | | - MessageText: undefined as React.ComponentType<any> | undefined, |
332 | | - // eslint-disable-next-line @typescript-eslint/no-explicit-any |
333 | | - PollContent: undefined as React.ComponentType<any> | undefined, |
| 312 | + ImageComponent: Image as React.ComponentType<ImageProps>, |
334 | 313 | }; |
| 314 | + |
| 315 | +/** |
| 316 | + * Optional component slots that have no default implementation. |
| 317 | + * These are `undefined` unless the integrator provides them via WithComponents. |
| 318 | + */ |
| 319 | +export interface OptionalComponentOverrides { |
| 320 | + AttachmentPickerIOSSelectMorePhotos?: React.ComponentType; |
| 321 | + ChatLoadingIndicator?: React.ComponentType | null; |
| 322 | + CreatePollContent?: React.ComponentType; |
| 323 | + Input?: React.ComponentType<{ |
| 324 | + additionalTextInputProps?: TextInputProps; |
| 325 | + getUsers: () => UserResponse[]; |
| 326 | + }>; |
| 327 | + ListHeaderComponent?: React.ComponentType; |
| 328 | + MessageActions?: React.ComponentType<MessageActionsProps>; |
| 329 | + MessageContentBottomView?: React.ComponentType; |
| 330 | + MessageContentLeadingView?: React.ComponentType; |
| 331 | + MessageContentTopView?: React.ComponentType; |
| 332 | + MessageContentTrailingView?: React.ComponentType; |
| 333 | + MessageLocation?: React.ComponentType<{ message: LocalMessage }>; |
| 334 | + MessageSpacer?: React.ComponentType; |
| 335 | + MessageText?: React.ComponentType<MessageTextProps>; |
| 336 | + PollContent?: React.ComponentType; |
| 337 | +} |
| 338 | + |
| 339 | +/** |
| 340 | + * All default component implementations used across the SDK. |
| 341 | + * These are the components used when no overrides are provided via WithComponents. |
| 342 | + * |
| 343 | + * The `NormalizeComponents` cast ensures that internal details like |
| 344 | + * `displayName: string` don't leak into the public override types. |
| 345 | + */ |
| 346 | +export const DEFAULT_COMPONENTS: NormalizeComponents<typeof components> = components; |
0 commit comments