import React, { createContext, useContext, type ReactNode } from 'react'; import type { SduiBlock } from '@proulr/sdui-contract'; import type { DiscoverNearbyProfileWire } from './lib/discover-profile-formatters'; export type SduiHybridStoryRailProps = { surface: 'discover' | 'vibes'; }; export type SduiHybridProfileCompletionBannerProps = { percent: number; onDismiss: () => void; onComplete: () => void; }; export type SduiHybridDiscoverMapPin = { id: string; lat: number; lng: number; display_name?: string | null; primary_photo_path?: string | null; is_online?: boolean | null; is_hosting?: boolean | null; mood_text?: string | null; distance_m?: number | null; status_label?: string | null; }; export type SduiHybridDiscoverMapProps = { center: { lat: number; lng: number }; label: string; height: number; pins?: SduiHybridDiscoverMapPin[]; onCenterChange: (coords: { lat: number; lng: number }) => void; onPinPress?: (profileId: string) => void; centerMoveToken: number; interactive?: boolean; }; export type SduiHybridDiscoverProfileCardProps = { person: DiscoverNearbyProfileWire; width: number; onPress: () => void; }; export type SduiNativeBlockRenderProps = { block: SduiBlock; data: Record; onAction: (actionId: string, vars?: Record) => void; dataRef?: string; conversationIdRef?: string; peerIdRef?: string; peerNameRef?: string; handleRef?: string; postIdRef?: string; albumIdRef?: string; profileIdRef?: string; }; export type SduiHybridRenderers = { renderStoryRail?: (props: SduiHybridStoryRailProps) => ReactNode; renderProfileCompletionBanner?: (props: SduiHybridProfileCompletionBannerProps) => ReactNode; renderDiscoverMap?: (props: SduiHybridDiscoverMapProps) => ReactNode; renderDiscoverProfileCard?: (props: SduiHybridDiscoverProfileCardProps) => ReactNode; renderDiscoverGrid?: (props: SduiNativeBlockRenderProps) => ReactNode; renderTextField?: (props: { dataRef: string; placeholder: string; value: string; submitActionId?: string; onSubmit: () => void; }) => ReactNode; onDiscoverMapCenterChange?: (coords: { lat: number; lng: number }) => void; renderChatThread?: (props: SduiNativeBlockRenderProps) => ReactNode; renderSocialPostFeed?: (props: SduiNativeBlockRenderProps) => ReactNode; renderThoughtFeed?: (props: SduiNativeBlockRenderProps) => ReactNode; renderProfileView?: (props: SduiNativeBlockRenderProps) => ReactNode; renderProfileSelf?: (props: SduiNativeBlockRenderProps) => ReactNode; renderProfileSetup?: (props: SduiNativeBlockRenderProps) => ReactNode; renderProfileOnboarding?: (props: SduiNativeBlockRenderProps) => ReactNode; renderProfileReport?: (props: SduiNativeBlockRenderProps) => ReactNode; renderAlbumGrid?: (props: SduiNativeBlockRenderProps) => ReactNode; renderAlbumDetail?: (props: SduiNativeBlockRenderProps) => ReactNode; renderNewPostComposer?: (props: SduiNativeBlockRenderProps) => ReactNode; renderNewStoryComposer?: (props: SduiNativeBlockRenderProps) => ReactNode; renderStoryViewersPanel?: (props: SduiNativeBlockRenderProps) => ReactNode; renderPostComments?: (props: SduiNativeBlockRenderProps) => ReactNode; renderSocialProfile?: (props: SduiNativeBlockRenderProps) => ReactNode; renderSettingsHome?: (props: SduiNativeBlockRenderProps) => ReactNode; renderSettingsPage?: (props: SduiNativeBlockRenderProps) => ReactNode; renderChatGroupCreate?: (props: SduiNativeBlockRenderProps) => ReactNode; renderChatGroupInfo?: (props: SduiNativeBlockRenderProps) => ReactNode; renderChatGroupAddMembers?: (props: SduiNativeBlockRenderProps) => ReactNode; renderChatGroupInvite?: (props: SduiNativeBlockRenderProps) => ReactNode; renderDiscoverBrowseLocation?: (props: SduiNativeBlockRenderProps) => ReactNode; renderRightNowFeed?: (props: SduiNativeBlockRenderProps) => ReactNode; renderRightNowCompose?: (props: SduiNativeBlockRenderProps) => ReactNode; renderSegmentedTabs?: (props: { block: SduiBlock; data: Record; onAction: (actionId: string, vars?: Record) => void; segmentsRef?: string; activeRef?: string; actionPrefix?: string; }) => ReactNode; renderEmptyState?: (props: { title: string; hint?: string }) => ReactNode; renderInboxPersonRow?: (props: { block: SduiBlock; data: Record; onAction: (actionId: string, vars?: Record) => void; variant: 'visit' | 'flash' | 'chat'; rowRef: string; actionId?: string; actionParams?: Record; }) => ReactNode; renderInboxSearchField?: (props: { block: SduiBlock; data: Record; onAction: (actionId: string, vars?: Record) => void; placeholder: string; layout: string; segment: string; }) => ReactNode; renderChatInboxCapabilities?: (props: SduiNativeBlockRenderProps) => ReactNode; renderFlashInboxCapabilities?: (props: SduiNativeBlockRenderProps) => ReactNode; renderProfileVisitsCapabilities?: (props: SduiNativeBlockRenderProps) => ReactNode; renderFloatingCreateMenu?: (props: SduiNativeBlockRenderProps) => ReactNode; renderInboxHubChrome?: ( props: SduiNativeBlockRenderProps & { hubRef?: string; activeFilterRef?: string; }, ) => ReactNode; /** * Optional host wrap for screen body (ex.: InboxHubSduiProvider). * Keeps domain providers out of the generic shell. */ wrapScreenBody?: (children: ReactNode) => ReactNode; }; const SduiHybridRendererContext = createContext({}); export function SduiHybridRendererProvider({ value, children, }: { value: SduiHybridRenderers; children: ReactNode; }) { return ( {children} ); } export function useSduiHybridRenderer(): SduiHybridRenderers { return useContext(SduiHybridRendererContext); }