@linktr.ee/messaging-react 3.29.1-rc-1785477229 → 3.29.1
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-BzRQzc30.js.map +1 -1
- package/dist/index-QK8rRCbK.cjs.map +1 -1
- package/dist/index.d.ts +3 -3
- package/package.json +2 -2
- package/src/components/ChannelView.broadcast-name.integration.test.tsx +0 -65
- package/src/components/ChannelView.tsx +6 -3
- package/src/components/CustomMessage/BroadcastNameContext.ts +8 -9
- package/src/types.ts +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-BzRQzc30.js","sources":["../src/providers/MessagingProvider.tsx","../src/hooks/useMessaging.ts","../src/hooks/useChannelStar.ts","../src/utils/resolveConversationParticipant.ts","../src/utils/resolveParticipantDisplayName.ts","../src/components/Avatar/getAvatarEmoji.ts","../src/components/Avatar/index.tsx","../src/hooks/useChannelModerationActions.ts","../src/components/ActionButton/index.tsx","../src/components/ChannelActionsMenu/index.tsx","../src/components/ChannelHeaderRedesign.tsx","../src/components/CustomDateSeparator/index.tsx","../src/hooks/useMessageVote.ts","../src/utils/getMessageDisplayText.ts","../src/utils/cdnImageUrl.ts","../src/components/AttachmentCard/utils/mimeType.ts","../src/components/AttachmentCard/utils/icons.ts","../src/components/AttachmentCard/MediaPlayer.tsx","../src/components/AttachmentCard/Thumbnail.tsx","../src/components/AttachmentCard/index.tsx","../src/components/MediaMessage/index.tsx","../src/components/MessageAttachment/_shared/Bubble.tsx","../src/components/MessageAttachment/_shared/DismissButton.tsx","../src/components/MessageAttachment/types.ts","../src/components/MessageAttachment/Audio/index.tsx","../src/components/MessageAttachment/_shared/fileMeta.ts","../src/components/MessageAttachment/_shared/CompactDocumentRow.tsx","../src/components/MessageAttachment/_shared/triggerDownload.ts","../src/components/MessageAttachment/File/index.tsx","../src/components/MessageAttachment/_shared/CarouselNav.tsx","../src/components/MessageAttachment/_shared/DownloadAction.tsx","../src/components/MessageAttachment/_shared/useCarousel.ts","../src/components/MessageAttachment/_shared/ViewerShell.tsx","../src/components/MessageAttachment/_shared/ImageViewer.tsx","../src/components/MessageAttachment/_shared/MediaStackGrid.tsx","../src/components/MessageAttachment/_shared/useViewer.ts","../src/components/MessageAttachment/Image/index.tsx","../src/components/MessageAttachment/_shared/PdfViewer.tsx","../src/components/MessageAttachment/Pdf/index.tsx","../src/components/MessageAttachment/_shared/VideoViewer.tsx","../src/components/MessageAttachment/Video/index.tsx","../src/components/MessageAttachment/index.tsx","../src/components/CustomMessage/BroadcastNameContext.ts","../src/components/CustomMessage/LockedAttachment/types.ts","../src/components/CustomMessage/context.tsx","../src/components/CustomMessage/LockedAttachment/index.tsx","../src/components/CustomMessage/MessageTag.tsx","../src/components/CustomMessage/MessageVoteButtons.tsx","../src/components/CustomMessage/SentMessageDeliveryStatus.tsx","../src/components/LinkAttachment/components/_shared/normalizeExternalHref.ts","../src/components/LinkAttachment/components/_shared/CardCta.tsx","../src/components/LinkAttachment/components/_shared/CardBody.tsx","../src/components/LinkAttachment/components/_shared/CardShell.tsx","../src/components/LinkAttachment/components/_shared/CardThumbnail.tsx","../../../node_modules/culori/src/rgb/parseNumber.js","../../../node_modules/culori/src/colors/named.js","../../../node_modules/culori/src/rgb/parseNamed.js","../../../node_modules/culori/src/rgb/parseHex.js","../../../node_modules/culori/src/util/regex.js","../../../node_modules/culori/src/rgb/parseRgbLegacy.js","../../../node_modules/culori/src/_prepare.js","../../../node_modules/culori/src/converter.js","../../../node_modules/culori/src/modes.js","../../../node_modules/culori/src/parse.js","../../../node_modules/culori/src/rgb/parseRgb.js","../../../node_modules/culori/src/rgb/parseTransparent.js","../../../node_modules/culori/src/interpolate/lerp.js","../../../node_modules/culori/src/interpolate/piecewise.js","../../../node_modules/culori/src/interpolate/linear.js","../../../node_modules/culori/src/fixup/alpha.js","../../../node_modules/culori/src/rgb/definition.js","../../../node_modules/culori/src/a98/convertA98ToXyz65.js","../../../node_modules/culori/src/a98/convertXyz65ToA98.js","../../../node_modules/culori/src/lrgb/convertRgbToLrgb.js","../../../node_modules/culori/src/xyz65/convertRgbToXyz65.js","../../../node_modules/culori/src/lrgb/convertLrgbToRgb.js","../../../node_modules/culori/src/xyz65/convertXyz65ToRgb.js","../../../node_modules/culori/src/a98/definition.js","../../../node_modules/culori/src/util/normalizeHue.js","../../../node_modules/culori/src/fixup/hue.js","../../../node_modules/culori/src/cubehelix/constants.js","../../../node_modules/culori/src/cubehelix/convertRgbToCubehelix.js","../../../node_modules/culori/src/cubehelix/convertCubehelixToRgb.js","../../../node_modules/culori/src/difference.js","../../../node_modules/culori/src/average.js","../../../node_modules/culori/src/cubehelix/definition.js","../../../node_modules/culori/src/lch/convertLabToLch.js","../../../node_modules/culori/src/lch/convertLchToLab.js","../../../node_modules/culori/src/xyz65/constants.js","../../../node_modules/culori/src/constants.js","../../../node_modules/culori/src/lab65/convertLab65ToXyz65.js","../../../node_modules/culori/src/lab65/convertLab65ToRgb.js","../../../node_modules/culori/src/lab65/convertXyz65ToLab65.js","../../../node_modules/culori/src/lab65/convertRgbToLab65.js","../../../node_modules/culori/src/dlch/constants.js","../../../node_modules/culori/src/dlch/convertDlchToLab65.js","../../../node_modules/culori/src/dlch/convertLab65ToDlch.js","../../../node_modules/culori/src/dlab/definition.js","../../../node_modules/culori/src/dlch/definition.js","../../../node_modules/culori/src/hsi/convertHsiToRgb.js","../../../node_modules/culori/src/hsi/convertRgbToHsi.js","../../../node_modules/culori/src/hsi/definition.js","../../../node_modules/culori/src/hsl/convertHslToRgb.js","../../../node_modules/culori/src/hsl/convertRgbToHsl.js","../../../node_modules/culori/src/util/hue.js","../../../node_modules/culori/src/hsl/parseHslLegacy.js","../../../node_modules/culori/src/hsl/parseHsl.js","../../../node_modules/culori/src/hsl/definition.js","../../../node_modules/culori/src/hsv/convertHsvToRgb.js","../../../node_modules/culori/src/hsv/convertRgbToHsv.js","../../../node_modules/culori/src/hsv/definition.js","../../../node_modules/culori/src/hwb/convertHwbToRgb.js","../../../node_modules/culori/src/hwb/convertRgbToHwb.js","../../../node_modules/culori/src/hwb/parseHwb.js","../../../node_modules/culori/src/hwb/definition.js","../../../node_modules/culori/src/hdr/constants.js","../../../node_modules/culori/src/hdr/transfer.js","../../../node_modules/culori/src/itp/convertItpToXyz65.js","../../../node_modules/culori/src/itp/convertXyz65ToItp.js","../../../node_modules/culori/src/itp/definition.js","../../../node_modules/culori/src/jab/convertXyz65ToJab.js","../../../node_modules/culori/src/jab/convertJabToXyz65.js","../../../node_modules/culori/src/jab/convertRgbToJab.js","../../../node_modules/culori/src/jab/convertJabToRgb.js","../../../node_modules/culori/src/jab/definition.js","../../../node_modules/culori/src/jch/convertJabToJch.js","../../../node_modules/culori/src/jch/convertJchToJab.js","../../../node_modules/culori/src/jch/definition.js","../../../node_modules/culori/src/xyz50/constants.js","../../../node_modules/culori/src/lab/convertLabToXyz50.js","../../../node_modules/culori/src/xyz50/convertXyz50ToRgb.js","../../../node_modules/culori/src/lab/convertLabToRgb.js","../../../node_modules/culori/src/xyz50/convertRgbToXyz50.js","../../../node_modules/culori/src/lab/convertXyz50ToLab.js","../../../node_modules/culori/src/lab/convertRgbToLab.js","../../../node_modules/culori/src/lab/parseLab.js","../../../node_modules/culori/src/lab/definition.js","../../../node_modules/culori/src/lab65/definition.js","../../../node_modules/culori/src/lch/parseLch.js","../../../node_modules/culori/src/lch/definition.js","../../../node_modules/culori/src/lch65/definition.js","../../../node_modules/culori/src/lchuv/convertLuvToLchuv.js","../../../node_modules/culori/src/lchuv/convertLchuvToLuv.js","../../../node_modules/culori/src/luv/convertXyz50ToLuv.js","../../../node_modules/culori/src/luv/convertLuvToXyz50.js","../../../node_modules/culori/src/lchuv/definition.js","../../../node_modules/culori/src/lrgb/definition.js","../../../node_modules/culori/src/luv/definition.js","../../../node_modules/culori/src/oklab/convertLrgbToOklab.js","../../../node_modules/culori/src/oklab/convertRgbToOklab.js","../../../node_modules/culori/src/oklab/convertOklabToLrgb.js","../../../node_modules/culori/src/oklab/convertOklabToRgb.js","../../../node_modules/culori/src/okhsl/helpers.js","../../../node_modules/culori/src/okhsl/convertOklabToOkhsl.js","../../../node_modules/culori/src/okhsl/convertOkhslToOklab.js","../../../node_modules/culori/src/okhsl/modeOkhsl.js","../../../node_modules/culori/src/okhsv/convertOklabToOkhsv.js","../../../node_modules/culori/src/okhsv/convertOkhsvToOklab.js","../../../node_modules/culori/src/okhsv/modeOkhsv.js","../../../node_modules/culori/src/oklab/parseOklab.js","../../../node_modules/culori/src/oklab/definition.js","../../../node_modules/culori/src/oklch/parseOklch.js","../../../node_modules/culori/src/oklch/definition.js","../../../node_modules/culori/src/p3/convertP3ToXyz65.js","../../../node_modules/culori/src/p3/convertXyz65ToP3.js","../../../node_modules/culori/src/p3/definition.js","../../../node_modules/culori/src/prophoto/convertXyz50ToProphoto.js","../../../node_modules/culori/src/prophoto/convertProphotoToXyz50.js","../../../node_modules/culori/src/prophoto/definition.js","../../../node_modules/culori/src/rec2020/convertXyz65ToRec2020.js","../../../node_modules/culori/src/rec2020/convertRec2020ToXyz65.js","../../../node_modules/culori/src/rec2020/definition.js","../../../node_modules/culori/src/xyb/constants.js","../../../node_modules/culori/src/xyb/convertRgbToXyb.js","../../../node_modules/culori/src/xyb/convertXybToRgb.js","../../../node_modules/culori/src/xyb/definition.js","../../../node_modules/culori/src/xyz50/definition.js","../../../node_modules/culori/src/xyz65/convertXyz65ToXyz50.js","../../../node_modules/culori/src/xyz65/convertXyz50ToXyz65.js","../../../node_modules/culori/src/xyz65/definition.js","../../../node_modules/culori/src/yiq/convertRgbToYiq.js","../../../node_modules/culori/src/yiq/convertYiqToRgb.js","../../../node_modules/culori/src/yiq/definition.js","../../../node_modules/culori/src/formatter.js","../../../node_modules/culori/src/clamp.js","../../../node_modules/culori/src/wcag.js","../../../node_modules/culori/src/index.js","../src/components/LinkAttachment/components/_shared/hex.ts","../src/components/LinkAttachment/components/_shared/chinContrast.ts","../src/components/LinkAttachment/components/_shared/accentSurface.ts","../src/components/LinkAttachment/components/_shared/useChinPalette.ts","../src/components/LinkAttachment/components/Composer/Card.tsx","../src/components/LinkAttachment/components/_shared/BubbleTail.tsx","../src/components/LinkAttachment/components/Received/Card.tsx","../src/components/LinkAttachment/components/Sent/Card.tsx","../src/components/LinkAttachment/index.tsx","../src/components/CustomMessage/StreamAttachmentMessage.tsx","../src/components/CustomMessage/index.tsx","../src/components/CustomMessage/CustomMessageActions.tsx","../src/components/CustomLinkPreviewList/index.tsx","../src/components/CustomMessageInput/index.tsx","../src/components/CustomSystemMessage/index.tsx","../src/components/CustomTypingIndicator/DmAgentContext.ts","../src/components/CustomTypingIndicator/index.tsx","../src/components/MessagingShell/ChannelEmptyState.tsx","../src/components/Loading/index.tsx","../src/components/MessagingShell/LoadingState.tsx","../src/components/ChannelView.tsx","../src/components/MessagingShell/ErrorState.tsx","../src/components/MessagingShell/index.tsx","../src/hooks/useRestorePendingMessages.ts","../src/components/ChannelList/ChannelListContext.tsx","../src/utils/formatRelativeTime.ts","../src/components/ChannelList/CustomChannelPreview.tsx","../src/components/ChannelList/index.tsx","../src/components/MessageBubble/components/_shared/bubbleTail.tsx","../src/components/MessageBubble/components/_shared/BubbleShell.tsx","../src/components/MessageBubble/components/Received/Card.tsx","../src/components/MessageBubble/components/Sent/Card.tsx","../src/components/MessageBubble/index.tsx","../src/components/FaqList/FaqListItem.tsx","../src/components/FaqList/index.tsx"],"sourcesContent":["/* eslint-disable react-hooks/refs, react-hooks/set-state-in-effect -- pre-existing pattern flagged by the React\n Compiler rules added in eslint-plugin-react-hooks v7; refactoring it is\n out of scope for the lint toolchain upgrade. */\nimport { StreamChatService } from '@linktr.ee/messaging-core'\nimport React, {\n createContext,\n useContext,\n useEffect,\n useState,\n useRef,\n useCallback,\n} from 'react'\nimport { StreamChat } from 'stream-chat'\nimport { Chat } from 'stream-chat-react'\n\nimport type { MessagingProviderProps, MessagingCapabilities } from '../types'\n\n/**\n * Context value for messaging state and service\n */\nexport interface MessagingContextValue {\n service: StreamChatService | null\n client: StreamChat | null // Stream Chat client\n isConnected: boolean\n isLoading: boolean\n error: string | null\n capabilities: MessagingCapabilities\n refreshConnection: () => Promise<void>\n debug: boolean\n}\n\nconst MessagingContext = createContext<MessagingContextValue>({\n service: null,\n client: null,\n isConnected: false,\n isLoading: false,\n error: null,\n capabilities: {},\n refreshConnection: async () => {},\n debug: false,\n})\n\n/**\n * Hook to access messaging context\n */\nexport const useMessagingContext = () => useContext(MessagingContext)\n\n/**\n * Provider component that wraps messaging-core with React state management\n */\nexport const MessagingProvider: React.FC<MessagingProviderProps> = ({\n children,\n user,\n serviceConfig,\n apiKey,\n capabilities = {},\n debug = false,\n client: injectedClient,\n}) => {\n // Create debug logger that respects the debug prop\n const debugLog = useCallback(\n (message: string, ...args: unknown[]) => {\n if (debug) {\n console.log(`🔥 [MessagingProvider] ${message}`, ...args)\n }\n },\n [debug]\n )\n\n debugLog('🔄 RENDER START', {\n userId: user?.id,\n apiKey: apiKey?.substring(0, 8) + '...',\n serviceConfig: !!serviceConfig,\n capabilities: Object.keys(capabilities),\n })\n\n const [service, setService] = useState<StreamChatService | null>(null)\n const [client, setClient] = useState<StreamChat | null>(null)\n const [isConnected, setIsConnected] = useState(false)\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n // Prevent multiple concurrent connection attempts\n const connectingRef = useRef(false)\n\n // The single service instance, for teardown in the client-cleanup effect.\n const serviceRef = useRef<StreamChatService | null>(null)\n\n // serviceConfig / debug are read at service-creation time via refs so that\n // changing them does not recreate the service (and re-adopt the live client).\n // The service is created once per client lifetime (apiKey); the connection is\n // driven by `user`. Real consumers pass a stable, memoized serviceConfig.\n const serviceConfigRef = useRef(serviceConfig)\n serviceConfigRef.current = serviceConfig\n const debugRef = useRef(debug)\n debugRef.current = debug\n\n // Track renders and prop changes\n const prevPropsRef = useRef({\n userId: user?.id,\n apiKey,\n serviceConfig,\n capabilities,\n })\n const renderCountRef = useRef(0)\n renderCountRef.current++\n\n debugLog('📊 RENDER INFO', {\n renderCount: renderCountRef.current,\n currentProps: { userId: user?.id, apiKey: apiKey?.substring(0, 8) + '...' },\n propChanges: {\n userChanged: prevPropsRef.current.userId !== user?.id,\n apiKeyChanged: prevPropsRef.current.apiKey !== apiKey,\n serviceConfigChanged:\n prevPropsRef.current.serviceConfig !== serviceConfig,\n capabilitiesChanged: prevPropsRef.current.capabilities !== capabilities,\n },\n })\n\n prevPropsRef.current = {\n userId: user?.id,\n apiKey,\n serviceConfig,\n capabilities,\n }\n\n // Construct the Stream client synchronously so <Chat> can render against a\n // stable instance on the very first render. Without this the subtree mounted\n // as a bare `children` while connecting, then remounted inside <Chat> once\n // connectUser resolved (~0.8s later) because the children's parent element\n // changed — re-running every mount effect (refetches, Stream listeners,\n // page-view events) and resetting transient state. This client is injected\n // into the service below, so connectUser connects this exact instance.\n //\n // Stored in a ref (not useMemo) so its identity is *guaranteed* stable for the\n // apiKey's lifetime. useMemo is unsafe here: React may discard a memo and\n // recompute it, which would mint a new client, re-run the service-init effect,\n // and tear down + rebuild the live connection — the very remount this fix\n // exists to prevent. Both effects below key on `chatClient`, so it must not\n // depend on memo retention. One client per provider mount (keyed on apiKey) —\n // not the process-wide StreamChat.getInstance, which is shared across keys and\n // provider instances.\n const clientRef = useRef<{ apiKey: string; client: StreamChat } | null>(null)\n if (!injectedClient && apiKey && clientRef.current?.apiKey !== apiKey) {\n clientRef.current = { apiKey, client: new StreamChat(apiKey) }\n }\n // An injected client takes precedence and short-circuits the apiKey-derived\n // client, the service, and the connect/disconnect lifecycle below — the\n // caller owns that instance (offline/dev via `createMockMessagingClient`, or\n // a test). Otherwise fall back to the apiKey-derived client as before.\n const chatClient = injectedClient\n ? injectedClient\n : apiKey\n ? (clientRef.current?.client ?? null)\n : null\n\n // Create the service once per client lifetime (apiKey). Keyed on `chatClient`\n // — NOT on serviceConfig/debug — so those changing does not spin up a second\n // service that would re-adopt the live client and race the in-flight connect.\n // serviceConfig/debug are read from refs at creation. There is therefore a\n // single service per client, which owns the connection lifecycle and tracks\n // the active user; `user` changes reconnect through it.\n useEffect(() => {\n const currentRender = renderCountRef.current\n const currentConfig = serviceConfigRef.current\n\n // An injected client owns its own connection — never create a service or\n // connect for it. Reset all apiKey-path connection state (service, client,\n // isConnected, error, isLoading): while injected these are masked by the\n // context, but on a later return to apiKey mode they would leak back —\n // before the fresh service reconnects — feeding the user-connection effect\n // a stale service and MessagingShell (which gates its load on\n // `client && isConnected`) a disconnected client to queryChannels on.\n if (injectedClient) {\n serviceRef.current = null\n setService(null)\n setClient(null)\n setIsConnected(false)\n setError(null)\n setIsLoading(false)\n return\n }\n\n if (!apiKey || !chatClient || !currentConfig) {\n debugLog('⚠️ SERVICE INIT SKIPPED', {\n renderCount: currentRender,\n reason: 'Missing apiKey, client, or serviceConfig',\n })\n return\n }\n\n debugLog('🚀 CREATING SERVICE', {\n renderCount: currentRender,\n apiKey: apiKey?.substring(0, 8) + '...',\n })\n\n const newService = new StreamChatService({\n ...currentConfig,\n apiKey,\n debug: debugRef.current,\n client: chatClient,\n })\n\n serviceRef.current = newService\n setService(newService)\n debugLog('✅ SERVICE SET', {\n renderCount: currentRender,\n serviceInstance: !!newService,\n })\n\n // No disconnect on cleanup here — disconnection is owned by the\n // client-cleanup effect below, keyed on `chatClient` (apiKey) and unmount.\n // eslint-disable-next-line react-hooks/exhaustive-deps -- serviceConfig/debug/debugLog are read via refs by design (see above); recreating on them would re-adopt the live client\n }, [apiKey, chatClient, injectedClient])\n\n // Track if we've already connected this user with this service to prevent duplicate connections\n const connectedUserRef = useRef<{\n serviceId: StreamChatService\n userId: string\n } | null>(null)\n\n // Connect user when service and user are available\n useEffect(() => {\n debugLog('🔗 USER CONNECTION EFFECT TRIGGERED', {\n hasService: !!service,\n hasUser: !!user,\n userId: user?.id,\n isConnecting: connectingRef.current,\n isConnected: isConnected,\n dependencies: { service: !!service, userId: user?.id },\n })\n\n // The injected client owns its own connection — never connect a service for\n // it. Without this guard a `user` change in injected-client mode would run\n // service.connectUser on a stale apiKey-path service (the toggle case).\n if (injectedClient) {\n return\n }\n\n if (!service || !user) {\n debugLog('⚠️ USER CONNECTION SKIPPED', 'Missing service or user')\n return\n }\n\n if (connectingRef.current) {\n debugLog('⚠️ USER CONNECTION SKIPPED', 'Already connecting')\n return\n }\n\n // Check if we've already connected this exact user with this exact service instance\n if (\n connectedUserRef.current?.serviceId === service &&\n connectedUserRef.current?.userId === user.id\n ) {\n debugLog(\n '⚠️ USER CONNECTION SKIPPED',\n 'Already connected this user with this service'\n )\n return\n }\n\n const connectUser = async () => {\n debugLog('🚀 STARTING USER CONNECTION', { userId: user.id })\n connectingRef.current = true\n setIsLoading(true)\n setError(null)\n\n try {\n debugLog('📞 CALLING SERVICE.CONNECTUSER', { userId: user.id })\n const streamClient = await service.connectUser(user)\n setClient(streamClient)\n setIsConnected(true)\n connectedUserRef.current = { serviceId: service, userId: user.id } // Mark as connected\n debugLog('✅ USER CONNECTION SUCCESS', {\n userId: user.id,\n clientId: streamClient.userID,\n })\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : 'Connection failed'\n setError(errorMessage)\n debugLog('❌ USER CONNECTION ERROR', {\n userId: user.id,\n error: errorMessage,\n })\n } finally {\n setIsLoading(false)\n connectingRef.current = false\n debugLog('🔄 USER CONNECTION FINISHED', {\n userId: user.id,\n isConnected,\n })\n }\n }\n\n connectUser()\n }, [service, user, debugLog, isConnected, injectedClient])\n\n // Disconnect tied to the client's lifetime: only when `chatClient` changes\n // (i.e. `apiKey` changes) or the provider unmounts — never on a mere\n // serviceConfig/debug change, which reuses the same client. Uses `serviceRef`\n // so the disconnect goes through the latest service instance. Deliberately\n // keyed on `chatClient` only: depending on `debugLog` (which changes identity\n // when the `debug` prop toggles) would tear down the live client just for a\n // logging change.\n useEffect(() => {\n const client = chatClient\n return () => {\n if (!client) return\n connectedUserRef.current = null // Reset connection tracking\n serviceRef.current?.disconnectUser().catch(console.error)\n }\n }, [chatClient])\n\n const refreshConnection = useCallback(async () => {\n debugLog('🔄 REFRESH CONNECTION CALLED', {\n hasService: !!service,\n hasUser: !!user,\n })\n\n // The injected client owns its own connection lifecycle — refresh is a\n // no-op. Guarding here (not just the context fields) stops a stale\n // apiKey-path `service` from being disconnected/reconnected if the same\n // provider previously connected via apiKey and then received a client.\n if (injectedClient) {\n return\n }\n\n if (!service || !user) {\n debugLog('⚠️ REFRESH CONNECTION SKIPPED', 'Missing service or user')\n return\n }\n\n debugLog('🚀 STARTING CONNECTION REFRESH', { userId: user.id })\n setIsLoading(true)\n try {\n debugLog('🔌 DISCONNECTING FOR REFRESH')\n await service.disconnectUser()\n debugLog('📞 RECONNECTING FOR REFRESH')\n const streamClient = await service.connectUser(user)\n setClient(streamClient)\n setIsConnected(true)\n setError(null)\n debugLog('✅ CONNECTION REFRESH SUCCESS', { userId: user.id })\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Refresh failed'\n setError(errorMessage)\n debugLog('❌ CONNECTION REFRESH ERROR', {\n userId: user.id,\n error: errorMessage,\n })\n } finally {\n setIsLoading(false)\n debugLog('🔄 CONNECTION REFRESH FINISHED', { userId: user.id })\n }\n }, [service, user, debugLog, injectedClient])\n\n // Memoize context value to prevent unnecessary re-renders\n const contextValue: MessagingContextValue = React.useMemo(() => {\n debugLog('💫 CONTEXT VALUE MEMOIZATION', {\n hasService: !!service,\n hasClient: !!client,\n isConnected,\n isLoading,\n hasError: !!error,\n capabilitiesKeys: Object.keys(capabilities),\n })\n\n return {\n // With an injected client, expose no service — the injected client owns\n // its lifecycle and there is no backend to reach. Suppressing it stops\n // service-dependent paths (channel creation, block/unblock) from calling\n // a stale apiKey-path service if the same provider previously connected.\n service: injectedClient ? null : service,\n // An injected client is already connected and owns its lifecycle, so\n // surface it directly and report a clean connected state — the apiKey\n // path's `client`/`isLoading`/`error` (from connectUser) must not leak\n // through if the same provider previously attempted an apiKey connect.\n client: injectedClient ?? client,\n isConnected: injectedClient ? true : isConnected,\n isLoading: injectedClient ? false : isLoading,\n error: injectedClient ? null : error,\n capabilities,\n refreshConnection,\n debug,\n }\n }, [\n service,\n client,\n injectedClient,\n isConnected,\n isLoading,\n error,\n capabilities,\n refreshConnection,\n debug,\n debugLog,\n ])\n\n debugLog('🔄 RENDER END', {\n renderCount: renderCountRef.current,\n willRenderChat: !!chatClient,\n contextValueReady: !!contextValue,\n })\n\n return (\n <MessagingContext.Provider value={contextValue}>\n {chatClient ? (\n <Chat\n client={chatClient}\n customClasses={{\n channelList:\n 'str-chat__channel-list str-chat__channel-list-react bg-transparent lg:border-r-2 border-r-0 border-[#0000000A]',\n }}\n >\n {children}\n </Chat>\n ) : (\n children\n )}\n </MessagingContext.Provider>\n )\n}\n","import { useMessagingContext } from '../providers/MessagingProvider';\nimport type { MessagingContextValue } from '../providers/MessagingProvider';\n\n/**\n * Hook to access messaging service and state\n */\nexport const useMessaging = (): MessagingContextValue => {\n return useMessagingContext();\n};\n","/* eslint-disable react-hooks/set-state-in-effect -- pre-existing pattern flagged by the React\n Compiler rules added in eslint-plugin-react-hooks v7; refactoring it is\n out of scope for the lint toolchain upgrade. */\nimport { useEffect, useState } from 'react'\nimport { Channel, Event } from 'stream-chat'\n\nexport const useChannelStar = (channel?: Channel) => {\n const [isChannelStarred, setIsChannelStarred] = useState(\n !!channel?.state?.membership?.pinned_at\n )\n\n useEffect(() => {\n if (!channel) {\n setIsChannelStarred(false)\n return\n }\n\n setIsChannelStarred(!!channel.state.membership?.pinned_at)\n\n const handleMemberUpdate = (event: Event) => {\n setIsChannelStarred(\n event?.member ? !!event.member.pinned_at : !!channel.state.membership?.pinned_at\n )\n }\n\n channel.on('member.updated', handleMemberUpdate)\n\n return () => {\n channel.off('member.updated', handleMemberUpdate)\n }\n }, [channel])\n\n return isChannelStarred\n}\n","import {\n isOfficialChannel,\n OFFICIAL_SENDER_USER_ID,\n} from '@linktr.ee/messaging-taxonomy'\nimport type { Channel } from 'stream-chat'\n\ntype ChannelMembers = NonNullable<Channel['state']>['members']\ntype ChannelMember = ChannelMembers[string]\n\n/**\n * Resolves the member to display as the conversation's \"other party\".\n *\n * For a normal 1:1 channel this is the member that isn't the current user. The\n * official channel is special: its display identity is always the official\n * sender (\"Linktree\"), regardless of who is viewing. That matters because an\n * unverified sensitive linker reads the official channel as a guest whose\n * random Stream id isn't a member, so the \"not me\" heuristic would otherwise\n * fall back to the linker's own member and show their name instead of Linktree.\n */\nexport function resolveConversationParticipant(\n members: ChannelMembers | undefined,\n currentUserId: string | undefined,\n channelType: string | undefined\n): ChannelMember | undefined {\n const memberList = Object.values(members || {})\n\n if (isOfficialChannel(channelType)) {\n const officialSender = memberList.find(\n (member) => member.user?.id === OFFICIAL_SENDER_USER_ID\n )\n if (officialSender) return officialSender\n }\n\n return memberList.find(\n (member) => member.user?.id && member.user.id !== currentUserId\n )\n}\n","const UUID_REGEX =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\n\nexport type ParticipantDisplayUser = {\n id?: string\n name?: string | null\n username?: string | null\n}\n\nexport function isUuidLike(value: string): boolean {\n return UUID_REGEX.test(value.trim())\n}\n\nfunction isUsableDisplayValue(\n value: string | null | undefined,\n userId?: string\n): value is string {\n const trimmed = value?.trim()\n if (!trimmed) return false\n if (userId && trimmed === userId) return false\n // Followers with no real name were historically provisioned in Stream Chat with a\n // placeholder name of the form `Follower <id>` (the string \"Follower \" + the user id).\n // Treat it as missing so surfaces fall back to their own label instead of leaking the\n // internal placeholder as a display name (MES-1077).\n if (userId && trimmed === `Follower ${userId}`) return false\n return !isUuidLike(trimmed)\n}\n\n/**\n * Resolves a human-readable participant label from Stream user fields.\n * Never falls back to user.id. UUID-like names are treated as missing.\n */\nexport function resolveParticipantDisplayName(\n user?: ParticipantDisplayUser | null\n): string {\n if (isUsableDisplayValue(user?.name, user?.id)) {\n return user.name.trim()\n }\n\n if (isUsableDisplayValue(user?.username, user?.id)) {\n return user.username.trim()\n }\n\n return 'Unknown member'\n}\n","/**\n * Fruit emojis paired with their avatar background color.\n * Single source of truth for both `getAvatarEmoji` and `getAvatarBgColor`.\n */\nconst FRUITS = [\n { emoji: '🍎', bgColor: '#FFD1DD' }, // Apple\n { emoji: '🍌', bgColor: '#FFF1C9' }, // Banana\n { emoji: '🍇', bgColor: '#E6D9FF' }, // Grape\n { emoji: '🍊', bgColor: '#D6F4FF' }, // Orange\n { emoji: '🍓', bgColor: '#FFE0AE' }, // Strawberry\n { emoji: '🥥', bgColor: '#F7E7D8' }, // Coconut\n { emoji: '🍒', bgColor: '#DFF4D8' }, // Cherry\n { emoji: '🥭', bgColor: '#FFD8C2' }, // Mango\n { emoji: '🍉', bgColor: '#D6EBFF' }, // Watermelon\n { emoji: '🍋', bgColor: '#CAEEB5' }, // Lemon\n { emoji: '🥝', bgColor: '#FFE7C7' }, // Kiwi\n { emoji: '🫒', bgColor: '#F6E3B4' }, // Olive\n { emoji: '🍈', bgColor: '#D9F7E1' }, // Melon\n]\n\n/**\n * Simple hash function to convert string to number\n */\nfunction hashString(str: string): number {\n let hash = 0\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i)\n hash = (hash << 5) - hash + char\n hash = hash & hash // Convert to 32-bit integer\n }\n return Math.abs(hash)\n}\n\n/**\n * Pick a consistent fruit for an id string\n */\nfunction getFruit(id: string) {\n return FRUITS[hashString(id) % FRUITS.length]\n}\n\n/**\n * Get a fruit emoji based on an id string\n * @param id - The string id to generate emoji from\n * @returns A fruit emoji string\n */\nexport function getAvatarEmoji(id: string): string {\n return getFruit(id).emoji\n}\n\n/**\n * Get the background color paired with an id's fruit emoji\n * @param id - The string id to generate the color from\n * @returns A hex color string\n */\nexport function getAvatarBgColor(id: string): string {\n return getFruit(id).bgColor\n}\n","import { StarIcon } from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React from 'react'\n\nimport { getAvatarBgColor, getAvatarEmoji } from './getAvatarEmoji'\n\nexport interface AvatarProps {\n id: string\n name: string\n image?: string\n size?: number\n className?: string\n starred?: boolean\n shape?: 'squircle' | 'circle'\n dmAgentEnabled?: boolean\n}\n\n/**\n * Avatar component that displays a user image or colored initial fallback\n */\nexport const Avatar = ({\n id,\n image,\n size = 40,\n className,\n starred = false,\n shape = 'squircle',\n dmAgentEnabled = false,\n}: AvatarProps) => {\n const emoji = getAvatarEmoji(id)\n const bgColor = getAvatarBgColor(id)\n\n // Small avatars scale the emoji with the avatar so it doesn't overpower a\n // tiny circle — a fixed floor read ~60% of a 17px avatar vs ~35% at 40px.\n // Larger avatars keep fixed sizes. 0.45 is continuous with the 14px step at\n // 32px; lower it to shrink small emoji further.\n const SMALL_EMOJI_RATIO = 0.45\n const getFontSize = () => {\n if (size < 32) return Math.round(size * SMALL_EMOJI_RATIO)\n if (size < 56) return 14\n if (size < 120) return 18\n return 36\n }\n\n const fontSize = getFontSize()\n // Match design treatment: 2px AI border at 40px avatar size.\n const aiBorderWidth = size >= 40 ? 2 : 1\n\n const borderStyle =\n shape === 'circle'\n ? { borderRadius: '50%' }\n : { borderRadius: '1rem' }\n\n const avatarInner = (\n <div className=\"h-full w-full overflow-hidden\" style={borderStyle}>\n {image ? (\n <img\n src={image}\n alt=\"\"\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <div\n aria-hidden=\"true\"\n className={classNames(\n 'avatar-fallback flex h-full w-full items-center justify-center font-semibold select-none transition-colors'\n )}\n style={{ fontSize, lineHeight: 1 }}\n >\n {emoji}\n </div>\n )}\n </div>\n )\n\n return (\n <div\n className={classNames(\n 'relative flex-shrink-0',\n className\n )}\n style={{\n '--str-chat__avatar-size': `${size}px`,\n width: `${size}px`,\n height: `${size}px`,\n backgroundColor: image ? undefined : bgColor,\n ...borderStyle,\n } as React.CSSProperties}\n >\n {starred && (\n <div\n aria-hidden=\"true\"\n className=\"absolute -left-1.5 -top-1.5 z-10 flex size-5 items-center justify-center rounded-full bg-white shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_4px_8px_rgba(0,0,0,0.06)]\"\n >\n <StarIcon className=\"size-3 text-yellow-600\" weight=\"duotone\" />\n </div>\n )}\n <div\n data-testid=\"avatar-ring\"\n className={classNames(\n 'h-full w-full',\n 'bg-transparent'\n )}\n style={{\n ...borderStyle,\n ...(dmAgentEnabled && {\n borderWidth: `${aiBorderWidth}px`,\n borderStyle: 'solid',\n borderColor: 'var(--AI-Gradient, #7F22FE)',\n boxShadow: 'inset 0 1px 2px 0 rgba(255, 255, 255, 0.5)',\n }),\n }}\n >\n {avatarInner}\n </div>\n </div>\n )\n}\n","/* eslint-disable react-hooks/set-state-in-effect -- pre-existing pattern flagged by the React\n Compiler rules added in eslint-plugin-react-hooks v7; refactoring it is\n out of scope for the lint toolchain upgrade. */\nimport { useEffect, useState } from 'react'\nimport type { Channel as ChannelType, ChannelMemberResponse } from 'stream-chat'\n\nimport { useMessagingContext } from '../providers/MessagingProvider'\n\n// Blocked user from Stream Chat API\ntype BlockedUser = {\n blocked_user_id: string\n}\n\nconst REPORT_URL = 'https://linktr.ee/s/about/trust-center/report'\n\nexport interface UseChannelModerationActionsParams {\n channel: ChannelType\n participant: ChannelMemberResponse | undefined\n /**\n * When false, the blocked-status lookup is skipped (the result would be\n * unused, e.g. the Linktree official channel does not offer blocking).\n * Defaults to true.\n */\n showBlockParticipant?: boolean\n /**\n * When false, the blocked-status lookup is deferred. Useful for surfaces\n * that mount the actions ahead of time (e.g. a closed popover) and only\n * need block state once visible. Defaults to true.\n */\n enabled?: boolean\n onLeaveConversation?: (channel: ChannelType) => void\n onBlockParticipant?: (participantId?: string) => void\n onDeleteConversationClick?: () => void\n onBlockParticipantClick?: () => void\n onReportParticipantClick?: () => void\n /**\n * Called after an action completes successfully (e.g. to close the\n * surrounding dialog or popover).\n */\n onActionComplete?: () => void\n /** Prefix used for debug logging. */\n logLabel?: string\n}\n\nexport interface ChannelModerationActions {\n isParticipantBlocked: boolean\n /**\n * True while the initial blocked-status lookup is in flight. Until this is\n * false, `isParticipantBlocked` has not yet been resolved and the\n * block/unblock action should not be acted on.\n */\n isCheckingBlockedStatus: boolean\n isLeaving: boolean\n isUpdatingBlockStatus: boolean\n handleLeaveConversation: () => Promise<void>\n handleBlockUser: () => Promise<void>\n handleUnblockUser: () => Promise<void>\n handleReportUser: () => void\n}\n\n/**\n * Encapsulates the conversation moderation actions (leave/delete, block,\n * unblock, report) shared by the channel info dialog and the channel actions\n * popover menu. Keeping the logic in one place ensures both surfaces stay in\n * sync.\n */\nexport const useChannelModerationActions = ({\n channel,\n participant,\n showBlockParticipant = true,\n enabled = true,\n onLeaveConversation,\n onBlockParticipant,\n onDeleteConversationClick,\n onBlockParticipantClick,\n onReportParticipantClick,\n onActionComplete,\n logLabel = 'useChannelModerationActions',\n}: UseChannelModerationActionsParams): ChannelModerationActions => {\n const { service, debug } = useMessagingContext()\n const participantId = participant?.user?.id\n const willLookup = Boolean(\n enabled && showBlockParticipant && service && participantId\n )\n\n const [isParticipantBlocked, setIsParticipantBlocked] = useState(false)\n // Tracks the participant + service the most recent lookup has completed\n // for. Keying on both so a service swap (e.g. MessagingProvider rebuilding\n // its StreamChatService when config/apiKey/debug changes) re-triggers the\n // loading state for the same participant — otherwise the menu would\n // briefly show actionable Block/Unblock against the new service with the\n // old service's blocked result. Computing the flag at render time — rather\n // than from a useState updated inside useEffect — also closes the brief\n // window where the menu would render the regular (enabled) Block button\n // before the effect flipped the disabled placeholder on.\n const [resolvedFor, setResolvedFor] = useState<{\n participantId: string\n service: unknown\n } | null>(null)\n const [isLeaving, setIsLeaving] = useState(false)\n const [isUpdatingBlockStatus, setIsUpdatingBlockStatus] = useState(false)\n\n const isCheckingBlockedStatus =\n willLookup &&\n (resolvedFor?.participantId !== participantId ||\n resolvedFor?.service !== service)\n\n // Resolve whether the participant is blocked whenever the participant or\n // surface visibility changes.\n useEffect(() => {\n // When the lookup is skipped (Block action hidden, surface disabled, or no\n // participant), clear any stale blocked state so a previous participant's\n // value can't leak into the next conversation.\n if (!willLookup || !service || !participantId) {\n setIsParticipantBlocked(false)\n setResolvedFor(null)\n return\n }\n\n let cancelled = false\n\n void (async () => {\n try {\n const blockedUsers = await service.getBlockedUsers()\n if (cancelled) return\n setIsParticipantBlocked(\n blockedUsers.some(\n (user: BlockedUser) => user.blocked_user_id === participantId\n )\n )\n } catch (error) {\n if (!cancelled) {\n console.error(`[${logLabel}] Failed to check blocked status:`, error)\n }\n } finally {\n // Mark the lookup as resolved regardless of success/failure so a\n // rejected `getBlockedUsers()` doesn't leave the menu stuck in the\n // disabled-spinner state. On failure the blocked flag stays at its\n // default (false), matching the prior behavior — the user can attempt\n // to block/unblock and the server rejects if the state is wrong.\n if (!cancelled) setResolvedFor({ participantId, service })\n }\n })()\n\n // Ignore an in-flight result if the participant/surface changes first.\n return () => {\n cancelled = true\n }\n }, [willLookup, service, participantId, logLabel])\n\n const handleLeaveConversation = async () => {\n if (isLeaving) return\n\n // Fire analytics callback before action\n onDeleteConversationClick?.()\n\n if (debug) {\n console.log(`[${logLabel}] Leave conversation`, channel.cid)\n }\n setIsLeaving(true)\n\n try {\n const actingUserId = channel._client?.userID ?? null\n await channel.hide(actingUserId, false)\n\n if (onLeaveConversation) {\n await onLeaveConversation(channel)\n }\n\n onActionComplete?.()\n } catch (error) {\n console.error(`[${logLabel}] Failed to leave conversation`, error)\n } finally {\n setIsLeaving(false)\n }\n }\n\n const handleBlockUser = async () => {\n if (isUpdatingBlockStatus || !service) return\n\n // Fire analytics callback before action\n onBlockParticipantClick?.()\n\n if (debug) {\n console.log(`[${logLabel}] Block member`, participant?.user?.id)\n }\n setIsUpdatingBlockStatus(true)\n\n try {\n await service.blockUser(participant?.user?.id)\n\n if (onBlockParticipant) {\n await onBlockParticipant(participant?.user?.id)\n }\n\n onActionComplete?.()\n } catch (error) {\n console.error(`[${logLabel}] Failed to block member`, error)\n } finally {\n setIsUpdatingBlockStatus(false)\n }\n }\n\n const handleUnblockUser = async () => {\n if (isUpdatingBlockStatus || !service) return\n\n // Fire analytics callback before action\n onBlockParticipantClick?.()\n\n if (debug) {\n console.log(`[${logLabel}] Unblock member`, participant?.user?.id)\n }\n setIsUpdatingBlockStatus(true)\n\n try {\n await service.unBlockUser(participant?.user?.id)\n\n if (onBlockParticipant) {\n await onBlockParticipant(participant?.user?.id)\n }\n\n onActionComplete?.()\n } catch (error) {\n console.error(`[${logLabel}] Failed to unblock member`, error)\n } finally {\n setIsUpdatingBlockStatus(false)\n }\n }\n\n const handleReportUser = () => {\n // Fire analytics callback before action\n onReportParticipantClick?.()\n\n onActionComplete?.()\n window.open(REPORT_URL, '_blank', 'noopener,noreferrer')\n }\n\n return {\n isParticipantBlocked,\n isCheckingBlockedStatus,\n isLeaving,\n isUpdatingBlockStatus,\n handleLeaveConversation,\n handleBlockUser,\n handleUnblockUser,\n handleReportUser,\n }\n}\n","import classNames from \"classnames\";\nimport React from \"react\";\n\nexport interface ActionButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: \"default\" | \"danger\";\n}\n\nconst ActionButton = ({\n variant = \"default\",\n className,\n children,\n ...rest\n}: ActionButtonProps) => {\n const isDanger = variant === \"danger\";\n return (\n <button\n type=\"button\"\n className={classNames(\n \"flex w-full items-center gap-3 rounded-lg px-4 py-3 text-left text-sm transition-colors focus-ring disabled:cursor-not-allowed disabled:opacity-60\",\n isDanger\n ? \"text-danger hover:bg-danger/50\"\n : \"text-charcoal hover:bg-sand\",\n className,\n )}\n {...rest}\n >\n {children}\n </button>\n );\n};\n\nexport default ActionButton;\n","import {\n DotsThreeIcon,\n FlagIcon,\n ProhibitInsetIcon,\n SignOutIcon,\n SpinnerGapIcon,\n} from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React, { useCallback, useEffect, useId, useRef, useState } from 'react'\nimport type { Channel as ChannelType, ChannelMemberResponse } from 'stream-chat'\n\nimport { useChannelModerationActions } from '../../hooks/useChannelModerationActions'\nimport ActionButton from '../ActionButton'\n\nexport interface ChannelActionsMenuProps {\n channel: ChannelType\n participant: ChannelMemberResponse | undefined\n showDeleteConversation?: boolean\n /**\n * Show the Block/Unblock action. Defaults to true.\n * Set false to hide it (e.g. the Linktree official channel).\n */\n showBlockParticipant?: boolean\n /**\n * Show the Report action. Defaults to true.\n * Set false to hide it (e.g. the Linktree official channel).\n */\n showReportParticipant?: boolean\n onLeaveConversation?: (channel: ChannelType) => void\n onBlockParticipant?: (participantId?: string) => void\n onDeleteConversationClick?: () => void\n onBlockParticipantClick?: () => void\n onReportParticipantClick?: () => void\n customChannelActions?: React.ReactNode\n /** Classes applied to the trigger (\"...\") button so it matches the header. */\n triggerClassName?: string\n}\n\n/**\n * Conversation overflow (\"...\") menu rendered as an anchored popover.\n *\n * Replaces the slide-in sidebar dialog for moderation actions: the trigger\n * opens a small popover that lists the available options (delete, block,\n * report) inline with their icons.\n */\nexport const ChannelActionsMenu: React.FC<ChannelActionsMenuProps> = ({\n channel,\n participant,\n showDeleteConversation = true,\n showBlockParticipant = true,\n showReportParticipant = true,\n onLeaveConversation,\n onBlockParticipant,\n onDeleteConversationClick,\n onBlockParticipantClick,\n onReportParticipantClick,\n customChannelActions,\n triggerClassName,\n}) => {\n const [isOpen, setIsOpen] = useState(false)\n const containerRef = useRef<HTMLDivElement>(null)\n const menuId = useId()\n\n const close = useCallback(() => setIsOpen(false), [])\n\n const {\n isParticipantBlocked,\n isCheckingBlockedStatus,\n isLeaving,\n isUpdatingBlockStatus,\n handleLeaveConversation,\n handleBlockUser,\n handleUnblockUser,\n handleReportUser,\n } = useChannelModerationActions({\n channel,\n participant,\n showBlockParticipant,\n enabled: isOpen,\n onLeaveConversation,\n onBlockParticipant,\n onDeleteConversationClick,\n onBlockParticipantClick,\n onReportParticipantClick,\n onActionComplete: close,\n logLabel: 'ChannelActionsMenu',\n })\n\n // Close the popover on outside click or Escape.\n useEffect(() => {\n if (!isOpen) return\n\n const handlePointerDown = (event: MouseEvent) => {\n if (\n containerRef.current &&\n !containerRef.current.contains(event.target as Node)\n ) {\n setIsOpen(false)\n }\n }\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n setIsOpen(false)\n }\n }\n\n document.addEventListener('mousedown', handlePointerDown)\n document.addEventListener('keydown', handleKeyDown)\n\n return () => {\n document.removeEventListener('mousedown', handlePointerDown)\n document.removeEventListener('keydown', handleKeyDown)\n }\n }, [isOpen])\n\n if (!participant) return null\n\n const hasActions =\n showDeleteConversation ||\n showBlockParticipant ||\n showReportParticipant ||\n Boolean(customChannelActions)\n\n if (!hasActions) return null\n\n return (\n <div ref={containerRef} className=\"relative\">\n <button\n className={triggerClassName}\n type=\"button\"\n aria-haspopup=\"true\"\n aria-expanded={isOpen}\n aria-controls={isOpen ? menuId : undefined}\n onClick={() => setIsOpen((open) => !open)}\n >\n <DotsThreeIcon className=\"size-5 text-black/90\" />\n <span className=\"sr-only\">More options</span>\n </button>\n\n {isOpen && (\n <div\n id={menuId}\n aria-label=\"Conversation options\"\n className={classNames(\n 'absolute right-0 top-full z-50 mt-2 w-56 overflow-hidden',\n 'rounded-lg border border-sand bg-white p-1 shadow-max-elevation-light'\n )}\n >\n <ul className=\"flex flex-col gap-1\">\n {showDeleteConversation && (\n <li>\n <ActionButton\n onClick={handleLeaveConversation}\n disabled={isLeaving}\n aria-busy={isLeaving}\n >\n {isLeaving ? (\n <SpinnerGapIcon className=\"h-5 w-5 animate-spin\" />\n ) : (\n <SignOutIcon className=\"h-5 w-5\" />\n )}\n <span>Delete Conversation</span>\n </ActionButton>\n </li>\n )}\n {showBlockParticipant && (\n <li>\n {isCheckingBlockedStatus ? (\n // Block status not yet resolved — show a disabled placeholder\n // so a premature click can't act on a stale block state.\n <ActionButton disabled aria-busy>\n <SpinnerGapIcon className=\"h-5 w-5 animate-spin\" />\n <span>Block</span>\n </ActionButton>\n ) : isParticipantBlocked ? (\n <ActionButton\n onClick={handleUnblockUser}\n disabled={isUpdatingBlockStatus}\n aria-busy={isUpdatingBlockStatus}\n >\n {isUpdatingBlockStatus ? (\n <SpinnerGapIcon className=\"h-5 w-5 animate-spin\" />\n ) : (\n <ProhibitInsetIcon className=\"h-5 w-5\" />\n )}\n <span>Unblock</span>\n </ActionButton>\n ) : (\n <ActionButton\n onClick={handleBlockUser}\n disabled={isUpdatingBlockStatus}\n aria-busy={isUpdatingBlockStatus}\n >\n {isUpdatingBlockStatus ? (\n <SpinnerGapIcon className=\"h-5 w-5 animate-spin\" />\n ) : (\n <ProhibitInsetIcon className=\"h-5 w-5\" />\n )}\n <span>Block</span>\n </ActionButton>\n )}\n </li>\n )}\n {showReportParticipant && (\n <li>\n <ActionButton variant=\"danger\" onClick={handleReportUser}>\n <FlagIcon className=\"h-5 w-5\" />\n <span>Report</span>\n </ActionButton>\n </li>\n )}\n {customChannelActions}\n </ul>\n </div>\n )}\n </div>\n )\n}\n\nexport default ChannelActionsMenu\n","import {\n ArrowLeftIcon,\n CaretRightIcon,\n CurrencyDollarIcon,\n StarIcon,\n} from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React from 'react'\nimport type { Channel as ChannelType } from 'stream-chat'\nimport { useChannelStateContext, useChatContext } from 'stream-chat-react'\n\nimport { useChannelStar } from '../hooks/useChannelStar'\nimport { resolveConversationParticipant } from '../utils/resolveConversationParticipant'\nimport { resolveParticipantDisplayName } from '../utils/resolveParticipantDisplayName'\n\nimport { Avatar } from './Avatar'\nimport { ChannelActionsMenu } from './ChannelActionsMenu'\n\nconst ICON_BTN_CLASS =\n 'flex size-10 flex-shrink-0 items-center justify-center rounded-full bg-white/65 shadow-[0px_4px_8px_0px_rgba(0,0,0,0.06),0px_0px_0px_1px_rgba(0,0,0,0.04)] backdrop-blur-[40px] transition-filter duration-150 hover:brightness-95 aria-expanded:brightness-95 focus-ring'\n\nconst CUSTOMER_PAID_TAG = 'CUSTOMER_PAID'\n\nconst isCustomerPaidTag = (value: unknown) =>\n typeof value === 'string' &&\n value\n .trim()\n .replace(/[\\s-]+/g, '_')\n .toUpperCase() === CUSTOMER_PAID_TAG\n\ninterface ChannelHeaderRedesignProps {\n className?: string\n onBack?: () => void\n showBackButton: boolean\n showStarButton?: boolean\n onLeaveConversation?: (channel: ChannelType) => void\n onBlockParticipant?: (participantId?: string) => void\n showDeleteConversation?: boolean\n showBlockParticipant?: boolean\n showReportParticipant?: boolean\n onDeleteConversationClick?: () => void\n onBlockParticipantClick?: () => void\n onReportParticipantClick?: () => void\n customChannelActions?: React.ReactNode\n renderChannelActions?: React.ReactNode\n showChannelInfo?: boolean\n onParticipantNameClick?: () => void\n}\n\nexport const ChannelHeaderRedesign: React.FC<ChannelHeaderRedesignProps> = ({\n className,\n onBack,\n showBackButton,\n showStarButton = false,\n onLeaveConversation,\n onBlockParticipant,\n showDeleteConversation = true,\n showBlockParticipant = true,\n showReportParticipant = true,\n onDeleteConversationClick,\n onBlockParticipantClick,\n onReportParticipantClick,\n customChannelActions,\n renderChannelActions,\n showChannelInfo = true,\n onParticipantNameClick,\n}) => {\n const { channel } = useChannelStateContext()\n const { client } = useChatContext()\n\n const participant = React.useMemo(\n () =>\n resolveConversationParticipant(\n channel.state?.members,\n client?.userID,\n channel.type\n ),\n [channel.state?.members, client?.userID, channel.type]\n )\n\n const participantName = resolveParticipantDisplayName(participant?.user)\n const participantImage = participant?.user?.image\n const isStarred = useChannelStar(channel)\n const isPaidCustomer =\n isCustomerPaidTag(channel.data?.customer_tag) &&\n participant?.is_follower === true\n\n const showStarBadge = showStarButton && isStarred\n const hasNameAdornment =\n isPaidCustomer || showStarBadge || Boolean(onParticipantNameClick)\n\n const handleStarClick = async () => {\n try {\n if (isStarred) {\n await (channel as ChannelType).unpin()\n } else {\n await (channel as ChannelType).pin()\n }\n } catch (error) {\n console.error(\n '[ChannelHeaderRedesign] Failed to update pinned status:',\n error\n )\n }\n }\n\n const identityContent = (\n <>\n <Avatar\n id={participant?.user?.id || channel.id || 'unknown'}\n name={participantName}\n image={participantImage}\n shape=\"circle\"\n size={48}\n className=\"-mb-2\"\n />\n <span\n className={classNames(\n 'relative z-10 flex max-w-full flex-col items-center justify-center rounded-full border border-white/10 bg-white/65 py-1.5 shadow-[0px_0px_0px_0px_rgba(0,0,0,0.04),0px_1px_2px_0px_rgba(0,0,0,0.04),0px_8px_32px_0px_rgba(0,0,0,0.1)] backdrop-blur-[2px] transition-filter duration-150 group-hover:brightness-95',\n hasNameAdornment ? 'pl-3 pr-2' : 'px-3'\n )}\n >\n <span className=\"flex max-w-full items-center justify-center\">\n <span className=\"min-w-0 truncate text-sm font-bold leading-[1.43] tracking-[0.28px] text-black/90\">\n {participantName}\n </span>\n {hasNameAdornment && (\n <span className=\"ml-2 flex gap-1\">\n {isPaidCustomer && (\n <span\n aria-label=\"Paid customer\"\n className=\"flex size-4 shrink-0 items-center justify-center rounded-full bg-[#34C759] text-white\"\n >\n <CurrencyDollarIcon className=\"size-2.5\" weight=\"bold\" />\n </span>\n )}\n {showStarBadge && (\n <span\n aria-label=\"Starred conversation\"\n className=\"flex size-4 shrink-0 items-center justify-center rounded-full bg-[#FFD60A] text-white\"\n >\n <StarIcon className=\"size-2.5\" weight=\"fill\" />\n </span>\n )}\n {onParticipantNameClick && (\n <CaretRightIcon\n aria-hidden=\"true\"\n className=\"size-4 shrink-0 text-black/65\"\n weight=\"bold\"\n />\n )}\n </span>\n )}\n </span>\n </span>\n </>\n )\n\n return (\n <div\n className={classNames(\n '@container bg-[linear-gradient(180deg,#FBFAF9_0%,rgba(251,250,249,0.92)_58%,rgba(251,250,249,0)_100%)]',\n className\n )}\n >\n <div className=\"grid min-h-[100px] grid-cols-[minmax(40px,1fr)_auto_minmax(40px,1fr)] items-start pb-2 pt-5 @lg:min-h-[104px] @lg:pt-6\">\n <div className=\"flex items-start\">\n {showBackButton && (\n <button\n className={classNames(\n ICON_BTN_CLASS,\n 'messaging-channel-view-back-button-mobile messaging-channel-view-back-button-desktop'\n )}\n onClick={onBack || (() => {})}\n type=\"button\"\n aria-label=\"Back to conversations\"\n >\n <ArrowLeftIcon className=\"size-5 text-black/90\" />\n </button>\n )}\n </div>\n\n <div className=\"flex min-w-0 justify-center\" data-dd-privacy=\"mask\">\n {onParticipantNameClick ? (\n <button\n type=\"button\"\n onClick={onParticipantNameClick}\n aria-label={`View details for ${participantName}`}\n className=\"group flex min-w-0 max-w-full appearance-none flex-col items-center border-0 bg-transparent px-2 focus-ring focus-visible:outline-none\"\n >\n {identityContent}\n </button>\n ) : (\n <div className=\"flex min-w-0 max-w-full flex-col items-center px-2\">\n {identityContent}\n </div>\n )}\n </div>\n\n <div className=\"flex items-start justify-end gap-2\">\n {showStarButton && (\n <button\n className={ICON_BTN_CLASS}\n onClick={handleStarClick}\n type=\"button\"\n aria-pressed={isStarred}\n aria-label={\n isStarred ? 'Unstar conversation' : 'Star conversation'\n }\n >\n <StarIcon\n className={classNames('size-5', {\n 'text-[#FFD60A]': isStarred,\n 'text-black/90': !isStarred,\n })}\n weight={isStarred ? 'fill' : 'regular'}\n />\n </button>\n )}\n {showChannelInfo &&\n (renderChannelActions !== undefined ? (\n renderChannelActions\n ) : (\n <ChannelActionsMenu\n channel={channel as ChannelType}\n participant={participant}\n showDeleteConversation={showDeleteConversation}\n showBlockParticipant={showBlockParticipant}\n showReportParticipant={showReportParticipant}\n onLeaveConversation={onLeaveConversation}\n onBlockParticipant={onBlockParticipant}\n onDeleteConversationClick={onDeleteConversationClick}\n onBlockParticipantClick={onBlockParticipantClick}\n onReportParticipantClick={onReportParticipantClick}\n customChannelActions={customChannelActions}\n triggerClassName={ICON_BTN_CLASS}\n />\n ))}\n </div>\n </div>\n </div>\n )\n}\n","import { DateSeparator, type DateSeparatorProps } from 'stream-chat-react'\n\nexport const CustomDateSeparator = (props: DateSeparatorProps) => (\n <DateSeparator {...props} position=\"center\" />\n)\n","import { useCallback, useMemo } from 'react'\nimport type { LocalMessage } from 'stream-chat'\nimport { useChannelStateContext, useChatContext } from 'stream-chat-react'\n\nexport type VoteSelection = 'up' | 'down' | null\n\nconst VOTE_UP = 'vote_up'\nconst VOTE_DOWN = 'vote_down'\n\nfunction getVoteFromReactions(\n ownReactions: LocalMessage['own_reactions']\n): VoteSelection {\n if (!ownReactions?.length) return null\n if (ownReactions.some((r) => r.type === VOTE_DOWN)) return 'down'\n if (ownReactions.some((r) => r.type === VOTE_UP)) return 'up'\n return null\n}\n\ninterface UseMessageVoteResult {\n selected: VoteSelection\n voteUp: () => void\n voteDown: () => void\n}\n\n/**\n * Hook that wraps Stream Chat reactions to provide toggle-style\n * upvote/downvote behavior on a message.\n *\n * Uses enforce_unique so sending a new reaction type automatically\n * removes the previous one. Uses skip_push to avoid notifying the\n * Linker on every vote.\n */\nexport function useMessageVote(message: LocalMessage): UseMessageVoteResult {\n const { channel } = useChannelStateContext()\n const { client } = useChatContext('useMessageVote')\n\n const selected = useMemo(\n () => getVoteFromReactions(message.own_reactions),\n [message.own_reactions]\n )\n\n const voteUp = useCallback(async () => {\n if (!client?.userID) return\n try {\n if (selected === 'up') {\n await channel.deleteReaction(message.id, VOTE_UP)\n } else {\n await channel.sendReaction(\n message.id,\n { type: VOTE_UP },\n { enforce_unique: true, skip_push: true }\n )\n }\n } catch {\n // Silently fail — voting is non-critical\n }\n }, [channel, client?.userID, message.id, selected])\n\n const voteDown = useCallback(async () => {\n if (!client?.userID) return\n try {\n if (selected === 'down') {\n await channel.deleteReaction(message.id, VOTE_DOWN)\n } else {\n await channel.sendReaction(\n message.id,\n { type: VOTE_DOWN },\n { enforce_unique: true, skip_push: true }\n )\n }\n } catch {\n // Silently fail — voting is non-critical\n }\n }, [channel, client?.userID, message.id, selected])\n\n return { selected, voteUp, voteDown }\n}\n","import type { LocalMessage } from 'stream-chat'\n\ntype MessageWithI18n = Pick<LocalMessage, 'text'> & {\n i18n?: Record<string, string> | null\n}\n\nexport function normalizeLanguageCode(language?: string): string | undefined {\n const normalized = language?.trim().toLowerCase().split(/[-_]/)[0]\n return normalized || undefined\n}\n\nexport function getMessageDisplayText({\n message,\n viewerLanguage,\n}: {\n message?: MessageWithI18n | null\n viewerLanguage?: string\n}): string | undefined {\n const fallbackText = message?.text\n const normalizedLanguage = normalizeLanguageCode(viewerLanguage)\n\n if (!normalizedLanguage) {\n return fallbackText\n }\n\n return message?.i18n?.[`${normalizedLanguage}_text`] ?? fallbackText\n}\n","const LINKTREE_CDN_HOSTS = ['linktr.ee']\n\nconst ATTACHMENT_IMAGE_SIZE_PRESET = 'messaging-attachment-v1_0'\n\nfunction hostnameFromUrl(url: string): string | null {\n try {\n return new URL(url).hostname.toLowerCase()\n } catch {\n return null\n }\n}\n\nfunction isLinktreeCdnHost(hostname: string): boolean {\n return LINKTREE_CDN_HOSTS.some(\n (host) => hostname === host || hostname.endsWith(`.${host}`)\n )\n}\n\nexport function optimizeMessagingAttachmentUrl(\n url: string | undefined | null\n): string | undefined {\n const trimmed = url?.trim()\n if (!trimmed) return undefined\n\n const hostname = hostnameFromUrl(trimmed)\n if (!hostname || !isLinktreeCdnHost(hostname)) return trimmed\n\n const parsedUrl = new URL(trimmed)\n const isAlreadyMessagingOptimized =\n parsedUrl.searchParams.get('io') === 'true' &&\n parsedUrl.searchParams.get('size') === ATTACHMENT_IMAGE_SIZE_PRESET\n\n if (isAlreadyMessagingOptimized) {\n return trimmed\n }\n\n parsedUrl.searchParams.set('io', 'true')\n parsedUrl.searchParams.set('size', ATTACHMENT_IMAGE_SIZE_PRESET)\n\n return parsedUrl.toString()\n}\n","export type AttachmentSourceType = 'image' | 'audio' | 'video' | 'document'\n\nexport type DocumentIconType =\n | 'pdf'\n | 'doc'\n | 'xls'\n | 'csv'\n | 'ppt'\n | 'zip'\n | 'text'\n | 'markdown'\n | 'generic'\n\nconst DOCUMENT_ICON_PATTERNS: Array<[RegExp, DocumentIconType]> = [\n [/pdf/, 'pdf'],\n [/wordprocessingml|msword|\\.doc/, 'doc'],\n [/spreadsheetml|ms-excel|\\.xls/, 'xls'],\n [/csv/, 'csv'],\n [/presentationml|ms-powerpoint|\\.ppt/, 'ppt'],\n [/zip|x-rar|x-7z|x-tar|x-gzip/, 'zip'],\n [/plain|rtf/, 'text'],\n [/markdown/, 'markdown'],\n]\n\nexport function getSourceType(mimeType: string): AttachmentSourceType {\n if (mimeType.startsWith('video/')) return 'video'\n if (mimeType.startsWith('audio/')) return 'audio'\n if (mimeType.startsWith('image/')) return 'image'\n return 'document'\n}\n\nexport function getDocumentIconType(mimeType: string): DocumentIconType {\n const match = DOCUMENT_ICON_PATTERNS.find(([pattern]) =>\n pattern.test(mimeType)\n )\n return match ? match[1] : 'generic'\n}\n","import {\n FileIcon,\n FileCsvIcon,\n FileDocIcon,\n FileMdIcon,\n FilePdfIcon,\n FilePptIcon,\n FileTextIcon,\n FileXlsIcon,\n FileZipIcon,\n ImageIcon,\n SpeakerHighIcon,\n VideoCameraIcon,\n IconProps,\n} from '@phosphor-icons/react'\nimport React from 'react'\n\nimport { getDocumentIconType, getSourceType } from './mimeType'\nimport type { AttachmentSourceType } from './mimeType'\n\nexport const MEDIA_TYPE_ICON: Record<AttachmentSourceType, React.ElementType> =\n {\n video: VideoCameraIcon,\n audio: SpeakerHighIcon,\n image: ImageIcon,\n document: FileIcon,\n }\n\nconst DOCUMENT_ICON_COMPONENT = {\n pdf: FilePdfIcon,\n doc: FileDocIcon,\n xls: FileXlsIcon,\n csv: FileCsvIcon,\n ppt: FilePptIcon,\n zip: FileZipIcon,\n text: FileTextIcon,\n markdown: FileMdIcon,\n generic: FileIcon,\n} as const\n\nexport function getTypeIcon(mimeType: string): React.ElementType {\n const sourceType = getSourceType(mimeType)\n if (sourceType !== 'document') return MEDIA_TYPE_ICON[sourceType]\n return DOCUMENT_ICON_COMPONENT[getDocumentIconType(mimeType)]\n}\n\n/** Use instead of `<TypeIcon />` where TypeIcon = getTypeIcon(mime) to satisfy react-hooks/static-components. */\nexport function renderTypeIcon(\n mimeType: string,\n props: IconProps\n): React.ReactElement {\n return React.createElement(getTypeIcon(mimeType), props)\n}\n","import { CircleNotchIcon, PauseIcon, PlayIcon } from '@phosphor-icons/react'\nimport React, { useCallback, useEffect, useRef, useState } from 'react'\n\nimport { isDevBuild } from '../../utils/isDevBuild'\n\nimport { renderTypeIcon } from './utils/icons'\nimport { getSourceType } from './utils/mimeType'\n\ntype TouchEventUnion =\n | MouseEvent\n | TouchEvent\n | React.MouseEvent\n | React.TouchEvent\n\n\nconst getClientXFromEvent = (e: TouchEventUnion): number => {\n if ('touches' in e) {\n return e.touches[0]?.clientX ?? e.changedTouches[0]?.clientX ?? 0\n }\n return e.clientX\n}\n\nexport interface MediaPlayerProps {\n source: string\n mimeType: string\n poster?: string\n autoPlay?: boolean\n /** Controlled playing state. When provided, syncs to internal play/pause. */\n playing?: boolean\n loop?: boolean\n controls?: boolean\n showProgress?: boolean\n /** When true, requests muted playback (helps autoplay policies on video). */\n muted?: boolean\n /**\n * When provided, overrides the default click-to-play-toggle behaviour on the\n * player container. The play/pause button (which calls stopPropagation) is\n * unaffected, so inline playback still works.\n */\n onContainerClick?: (e: React.MouseEvent) => void\n}\n\nconst MediaPlayer: React.FC<MediaPlayerProps> = ({\n source,\n mimeType,\n poster,\n autoPlay = false,\n playing: playingProp,\n loop = false,\n controls = true,\n showProgress = false,\n muted = false,\n onContainerClick,\n}) => {\n // --- Derived ---\n const sourceType = getSourceType(mimeType)\n\n // --- Refs ---\n const playerRef = useRef<HTMLMediaElement>(null)\n const trackRef = useRef<HTMLDivElement>(null)\n const rafRef = useRef<number | null>(null)\n const prevPlayingPropRef = useRef(playingProp)\n\n // --- State: playback ---\n const [playing, setPlaying] = useState(autoPlay)\n const [played, setPlayed] = useState(0)\n const [seeking, setSeeking] = useState(false)\n\n // --- State: UI ---\n const [scrubberHovered, setScrubberHovered] = useState(false)\n /** Set when autoplay/play() was rejected so user can start via gesture (no controls UI). */\n const [manualPlayRequired, setManualPlayRequired] = useState(false)\n\n // --- State: loading ---\n const [buffering, setBuffering] = useState(false)\n /** True until the first canPlay fires for the current source — hides controls/spinner behind poster. */\n const [initialLoad, setInitialLoad] = useState(true)\n const [videoAspect, setVideoAspect] = useState<number | null>(null)\n\n // --- Callbacks ---\n const startPlaybackFromGesture = useCallback(() => {\n setManualPlayRequired(false)\n setPlaying(true)\n }, [])\n\n const getFraction = useCallback((e: TouchEventUnion) => {\n const track = trackRef.current\n if (!track) return 0\n const rect = track.getBoundingClientRect()\n return Math.max(\n 0,\n Math.min(1, (getClientXFromEvent(e) - rect.left) / rect.width)\n )\n }, [])\n\n const seekTo = useCallback((fraction: number) => {\n const el = playerRef.current\n if (el && el.duration) el.currentTime = fraction * el.duration\n }, [])\n\n const handleTrackPointerDown = (\n e: React.MouseEvent<HTMLDivElement> | React.TouchEvent<HTMLDivElement>\n ) => {\n e.stopPropagation()\n setSeeking(true)\n const fraction = getFraction(e)\n setPlayed(fraction)\n seekTo(fraction)\n }\n\n // --- Effects ---\n\n // Sync controlled playing prop to internal state\n useEffect(() => {\n if (\n playingProp !== undefined &&\n playingProp !== prevPlayingPropRef.current\n ) {\n prevPlayingPropRef.current = playingProp\n setPlaying(playingProp)\n }\n }, [playingProp])\n\n // RAF-driven progress updates\n useEffect(() => {\n if (!playing) {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current)\n rafRef.current = null\n }\n return\n }\n const tick = () => {\n const el = playerRef.current\n if (el && el.duration && !seeking) setPlayed(el.currentTime / el.duration)\n rafRef.current = requestAnimationFrame(tick)\n }\n rafRef.current = requestAnimationFrame(tick)\n return () => {\n if (rafRef.current !== null) cancelAnimationFrame(rafRef.current)\n }\n }, [playing, seeking])\n\n // ReactPlayer v3 uses native HTML media elements and does not support a\n // declarative `playing` prop — playback must be driven imperatively.\n useEffect(() => {\n const el = playerRef.current\n if (!el) return\n if (playing) {\n void el.play().catch((err) => {\n setPlaying(false)\n setManualPlayRequired(true)\n if (isDevBuild()) {\n console.debug('[MediaPlayer] play() failed', err)\n }\n })\n } else {\n el.pause()\n }\n }, [playing])\n\n // Global seeking listeners\n useEffect(() => {\n if (!seeking) return\n const onMove = (e: MouseEvent | TouchEvent) => setPlayed(getFraction(e))\n const onUp = (e: MouseEvent | TouchEvent) => {\n setSeeking(false)\n seekTo(getFraction(e))\n }\n window.addEventListener('mousemove', onMove)\n window.addEventListener('mouseup', onUp)\n window.addEventListener('touchmove', onMove, { passive: true })\n window.addEventListener('touchend', onUp)\n return () => {\n window.removeEventListener('mousemove', onMove)\n window.removeEventListener('mouseup', onUp)\n window.removeEventListener('touchmove', onMove)\n window.removeEventListener('touchend', onUp)\n }\n }, [seeking, getFraction, seekTo])\n\n // --- Derived render values ---\n // Use natural aspect ratio once metadata loads, fall back to 16:9 before then.\n const aspectStyle = videoAspect\n ? { aspectRatio: String(videoAspect) }\n : undefined\n const aspectClass = !videoAspect ? ' aspect-video' : ''\n const scrubberPercent = Math.round(played * 100)\n\n return (\n <div\n role=\"button\"\n tabIndex={0}\n className={`relative cursor-pointer overflow-hidden bg-black ${aspectClass}`}\n style={aspectStyle}\n onClick={(e) => {\n if (onContainerClick) { onContainerClick(e); return }\n if (manualPlayRequired) return\n if (controls) setPlaying((p) => !p)\n }}\n onKeyDown={(e) => {\n if (e.key !== 'Enter' && e.key !== ' ') return\n e.preventDefault()\n if (onContainerClick) { onContainerClick(e as unknown as React.MouseEvent); return }\n if (manualPlayRequired) return\n if (controls) setPlaying((p) => !p)\n }}\n >\n {/* For audio, poster persists as a visual background. For video, hide once loaded. */}\n {poster && (sourceType === 'audio' || initialLoad) && (\n <img\n src={poster}\n alt=\"\"\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n )}\n {!poster && (sourceType === 'audio' || initialLoad) && (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n {renderTypeIcon(mimeType, {\n className: 'size-12 text-black/20',\n weight: 'regular',\n })}\n </div>\n )}\n <div className=\"absolute inset-0\">\n {sourceType === 'audio' ? (\n <audio\n ref={playerRef as React.RefObject<HTMLAudioElement>}\n src={source}\n loop={loop}\n muted={muted}\n style={{ width: '100%', height: '100%' }}\n onLoadStart={() => setBuffering(true)}\n onCanPlay={() => {\n setBuffering(false)\n setInitialLoad(false)\n }}\n onWaiting={() => setBuffering(true)}\n onPlay={() => setManualPlayRequired(false)}\n onEnded={() => {\n if (!loop) {\n setPlaying(false)\n setPlayed(0)\n }\n }}\n >\n <track kind=\"captions\" />\n </audio>\n ) : (\n <video\n ref={playerRef as React.RefObject<HTMLVideoElement>}\n src={source}\n loop={loop}\n muted={muted}\n playsInline\n style={{ width: '100%', height: '100%' }}\n onLoadStart={() => setBuffering(true)}\n onCanPlay={() => {\n setBuffering(false)\n setInitialLoad(false)\n }}\n onWaiting={() => setBuffering(true)}\n onPlay={() => setManualPlayRequired(false)}\n onLoadedMetadata={() => {\n const el = playerRef.current\n if (\n el instanceof HTMLVideoElement &&\n el.videoWidth &&\n el.videoHeight\n ) {\n setVideoAspect(el.videoWidth / el.videoHeight)\n }\n }}\n onEnded={() => {\n if (!loop) {\n setPlaying(false)\n setPlayed(0)\n }\n }}\n >\n <track kind=\"captions\" />\n </video>\n )}\n </div>\n\n {buffering && !manualPlayRequired && (\n <div className=\"absolute inset-0 z-10 flex items-center justify-center\">\n <CircleNotchIcon\n className=\"size-8 animate-spin text-white/80\"\n weight=\"bold\"\n />\n </div>\n )}\n\n {manualPlayRequired && !controls && (\n <div\n className=\"absolute inset-0 z-30 flex cursor-pointer items-center justify-center bg-black/35\"\n role=\"button\"\n tabIndex={0}\n aria-label=\"Play preview\"\n onClick={(e) => {\n e.stopPropagation()\n startPlaybackFromGesture()\n }}\n onKeyDown={(e) => {\n if (e.key !== 'Enter' && e.key !== ' ') return\n e.preventDefault()\n e.stopPropagation()\n startPlaybackFromGesture()\n }}\n >\n <span className=\"flex size-16 items-center justify-center rounded-full bg-white/20 text-white backdrop-blur-sm\">\n <PlayIcon className=\"size-9 translate-x-0.5\" weight=\"fill\" />\n </span>\n </div>\n )}\n\n {showProgress && !controls && (\n <div className=\"absolute inset-x-0 bottom-0 px-3 pb-2.5 pt-6 bg-gradient-to-t from-black/40 to-transparent\">\n <div\n role=\"slider\"\n aria-label=\"Playback position\"\n aria-valuenow={scrubberPercent}\n aria-valuemin={0}\n aria-valuemax={100}\n tabIndex={0}\n ref={trackRef}\n className=\"relative flex h-4 w-full cursor-pointer items-center\"\n onMouseDown={handleTrackPointerDown}\n onTouchStart={handleTrackPointerDown}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => {\n if (e.key === 'ArrowRight') seekTo(Math.min(1, played + 0.05))\n if (e.key === 'ArrowLeft') seekTo(Math.max(0, played - 0.05))\n }}\n >\n <div className=\"w-full overflow-hidden rounded-full bg-white/30 h-1\">\n <div\n className=\"h-full rounded-full bg-white\"\n style={{ width: `${scrubberPercent}%` }}\n />\n </div>\n </div>\n </div>\n )}\n\n {controls && (\n <div className=\"absolute inset-x-0 bottom-0 flex items-center gap-2 bg-gradient-to-t from-black/60 to-transparent px-3 pb-2.5 pt-6 transition-all duration-200\">\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n setPlaying((p) => !p)\n }}\n className=\"shrink-0 text-white\"\n aria-label={playing ? 'Pause' : 'Play'}\n >\n {playing ? (\n <PauseIcon className=\"size-5\" weight=\"fill\" />\n ) : (\n <PlayIcon className=\"size-5 translate-x-px\" weight=\"fill\" />\n )}\n </button>\n\n <div\n role=\"slider\"\n aria-label=\"Playback position\"\n aria-valuenow={scrubberPercent}\n aria-valuemin={0}\n aria-valuemax={100}\n tabIndex={0}\n ref={trackRef}\n className=\"relative flex h-4 w-full cursor-pointer items-center\"\n onMouseDown={handleTrackPointerDown}\n onTouchStart={handleTrackPointerDown}\n onClick={(e) => e.stopPropagation()}\n onMouseEnter={() => setScrubberHovered(true)}\n onMouseLeave={() => setScrubberHovered(false)}\n onKeyDown={(e) => {\n if (e.key === 'ArrowRight') seekTo(Math.min(1, played + 0.05))\n if (e.key === 'ArrowLeft') seekTo(Math.max(0, played - 0.05))\n }}\n >\n <div\n className={`w-full overflow-hidden rounded-full bg-white/30 transition-all duration-200 ${scrubberHovered || seeking ? 'h-1.5' : 'h-1'}`}\n >\n <div\n className=\"h-full rounded-full bg-white\"\n style={{ width: `${scrubberPercent}%` }}\n />\n </div>\n <div\n className={`absolute size-3 -translate-x-1/2 rounded-full bg-white shadow transition-[opacity,transform] duration-200 ${scrubberHovered || seeking ? 'scale-100 opacity-100' : 'scale-0 opacity-0'}`}\n style={{ left: `${scrubberPercent}%` }}\n />\n </div>\n </div>\n )}\n </div>\n )\n}\n\nexport default MediaPlayer\n","import React, { useState } from 'react'\n\nimport { optimizeMessagingAttachmentUrl } from '../../utils/cdnImageUrl'\n\nimport MediaPlayer, { type MediaPlayerProps } from './MediaPlayer'\nimport { renderTypeIcon } from './utils/icons'\nimport { getSourceType } from './utils/mimeType'\n\nexport type AttachmentThumbnailVariant = 'light' | 'dark'\n\nexport interface AttachmentThumbnailProps {\n mimeType: string\n sourceUrl?: string\n thumbnailUrl?: string\n title?: string\n variant: AttachmentThumbnailVariant\n /** Extra props passed to MediaPlayer when source is video or audio. */\n mediaPlayerProps?: Partial<\n Pick<\n MediaPlayerProps,\n 'autoPlay' | 'loop' | 'muted' | 'controls' | 'onContainerClick'\n >\n >\n /**\n * When true (Visitor unlocked image/document), use aspect-video + object-contain fade-in.\n */\n containedImage?: boolean\n}\n\nconst placeholderIconClass = (variant: AttachmentThumbnailVariant) =>\n variant === 'dark' ? 'size-12 text-white/20' : 'size-12 text-black/20'\n\nconst posterShellClass = (variant: AttachmentThumbnailVariant) =>\n variant === 'dark'\n ? 'aspect-video overflow-hidden bg-white/10'\n : 'aspect-video overflow-hidden bg-black/5'\n\n/**\n * Renders the media preview area for attachment cards (LockedAttachment, MediaMessage).\n * Overlays (dim, lock, eye toggle) are composed by the parent.\n */\nconst AttachmentThumbnail: React.FC<AttachmentThumbnailProps> = ({\n mimeType,\n sourceUrl,\n thumbnailUrl,\n title,\n variant,\n mediaPlayerProps,\n containedImage = false,\n}) => {\n const sourceType = getSourceType(mimeType)\n const [sourceReady, setSourceReady] = useState(false)\n const optimizedSourceUrl = optimizeMessagingAttachmentUrl(sourceUrl)\n const optimizedThumbnailUrl = optimizeMessagingAttachmentUrl(thumbnailUrl)\n\n if (sourceUrl && (sourceType === 'video' || sourceType === 'audio')) {\n return (\n <MediaPlayer\n source={sourceUrl}\n mimeType={mimeType}\n poster={optimizedThumbnailUrl}\n controls\n {...mediaPlayerProps}\n />\n )\n }\n\n if (sourceUrl && sourceType === 'image') {\n if (containedImage) {\n return (\n <div className=\"relative aspect-video overflow-hidden bg-black/5\">\n <img\n src={optimizedSourceUrl ?? sourceUrl}\n alt={title ?? ''}\n className={`absolute inset-0 h-full w-full object-contain transition-opacity duration-300 ${sourceReady ? 'opacity-100' : 'opacity-0'}`}\n draggable={false}\n onLoad={() => setSourceReady(true)}\n />\n </div>\n )\n }\n return (\n <img\n src={optimizedSourceUrl ?? sourceUrl}\n alt={title ?? ''}\n className=\"block w-full\"\n draggable={false}\n />\n )\n }\n\n if (sourceUrl && sourceType === 'document') {\n if (thumbnailUrl) {\n if (containedImage) {\n return (\n <div className=\"relative aspect-video overflow-hidden bg-black/5\">\n <img\n src={optimizedThumbnailUrl ?? thumbnailUrl}\n alt={title ?? ''}\n className={`absolute inset-0 h-full w-full object-contain transition-opacity duration-300 ${sourceReady ? 'opacity-100' : 'opacity-0'}`}\n draggable={false}\n onLoad={() => setSourceReady(true)}\n />\n </div>\n )\n }\n return (\n <img\n src={optimizedThumbnailUrl ?? thumbnailUrl}\n alt=\"\"\n className=\"block w-full\"\n draggable={false}\n />\n )\n }\n return (\n <div\n className={`flex aspect-video w-full items-center justify-center ${variant === 'dark' ? 'bg-white/10' : 'bg-black/5'}`}\n >\n {renderTypeIcon(mimeType, {\n className: placeholderIconClass(variant),\n weight: 'regular',\n })}\n </div>\n )\n }\n\n // Poster-only or empty (no sourceUrl)\n if (thumbnailUrl) {\n return (\n <div className={`relative ${posterShellClass(variant)}`}>\n <img\n src={optimizedThumbnailUrl ?? thumbnailUrl}\n alt={title ?? ''}\n draggable={false}\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n </div>\n )\n }\n\n return (\n <div\n className={`flex aspect-video w-full items-center justify-center ${variant === 'dark' ? 'bg-white/10' : 'bg-black/5'}`}\n >\n {renderTypeIcon(mimeType, {\n className: placeholderIconClass(variant),\n weight: 'regular',\n })}\n </div>\n )\n}\n\nexport default AttachmentThumbnail\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport { renderTypeIcon } from './utils/icons'\n\nexport { default as AttachmentThumbnail } from './Thumbnail'\nexport type {\n AttachmentThumbnailProps,\n AttachmentThumbnailVariant,\n} from './Thumbnail'\nexport { default as MediaPlayer } from './MediaPlayer'\nexport type { MediaPlayerProps } from './MediaPlayer'\nexport { renderTypeIcon, getTypeIcon, MEDIA_TYPE_ICON } from './utils/icons'\nexport {\n getSourceType,\n getDocumentIconType,\n type AttachmentSourceType,\n type DocumentIconType,\n} from './utils/mimeType'\n\nexport interface AttachmentCardProps {\n variant: 'light' | 'dark'\n thumbnail: React.ReactNode\n title?: string\n placeholderTitle?: string\n mimeType: string\n detail?: string\n statusBadge?: React.ReactNode\n action?: React.ReactNode\n topLeft?: React.ReactNode\n topRight?: React.ReactNode\n rootRef?: React.Ref<HTMLDivElement>\n 'data-testid'?: string\n}\n\nconst AttachmentCard: React.FC<AttachmentCardProps> = ({\n variant,\n thumbnail,\n title,\n placeholderTitle = 'Attachment title',\n mimeType,\n detail,\n statusBadge,\n action,\n topLeft,\n topRight,\n rootRef,\n 'data-testid': dataTestId,\n}) => {\n const isDark = variant === 'dark'\n const displayTitle = isDark ? (title ?? placeholderTitle) : (title ?? '')\n const titleDimmed = isDark && !title\n\n return (\n <div\n ref={rootRef}\n data-testid={dataTestId}\n className={classNames(\n 'relative w-[280px] select-none overflow-hidden rounded-[24px] shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_4px_8px_rgba(0,0,0,0.06)]',\n isDark ? 'bg-[#1e2330]' : 'bg-white'\n )}\n >\n {topLeft ? (\n <div className=\"pointer-events-auto absolute left-3 top-3 z-50\">{topLeft}</div>\n ) : null}\n {topRight ? (\n <div className=\"pointer-events-auto absolute right-3 top-3 z-50\">{topRight}</div>\n ) : null}\n\n {thumbnail}\n\n <div className=\"px-4 pb-3 pt-3\">\n {displayTitle.trim() !== '' && (\n <p\n className={classNames('mb-0.5 truncate text-base font-medium', {\n 'text-black': !isDark,\n 'text-white/30': isDark && titleDimmed,\n 'text-white': isDark && !titleDimmed,\n })}\n >\n {displayTitle}\n </p>\n )}\n\n <div className=\"flex flex-wrap items-center gap-1\">\n {renderTypeIcon(mimeType, {\n className: classNames(\n 'size-5 shrink-0',\n isDark ? 'text-white/55' : 'text-black/55'\n ),\n weight: 'regular',\n })}\n\n {detail != null && detail !== '' && (\n <span\n className={classNames(\n 'text-xs font-medium',\n isDark ? 'text-white/55' : 'text-black/55'\n )}\n >\n {detail}\n </span>\n )}\n\n {statusBadge}\n </div>\n\n {action}\n </div>\n </div>\n )\n}\n\nexport default AttachmentCard\n","import { CircleNotchIcon, DownloadSimpleIcon, LinkIcon } from '@phosphor-icons/react'\nimport React, { useState } from 'react'\nimport type { Attachment, LocalMessage } from 'stream-chat'\n\nimport { optimizeMessagingAttachmentUrl } from '../../utils/cdnImageUrl'\nimport AttachmentCard, {\n AttachmentThumbnail,\n getSourceType,\n} from '../AttachmentCard'\nimport { Avatar } from '../Avatar'\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\nfunction linkCardShellClass(isMyMessage: boolean) {\n const bg = isMyMessage ? 'bg-[#1e2330]' : 'bg-[#F3F3F1]'\n return `w-[280px] select-none overflow-hidden rounded-[24px] ${bg} shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_4px_8px_rgba(0,0,0,0.06)]`\n}\n\nfunction linkThumbnailBg(isMyMessage: boolean) {\n return isMyMessage ? 'bg-white/10' : 'bg-black/5'\n}\n\nfunction linkPrimaryText(isMyMessage: boolean) {\n return isMyMessage ? 'text-white' : 'text-black'\n}\n\nfunction linkSecondaryText(isMyMessage: boolean) {\n return isMyMessage ? 'text-white/55' : 'text-black/55'\n}\n\nfunction linkTertiaryText(isMyMessage: boolean) {\n return isMyMessage ? 'text-white/40' : 'text-black/40'\n}\n\nfunction linkIconColor(isMyMessage: boolean) {\n return isMyMessage ? 'text-white/20' : 'text-black/20'\n}\n\n/** Link preview (OG) — no download; opens in a new tab. */\nconst LinkCard: React.FC<{\n attachment: Attachment\n isMyMessage: boolean\n}> = ({ attachment, isMyMessage }) => {\n const { title, text, image_url, og_scrape_url, title_link } = attachment\n const rawUrl = og_scrape_url ?? title_link\n const url =\n typeof rawUrl === 'string' && rawUrl.trim() !== '' ? rawUrl : undefined\n\n const body = (\n <React.Fragment>\n <div className=\"p-2\">\n {image_url ? (\n <img\n src={optimizeMessagingAttachmentUrl(image_url) ?? image_url}\n alt={title ?? ''}\n className=\"aspect-video w-full rounded-[20px] object-cover\"\n />\n ) : (\n <div\n className={`aspect-video w-full rounded-[20px] ${linkThumbnailBg(isMyMessage)} flex items-center justify-center`}\n >\n <LinkIcon className={`size-12 ${linkIconColor(isMyMessage)}`} />\n </div>\n )}\n </div>\n <div className=\"px-3 pb-3\">\n {title && (\n <p className={`truncate text-[14px] font-medium leading-5 ${linkPrimaryText(isMyMessage)}`}>\n {title}\n </p>\n )}\n {text && (\n <p className={`truncate text-[12px] leading-4 ${linkSecondaryText(isMyMessage)}`}>{text}</p>\n )}\n {url && (\n <p className={`mt-1 truncate text-[12px] leading-4 ${linkTertiaryText(isMyMessage)}`}>\n {url}\n </p>\n )}\n </div>\n </React.Fragment>\n )\n\n if (url) {\n return (\n <a href={url} target=\"_blank\" rel=\"noopener noreferrer\" className=\"block no-underline\">\n {body}\n </a>\n )\n }\n\n return <div className=\"block\">{body}</div>\n}\n\nexport function isLinkAttachment(a: Attachment): boolean {\n return a.type === 'link' || (!!a.og_scrape_url && !a.asset_url)\n}\n\nexport function resolveLinkAttachment(\n message: LocalMessage\n): Attachment | undefined {\n return message.attachments?.find(isLinkAttachment)\n}\n\nasync function triggerDownload(url: string, filename?: string): Promise<void> {\n let name: string\n try { name = filename ?? new URL(url).pathname.split('/').pop() ?? 'download' }\n catch { name = filename ?? 'download' }\n const res = await fetch(url, { mode: 'cors' })\n if (!res.ok) throw new Error(`HTTP ${res.status}`)\n const blob = await res.blob()\n const objectUrl = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = objectUrl\n a.download = name\n a.style.display = 'none'\n document.body.appendChild(a)\n a.click()\n document.body.removeChild(a)\n URL.revokeObjectURL(objectUrl)\n}\n\nconst DownloadAction: React.FC<{ url: string; filename?: string }> = ({\n url,\n filename,\n}) => {\n const [busy, setBusy] = useState(false)\n\n const handleClick = (e: React.MouseEvent) => {\n e.stopPropagation()\n const fallback = window.open('', '_blank', 'noopener,noreferrer')\n setBusy(true)\n triggerDownload(url, filename)\n .then(() => { fallback?.close() })\n .catch(() => { if (fallback) fallback.location.href = url })\n .finally(() => setBusy(false))\n }\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={busy}\n className=\"mt-3 inline-flex h-10 w-full items-center justify-center gap-2 rounded-full bg-[#121110] px-4 text-sm font-medium leading-none text-white hover:bg-[#2a2928] disabled:opacity-70\"\n >\n {busy ? (\n <CircleNotchIcon className=\"size-4 animate-spin text-white\" weight=\"bold\" />\n ) : (\n <React.Fragment>\n <DownloadSimpleIcon className=\"size-4 text-white\" weight=\"bold\" />\n Download\n </React.Fragment>\n )}\n </button>\n )\n}\n\nexport interface MediaMessageResolved {\n resolvedUrl: string\n resolvedType: string\n title?: string\n fileSize?: number\n thumbnailUrl?: string\n}\n\nexport function resolveMediaFromMessage(\n message: LocalMessage\n): MediaMessageResolved | null {\n const videoAttachment = message.attachments?.find(\n (a) => a.type === 'video' && a.asset_url\n )\n const imageAttachment = message.attachments?.find(\n (a) => a.type === 'image' && (a as { image_url?: string }).image_url\n )\n const audioAttachment = message.attachments?.find(\n (a) => a.type === 'audio' && a.asset_url\n )\n const fileAttachment = message.attachments?.find(\n (a) => a.type === 'file' && a.asset_url\n )\n\n const activeAttachment =\n videoAttachment ?? imageAttachment ?? audioAttachment ?? fileAttachment\n\n const resolvedUrl =\n videoAttachment?.asset_url ??\n (imageAttachment as { image_url?: string } | undefined)?.image_url ??\n audioAttachment?.asset_url ??\n fileAttachment?.asset_url\n\n if (!resolvedUrl) return null\n\n const resolvedType =\n activeAttachment?.mime_type ??\n (activeAttachment?.type === 'image'\n ? 'image/jpeg'\n : activeAttachment?.type === 'video'\n ? 'video/mp4'\n : activeAttachment?.type === 'audio'\n ? 'audio/mpeg'\n : 'application/octet-stream')\n\n const title = (activeAttachment as { title?: string } | undefined)?.title\n const fileSize = (activeAttachment as { file_size?: number } | undefined)?.file_size\n const thumbnailUrl = (videoAttachment as { thumb_url?: string } | undefined)?.thumb_url\n\n return {\n resolvedUrl,\n resolvedType,\n title,\n fileSize,\n thumbnailUrl,\n }\n}\n\n/** Dark card (sent / own message) — matches LockedAttachment.Sent preview without toggle. */\nconst Creator: React.FC<MediaMessageResolved> = ({\n resolvedUrl,\n resolvedType,\n title,\n fileSize,\n thumbnailUrl,\n}) => {\n const detail = fileSize !== undefined ? formatBytes(fileSize) : undefined\n\n return (\n <AttachmentCard\n variant=\"dark\"\n title={title}\n placeholderTitle=\"\"\n mimeType={resolvedType}\n detail={detail}\n thumbnail={\n <AttachmentThumbnail\n mimeType={resolvedType}\n sourceUrl={resolvedUrl}\n thumbnailUrl={thumbnailUrl}\n title={title}\n variant=\"dark\"\n />\n }\n />\n )\n}\n\n/** Light card (received) — matches LockedAttachment.Received unlocked without Purchased copy. */\nconst Visitor: React.FC<MediaMessageResolved> = ({\n resolvedUrl,\n resolvedType,\n title,\n fileSize,\n thumbnailUrl,\n}) => {\n const sourceType = getSourceType(resolvedType)\n const detail = fileSize !== undefined ? formatBytes(fileSize) : undefined\n\n return (\n <AttachmentCard\n variant=\"light\"\n title={title}\n mimeType={resolvedType}\n detail={detail}\n thumbnail={\n <AttachmentThumbnail\n mimeType={resolvedType}\n sourceUrl={resolvedUrl}\n thumbnailUrl={thumbnailUrl}\n title={title}\n variant=\"light\"\n containedImage={sourceType === 'image' || sourceType === 'document'}\n />\n }\n action={<DownloadAction url={resolvedUrl} filename={title} />}\n />\n )\n}\n\nexport interface MediaMessageProps {\n message: LocalMessage\n isMyMessage?: boolean\n}\n\n/**\n * @deprecated Slated for removal once the profile repo is migrated to\n * `LinkAttachment` (and its forthcoming media-only Attachment variants).\n * New consumers should reach for `LinkAttachment.Composer`,\n * `LinkAttachment.Sent`, or `LinkAttachment.Received` instead.\n */\nconst MediaMessageRoot: React.FC<MediaMessageProps> = ({\n message,\n isMyMessage = false,\n}) => {\n const linkAttachment = resolveLinkAttachment(message)\n const resolved = resolveMediaFromMessage(message)\n if (!linkAttachment && !resolved) return null\n\n const messageClass = isMyMessage\n ? 'str-chat__message str-chat__message-simple str-chat__message--me str-chat__message-simple--me'\n : 'str-chat__message str-chat__message-simple str-chat__message--other'\n\n return (\n <div className={messageClass} data-dd-privacy=\"mask\">\n {!isMyMessage && message.user && (\n <Avatar\n className=\"str-chat__avatar str-chat__message-sender-avatar\"\n id={message.user.id}\n image={message.user.image}\n name={message.user.name ?? message.user.id}\n />\n )}\n <div\n className=\"str-chat__message-inner\"\n style={{ marginInlineEnd: 0, marginInlineStart: 0 }}\n >\n <div className=\"str-chat__message-bubble-wrapper\">\n <div\n className=\"str-chat__message-bubble\"\n // The visible child is a self-contained AttachmentCard (white /\n // #1e2330 card with its own shadow + radius), not a speech\n // bubble, and this wrapper is transparent. Mark it so the\n // received/sent tail in `styles.css` skips it — otherwise a\n // tail tinted from the text-bubble surface (#f2f1ef) hangs off\n // a white card and reads as a detached grey nub.\n data-attachment-bubble=\"true\"\n style={{ padding: 0, borderRadius: 0, overflow: 'visible', background: 'transparent' }}\n >\n {linkAttachment ? (\n <div className={linkCardShellClass(isMyMessage)}>\n <LinkCard attachment={linkAttachment} isMyMessage={isMyMessage} />\n </div>\n ) : isMyMessage ? (\n <Creator {...resolved!} />\n ) : (\n <Visitor {...resolved!} />\n )}\n </div>\n </div>\n </div>\n </div>\n )\n}\n\nconst MediaMessageCreatorEntry: React.FC<{ message: LocalMessage }> = ({\n message,\n}) => {\n const linkAttachment = resolveLinkAttachment(message)\n if (linkAttachment) {\n return (\n <div className={linkCardShellClass(true)} data-dd-privacy=\"mask\">\n <LinkCard attachment={linkAttachment} isMyMessage={true} />\n </div>\n )\n }\n const resolved = resolveMediaFromMessage(message)\n if (!resolved) return null\n return (\n <div style={{ display: 'contents' }} data-dd-privacy=\"mask\">\n <Creator {...resolved} />\n </div>\n )\n}\n\nconst MediaMessageVisitorEntry: React.FC<{ message: LocalMessage }> = ({\n message,\n}) => {\n const linkAttachment = resolveLinkAttachment(message)\n if (linkAttachment) {\n return (\n <div className={linkCardShellClass(false)} data-dd-privacy=\"mask\">\n <LinkCard attachment={linkAttachment} isMyMessage={false} />\n </div>\n )\n }\n const resolved = resolveMediaFromMessage(message)\n if (!resolved) return null\n return (\n <div style={{ display: 'contents' }} data-dd-privacy=\"mask\">\n <Visitor {...resolved} />\n </div>\n )\n}\n\nexport const MediaMessage = Object.assign(MediaMessageRoot, {\n Creator: MediaMessageCreatorEntry,\n Visitor: MediaMessageVisitorEntry,\n})\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport type { BubbleGroupPosition, BubbleVariant } from '../types'\n\nexport interface BubbleProps {\n variant: BubbleVariant\n /** Optional message text rendered below the attachment slot. */\n text?: React.ReactNode\n /**\n * Renders a hairline border around the bubble. Defaults to `true` —\n * matches the design system's \"small border around link / message\n * attachments\" treatment from the mobile spec.\n */\n bordered?: boolean\n /**\n * Position of this bubble inside a same-author message run. Drives\n * the corner-flattening that visually merges consecutive bubbles\n * (matches the grouping stream-chat-react applies to text bubbles).\n * Defaults to `'single'` so standalone usage keeps every corner\n * fully rounded.\n */\n groupPosition?: BubbleGroupPosition\n /**\n * Width utility that REPLACES the default `'w-[280px]'`. Supply the\n * whole declaration (`'w-fit'`, `'w-[383px] max-w-full'`) — nothing\n * is merged with the default.\n */\n widthClassName?: string\n /**\n * Padding utility that REPLACES the default `'px-2 py-2'`. Supply\n * the full inset (`'p-0.5'`, `'py-5 pl-5 pr-3'`).\n */\n paddingClassName?: string\n /**\n * Corner utility that REPLACES the `groupPosition`-derived corner\n * table entirely. Opting in means opting OUT of same-author corner\n * flattening — the bubble renders the supplied radius on all four\n * corners. That is what the attachment redesign wants: Figma draws\n * media cards at a uniform r20 even when a caption bubble sits 4px\n * below (nodes `1973:12776`, `1973:20239`).\n *\n * It replaces rather than appends because appending cannot be made\n * reliable — an appended `rounded-[20px]` and the corner table have\n * identical CSS specificity, so Tailwind's emitted source order,\n * not argument order, would pick the winner.\n */\n radiusClassName?: string\n className?: string\n children: React.ReactNode\n 'data-testid'?: string\n}\n\n// Colors and metrics tracked from `stream-chat-react`'s default\n// `.str-chat__message-bubble` token set so attachments visually drop\n// into a normal `CustomMessage` thread without any seams:\n// - light → `--str-chat__message-bubble-background-color` in `styles.css` (#f2f1ef)\n// - dark → `.str-chat__message--me` override in `styles.css` (#1e2330)\n// - text padding → `--str-chat__spacing-2 --str-chat__spacing-4` = 8px 16px\n// - border-radius → `--str-chat__border-radius-md` = 18px\n//\n// TODO: migrate to Tailwind theme tokens once they exist for the\n// `linktree.dark` / `linktree.surface.secondary` palette — these hex\n// literals are repeated across LinkAttachment / LockedAttachment /\n// MediaMessage / CustomMessageInput / DownloadAction etc., so a\n// rebrand would need to touch every site. A central token would\n// collapse the migration to one definition.\nconst BUBBLE_BG_BY_VARIANT: Record<BubbleVariant, string> = {\n dark: 'bg-[#1e2330]',\n light: 'bg-[#f2f1ef]',\n}\n\nconst BUBBLE_TEXT_BY_VARIANT: Record<BubbleVariant, string> = {\n dark: 'text-white',\n light: 'text-[#000000]',\n}\n\nconst BUBBLE_BORDER_BY_VARIANT: Record<BubbleVariant, string> = {\n dark: 'border-white/[0.08]',\n light: 'border-black/[0.08]',\n}\n\n/**\n * Per-corner rounding tables that mirror stream-chat-react's default\n * bubble grouping. Sender bubbles cluster against the right edge so\n * the right corners get flattened in a run; receiver bubbles cluster\n * against the left edge so the left corners get flattened.\n *\n * Rounded corners use `--str-chat__border-radius-md` (18px) and\n * flattened corners use `--str-chat__border-radius-sm` (4px) — same\n * tokens stream's stylesheet uses for `.str-chat__message-bubble`\n * inside a `--first` / `--group` / `--end` wrapper.\n */\ntype BubbleSide = 'sender' | 'receiver'\n\nconst sideForVariant = (variant: BubbleVariant): BubbleSide =>\n variant === 'dark' ? 'sender' : 'receiver'\n\nconst CORNER_CLASSES_BY_SIDE_AND_POSITION: Record<\n BubbleSide,\n Record<BubbleGroupPosition, string>\n> = {\n sender: {\n single:\n 'rounded-tl-[18px] rounded-tr-[18px] rounded-bl-[18px] rounded-br-[18px]',\n first:\n 'rounded-tl-[18px] rounded-tr-[18px] rounded-bl-[18px] rounded-br-[4px]',\n middle:\n 'rounded-tl-[18px] rounded-tr-[4px] rounded-bl-[18px] rounded-br-[4px]',\n end: 'rounded-tl-[18px] rounded-tr-[4px] rounded-bl-[18px] rounded-br-[18px]',\n },\n receiver: {\n single:\n 'rounded-tl-[18px] rounded-tr-[18px] rounded-bl-[18px] rounded-br-[18px]',\n first:\n 'rounded-tl-[18px] rounded-tr-[18px] rounded-bl-[4px] rounded-br-[18px]',\n middle:\n 'rounded-tl-[4px] rounded-tr-[18px] rounded-bl-[4px] rounded-br-[18px]',\n end: 'rounded-tl-[4px] rounded-tr-[18px] rounded-bl-[18px] rounded-br-[18px]',\n },\n}\n\n/**\n * Chat-bubble container shared by every `MessageAttachment.*` card.\n *\n * Holds the attachment slot (image / video / row) and an optional\n * `text` caption rendered below it — mirrors the mobile chat layout\n * where a sender can attach a caption alongside an attachment ('Here\n * is the file', 'Here is the image').\n *\n * Two visual variants:\n * - `dark` — sender-side (Composer / Sent), white text on `#1e2330`.\n * - `light` — recipient-side (Received), dark text on `#f2f1ef`.\n *\n * Background colors, padding, border-radius, and inherited font come\n * from the stream-chat-react `.str-chat__message-bubble` token set so\n * attachments line up with the `CustomMessage` text bubbles in a real\n * conversation. Padding is uniform across every variant — text rows,\n * audio rows, document rows, and media bubbles all get the same\n * 8px / 16px inset, with media inside getting its own rounded corners.\n */\nconst Bubble: React.FC<BubbleProps> = ({\n variant,\n text,\n bordered = true,\n groupPosition = 'single',\n widthClassName = 'w-[280px]',\n paddingClassName = 'px-2 py-2',\n radiusClassName,\n className,\n children,\n 'data-testid': dataTestId,\n}) => {\n const hasText = text != null && text !== ''\n const cornerClasses =\n radiusClassName ??\n CORNER_CLASSES_BY_SIDE_AND_POSITION[sideForVariant(variant)][groupPosition]\n\n return (\n <div\n data-testid={dataTestId}\n data-group-position={groupPosition}\n className={classNames(\n // Defaults describe a 280px-wide document / audio / link\n // bubble: that width matches the mobile chat attachment and\n // the 8px / 16px inset matches `--str-chat__spacing-2\n // --str-chat__spacing-4`, so attachments share the same hit /\n // negative-space rhythm as the surrounding `CustomMessage`\n // text bubbles. Media cards override both — Figma sizes them\n // to the media (330 / 383px) with a 2px frame instead.\n 'relative',\n widthClassName,\n 'overflow-hidden',\n paddingClassName,\n // The caption below owns the bubble's whole bottom inset when\n // it is present, so the container hands it over. Without this\n // the inset is whatever `paddingClassName` happens to supply,\n // which is 2px for the media cards' `p-0.5` frame and leaves\n // caption text sitting on the card edge. Safe to append: this\n // is shorthand-then-longhand (`p-*`/`py-*` then `pb-*`), which\n // Tailwind always emits in that order inside its `padding`\n // plugin — unlike the same-utility `rounded-*` clash above,\n // there is no ambiguity to resolve.\n hasText && 'pb-0',\n cornerClasses,\n BUBBLE_BG_BY_VARIANT[variant],\n BUBBLE_TEXT_BY_VARIANT[variant],\n bordered && 'border',\n bordered && BUBBLE_BORDER_BY_VARIANT[variant],\n className\n )}\n >\n {children}\n\n {hasText ? (\n <p\n className={classNames(\n // No `text-*` / `font-*` overrides here — caption inherits\n // the same font family + size as `.str-chat__message-text`\n // so it matches the surrounding `CustomMessage` bubbles.\n 'whitespace-pre-wrap break-words leading-snug',\n // Owns the full vertical inset: an 8px gutter above (the\n // children render flush against their own bottom edge)\n // and the bubble's 8px bottom inset below, which the\n // container gave up via `pb-0`. Horizontally this stacks\n // on the container's inset so a default bubble's caption\n // lands at the 16px `--str-chat__spacing-4` text inset.\n 'pb-2 pt-2',\n 'px-2'\n )}\n >\n {text}\n </p>\n ) : null}\n </div>\n )\n}\n\nexport default Bubble\n","import { XIcon } from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React from 'react'\n\nexport interface DismissButtonProps {\n onClick: () => void\n /**\n * `'overlay'` — translucent button sitting on top of media (image /\n * video corner). `'inline'` — opaque button placed in the row of a\n * compact attachment alongside other content.\n */\n variant?: 'overlay' | 'inline'\n ariaLabel?: string\n}\n\nconst DismissButton: React.FC<DismissButtonProps> = ({\n onClick,\n variant = 'overlay',\n ariaLabel = 'Dismiss attachment',\n}) => (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n onClick()\n }}\n aria-label={ariaLabel}\n className={classNames(\n 'flex size-6 items-center justify-center rounded-full text-white',\n variant === 'overlay'\n ? 'bg-[#121110]/85 backdrop-blur'\n : 'bg-white/15 hover:bg-white/25'\n )}\n >\n <XIcon className=\"size-3\" weight=\"bold\" />\n </button>\n)\n\nexport default DismissButton\n","import type React from 'react'\n\n/**\n * Three messaging states a `MessageAttachment.*` card can render in,\n * mirroring the LinkAttachment / LockedAttachment families.\n */\nexport type MessageAttachmentState = 'composer' | 'sent' | 'received'\n\n/**\n * Visual variant of the surrounding `Bubble` chrome. Sender-side bubbles\n * (`composer`, `sent`) get the dark treatment; recipient-side bubbles\n * (`received`) get the light treatment.\n */\nexport type BubbleVariant = 'dark' | 'light'\n\n/** Maps a state to the bubble chrome it should render with. */\nexport const bubbleVariantForState = (\n state: MessageAttachmentState\n): BubbleVariant => (state === 'received' ? 'light' : 'dark')\n\n/**\n * Position of a bubble inside a same-author run, mirroring the grouping\n * stream-chat-react applies to consecutive messages from the same user:\n *\n * - `'single'` — standalone message, every corner fully rounded.\n * - `'first'` — first in a 2+ message run; the corner facing the\n * next bubble in the run is flattened.\n * - `'middle'` — both the corner facing the previous bubble and the\n * corner facing the next bubble are flattened.\n * - `'end'` — last in a 2+ message run; the corner facing the\n * previous bubble is flattened (this is also the\n * bubble the avatar attaches to on the receiver side).\n *\n * \"Facing\" is determined by the bubble's side: sender-aligned bubbles\n * cluster against their right edge, receiver-aligned bubbles against\n * their left edge.\n */\nexport type BubbleGroupPosition = 'single' | 'first' | 'middle' | 'end'\n\n/**\n * Convenience adapter that derives the `BubbleGroupPosition` from the\n * three booleans `stream-chat-react` forwards into the `Message` HOC.\n * Drop-in for `useMessageContext()` consumers:\n *\n * ```tsx\n * const { firstOfGroup, endOfGroup, groupedByUser } = useMessageContext()\n * <MessageAttachment.Image.Sent\n * {...props}\n * groupPosition={bubbleGroupPositionFromStream({\n * firstOfGroup, endOfGroup, groupedByUser,\n * })}\n * />\n * ```\n */\nexport const bubbleGroupPositionFromStream = ({\n firstOfGroup,\n endOfGroup,\n groupedByUser,\n}: {\n firstOfGroup?: boolean\n endOfGroup?: boolean\n groupedByUser?: boolean\n}): BubbleGroupPosition => {\n if (!groupedByUser) return 'single'\n if (firstOfGroup && endOfGroup) return 'single'\n if (firstOfGroup) return 'first'\n if (endOfGroup) return 'end'\n return 'middle'\n}\n\n/** Loading hint forwarded to the underlying `<img>` element. */\nexport type ImageLoadingMode = 'lazy' | 'eager'\n\n/** Preload hint forwarded to the underlying `<video>` / `<audio>` element. */\nexport type MediaPreloadMode = 'none' | 'metadata' | 'auto'\n\n/** A single image inside an Image attachment (single or stacked). */\nexport interface ImageItem {\n src: string\n alt?: string\n /** Optional width/height hint — preserved aspect on cover-fit. */\n width?: number\n height?: number\n /**\n * Per-tile native lazy-load override. Defaults to the parent\n * attachment's `loading` value (which itself defaults to `'lazy'`).\n * Pass `'eager'` for above-the-fold hero tiles.\n */\n loading?: ImageLoadingMode\n}\n\n/** A single video inside a Video attachment (single or stacked). */\nexport interface VideoItem {\n src: string\n /** Poster / thumbnail rendered before playback starts. */\n poster?: string\n /** Optional MIME type (e.g. `video/mp4`). */\n mimeType?: string\n /**\n * Per-item override for the `<video preload>` hint. Defaults to the\n * parent attachment's `preload` value (which itself defaults to\n * `'none'` so the poster carries the visual weight and no video\n * bytes are fetched until playback).\n */\n preload?: MediaPreloadMode\n}\n\n/** A single PDF inside a Pdf attachment (single or stacked). */\nexport interface PdfItem {\n src: string\n /** Filename — drives the row title + the meta line + the viewer dialog's accessible name. */\n filename?: string\n /** File size in bytes — formatted into the `EXT · SIZE` meta line. */\n fileSize?: number\n /** Override displayed title. Defaults to `filename`. */\n title?: string\n}\n\n/** A single audio file inside an Audio attachment (single or stacked). */\nexport interface AudioItem {\n src: string\n /** MIME type hint — typed onto the inline `<source>` element. */\n mimeType?: string\n /**\n * Filename — used as the download default name (consumed by the\n * native player's kebab menu).\n */\n filename?: string\n /**\n * Per-track override for the `<audio preload>` hint. Defaults to\n * the parent attachment's `preload` value, which itself defaults\n * to `'metadata'` for a single audio (so the native player can\n * surface duration immediately) and `'none'` for a stacked thread\n * (so a fan-out of metadata requests doesn't happen on first paint).\n */\n preload?: MediaPreloadMode\n}\n\n/** A single generic file inside a File attachment (single or stacked). */\nexport interface FileItem {\n src: string\n /** Filename — drives the title + the meta line + the download default name. */\n filename?: string\n /** File size in bytes — formatted into the `EXT · SIZE` meta line. */\n fileSize?: number\n /** MIME type — drives the type icon. Defaults to `application/octet-stream`. */\n mimeType?: string\n /** Override displayed title. Defaults to `filename`. */\n title?: string\n}\n\n/** Shared props every `MessageAttachment.*.{Composer|Sent|Received}` accepts. */\nexport interface MessageAttachmentBaseProps {\n /**\n * Optional text rendered below the attachment inside the same bubble.\n * Mirrors the chat behavior in the mobile screenshots — `'Here is the\n * file'`, `'Here is the image'`, etc.\n */\n text?: React.ReactNode\n /**\n * Position of this attachment inside a same-author message run —\n * mirrors the corner-flattening stream-chat-react applies to text\n * bubbles in a clustered conversation. Defaults to `'single'`, so\n * standalone usage keeps every corner rounded. Pass the value\n * derived from `bubbleGroupPositionFromStream({ firstOfGroup,\n * endOfGroup, groupedByUser })` when rendering inside a real\n * `CustomMessage` thread to make the attachment visually merge\n * with adjacent bubbles. Image / Video Composer ignore this — the\n * draft preview renders bare without the surrounding bubble.\n */\n groupPosition?: BubbleGroupPosition\n}\n\n/** Shared props for the `Composer` state of every attachment type. */\nexport interface ComposerExtras {\n /** Renders a dismiss `×` button overlaid on the attachment. */\n onDismiss?: () => void\n}\n","import React from 'react'\n\nimport Bubble from '../_shared/Bubble'\nimport DismissButton from '../_shared/DismissButton'\nimport {\n bubbleVariantForState,\n type AudioItem,\n type ComposerExtras,\n type MediaPreloadMode,\n type MessageAttachmentBaseProps,\n type MessageAttachmentState,\n} from '../types'\n\nexport interface AudioAttachmentSharedProps extends MessageAttachmentBaseProps {\n /** Audio source URL (`mp3`, `aac`, `wav`, …). */\n src?: string\n /** MIME type hint — typed onto the inline `<source>` element. */\n mimeType?: string\n /**\n * Filename — used as the download default name (consumed by the\n * native player's kebab menu). The HTML `<audio>` element doesn't\n * expose a built-in title slot, so we don't render the filename\n * inside the bubble itself.\n */\n filename?: string\n /**\n * Stacked audio. Takes precedence over `src` when set. Each item\n * renders its own native `<audio controls>` player, vertically\n * stacked inside the same bubble with an 8px gap between players.\n * Sent + Received only — the composer surface accepts a single\n * attachment at a time.\n */\n items?: AudioItem[]\n /**\n * `<audio preload>` hint applied to every player on the bubble.\n * When omitted, the default depends on the rendered shape:\n *\n * - Single audio (no `items`, or `items.length === 1`) →\n * `'metadata'` so the native player surfaces duration\n * immediately.\n * - Stacked audio (`items.length > 1`) → `'none'` so a thread\n * of voice memos doesn't fan out N parallel metadata requests\n * on first paint.\n *\n * Per-track overrides live on `AudioItem.preload`.\n */\n preload?: MediaPreloadMode\n}\n\nconst resolveItems = ({\n src,\n mimeType,\n filename,\n items,\n}: {\n src?: string\n mimeType?: string\n filename?: string\n items?: AudioItem[]\n}): AudioItem[] => {\n if (items && items.length > 0) return items\n if (src) return [{ src, mimeType, filename }]\n return []\n}\n\nconst NativeAudioPlayer: React.FC<{\n item: AudioItem\n preload: MediaPreloadMode\n trailingAction?: React.ReactNode\n}> = ({ item, preload, trailingAction }) => (\n <div className=\"flex items-center gap-2\">\n {/* No `<track>` is rendered — we don't author caption sidecars\n for chat attachments, and an empty `<track kind=\"captions\" />`\n emits a runtime warning. Re-add a real track (with `src`,\n `srcLang`, and `default`) once caption support actually ships.\n The `jsx-a11y/media-has-caption` rule is suppressed for the\n same reason. */}\n {/* eslint-disable-next-line jsx-a11y/media-has-caption */}\n <audio\n src={item.src}\n controls\n preload={item.preload ?? preload}\n className=\"block min-w-0 flex-1\"\n >\n {item.mimeType ? <source src={item.src} type={item.mimeType} /> : null}\n </audio>\n {trailingAction ?? null}\n </div>\n)\n\ninterface InternalAudioRowProps extends AudioAttachmentSharedProps {\n state: MessageAttachmentState\n onDismiss?: () => void\n}\n\nconst AudioAttachmentRow: React.FC<InternalAudioRowProps> = ({\n state,\n src,\n mimeType,\n filename,\n items,\n text,\n groupPosition,\n preload,\n onDismiss,\n}) => {\n const variant = bubbleVariantForState(state)\n const showDismiss = state === 'composer' && !!onDismiss\n const resolvedItems = resolveItems({ src, mimeType, filename, items })\n\n if (resolvedItems.length === 0) {\n return null\n }\n\n // Default rule: surface duration immediately for a single player,\n // but avoid fanning out N metadata requests when the bubble is a\n // thread of voice memos. An explicit `preload` prop overrides;\n // per-track overrides live on `AudioItem.preload`.\n const resolvedPreload: MediaPreloadMode =\n preload ?? (resolvedItems.length > 1 ? 'none' : 'metadata')\n\n return (\n <Bubble\n variant={variant}\n text={text}\n groupPosition={groupPosition}\n data-testid=\"audio-attachment\"\n >\n {/* Native `<audio controls>` already exposes a download in its\n kebab menu, so we don't render a separate Download button.\n The element also has no built-in title slot — the dismiss\n button (Composer only) sits inline next to the player.\n Stacked players get an 8px vertical gap so each track reads\n as a discrete attachment. */}\n <div className=\"flex flex-col gap-2\">\n {resolvedItems.map((item, index) => (\n <NativeAudioPlayer\n key={`${item.src}-${index}`}\n item={item}\n preload={resolvedPreload}\n trailingAction={\n // Composer only supports a single attachment, so the\n // dismiss control sits on the only player.\n showDismiss && index === 0 ? (\n <DismissButton onClick={onDismiss!} variant=\"inline\" />\n ) : undefined\n }\n />\n ))}\n </div>\n </Bubble>\n )\n}\n\n/**\n * Composer-only props. Single audio (`src`) only — the composer\n * surface accepts a single attachment at a time, so `items` is not\n * supported. Captions (`text`) and `groupPosition` are also dropped:\n * the composer renders a standalone draft, not part of a same-author\n * run, and captions live in the message-input textarea, not inside\n * the draft attachment preview.\n */\nexport interface AudioComposerProps extends ComposerExtras {\n src?: string\n mimeType?: string\n filename?: string\n /** See `AudioAttachmentSharedProps.preload`. */\n preload?: MediaPreloadMode\n}\nexport type AudioSentProps = AudioAttachmentSharedProps\nexport type AudioReceivedProps = AudioAttachmentSharedProps\n\nconst AudioComposer: React.FC<AudioComposerProps> = (props) => (\n <AudioAttachmentRow {...props} state=\"composer\" />\n)\nconst AudioSent: React.FC<AudioSentProps> = (props) => (\n <AudioAttachmentRow {...props} state=\"sent\" />\n)\nconst AudioReceived: React.FC<AudioReceivedProps> = (props) => (\n <AudioAttachmentRow {...props} state=\"received\" />\n)\n\nconst AudioAttachment = {\n Composer: AudioComposer,\n Sent: AudioSent,\n Received: AudioReceived,\n}\n\nexport default AudioAttachment\n","import {\n getDocumentIconType,\n getSourceType,\n} from '../../AttachmentCard/utils/mimeType'\n\n/**\n * Format a byte count as a short human-readable string (`'379.5 KB'`).\n * Mirrors the meta line shown next to file attachments in the mobile chat\n * design — `EXT · SIZE`, e.g. `PDF · 379.5 KB`.\n */\nexport function formatFileSize(bytes: number): string {\n if (!Number.isFinite(bytes) || bytes < 0) return ''\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n if (bytes < 1024 * 1024 * 1024)\n return `${(bytes / (1024 * 1024)).toFixed(2)} MB`\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`\n}\n\nconst EXTENSION_LABEL_BY_DOCUMENT_TYPE: Record<string, string> = {\n pdf: 'PDF',\n doc: 'DOC',\n xls: 'XLS',\n csv: 'CSV',\n ppt: 'PPT',\n zip: 'ZIP',\n text: 'TXT',\n markdown: 'MD',\n}\n\n/**\n * Returns the short uppercase extension label shown in the meta line of\n * compact document / file attachments. Prefers the filename extension\n * when present (matches the mobile design which trusts the filename),\n * and falls back to a label derived from the MIME type.\n */\nexport function getFileExtensionLabel(\n mimeType?: string,\n filename?: string\n): string | undefined {\n if (filename) {\n const lastDot = filename.lastIndexOf('.')\n if (lastDot > 0 && lastDot < filename.length - 1) {\n const ext = filename.slice(lastDot + 1)\n if (ext && ext.length <= 5) return ext.toUpperCase()\n }\n }\n\n if (!mimeType) return undefined\n\n const sourceType = getSourceType(mimeType)\n if (sourceType === 'document') {\n const docType = getDocumentIconType(mimeType)\n const docLabel = EXTENSION_LABEL_BY_DOCUMENT_TYPE[docType]\n if (docLabel) return docLabel\n if (mimeType === 'application/octet-stream') return undefined\n }\n\n const subtype = mimeType.split('/')[1]\n if (!subtype || subtype === '*') return undefined\n return subtype.toUpperCase()\n}\n\n/**\n * Build the meta line shown under the title in compact document / file\n * attachments — `EXT · SIZE` (`PDF · 379.5 KB`). Either part is dropped\n * when not available so audio / generic files still get a useful label.\n */\nexport function buildCompactMetaLabel(\n mimeType?: string,\n filename?: string,\n fileSize?: number\n): string | undefined {\n const ext = getFileExtensionLabel(mimeType, filename)\n const size =\n typeof fileSize === 'number' && fileSize > 0\n ? formatFileSize(fileSize)\n : undefined\n return [ext, size].filter(Boolean).join(' · ') || undefined\n}\n\n/**\n * Derive a sensible filename from a URL — used as the fallback save name\n * when the attachment has no `filename` set. Returns `'download'` for\n * URLs we can't parse.\n */\nexport function filenameFromUrl(url: string): string {\n try {\n const parsed = new URL(url)\n const last = parsed.pathname.split('/').pop()\n return last && last.length > 0 ? decodeURIComponent(last) : 'download'\n } catch {\n return 'download'\n }\n}\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport { renderTypeIcon } from '../../AttachmentCard'\nimport type { BubbleVariant } from '../types'\n\nimport { buildCompactMetaLabel } from './fileMeta'\n\nexport interface CompactDocumentRowProps {\n variant: BubbleVariant\n /** Filename — drives the title (when no `title` set) and the `EXT` label. */\n filename?: string\n /** Override displayed title. Defaults to `filename`. */\n title?: string\n mimeType?: string\n fileSize?: number\n /**\n * When set, the icon + filename area becomes a `<button>` that fires\n * this handler. Lets the row's primary activation (e.g. opening the\n * PDF viewer) live separately from the trailing slot's own button\n * (e.g. a download icon) without nesting `<button>` inside `<button>`.\n * When omitted, the row renders as a plain presentational `<div>`\n * and the caller is responsible for any outer activation wrapper.\n */\n onActivate?: () => void\n /**\n * Required when `onActivate` is set. Visible to assistive tech as\n * the inner button's label (e.g. `'Open ESOP-summary.pdf'`).\n */\n activateLabel?: string\n /**\n * Optional trailing slot — sits outside the activation button so it\n * can host its own interactive controls (e.g. a download `<button>`,\n * the Composer's `DismissButton`) without nesting one button inside\n * another.\n */\n trailingAction?: React.ReactNode\n}\n\n// Meta line + icon tile are tinted relative to the bubble background,\n// so they stay variant-aware. The title inherits the bubble's text\n// color (set on the parent `Bubble`).\n//\n// `text-black/55` on the `#f2f1ef` light bubble lands right at the\n// WCAG AA 4.5:1 small-text threshold (≈4.5:1) — bump to `/65` so\n// the meta line has a comfortable margin on the light bubble. The\n// dark variant (`text-white/55` on `#1e2330`) already passes AA,\n// so we leave it alone.\nconst META_CLASS_BY_VARIANT: Record<BubbleVariant, string> = {\n dark: 'text-white/55',\n light: 'text-black/65',\n}\n\nconst ICON_BG_BY_VARIANT: Record<BubbleVariant, string> = {\n dark: 'bg-white/10',\n light: 'bg-black/5',\n}\n\nconst ICON_COLOR_BY_VARIANT: Record<BubbleVariant, string> = {\n dark: 'text-white/85',\n light: 'text-black/85',\n}\n\n/**\n * Compact icon-row used by `Pdf` / `File` `MessageAttachment` variants.\n * Mirrors the mobile chat document attachment from\n * `EARN-8448/pr-2-chat-bubbles-and-file-icons` — a 40x40 typed icon\n * tile on the left, filename + `EXT · SIZE` meta on the right.\n *\n * The row is always wrapped by `Bubble`, which contributes the bubble\n * background, padding, border, and (when the parent wires it up) the\n * click target.\n */\nconst CompactDocumentRow: React.FC<CompactDocumentRowProps> = ({\n variant,\n filename,\n title,\n mimeType = 'application/octet-stream',\n fileSize,\n onActivate,\n activateLabel,\n trailingAction,\n}) => {\n const resolvedTitle = title ?? filename ?? 'File'\n const metaLabel = buildCompactMetaLabel(mimeType, filename, fileSize)\n\n const iconTile = (\n <div\n className={classNames(\n 'flex size-10 shrink-0 items-center justify-center rounded-sm',\n ICON_BG_BY_VARIANT[variant]\n )}\n aria-hidden\n >\n {renderTypeIcon(mimeType, {\n className: classNames('size-6', ICON_COLOR_BY_VARIANT[variant]),\n weight: 'regular',\n })}\n </div>\n )\n\n const textBlock = (\n <div className=\"flex min-w-0 flex-1 flex-col text-left\">\n <p className=\"truncate font-medium leading-snug\">{resolvedTitle}</p>\n {metaLabel ? (\n <p\n className={classNames(\n 'truncate text-xs leading-4',\n META_CLASS_BY_VARIANT[variant]\n )}\n >\n {metaLabel}\n </p>\n ) : null}\n </div>\n )\n\n // When the row is activatable, its body (icon + text) becomes the\n // click target — wrapping it in a `<button>` rather than wrapping\n // the entire row preserves the trailing slot for its own buttons\n // (download / dismiss) instead of nesting them inside one.\n const body = onActivate ? (\n <button\n type=\"button\"\n onClick={onActivate}\n aria-label={activateLabel}\n className={classNames(\n 'flex min-w-0 flex-1 items-center gap-3 rounded-sm text-left transition-colors',\n variant === 'dark'\n ? 'hover:bg-white/[0.04]'\n : 'hover:bg-black/[0.04]'\n )}\n >\n {iconTile}\n {textBlock}\n </button>\n ) : (\n <>\n {iconTile}\n {textBlock}\n </>\n )\n\n return (\n <div className=\"flex items-center gap-3 px-3 py-2\">\n {body}\n {trailingAction ? <div className=\"shrink-0\">{trailingAction}</div> : null}\n </div>\n )\n}\n\nexport default CompactDocumentRow\n","import { filenameFromUrl } from './fileMeta'\n\n/**\n * Download a remote asset with the desired filename.\n *\n * Tries the same-origin `fetch` → `Blob` → invisible-`<a>.download`\n * route first so the file lands on disk under `filename` instead of\n * navigating the tab to it. When CORS / network errors trip us up we\n * fall back to `window.open` and then to a no-window anchor — the\n * popup-blocker fallback ensures the download still fires even when\n * a browser blocks the `_blank` window.\n *\n * Shared by `DownloadAction` (rendered as an explicit Download button\n * in PDF / image / video viewers) and `MessageAttachment.File` rows\n * (where the entire row is the download trigger). Centralizing here\n * keeps one source of truth for the fallback chain.\n */\nexport async function triggerDownload(\n url: string,\n filename?: string\n): Promise<void> {\n const name = filename ?? filenameFromUrl(url)\n\n try {\n const res = await fetch(url, { mode: 'cors' })\n if (!res.ok) throw new Error(`HTTP ${res.status}`)\n const blob = await res.blob()\n const objectUrl = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = objectUrl\n a.download = name\n a.style.display = 'none'\n document.body.appendChild(a)\n a.click()\n document.body.removeChild(a)\n URL.revokeObjectURL(objectUrl)\n } catch {\n const fallback = window.open(url, '_blank', 'noopener,noreferrer')\n if (!fallback) {\n // popup blocked — fall back to a non-windowed anchor\n const a = document.createElement('a')\n a.href = url\n a.download = name\n a.target = '_blank'\n a.rel = 'noopener noreferrer'\n a.style.display = 'none'\n document.body.appendChild(a)\n a.click()\n document.body.removeChild(a)\n }\n }\n}\n\nexport default triggerDownload\n","import { DownloadSimpleIcon } from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React from 'react'\n\nimport Bubble from '../_shared/Bubble'\nimport CompactDocumentRow from '../_shared/CompactDocumentRow'\nimport DismissButton from '../_shared/DismissButton'\nimport { filenameFromUrl } from '../_shared/fileMeta'\nimport { triggerDownload } from '../_shared/triggerDownload'\nimport {\n bubbleVariantForState,\n type BubbleVariant,\n type ComposerExtras,\n type FileItem,\n type MessageAttachmentBaseProps,\n type MessageAttachmentState,\n} from '../types'\n\nexport interface FileAttachmentSharedProps extends MessageAttachmentBaseProps {\n /** Source URL of the file (used as the download target). */\n src?: string\n /** Filename — drives the title + the meta line + the download default name. */\n filename?: string\n fileSize?: number\n /** MIME type — drives the type icon. Defaults to `application/octet-stream`. */\n mimeType?: string\n /**\n * Override displayed title (defaults to `filename`). Useful when a\n * sender renames the attachment before sending.\n */\n title?: string\n /**\n * Stacked files. Takes precedence over `src` when set. Each item\n * renders as its own row inside the bubble; clicking a row downloads\n * that file. Sent + Received only — the composer surface accepts a\n * single attachment at a time.\n */\n items?: FileItem[]\n /**\n * Forwarded to the row trigger. When omitted the click still\n * downloads the file. Supply this for analytics, or return `false`\n * to fully intercept the download (e.g. show a confirmation modal,\n * route to a custom preview, throttle large files). Any other\n * return value — including `void`/`undefined` — lets the built-in\n * download proceed. For stacked attachments the `index` argument\n * identifies the row.\n */\n onClick?: (index: number) => boolean | void\n}\n\nconst resolveItems = ({\n src,\n filename,\n fileSize,\n mimeType,\n title,\n items,\n}: {\n src?: string\n filename?: string\n fileSize?: number\n mimeType?: string\n title?: string\n items?: FileItem[]\n}): FileItem[] => {\n if (items && items.length > 0) return items\n if (src) return [{ src, filename, fileSize, mimeType, title }]\n return []\n}\n\ninterface FileRowButtonProps {\n variant: BubbleVariant\n item: FileItem\n index: number\n onActivate: (index: number) => void\n trailingAction: React.ReactNode\n}\n\n/**\n * Single tappable file row — used both for the lone file case and\n * for each child of a stacked attachment. The icon + filename area\n * is the click target (downloads the asset); the trailing slot is\n * decorative on Sent / Received and hosts the dismiss control on\n * Composer.\n */\nconst FileRowButton: React.FC<FileRowButtonProps> = ({\n variant,\n item,\n index,\n onActivate,\n trailingAction,\n}) => {\n const resolvedFilename = item.filename ?? filenameFromUrl(item.src)\n return (\n <CompactDocumentRow\n variant={variant}\n filename={resolvedFilename}\n title={item.title}\n mimeType={item.mimeType ?? 'application/octet-stream'}\n fileSize={item.fileSize}\n onActivate={() => onActivate(index)}\n activateLabel={`Download ${resolvedFilename}`}\n trailingAction={trailingAction}\n />\n )\n}\n\ninterface InternalFileRowProps extends FileAttachmentSharedProps {\n state: MessageAttachmentState\n onDismiss?: () => void\n}\n\nconst FileAttachmentRow: React.FC<InternalFileRowProps> = ({\n state,\n src,\n filename,\n fileSize,\n mimeType,\n title,\n items,\n text,\n groupPosition,\n onClick,\n onDismiss,\n}) => {\n const variant = bubbleVariantForState(state)\n const showDismiss = state === 'composer' && !!onDismiss\n const resolvedItems = resolveItems({\n src,\n filename,\n fileSize,\n mimeType,\n title,\n items,\n })\n\n // `useCallback` would be pointless here — `resolvedItems` is rebuilt\n // every render, so memoizing on it produces a fresh function every\n // render anyway. Keep this as a plain function.\n const handleActivate = (index: number) => {\n // `onClick` returning `false` cancels the built-in download so\n // consumers can route the click to a confirmation modal, custom\n // preview, etc. Any other return value (including void) lets the\n // default download proceed.\n if (onClick?.(index) === false) return\n const item = resolvedItems[index]\n if (!item) return\n const resolvedFilename = item.filename ?? filenameFromUrl(item.src)\n void triggerDownload(item.src, resolvedFilename)\n }\n\n if (resolvedItems.length === 0) {\n return null\n }\n\n const downloadIcon = (\n <span\n className={classNames(\n 'flex size-8 items-center justify-center rounded-full',\n variant === 'dark' ? 'text-white/70' : 'text-black/70'\n )}\n aria-hidden\n >\n <DownloadSimpleIcon className=\"size-5\" weight=\"bold\" />\n </span>\n )\n\n return (\n <Bubble\n variant={variant}\n text={text}\n groupPosition={groupPosition}\n data-testid=\"file-attachment\"\n >\n {/* Stacked rows get a small vertical gap so each file reads as\n a discrete attachment rather than one merged blob. Single\n row falls through to a no-op `gap-0`. */}\n <div className=\"flex flex-col gap-2\">\n {resolvedItems.map((item, index) => {\n // Composer only supports a single attachment so the dismiss\n // control sits on the only row; otherwise every row gets\n // the trailing download icon hint.\n const trailingAction =\n showDismiss && index === 0 ? (\n <DismissButton onClick={onDismiss!} variant=\"inline\" />\n ) : (\n downloadIcon\n )\n return (\n <FileRowButton\n key={`${item.src}-${index}`}\n variant={variant}\n item={item}\n index={index}\n onActivate={handleActivate}\n trailingAction={trailingAction}\n />\n )\n })}\n </div>\n </Bubble>\n )\n}\n\n/**\n * Composer-only props. Single file (`src`) only — the composer surface\n * accepts a single attachment at a time, so `items` is not supported.\n * Captions (`text`) and `groupPosition` are also dropped: the composer\n * renders a standalone draft, not part of a same-author run, and\n * captions live in the message-input textarea, not inside the draft\n * attachment preview.\n */\nexport interface FileComposerProps extends ComposerExtras {\n src?: string\n filename?: string\n fileSize?: number\n mimeType?: string\n title?: string\n onClick?: (index: number) => boolean | void\n}\nexport type FileSentProps = FileAttachmentSharedProps\nexport type FileReceivedProps = FileAttachmentSharedProps\n\nconst FileComposer: React.FC<FileComposerProps> = (props) => (\n <FileAttachmentRow {...props} state=\"composer\" />\n)\nconst FileSent: React.FC<FileSentProps> = (props) => (\n <FileAttachmentRow {...props} state=\"sent\" />\n)\nconst FileReceived: React.FC<FileReceivedProps> = (props) => (\n <FileAttachmentRow {...props} state=\"received\" />\n)\n\nconst FileAttachment = {\n Composer: FileComposer,\n Sent: FileSent,\n Received: FileReceived,\n}\n\nexport default FileAttachment\n","import { CaretLeftIcon, CaretRightIcon } from '@phosphor-icons/react'\nimport React from 'react'\n\nexport interface CarouselNavProps {\n onPrev: () => void\n onNext: () => void\n /** Accessible label for the previous-item button. */\n prevLabel?: string\n /** Accessible label for the next-item button. */\n nextLabel?: string\n}\n\n/**\n * Prev / next chrome shared by every carousel-aware viewer. Rendered\n * inside the dialog body so the buttons sit absolutely positioned\n * against the viewer (`.mes-media-viewer__nav--{prev,next}`).\n *\n * Styling lives as plain CSS in `styles.css` so the buttons render\n * correctly regardless of whether the consumer has Tailwind wired up.\n */\nconst CarouselNav: React.FC<CarouselNavProps> = ({\n onPrev,\n onNext,\n prevLabel = 'Previous',\n nextLabel = 'Next',\n}) => (\n <>\n <button\n type=\"button\"\n onClick={onPrev}\n aria-label={prevLabel}\n className=\"mes-media-viewer__nav mes-media-viewer__nav--prev\"\n >\n <CaretLeftIcon size={20} weight=\"bold\" aria-hidden />\n </button>\n <button\n type=\"button\"\n onClick={onNext}\n aria-label={nextLabel}\n className=\"mes-media-viewer__nav mes-media-viewer__nav--next\"\n >\n <CaretRightIcon size={20} weight=\"bold\" aria-hidden />\n </button>\n </>\n)\n\nexport default CarouselNav\n","import {\n CircleNotchIcon,\n DownloadSimpleIcon,\n IconProps,\n} from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React, { useCallback, useState } from 'react'\n\nimport { triggerDownload } from './triggerDownload'\n\nexport type DownloadActionVariant =\n /** Solid pill button used inside compact / file rows. */\n | 'pill'\n /**\n * Compact round icon button sized for the trailing slot of a\n * `CompactDocumentRow` (PDF / File rows). Adopts the row's tone so\n * it sits inline next to the filename without competing with it.\n */\n | 'inline'\n /**\n * Round icon button sized to match the close action in the\n * `ViewerShell` chrome — used by `ImageViewer` for in-viewer\n * downloads. Styled with plain CSS (`.mes-media-viewer__action`) so\n * it renders correctly without a Tailwind dependency in the\n * consumer's app.\n */\n | 'viewer'\n\nexport interface DownloadActionProps {\n url: string\n filename?: string\n variant?: DownloadActionVariant\n /**\n * Override the visible label on `pill` variants. Defaults to\n * `'Download'`. On `inline` / `viewer` variants the label is\n * hidden visually and surfaced as the button's `aria-label`.\n */\n label?: string\n /** Hide the label, keeping just the icon. Defaults to `true` for non-pill variants. */\n iconOnly?: boolean\n /** Tone of the surface. Used by the `pill` variant. */\n tone?: 'dark' | 'light'\n /**\n * Triggered after the download starts so consumers can fire analytics\n * or close a viewer. Errors during download don't suppress the call.\n */\n onTriggered?: () => void\n}\n\nconst DownloadAction: React.FC<DownloadActionProps> = ({\n url,\n filename,\n variant = 'pill',\n label = 'Download',\n iconOnly,\n tone = 'dark',\n onTriggered,\n}) => {\n const [busy, setBusy] = useState(false)\n\n const handleClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation()\n if (busy) return\n setBusy(true)\n triggerDownload(url, filename)\n .catch(() => {\n /* swallowed — fallback path inside `triggerDownload` */\n })\n .finally(() => {\n setBusy(false)\n onTriggered?.()\n })\n },\n [busy, url, filename, onTriggered]\n )\n\n const showIconOnly = iconOnly ?? variant !== 'pill'\n\n const iconClass = classNames(\n variant === 'pill' ? 'size-4' : 'size-5',\n 'shrink-0'\n )\n const iconProps: IconProps = { className: iconClass, weight: 'bold' }\n\n if (variant === 'inline') {\n // Sized to match the existing trailing slot used by `DismissButton`\n // and the decorative download span in `FileAttachment`. Tone keys\n // off the surrounding `Bubble` variant so a sender (dark) bubble\n // gets a lighter icon and a receiver (light) bubble gets a darker\n // one — same approach `CompactDocumentRow` already uses for the\n // type icon.\n const inlineToneClasses: Record<'dark' | 'light', string> = {\n dark: 'text-white/70 hover:bg-white/[0.08] hover:text-white',\n light: 'text-black/70 hover:bg-black/[0.08] hover:text-black',\n }\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={busy}\n aria-label={label}\n className={classNames(\n 'flex size-8 shrink-0 items-center justify-center rounded-full transition-colors disabled:opacity-70',\n inlineToneClasses[tone]\n )}\n >\n {busy ? (\n <CircleNotchIcon\n className=\"size-4 animate-spin\"\n weight=\"bold\"\n aria-hidden\n />\n ) : (\n <DownloadSimpleIcon\n className=\"size-5 shrink-0\"\n weight=\"bold\"\n aria-hidden\n />\n )}\n </button>\n )\n }\n\n if (variant === 'viewer') {\n // Styled entirely through `.mes-media-viewer__action` (plain CSS\n // in `styles.css`) so the button renders correctly when consumed\n // outside this repo without a Tailwind setup. Sits next to the\n // close action inside `ViewerShell`'s top-right chrome.\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={busy}\n aria-label={label}\n className=\"mes-media-viewer__action\"\n >\n {busy ? (\n <CircleNotchIcon size={20} weight=\"bold\" aria-hidden />\n ) : (\n <DownloadSimpleIcon size={20} weight=\"bold\" aria-hidden />\n )}\n </button>\n )\n }\n\n // pill — only remaining variant\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={busy}\n aria-label={showIconOnly ? label : undefined}\n className={classNames(\n 'mt-3 inline-flex h-10 w-full items-center justify-center gap-2 rounded-full px-4 text-sm font-medium leading-none transition-colors disabled:opacity-70',\n tone === 'dark'\n ? 'bg-[#121110] text-white hover:bg-[#2a2928]'\n : 'bg-white text-[#121110] hover:bg-white/90'\n )}\n >\n {busy ? (\n <CircleNotchIcon\n className=\"size-4 animate-spin\"\n weight=\"bold\"\n aria-hidden\n />\n ) : (\n <DownloadSimpleIcon {...iconProps} aria-hidden />\n )}\n {showIconOnly ? null : label}\n </button>\n )\n}\n\nexport default DownloadAction\n","/* eslint-disable react-hooks/set-state-in-effect -- pre-existing pattern flagged by the React\n Compiler rules added in eslint-plugin-react-hooks v7; refactoring it is\n out of scope for the lint toolchain upgrade. */\nimport { useCallback, useEffect, useState } from 'react'\n\nconst clamp = (value: number, min: number, max: number) =>\n Math.min(Math.max(value, min), max)\n\nexport interface UseCarouselOptions {\n /** Total number of items in the carousel. */\n length: number\n /** Index to display when the carousel first opens / re-opens. */\n initialIndex: number\n /** When `false`, the keyboard listener is detached. */\n open: boolean\n}\n\nexport interface UseCarouselResult {\n /** Currently displayed index (clamped to `[0, length - 1]`). */\n index: number\n /** Step one item back, wrapping at the start. */\n prev: () => void\n /** Step one item forward, wrapping at the end. */\n next: () => void\n}\n\n/**\n * Tiny carousel state used by `ImageViewer`, `VideoViewer`, and\n * `PdfViewer` when their items array has more than one entry.\n *\n * - Resets to `initialIndex` whenever the viewer (re-)opens, so\n * clicking a different tile on the bubble surface lands on that\n * item rather than restoring the last-viewed position.\n * - Clamps defensively when `length` shrinks below the active index\n * (server push / optimistic update / stack edit) so the viewer\n * gracefully falls back instead of dereferencing `undefined`.\n * - Listens for `ArrowLeft` / `ArrowRight` while the viewer is open,\n * but yields when the focused element is a `<video>` / `<audio>`\n * element so the native media controls can use the same keys for\n * seek / volume.\n */\nexport const useCarousel = ({\n length,\n initialIndex,\n open,\n}: UseCarouselOptions): UseCarouselResult => {\n const safeInitial = clamp(initialIndex, 0, Math.max(length - 1, 0))\n const [index, setIndex] = useState(safeInitial)\n\n // Snap the active index back to whatever the caller asked for every\n // time the viewer (re)opens or its initial target / length changes.\n // Without this the viewer would remember the last index across\n // open/close cycles, which is wrong for a chat lightbox where each\n // tile click should land on that tile.\n useEffect(() => {\n if (!open) return\n setIndex(clamp(initialIndex, 0, Math.max(length - 1, 0)))\n }, [open, initialIndex, length])\n\n // Re-clamp on length change so a stale index doesn't dereference\n // past the new array bounds (e.g. items shrank while the viewer is\n // open). The `Math.max(..., 0)` keeps the index at `0` when the\n // array empties out so callers can render an empty-state instead of\n // a runtime crash.\n useEffect(() => {\n setIndex((i) => clamp(i, 0, Math.max(length - 1, 0)))\n }, [length])\n\n const prev = useCallback(() => {\n if (length <= 1) return\n setIndex((i) => (i <= 0 ? length - 1 : i - 1))\n }, [length])\n\n const next = useCallback(() => {\n if (length <= 1) return\n setIndex((i) => (i >= length - 1 ? 0 : i + 1))\n }, [length])\n\n useEffect(() => {\n if (!open || length <= 1) return undefined\n\n const onKey = (e: KeyboardEvent) => {\n if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return\n // Don't hijack arrow keys when a native media element is\n // focused — the browser's own controls already use them for\n // seek / volume, and stealing them would feel broken.\n const active = document.activeElement\n if (\n active &&\n (active.tagName === 'VIDEO' || active.tagName === 'AUDIO')\n ) {\n return\n }\n e.preventDefault()\n if (e.key === 'ArrowLeft') prev()\n else next()\n }\n\n window.addEventListener('keydown', onKey)\n return () => window.removeEventListener('keydown', onKey)\n }, [open, length, prev, next])\n\n return { index, prev, next }\n}\n\nexport default useCarousel\n","import { XIcon } from '@phosphor-icons/react'\nimport React, { useEffect, useRef } from 'react'\n\nexport interface ViewerShellProps {\n open: boolean\n onClose: () => void\n /**\n * Accessible label for the dialog — usually the media's filename. We\n * intentionally don't render a visible title bar (the chrome is a\n * single close button + optional actions so the media stays the\n * focus), so this is the only way assistive tech gets a name for\n * the modal.\n */\n ariaLabel?: string\n /**\n * Optional counter rendered in the top-left chrome (e.g. `2 / 6`).\n * Carousel-aware viewers set this when their items array has more\n * than one entry; omit it for single-item viewers.\n */\n counter?: React.ReactNode\n /**\n * Extra buttons rendered alongside the close button in the top-right\n * chrome (e.g. a download action). They share `.mes-media-viewer__action`\n * styling so the row reads as one consistent button group.\n */\n actions?: React.ReactNode\n children: React.ReactNode\n 'data-testid'?: string\n}\n\n/**\n * Full-viewport lightbox shell shared by `ImageViewer`, `VideoViewer`,\n * and `PdfViewer`. Built on a native `<dialog>` so the package ships\n * without a Tailwind dependency for the load-bearing chrome:\n *\n * - Top-layer + body-scroll lock come for free from `showModal()`.\n * - `Escape` to close is wired by the platform.\n * - Focus management (move-in on open, restore on close) is handled\n * by the browser; we explicitly focus the close button as a\n * fallback for environments where `showModal` is unavailable\n * (jsdom under tests).\n *\n * The structural styling lives as plain CSS under `.mes-media-viewer*`\n * in `styles.css` so a consumer who imports\n * `@linktr.ee/messaging-react/styles.css` gets a working lightbox even\n * if their Tailwind pipeline isn't scanning our `dist`.\n */\nconst ViewerShell: React.FC<ViewerShellProps> = ({\n open,\n onClose,\n ariaLabel,\n counter,\n actions,\n children,\n 'data-testid': dataTestId,\n}) => {\n const dialogRef = useRef<HTMLDialogElement | null>(null)\n const closeButtonRef = useRef<HTMLButtonElement | null>(null)\n\n // Drive `<dialog>` open/close imperatively from the React `open` prop.\n // We guard `showModal` / `close` because jsdom 23 ships the element\n // without those methods — falling back to the `[open]` attribute\n // keeps tests (and any other non-DOM environment) functional even if\n // the true top-layer modal behavior isn't available there.\n useEffect(() => {\n const dialog = dialogRef.current\n if (!dialog) return undefined\n\n if (open) {\n if (!dialog.open) {\n if (typeof dialog.showModal === 'function') {\n try {\n dialog.showModal()\n } catch {\n dialog.setAttribute('open', '')\n }\n } else {\n dialog.setAttribute('open', '')\n }\n }\n\n const previouslyFocused =\n typeof document !== 'undefined'\n ? (document.activeElement as HTMLElement | null)\n : null\n\n // Explicitly focus the close button. In a real browser\n // `showModal()` would already focus the first sequentially\n // focusable child (which is the close button), but doing it\n // ourselves guarantees the same behavior in jsdom and in any\n // browser where focus heuristics differ.\n closeButtonRef.current?.focus()\n\n return () => {\n if (dialog.open) {\n if (typeof dialog.close === 'function') {\n try {\n dialog.close()\n } catch {\n dialog.removeAttribute('open')\n }\n } else {\n dialog.removeAttribute('open')\n }\n }\n if (previouslyFocused && document.body.contains(previouslyFocused)) {\n previouslyFocused.focus()\n }\n }\n }\n\n if (dialog.open) {\n if (typeof dialog.close === 'function') {\n try {\n dialog.close()\n } catch {\n dialog.removeAttribute('open')\n }\n } else {\n dialog.removeAttribute('open')\n }\n }\n return undefined\n }, [open])\n\n // The platform fires `close` when the user dismisses via Escape or\n // any other native path. Mirror that into React state so the parent's\n // `open` flag stays in sync — otherwise the dialog would close\n // visually but our effect would re-open it on the next render.\n const handleDialogClose = () => {\n onClose()\n }\n\n // Backdrop click closes the viewer. The click lands on the `<dialog>`\n // itself (not its children) because the body sits inside an inner\n // wrapper — the easiest reliable check.\n const handleDialogClick = (e: React.MouseEvent<HTMLDialogElement>) => {\n if (e.target === dialogRef.current) onClose()\n }\n\n return (\n // The native `<dialog>` element ships its own keyboard dismissal\n // (Escape, handled by the platform and surfaced through `onClose`),\n // so the `onClick` on the backdrop doesn't need a paired keyboard\n // listener — that's the whole point of using `<dialog>`. The\n // `jsx-a11y` rules below don't model `<dialog>` as interactive, so\n // we silence them locally with the rationale captured here.\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions\n <dialog\n ref={dialogRef}\n className=\"mes-media-viewer\"\n aria-label={ariaLabel ?? 'Attachment viewer'}\n data-testid={dataTestId}\n onClose={handleDialogClose}\n onClick={handleDialogClick}\n >\n <div className=\"mes-media-viewer__chrome\">\n {counter ? (\n <span className=\"mes-media-viewer__counter\">{counter}</span>\n ) : null}\n <div className=\"mes-media-viewer__actions\">\n {actions}\n <button\n ref={closeButtonRef}\n type=\"button\"\n onClick={onClose}\n aria-label=\"Close viewer\"\n className=\"mes-media-viewer__action\"\n >\n <XIcon size={20} weight=\"bold\" aria-hidden />\n </button>\n </div>\n </div>\n <div className=\"mes-media-viewer__body\">{children}</div>\n </dialog>\n )\n}\n\nexport default ViewerShell\n","import React, { useMemo } from 'react'\n\nimport CarouselNav from './CarouselNav'\nimport DownloadAction from './DownloadAction'\nimport { filenameFromUrl } from './fileMeta'\nimport { useCarousel } from './useCarousel'\nimport ViewerShell from './ViewerShell'\n\nexport interface ImageViewerItem {\n src: string\n alt?: string\n /**\n * Filename used by the download action and as the dialog's\n * accessible name. Falls back to the last pathname segment of\n * `src` when omitted.\n */\n filename?: string\n}\n\nexport interface ImageViewerProps {\n open: boolean\n items: ImageViewerItem[]\n /** Index to display when the viewer first opens. Defaults to `0`. */\n initialIndex?: number\n onClose: () => void\n}\n\n/**\n * Native lightbox-style image viewer — full-viewport `<dialog>` with\n * the image centered at reasonable max dimensions, a single close\n * button, and a download action in the chrome.\n *\n * When `items.length > 1` the viewer becomes a carousel:\n *\n * - Prev / next on-screen controls hug the viewport sides.\n * - `ArrowLeft` / `ArrowRight` step between siblings (the keyboard\n * listener is parked while a `<video>` / `<audio>` element is\n * focused so native media seek still works in mixed contexts).\n * - A `current / total` counter sits in the top-left chrome.\n *\n * Used by every `MessageAttachment.Image.*` variant\n * (Composer / Sent / Received) so admins can preview attachments\n * before sending and recipients can preview after receipt.\n */\nconst ImageViewer: React.FC<ImageViewerProps> = ({\n open,\n items,\n initialIndex = 0,\n onClose,\n}) => {\n const { index, prev, next } = useCarousel({\n length: items.length,\n initialIndex,\n open,\n })\n\n const item = items[index]\n const filename = useMemo(\n () => item?.filename ?? (item ? filenameFromUrl(item.src) : 'image'),\n [item]\n )\n\n if (!item) return null\n\n return (\n <ViewerShell\n open={open}\n onClose={onClose}\n ariaLabel={filename}\n counter={\n items.length > 1 ? `${index + 1} / ${items.length}` : undefined\n }\n actions={\n <DownloadAction\n url={item.src}\n filename={filename}\n variant=\"viewer\"\n label={`Download ${filename}`}\n />\n }\n data-testid=\"image-viewer\"\n >\n {open ? (\n <img\n // Forcing a key swap on item change ensures React replaces\n // the `<img>` cleanly between siblings — otherwise the\n // previous image stays painted for a frame while the new\n // `src` decodes, which reads as a stutter at carousel pace.\n key={`${index}:${item.src}`}\n src={item.src}\n alt={item.alt ?? filename}\n draggable={false}\n // The user has explicitly opened the viewer, so we want the\n // active image to appear immediately rather than fall to the\n // browser's lazy-load heuristics. Which is exactly why the\n // element is gated on `open`: `ViewerShell` keeps its\n // `<dialog>` mounted across open/close so the platform\n // transition can play, and an eager `<img>` inside a closed\n // dialog made every image bubble in a thread download its\n // full-resolution original — note the viewer intentionally\n // uses the raw `item.src`, not the CDN-optimised URL the\n // bubble tile renders.\n loading=\"eager\"\n decoding=\"async\"\n className=\"mes-media-viewer__image\"\n />\n ) : null}\n\n {items.length > 1 ? (\n <CarouselNav\n onPrev={prev}\n onNext={next}\n prevLabel=\"Previous image\"\n nextLabel=\"Next image\"\n />\n ) : null}\n </ViewerShell>\n )\n}\n\nexport default ImageViewer\n","import classNames from 'classnames'\nimport React from 'react'\n\nexport interface MediaStackTile {\n /** Renderable tile content (image / video / poster). */\n content: React.ReactNode\n /** Pure-tile aria label (e.g. `'Photo 1'`). Used by `Pressable` mode. */\n ariaLabel?: string\n}\n\nexport interface MediaStackGridProps {\n tiles: MediaStackTile[]\n /**\n * When set, every tile is wrapped in a `<button>` and forwards the\n * tile index to `onTileActivate`. Used by Image / Video so any tile\n * opens the lightbox / video viewer at the right index.\n */\n onTileActivate?: (index: number) => void\n /**\n * Maximum tiles to render before the last one collapses into an\n * \"+N more\" overflow indicator. Defaults to `4`.\n */\n maxVisible?: number\n /**\n * Aspect ratio (width / height) for the SINGLE-tile layout. Applies\n * to every media kind, not just images. When omitted the 1-tile\n * branch keeps today's `aspect-square`. Ignored for 2+ tiles, whose\n * grid aspect is fixed.\n */\n singleAspectRatio?: number\n className?: string\n}\n\n// The tile is the focusable element, and its focus ring has to be drawn\n// INSIDE it. Figma leaves only a 2px frame around the media and `Bubble`\n// clips its own overflow, so an outset ring is swallowed by the frame;\n// an inset ring or a negative-offset `outline` on the tile is covered by\n// the media, which is `absolute inset-0`. A positioned `::after` is the\n// last child in tree order, so it paints above the media, inherits the\n// tile's outer-corner radius, and ignores every ancestor clip. Same\n// two-tone treatment as before — a dark band over a white ring — so it\n// stays legible on light and dark photos alike. Verified in Chromium.\nconst TILE_SHELL =\n 'relative block size-full overflow-hidden bg-black/5 outline-none after:pointer-events-none after:absolute after:inset-0 after:rounded-[inherit] focus-visible:after:ring-2 focus-visible:after:ring-inset focus-visible:after:ring-white/80 focus-visible:after:ring-offset-2 focus-visible:after:ring-offset-black'\n\n// Figma rounds only the four OUTER corners of a media cluster and leaves\n// every inner edge square: on `attachment-single-image` 1973:13863 the\n// `left` column carries `rectangleCornerRadii [18,0,0,18]` and `right`\n// `[0,18,18,0]`, while the tiles themselves carry none.\n//\n// So the radius lives on the tiles, keyed by layout and DOM position.\n// A single `overflow-hidden rounded-[18px]` container would be shorter,\n// but it also clips the tiles' `focus-visible` ring — an outset\n// `box-shadow` — and in the 1-tile layout the tile fills the container\n// exactly, so keyboard users would get no focus indicator at all.\n// Neither `ring-inset` nor a negative `outline-offset` rescues that:\n// the tile's `<img>` is `absolute inset-0` and paints over both.\n// Measured in Chromium, not assumed.\nconst OUTER_CORNER_CLASSES: Record<number, readonly string[]> = {\n 1: ['rounded-[18px]'],\n 2: ['rounded-l-[18px]', 'rounded-r-[18px]'],\n 3: ['rounded-l-[18px]', 'rounded-tr-[18px]', 'rounded-br-[18px]'],\n 4: [\n 'rounded-tl-[18px]',\n 'rounded-tr-[18px]',\n 'rounded-bl-[18px]',\n 'rounded-br-[18px]',\n ],\n}\n\n// Figma fits a single media item inside a max 326x436 content box on\n// web and 309x436 on mobile, preserving its aspect ratio, and the card\n// then adopts the resulting box — so `object-fit: cover` performs no\n// crop and nothing is letterboxed.\n//\n// The fit is `width = min(widthCap, heightCap * ratio)`, with\n// `aspect-ratio` supplying the other axis. Only the width cap is\n// breakpoint-dependent, so it travels as a custom property while the\n// ratio-derived term resolves to a concrete pixel value. Together they\n// reproduce all eight measured frames (`2032:22651` / `23000` /\n// `23353` / `23707` plus their mobile counterparts) to within Figma's\n// float rounding — including the 9:16 portrait, which renders 246x436\n// on web *and* mobile precisely because the height cap is NOT\n// breakpoint-dependent: a width-only rule would give mobile 309x547.6.\n//\n// The property name is spelled out again inside `SINGLE_WIDTH_CAPS` on\n// purpose. Tailwind extracts classes by scanning source text, so an\n// interpolated `` `[${SINGLE_WIDTH_CAP_PROPERTY}:309px]` `` would emit\n// no CSS at all and silently drop the width cap. Keep it literal.\nconst SINGLE_WIDTH_CAP_PROPERTY = '--mes-single-width-cap'\nconst SINGLE_WIDTH_CAPS =\n '[--mes-single-width-cap:309px] sm:[--mes-single-width-cap:326px]'\nconst SINGLE_HEIGHT_CAP_PX = 436\n\n/**\n * Adaptive grid used by stacked image / video attachments. Layouts:\n *\n * - 1 tile — full-bleed\n * - 2 tiles — equal-width side-by-side row\n * - 3 tiles — one large left tile + two stacked right tiles\n * - 4 tiles — 2×2 grid\n * - 5+ — 2×2 grid with the bottom-right tile showing \"+N more\"\n *\n * A single tile adopts `singleAspectRatio` when supplied and otherwise\n * stays square; 2 tiles sit in a 16:9 row, 3 in a 4:3 box, and 4 in\n * the 379x286 content box Figma draws for a stacked media card. Only\n * the cluster's four outer corners round — see `OUTER_CORNER_CLASSES`.\n */\nconst MediaStackGrid: React.FC<MediaStackGridProps> = ({\n tiles,\n onTileActivate,\n maxVisible = 4,\n singleAspectRatio,\n className,\n}) => {\n const total = tiles.length\n if (total === 0) return null\n\n const visible = tiles.slice(0, Math.min(total, maxVisible))\n const overflow = total - visible.length\n\n const renderTile = (tile: MediaStackTile, index: number, extra?: React.ReactNode) => {\n const sharedClass = classNames(\n TILE_SHELL,\n 'h-full w-full',\n OUTER_CORNER_CLASSES[visible.length]?.[index]\n )\n if (onTileActivate) {\n return (\n <button\n type=\"button\"\n key={index}\n onClick={() => onTileActivate(index)}\n aria-label={tile.ariaLabel ?? `Open media ${index + 1}`}\n className={classNames(sharedClass, 'cursor-zoom-in')}\n >\n {tile.content}\n {extra}\n </button>\n )\n }\n return (\n <div key={index} className={sharedClass}>\n {tile.content}\n {extra}\n </div>\n )\n }\n\n let singleTileStyle: React.CSSProperties | undefined\n if (singleAspectRatio) {\n singleTileStyle = {\n aspectRatio: singleAspectRatio,\n // Hundredths keep the emitted declaration readable in devtools;\n // the rounding error is well under a device pixel.\n width: `min(var(${SINGLE_WIDTH_CAP_PROPERTY}), ${\n Math.round(SINGLE_HEIGHT_CAP_PX * singleAspectRatio * 100) / 100\n }px)`,\n // Only bites in a container narrower than the width cap.\n maxWidth: '100%',\n }\n }\n\n if (visible.length === 1) {\n return (\n <div\n className={classNames(\n singleAspectRatio ? SINGLE_WIDTH_CAPS : 'aspect-square w-full',\n className\n )}\n style={singleTileStyle}\n >\n {renderTile(visible[0], 0)}\n </div>\n )\n }\n\n if (visible.length === 2) {\n return (\n <div\n className={classNames(\n 'grid aspect-[16/9] w-full grid-cols-2 gap-0.5',\n className\n )}\n >\n {visible.map((tile, index) => renderTile(tile, index))}\n </div>\n )\n }\n\n if (visible.length === 3) {\n return (\n <div\n className={classNames(\n 'grid aspect-[4/3] w-full grid-cols-2 grid-rows-2 gap-0.5',\n className\n )}\n >\n <div className=\"row-span-2\">{renderTile(visible[0], 0)}</div>\n {renderTile(visible[1], 1)}\n {renderTile(visible[2], 2)}\n </div>\n )\n }\n\n // 4 tiles (or 4 visible with overflow on the last)\n return (\n <div\n className={classNames(\n // 379x286 is the content box of Figma's 383x290 stacked-media\n // card (`attachment-single-image` 1973:13863) once its 2px\n // frame is removed. Pinning the aspect on the container — as\n // this branch has always done — makes the card resolve to\n // exactly 383x290, and the 2px gutters then split it into\n // 188.5x142 tiles (Figma draws 188x142; its own 383 does not\n // divide evenly, so half a pixel goes to the columns).\n 'grid aspect-[379/286] w-full grid-cols-2 grid-rows-2 gap-0.5',\n className\n )}\n >\n {visible.map((tile, index) => {\n const isLastWithOverflow = overflow > 0 && index === visible.length - 1\n return renderTile(\n tile,\n index,\n isLastWithOverflow ? (\n <div className=\"absolute inset-0 flex items-center justify-center bg-black/55 text-2xl font-semibold text-white\">\n +{overflow}\n </div>\n ) : null\n )\n })}\n </div>\n )\n}\n\nexport default MediaStackGrid\n","import { useCallback, useState } from 'react'\n\n/**\n * Optional click handler used by every viewer-backed attachment.\n *\n * Return `false` to cancel the default open behavior — useful for\n * route-based viewers or confirmation modals. Any other return value\n * (including `void`/`undefined`) lets the built-in viewer open as\n * normal. The `index` argument identifies the row in stacked\n * attachments and is `0` for the single-attachment shape.\n */\nexport type ViewerClickHandler = (index: number) => boolean | void\n\nexport interface UseViewerResult {\n viewerOpen: boolean\n viewerIndex: number\n /**\n * Open the viewer at the given index. Forwards to the caller's\n * `onClick` first so analytics + intercept logic can fire before\n * the viewer mounts; if `onClick` returns `false` the open is\n * skipped entirely.\n */\n handleActivate: (index: number) => void\n closeViewer: () => void\n}\n\n/**\n * Tiny piece of state shared by every `MessageAttachment` that opens\n * a fullscreen viewer (`Image`, `Video`, `Pdf`). Tracks the open flag\n * + the active index, and threads the caller's `onClick` callback\n * through `handleActivate` so consumers can intercept the open\n * (e.g. analytics) or cancel it (return `false` to swap in a\n * route-based viewer / confirmation modal).\n */\nexport const useViewer = (onClick?: ViewerClickHandler): UseViewerResult => {\n const [viewerOpen, setViewerOpen] = useState(false)\n const [viewerIndex, setViewerIndex] = useState(0)\n\n const handleActivate = useCallback(\n (index: number) => {\n if (onClick?.(index) === false) return\n setViewerIndex(index)\n setViewerOpen(true)\n },\n [onClick]\n )\n\n const closeViewer = useCallback(() => setViewerOpen(false), [])\n\n return { viewerOpen, viewerIndex, handleActivate, closeViewer }\n}\n\nexport default useViewer\n","import React from 'react'\n\nimport { optimizeMessagingAttachmentUrl } from '../../../utils/cdnImageUrl'\nimport Bubble from '../_shared/Bubble'\nimport DismissButton from '../_shared/DismissButton'\nimport ImageViewer, {\n type ImageViewerItem,\n} from '../_shared/ImageViewer'\nimport MediaStackGrid, {\n type MediaStackTile,\n} from '../_shared/MediaStackGrid'\nimport { useViewer } from '../_shared/useViewer'\nimport {\n bubbleVariantForState,\n type ImageItem,\n type ImageLoadingMode,\n type MessageAttachmentBaseProps,\n type MessageAttachmentState,\n} from '../types'\n\nexport interface ImageAttachmentSharedProps extends MessageAttachmentBaseProps {\n /** Single image — convenience for the most common case. */\n src?: string\n alt?: string\n /** Filename used as the viewer dialog's accessible name. */\n filename?: string\n /**\n * Stacked images. Takes precedence over `src` when set. Renders a\n * 1 / 2 / 3 / 4-tile grid (5+ collapse into a `+N` overflow tile).\n * Sent + Received only — the composer surface intentionally accepts\n * a single attachment at a time.\n */\n items?: ImageItem[]\n /**\n * Native lazy-load hint forwarded to every `<img>` rendered on the\n * bubble surface (Composer thumbnail, single + stacked tiles, and\n * the `+N` overflow tile). Defaults to `'lazy'` — chat surfaces\n * usually scroll a long history, and lazy loading prevents every\n * historical image from being fetched on mount. Set `'eager'` for\n * above-the-fold hero attachments. Per-tile overrides live on\n * `ImageItem.loading`. The opened `ImageViewer` always eager-loads\n * the active image regardless of this value.\n */\n loading?: ImageLoadingMode\n /**\n * Forwarded to the Image viewer trigger. When omitted the click\n * still opens the built-in viewer — supply this for analytics, or\n * return `false` to intercept the open (e.g. switch to a route-\n * based gallery / confirmation modal). Any other return value\n * (including `void`/`undefined`) lets the built-in viewer open.\n * For stacked attachments the `index` argument identifies the tile.\n */\n onClick?: (index: number) => boolean | void\n}\n\nconst tileFromItem = ({\n item,\n index,\n totalCount,\n fallbackLoading,\n imgRef,\n onLoad,\n}: {\n item: ImageItem\n index: number\n totalCount: number\n fallbackLoading: ImageLoadingMode\n /** Set on the single-image tile only — see `useSingleImageRatio`. */\n imgRef?: React.Ref<HTMLImageElement>\n onLoad?: React.ReactEventHandler<HTMLImageElement>\n}): MediaStackTile => ({\n ariaLabel: `Open image ${index + 1} of ${totalCount}`,\n content: (\n // No corner radius here: `MediaStackGrid` clips the four outer\n // corners of the whole cluster and keeps every inner edge square.\n <img\n ref={imgRef}\n src={optimizeMessagingAttachmentUrl(item.src) ?? item.src}\n alt={item.alt ?? ''}\n width={item.width}\n height={item.height}\n draggable={false}\n loading={item.loading ?? fallbackLoading}\n decoding=\"async\"\n onLoad={onLoad}\n className=\"absolute inset-0 size-full object-cover\"\n />\n ),\n})\n\nconst resolveItems = ({\n src,\n alt,\n items,\n}: {\n src?: string\n alt?: string\n items?: ImageItem[]\n}): ImageItem[] => {\n if (items && items.length > 0) return items\n if (src) return [{ src, alt }]\n return []\n}\n\ninterface InternalImageRowProps extends ImageAttachmentSharedProps {\n state: MessageAttachmentState\n /**\n * Renders a dismiss button on each tile (Composer only). When the\n * stack has multiple tiles, the dismiss applies to the whole stack\n * — that mirrors the mobile composer where attachments are removed\n * as a single unit.\n */\n onDismiss?: () => void\n}\n\n/**\n * Project the bubble's `ImageItem`s onto the carousel-aware viewer's\n * `ImageViewerItem` shape. When a shared outer `filename` is supplied\n * for a stacked bubble, suffix `(N)` per sibling so each carousel page\n * still gets a distinct accessible name + download default.\n */\nconst buildViewerItems = (\n resolvedItems: ImageItem[],\n filename?: string\n): ImageViewerItem[] =>\n resolvedItems.map((item, index) => ({\n src: item.src,\n alt: item.alt,\n filename:\n filename && resolvedItems.length === 1\n ? filename\n : filename\n ? `${filename} (${index + 1})`\n : undefined,\n }))\n\n/**\n * Composer rendering — bare 280px-square image with a dismiss `×`\n * overlay and `rounded-md` corners. Intentionally renders without the\n * shared `Bubble` chrome (no border / no background / no padding) so\n * the in-progress attachment looks like a draft preview, not a sent\n * message. The composer surface only supports a single attachment at\n * a time — `items` and `text` are ignored here.\n */\nconst ImageComposerInner: React.FC<{\n src: string\n alt?: string\n filename?: string\n loading?: ImageLoadingMode\n onClick?: (index: number) => boolean | void\n onDismiss?: () => void\n}> = ({ src, alt, filename, loading = 'lazy', onClick, onDismiss }) => {\n const { viewerOpen, viewerIndex, handleActivate, closeViewer } = useViewer(\n onClick\n )\n\n return (\n <div className=\"relative w-fit\">\n <button\n type=\"button\"\n onClick={() => handleActivate(0)}\n aria-label=\"Open image\"\n className=\"block size-[280px] cursor-zoom-in overflow-hidden rounded-md outline-none focus-visible:ring-2 focus-visible:ring-black/40\"\n >\n <img\n src={optimizeMessagingAttachmentUrl(src) ?? src}\n alt={alt ?? ''}\n draggable={false}\n loading={loading}\n decoding=\"async\"\n className=\"size-full object-cover\"\n />\n </button>\n {onDismiss ? (\n <div className=\"absolute right-2 top-2 z-10\">\n <DismissButton onClick={onDismiss} />\n </div>\n ) : null}\n\n <ImageViewer\n open={viewerOpen}\n items={buildViewerItems([{ src, alt }], filename)}\n initialIndex={viewerIndex}\n onClose={closeViewer}\n />\n </div>\n )\n}\n\n/**\n * Box reserved for a single image whose ratio is not known yet — the\n * 4:3 landscape card Figma draws for the most common case (330×250\n * card, 326×246 content, `attachment-single-media` 1972:13149). A\n * bounded reserve keeps a scrolling thread from jumping by an\n * arbitrary amount between mount and decode.\n */\nconst RESERVED_SINGLE_ASPECT_RATIO = 326 / 246\n\n/**\n * Resolves the aspect ratio of a single-image bubble, in order:\n *\n * 1. caller-supplied `ImageItem.width` / `height` — ratio known at\n * first paint, so the card never resizes;\n * 2. the decoded `<img>`'s `naturalWidth` / `naturalHeight`;\n * 3. `RESERVED_SINGLE_ASPECT_RATIO`.\n *\n * Nothing propagates dimensions through the Stream path today, so (2)\n * is the branch that runs in production. It reads both on `load` and\n * from the ref, because an image already in the browser cache can be\n * `complete` before React attaches a `load` listener.\n */\nconst useSingleImageRatio = (item: ImageItem | undefined) => {\n const src = item?.src\n const [measured, setMeasured] = React.useState<{\n src: string\n ratio: number\n }>()\n\n const measure = React.useCallback(\n (img: HTMLImageElement | null) => {\n if (!img || img.naturalWidth <= 0 || img.naturalHeight <= 0) return\n if (src === undefined) return\n const ratio = img.naturalWidth / img.naturalHeight\n // Returning `prev` unchanged matters: the ref callback runs on\n // every commit, and a fresh object each time would schedule an\n // endless render loop.\n setMeasured((prev) =>\n prev && prev.src === src && prev.ratio === ratio ? prev : { src, ratio }\n )\n },\n [src]\n )\n\n const handleLoad = React.useCallback(\n (event: React.SyntheticEvent<HTMLImageElement>) =>\n measure(event.currentTarget),\n [measure]\n )\n\n const supplied =\n item?.width && item?.height ? item.width / item.height : undefined\n // Discard a measurement left over from a previous `src`.\n const measuredRatio =\n measured && measured.src === src ? measured.ratio : undefined\n\n return {\n ratio: supplied ?? measuredRatio ?? RESERVED_SINGLE_ASPECT_RATIO,\n imgRef: measure,\n onLoad: handleLoad,\n }\n}\n\n/**\n * Sent / Received rendering — wrapped in the shared `Bubble` chrome,\n * supports single or stacked items, and renders an optional caption\n * below the media.\n */\nconst ImageBubbleRow: React.FC<InternalImageRowProps> = ({\n state,\n src,\n alt,\n filename,\n items,\n text,\n groupPosition,\n loading = 'lazy',\n onClick,\n}) => {\n const resolvedItems = resolveItems({ src, alt, items })\n const variant = bubbleVariantForState(state)\n const { viewerOpen, viewerIndex, handleActivate, closeViewer } = useViewer(\n onClick\n )\n const isSingle = resolvedItems.length === 1\n const single = useSingleImageRatio(isSingle ? resolvedItems[0] : undefined)\n\n if (resolvedItems.length === 0) {\n return null\n }\n\n const tiles: MediaStackTile[] = resolvedItems.map((item, index) =>\n tileFromItem({\n item,\n index,\n totalCount: resolvedItems.length,\n fallbackLoading: loading,\n imgRef: isSingle ? single.imgRef : undefined,\n onLoad: isSingle ? single.onLoad : undefined,\n })\n )\n\n return (\n <Bubble\n variant={variant}\n text={text}\n groupPosition={groupPosition}\n // Media cards drop the 280px document width and the 8px inset\n // for a 2px frame around the media, at a uniform r20 that never\n // flattens against a caption bubble — `attachment-single-media`\n // 330×250 and `attachment-single-image` 383×290, both `pad2`\n // `cornerRadius: 20` with no stroke. The single card sizes to\n // the fitted media box (capped so a long in-bubble caption can\n // not stretch it past the 330px design maximum); the stacked\n // card is a fixed 383px, capped so it cannot overflow a narrow\n // viewport. `bordered={false}` because a hairline on top of the\n // 2px frame would read as a third edge and push the card 2px\n // over its measured width.\n bordered={false}\n widthClassName={\n isSingle\n ? 'w-fit max-w-[313px] sm:max-w-[330px]'\n : 'w-[383px] max-w-full'\n }\n paddingClassName=\"p-0.5\"\n radiusClassName=\"rounded-[20px]\"\n data-testid=\"image-attachment\"\n >\n <div className=\"relative\">\n <MediaStackGrid\n tiles={tiles}\n onTileActivate={handleActivate}\n singleAspectRatio={isSingle ? single.ratio : undefined}\n />\n </div>\n\n <ImageViewer\n open={viewerOpen}\n items={buildViewerItems(resolvedItems, filename)}\n initialIndex={viewerIndex}\n onClose={closeViewer}\n />\n </Bubble>\n )\n}\n\n/**\n * Composer-only props. Single image (`src`) is required; stacked\n * `items` and `text` captions are not supported in the composer state.\n */\nexport interface ImageComposerProps {\n src: string\n alt?: string\n filename?: string\n /**\n * Native lazy-load hint forwarded to the composer thumbnail `<img>`.\n * Defaults to `'lazy'`. See `ImageAttachmentSharedProps.loading` for\n * the rationale.\n */\n loading?: ImageLoadingMode\n onClick?: (index: number) => boolean | void\n onDismiss?: () => void\n}\n\nexport type ImageSentProps = ImageAttachmentSharedProps\nexport type ImageReceivedProps = ImageAttachmentSharedProps\n\nconst ImageComposer: React.FC<ImageComposerProps> = (props) => (\n <ImageComposerInner {...props} />\n)\nconst ImageSent: React.FC<ImageSentProps> = (props) => (\n <ImageBubbleRow {...props} state=\"sent\" />\n)\nconst ImageReceived: React.FC<ImageReceivedProps> = (props) => (\n <ImageBubbleRow {...props} state=\"received\" />\n)\n\nconst ImageAttachment = {\n Composer: ImageComposer,\n Sent: ImageSent,\n Received: ImageReceived,\n}\n\nexport default ImageAttachment\n","import React, { useMemo } from 'react'\n\nimport CarouselNav from './CarouselNav'\nimport { filenameFromUrl } from './fileMeta'\nimport { useCarousel } from './useCarousel'\nimport ViewerShell from './ViewerShell'\n\nexport interface PdfViewerItem {\n /** Source URL of the PDF document. */\n src: string\n /** Filename used as the dialog's accessible name. */\n filename?: string\n}\n\nexport interface PdfViewerProps {\n open: boolean\n items: PdfViewerItem[]\n /** Index to display when the viewer first opens. Defaults to `0`. */\n initialIndex?: number\n onClose: () => void\n}\n\n/**\n * Modal PDF viewer that hosts the active document inside a sandboxed\n * `<iframe>`, leaving native rendering, scroll, search, and the\n * browser's built-in download controls to the browser. The lightbox\n * chrome is intentionally just a close button plus, for stacked\n * attachments, carousel prev/next + counter.\n */\nconst PdfViewer: React.FC<PdfViewerProps> = ({\n open,\n items,\n initialIndex = 0,\n onClose,\n}) => {\n const { index, prev, next } = useCarousel({\n length: items.length,\n initialIndex,\n open,\n })\n\n const item = items[index]\n const filename = useMemo(\n () => item?.filename ?? (item ? filenameFromUrl(item.src) : 'document'),\n [item]\n )\n\n // `#toolbar=0` is honored by Chromium-family browsers and hides the\n // built-in PDF toolbar's redundant controls. Firefox / Safari ignore\n // it and keep their native toolbars, which is fine — the user gets a\n // familiar experience either way.\n //\n // Preserve any existing fragment the caller supplied (e.g.\n // `#page=3`) by merging our params into it rather than naively\n // appending a second `#…` segment.\n const iframeSrc = useMemo(\n () => (item ? withPdfViewerParams(item.src) : undefined),\n [item]\n )\n\n if (!item || !iframeSrc) return null\n\n return (\n <ViewerShell\n open={open}\n onClose={onClose}\n ariaLabel={filename}\n counter={\n items.length > 1 ? `${index + 1} / ${items.length}` : undefined\n }\n data-testid=\"pdf-viewer\"\n >\n <iframe\n // Force a key swap on item change so the iframe remounts a\n // fresh document rather than re-using the previous scroll\n // position / search state when the user navigates between\n // siblings.\n key={`${index}:${item.src}`}\n src={iframeSrc}\n title={filename}\n className=\"mes-media-viewer__iframe\"\n // Sandbox the iframe to stop the embedded document from\n // reaching parent context. We intentionally omit\n // `allow-same-origin`: even when the PDF host happens to share\n // our origin, granting it defeats the rest of the sandbox.\n // `allow-scripts` keeps the native PDF viewer's interactive\n // affordances (search, page nav, form filling) working,\n // `allow-downloads` lets the user save via the built-in\n // toolbar where it's still visible (Firefox / Safari), and\n // `allow-popups` lets external links inside the PDF open in a\n // new tab.\n sandbox=\"allow-scripts allow-forms allow-popups allow-downloads\"\n />\n\n {items.length > 1 ? (\n <CarouselNav\n onPrev={prev}\n onNext={next}\n prevLabel=\"Previous document\"\n nextLabel=\"Next document\"\n />\n ) : null}\n </ViewerShell>\n )\n}\n\n/**\n * Merge our PDF-viewer params (`toolbar=0`, `navpanes=0`) into the\n * URL's existing fragment so callers can still pass things like\n * `#page=3` without us clobbering them — naively appending\n * `#toolbar=0` to a URL that already has a fragment produces\n * `…#page=3#toolbar=0` which most readers ignore.\n */\nconst withPdfViewerParams = (src: string): string => {\n const hashIndex = src.indexOf('#')\n const base = hashIndex === -1 ? src : src.slice(0, hashIndex)\n const existing = hashIndex === -1 ? '' : src.slice(hashIndex + 1)\n\n const params = new URLSearchParams(existing)\n if (!params.has('toolbar')) params.set('toolbar', '0')\n if (!params.has('navpanes')) params.set('navpanes', '0')\n\n return `${base}#${params.toString()}`\n}\n\nexport default PdfViewer\n","import React from 'react'\n\nimport Bubble from '../_shared/Bubble'\nimport CompactDocumentRow from '../_shared/CompactDocumentRow'\nimport DismissButton from '../_shared/DismissButton'\nimport DownloadAction from '../_shared/DownloadAction'\nimport { filenameFromUrl } from '../_shared/fileMeta'\nimport PdfViewer, { type PdfViewerItem } from '../_shared/PdfViewer'\nimport { useViewer } from '../_shared/useViewer'\nimport {\n bubbleVariantForState,\n type BubbleVariant,\n type ComposerExtras,\n type MessageAttachmentBaseProps,\n type MessageAttachmentState,\n type PdfItem,\n} from '../types'\n\nexport interface PdfAttachmentSharedProps extends MessageAttachmentBaseProps {\n /** Single PDF — convenience for the most common case. */\n src?: string\n /** Filename — drives the row title + the meta line + the viewer dialog's accessible name. */\n filename?: string\n /** File size in bytes — formatted into the `EXT · SIZE` meta line. */\n fileSize?: number\n /**\n * Override displayed title (defaults to `filename`). Useful when a\n * sender re-titles a generated PDF before sending.\n */\n title?: string\n /**\n * Stacked PDFs. Takes precedence over `src` when set. Each item\n * renders as its own row inside the bubble; clicking a row opens\n * that PDF in the viewer. Sent + Received only — the composer\n * surface accepts a single attachment at a time.\n */\n items?: PdfItem[]\n /**\n * Forwarded to the viewer trigger. When omitted the click still\n * opens the built-in `PdfViewer`. Supply this to fire analytics, or\n * return `false` to intercept the open (e.g. swap to a route-based\n * viewer / confirmation modal). Any other return value (including\n * `void`/`undefined`) lets the built-in viewer open. For stacked\n * attachments the `index` argument identifies the row.\n */\n onClick?: (index: number) => boolean | void\n}\n\nconst resolveItems = ({\n src,\n filename,\n fileSize,\n title,\n items,\n}: {\n src?: string\n filename?: string\n fileSize?: number\n title?: string\n items?: PdfItem[]\n}): PdfItem[] => {\n if (items && items.length > 0) return items\n if (src) return [{ src, filename, fileSize, title }]\n return []\n}\n\ninterface PdfRowButtonProps {\n variant: BubbleVariant\n item: PdfItem\n index: number\n onActivate: (index: number) => void\n trailingAction?: React.ReactNode\n}\n\n/**\n * Single tappable PDF row — used both for the lone PDF case and for\n * each child of a stacked attachment. The icon + filename area opens\n * the viewer; the trailing slot hosts a separate, sibling button\n * (download or dismiss) so each affordance owns its own click target.\n */\nconst PdfRowButton: React.FC<PdfRowButtonProps> = ({\n variant,\n item,\n index,\n onActivate,\n trailingAction,\n}) => {\n const resolvedFilename = item.filename ?? filenameFromUrl(item.src)\n return (\n <CompactDocumentRow\n variant={variant}\n filename={resolvedFilename}\n title={item.title}\n mimeType=\"application/pdf\"\n fileSize={item.fileSize}\n onActivate={() => onActivate(index)}\n activateLabel={`Open ${resolvedFilename}`}\n trailingAction={trailingAction}\n />\n )\n}\n\ninterface InternalPdfRowProps extends PdfAttachmentSharedProps {\n state: MessageAttachmentState\n onDismiss?: () => void\n}\n\nconst PdfAttachmentRow: React.FC<InternalPdfRowProps> = ({\n state,\n src,\n filename,\n fileSize,\n title,\n items,\n text,\n groupPosition,\n onClick,\n onDismiss,\n}) => {\n const variant = bubbleVariantForState(state)\n const resolvedItems = resolveItems({ src, filename, fileSize, title, items })\n const { viewerOpen, viewerIndex, handleActivate, closeViewer } = useViewer(\n onClick\n )\n const showDismiss = state === 'composer' && !!onDismiss\n\n if (resolvedItems.length === 0) {\n return null\n }\n\n // Project the bubble's `PdfItem`s onto the viewer's carousel-aware\n // shape. The viewer clamps its own active index defensively, so we\n // don't need to second-guess `viewerIndex` here.\n const viewerItems: PdfViewerItem[] = resolvedItems.map((item) => ({\n src: item.src,\n filename: item.filename ?? filenameFromUrl(item.src),\n }))\n\n return (\n <Bubble\n variant={variant}\n text={text}\n groupPosition={groupPosition}\n data-testid=\"pdf-attachment\"\n >\n {/* Stacked rows get a small vertical gap so each PDF reads as\n a discrete attachment rather than one merged blob. Single\n row falls through to a no-op `gap-0`. */}\n <div className=\"flex flex-col gap-2\">\n {resolvedItems.map((item, index) => {\n const itemFilename = item.filename ?? filenameFromUrl(item.src)\n // Composer only supports a single attachment so the dismiss\n // control sits on the only row. Sent / Received rows expose\n // a download icon button so the user can grab the PDF\n // without opening the viewer first — the viewer dialog is\n // intentionally just the document + a close button, so this\n // sibling action is the only one-click download surface.\n const trailingAction =\n showDismiss && index === 0 ? (\n <DismissButton onClick={onDismiss!} variant=\"inline\" />\n ) : state === 'composer' ? undefined : (\n <DownloadAction\n url={item.src}\n filename={itemFilename}\n variant=\"inline\"\n label={`Download ${itemFilename}`}\n tone={variant}\n />\n )\n return (\n <PdfRowButton\n key={`${item.src}-${index}`}\n variant={variant}\n item={item}\n index={index}\n onActivate={handleActivate}\n trailingAction={trailingAction}\n />\n )\n })}\n </div>\n\n <PdfViewer\n open={viewerOpen}\n items={viewerItems}\n initialIndex={viewerIndex}\n onClose={closeViewer}\n />\n </Bubble>\n )\n}\n\n/**\n * Composer-only props. Single PDF (`src`) only — the composer surface\n * accepts a single attachment at a time, so `items` is not supported.\n * Captions (`text`) and `groupPosition` are also dropped: the composer\n * renders a standalone draft, not part of a same-author run, and\n * captions live in the message-input textarea, not inside the draft\n * attachment preview.\n */\nexport interface PdfComposerProps extends ComposerExtras {\n src?: string\n filename?: string\n fileSize?: number\n title?: string\n onClick?: (index: number) => boolean | void\n}\nexport type PdfSentProps = PdfAttachmentSharedProps\nexport type PdfReceivedProps = PdfAttachmentSharedProps\n\nconst PdfComposer: React.FC<PdfComposerProps> = (props) => (\n <PdfAttachmentRow {...props} state=\"composer\" />\n)\nconst PdfSent: React.FC<PdfSentProps> = (props) => (\n <PdfAttachmentRow {...props} state=\"sent\" />\n)\nconst PdfReceived: React.FC<PdfReceivedProps> = (props) => (\n <PdfAttachmentRow {...props} state=\"received\" />\n)\n\nconst PdfAttachment = {\n Composer: PdfComposer,\n Sent: PdfSent,\n Received: PdfReceived,\n}\n\nexport default PdfAttachment\n","import React, { useMemo } from 'react'\n\nimport type { MediaPreloadMode } from '../types'\n\nimport CarouselNav from './CarouselNav'\nimport { filenameFromUrl } from './fileMeta'\nimport { useCarousel } from './useCarousel'\nimport ViewerShell from './ViewerShell'\n\nexport interface VideoViewerItem {\n src: string\n poster?: string\n mimeType?: string\n filename?: string\n /**\n * Per-item `<video preload>` override. Defaults to `'metadata'`\n * for the active item so duration / first-frame are available\n * immediately. Non-active siblings aren't mounted here (we render\n * only `items[index]` at a time via a `key` swap), so they\n * naturally stay unloaded.\n */\n preload?: MediaPreloadMode\n}\n\nexport interface VideoViewerProps {\n open: boolean\n items: VideoViewerItem[]\n /** Index to display when the viewer first opens. Defaults to `0`. */\n initialIndex?: number\n onClose: () => void\n}\n\n/**\n * Full-viewport video viewer used by every `MessageAttachment.Video.*`\n * variant. Renders a single `<video controls>` element with the\n * browser's native chrome (play / pause / seek / fullscreen / volume /\n * download).\n *\n * When `items.length > 1` the viewer becomes a carousel — see\n * `ImageViewer` for the same behavior; arrow-key navigation yields to\n * the focused `<video>` so the native seek shortcuts still work.\n */\nconst VideoViewer: React.FC<VideoViewerProps> = ({\n open,\n items,\n initialIndex = 0,\n onClose,\n}) => {\n const { index, prev, next } = useCarousel({\n length: items.length,\n initialIndex,\n open,\n })\n\n const item = items[index]\n const filename = useMemo(\n () => item?.filename ?? (item ? filenameFromUrl(item.src) : 'video'),\n [item]\n )\n\n if (!item) return null\n\n return (\n <ViewerShell\n open={open}\n onClose={onClose}\n ariaLabel={filename}\n counter={\n items.length > 1 ? `${index + 1} / ${items.length}` : undefined\n }\n data-testid=\"video-viewer\"\n >\n {/* No `<track>` is rendered — we don't author caption sidecars\n for chat attachments, and an empty `<track kind=\"captions\" />`\n emits a runtime warning. Re-add a real track (with `src`,\n `srcLang`, and `default`) once caption support ships. */}\n <video\n // Forcing a key swap on item change ensures the new source\n // mounts a fresh element instead of reusing the previous\n // playback state — keeps the video paused-at-start when\n // navigating between stacked items.\n key={`${index}:${item.src}`}\n src={item.src}\n poster={item.poster}\n controls\n // `autoPlay` without `muted` is blocked by Chrome / Safari /\n // Firefox autoplay policies — the click that opens the viewer\n // doesn't count as a user-gesture for the freshly-mounted\n // `<video>` element. Defaulting to muted means playback\n // actually starts (matches how IG / Slack handle their video\n // lightboxes); the user can unmute via the native controls if\n // they want sound.\n autoPlay\n muted\n playsInline\n preload={item.preload ?? 'metadata'}\n className=\"mes-media-viewer__video\"\n >\n {item.mimeType ? <source src={item.src} type={item.mimeType} /> : null}\n </video>\n\n {items.length > 1 ? (\n <CarouselNav\n onPrev={prev}\n onNext={next}\n prevLabel=\"Previous video\"\n nextLabel=\"Next video\"\n />\n ) : null}\n </ViewerShell>\n )\n}\n\nexport default VideoViewer\n","import { PlayIcon, VideoCameraIcon } from '@phosphor-icons/react'\nimport React from 'react'\n\nimport Bubble from '../_shared/Bubble'\nimport DismissButton from '../_shared/DismissButton'\nimport MediaStackGrid, {\n type MediaStackTile,\n} from '../_shared/MediaStackGrid'\nimport { useViewer } from '../_shared/useViewer'\nimport VideoViewer, { type VideoViewerItem } from '../_shared/VideoViewer'\nimport {\n bubbleVariantForState,\n type MediaPreloadMode,\n type MessageAttachmentBaseProps,\n type MessageAttachmentState,\n type VideoItem,\n} from '../types'\n\nexport interface VideoAttachmentSharedProps extends MessageAttachmentBaseProps {\n /** Single video — convenience for the most common case. */\n src?: string\n /** Poster image — preview shown before playback starts. */\n poster?: string\n /** MIME type hint — typed onto the inline `<source>` element. */\n mimeType?: string\n /** Filename used as the viewer dialog's accessible name. */\n filename?: string\n /**\n * Stacked videos. Takes precedence over `src` when set. Renders a\n * 1 / 2 / 3 / 4-tile grid (5+ collapse into a `+N` overflow tile).\n * Sent + Received only — the composer surface intentionally accepts\n * a single attachment at a time.\n */\n items?: VideoItem[]\n /**\n * `<video preload>` hint forwarded into the viewer. Defaults to\n * `'none'` — the poster `<img>` carries the visual weight on the\n * bubble surface, and we shouldn't fetch any video bytes until the\n * user actually opens the viewer. Per-item overrides live on\n * `VideoItem.preload`. The opened `VideoViewer` always preloads\n * metadata for the active item (so duration / first-frame appear\n * immediately) regardless of this value.\n */\n preload?: MediaPreloadMode\n /**\n * Forwarded to the viewer trigger. When omitted the click still\n * opens the built-in `VideoViewer` — supply this for analytics, or\n * return `false` to intercept the open (e.g. switch to a route-\n * based player / confirmation modal). Any other return value\n * (including `void`/`undefined`) lets the built-in viewer open.\n * For stacked attachments the `index` argument identifies the tile.\n */\n onClick?: (index: number) => boolean | void\n}\n\nconst PlayBadge: React.FC = () => (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <span className=\"flex size-12 items-center justify-center rounded-full bg-black/55 text-white backdrop-blur\">\n <PlayIcon className=\"size-6\" weight=\"fill\" aria-hidden />\n </span>\n </div>\n)\n\n// The tile shell owns the cluster's geometry: `MediaStackGrid` gives\n// each tile the 18px radius on the cluster's OUTER corners only and\n// clips with `overflow-hidden`, so a poster must carry no radius of\n// its own. A `rounded-md` here would round all four corners of every\n// tile at 6px, cutting dark wedges out of the `bg-[#0d0d0d]` backing\n// at each interior grid junction.\nconst PosterTile: React.FC<{ item: VideoItem; index: number }> = ({\n item,\n index,\n}) => (\n <div className=\"absolute inset-0 size-full bg-[#0d0d0d]\">\n {item.poster ? (\n <img\n src={item.poster}\n alt={`Video ${index + 1} thumbnail`}\n draggable={false}\n loading=\"lazy\"\n decoding=\"async\"\n className=\"absolute inset-0 size-full object-cover\"\n />\n ) : (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <VideoCameraIcon\n className=\"size-16 text-white/30\"\n weight=\"regular\"\n aria-hidden\n />\n </div>\n )}\n <PlayBadge />\n </div>\n)\n\nconst tileFromItem = (\n item: VideoItem,\n index: number,\n totalCount: number\n): MediaStackTile => ({\n ariaLabel: `Play video ${index + 1} of ${totalCount}`,\n content: <PosterTile item={item} index={index} />,\n})\n\nconst resolveItems = ({\n src,\n poster,\n mimeType,\n preload,\n items,\n}: {\n src?: string\n poster?: string\n mimeType?: string\n preload?: MediaPreloadMode\n items?: VideoItem[]\n}): VideoItem[] => {\n if (items && items.length > 0) {\n return preload ? items.map((it) => ({ ...it, preload: it.preload ?? preload })) : items\n }\n if (src) return [{ src, poster, mimeType, preload }]\n return []\n}\n\ninterface InternalVideoRowProps extends VideoAttachmentSharedProps {\n state: MessageAttachmentState\n}\n\n/**\n * Project the bubble's `VideoItem`s onto the carousel-aware viewer's\n * `VideoViewerItem` shape. When a shared outer `filename` is supplied\n * for a stacked bubble, suffix `(N)` per sibling so each carousel page\n * still gets a distinct accessible name.\n */\nconst buildViewerItems = (\n resolvedItems: VideoItem[],\n filename?: string\n): VideoViewerItem[] =>\n resolvedItems.map((item, index) => ({\n src: item.src,\n poster: item.poster,\n mimeType: item.mimeType,\n preload: item.preload,\n filename:\n filename && resolvedItems.length === 1\n ? filename\n : filename\n ? `${filename} (${index + 1})`\n : undefined,\n }))\n\n/**\n * Composer rendering — bare 280px-square poster with a play badge,\n * a dismiss `×` overlay, and `rounded-md` corners. Renders without the\n * shared `Bubble` chrome (no border / no background / no padding) so\n * the in-progress attachment looks like a draft preview rather than a\n * sent message. Single attachment only — `items` and `text` are not\n * supported on the composer surface.\n */\nconst VideoComposerInner: React.FC<{\n src: string\n poster?: string\n mimeType?: string\n filename?: string\n preload?: MediaPreloadMode\n onClick?: (index: number) => boolean | void\n onDismiss?: () => void\n}> = ({ src, poster, mimeType, filename, preload, onClick, onDismiss }) => {\n const { viewerOpen, viewerIndex, handleActivate, closeViewer } = useViewer(\n onClick\n )\n\n return (\n <div className=\"relative w-fit\">\n <button\n type=\"button\"\n onClick={() => handleActivate(0)}\n aria-label=\"Play video\"\n className=\"relative block size-[280px] cursor-pointer overflow-hidden rounded-md outline-none focus-visible:ring-2 focus-visible:ring-black/40\"\n >\n <PosterTile item={{ src, poster, mimeType }} index={0} />\n </button>\n {onDismiss ? (\n <div className=\"absolute right-2 top-2 z-10\">\n <DismissButton onClick={onDismiss} />\n </div>\n ) : null}\n\n <VideoViewer\n open={viewerOpen}\n items={buildViewerItems(\n [{ src, poster, mimeType, preload }],\n filename\n )}\n initialIndex={viewerIndex}\n onClose={closeViewer}\n />\n </div>\n )\n}\n\n/**\n * Sent / Received rendering — wrapped in the shared `Bubble` chrome,\n * supports single or stacked items, and renders an optional caption\n * below the media.\n */\nconst VideoBubbleRow: React.FC<InternalVideoRowProps> = ({\n state,\n src,\n poster,\n mimeType,\n filename,\n items,\n text,\n groupPosition,\n preload,\n onClick,\n}) => {\n const resolvedItems = resolveItems({ src, poster, mimeType, preload, items })\n const variant = bubbleVariantForState(state)\n const { viewerOpen, viewerIndex, handleActivate, closeViewer } = useViewer(\n onClick\n )\n\n if (resolvedItems.length === 0) {\n return null\n }\n\n const tiles: MediaStackTile[] = resolvedItems.map((item, index) =>\n tileFromItem(item, index, resolvedItems.length)\n )\n\n return (\n <Bubble\n variant={variant}\n text={text}\n groupPosition={groupPosition}\n data-testid=\"video-attachment\"\n >\n <div className=\"relative\">\n <MediaStackGrid tiles={tiles} onTileActivate={handleActivate} />\n </div>\n\n <VideoViewer\n open={viewerOpen}\n items={buildViewerItems(resolvedItems, filename)}\n initialIndex={viewerIndex}\n onClose={closeViewer}\n />\n </Bubble>\n )\n}\n\n/**\n * Composer-only props. Single video (`src`) is required; stacked\n * `items` and `text` captions are not supported in the composer state.\n */\nexport interface VideoComposerProps {\n src: string\n poster?: string\n mimeType?: string\n filename?: string\n /**\n * `<video preload>` hint forwarded into the viewer. Defaults to\n * `'none'`. See `VideoAttachmentSharedProps.preload`.\n */\n preload?: MediaPreloadMode\n onClick?: (index: number) => boolean | void\n onDismiss?: () => void\n}\n\nexport type VideoSentProps = VideoAttachmentSharedProps\nexport type VideoReceivedProps = VideoAttachmentSharedProps\n\nconst VideoComposer: React.FC<VideoComposerProps> = (props) => (\n <VideoComposerInner {...props} />\n)\nconst VideoSent: React.FC<VideoSentProps> = (props) => (\n <VideoBubbleRow {...props} state=\"sent\" />\n)\nconst VideoReceived: React.FC<VideoReceivedProps> = (props) => (\n <VideoBubbleRow {...props} state=\"received\" />\n)\n\nconst VideoAttachment = {\n Composer: VideoComposer,\n Sent: VideoSent,\n Received: VideoReceived,\n}\n\nexport default VideoAttachment\n","import AudioAttachment, {\n type AudioComposerProps,\n type AudioReceivedProps,\n type AudioSentProps,\n} from './Audio'\nimport FileAttachment, {\n type FileComposerProps,\n type FileReceivedProps,\n type FileSentProps,\n} from './File'\nimport ImageAttachment, {\n type ImageComposerProps,\n type ImageReceivedProps,\n type ImageSentProps,\n} from './Image'\nimport PdfAttachment, {\n type PdfComposerProps,\n type PdfReceivedProps,\n type PdfSentProps,\n} from './Pdf'\nimport VideoAttachment, {\n type VideoComposerProps,\n type VideoReceivedProps,\n type VideoSentProps,\n} from './Video'\n\n/**\n * Per-MIME chat attachment cards used inside the messaging stream.\n *\n * Each subnamespace (`Image`, `Video`, `Audio`, `Pdf`, `File`) exposes\n * three states (`Composer`, `Sent`, `Received`) that map to the\n * sender / recipient sides of a chat:\n *\n * - `Composer` — sender draft state with a dismiss `×` affordance.\n * - `Sent` — sender-side state shown after posting.\n * - `Received` — recipient-side state.\n *\n * Sent / Received variants accept an optional `text` prop that renders\n * inside the same bubble as the attachment — mirroring the mobile chat\n * where a sender can pair a caption with an attachment ('Here is the\n * file', 'Here is the image'). Composer prop types intentionally omit\n * `text` (and `items` / `groupPosition`) so the type system enforces\n * the same contract: captions live in the message-input textarea, not\n * inside the draft attachment preview.\n *\n * Stacked attachments — every type except `Composer` accepts an\n * `items={[…]}` prop on Sent / Received that takes precedence over\n * the singular `src`/`filename`/etc. inputs:\n *\n * - Image / Video render a 1 / 2 / 3 / 4-tile grid (5+ collapse\n * into a `+N` overflow tile). Activating any tile opens the\n * built-in `ImageViewer` / `VideoViewer` at that index; when\n * `items.length > 1` the lightbox becomes a carousel (prev / next\n * chrome, ArrowLeft / ArrowRight, current / total counter) so the\n * user can browse siblings without closing the modal.\n * - Pdf / Audio / File render their compact rows / players in a\n * vertical stack with an 8px gap between rows. Each row keeps\n * its own activation target — Pdf opens the carousel-aware\n * `PdfViewer` at that index, Audio gets its own native player,\n * and File downloads the asset for that row.\n *\n * The Composer surface accepts only a single attachment at a time,\n * so its props omit `items` / `text`.\n *\n * Image / Video Composer renders bare — just the media with rounded\n * corners and a dismiss overlay, no surrounding bubble — so the draft\n * preview reads as an in-progress attachment instead of a sent\n * message. Sent / Received wrap the media in the shared bubble chrome.\n *\n * Image / Video / Pdf are interactive in every state (Composer, Sent,\n * Received) — clicks open the corresponding native lightbox `<dialog>`,\n * which centers the media at reasonable max dimensions (Escape and\n * backdrop click also dismiss). The Image viewer adds an explicit\n * download button to the chrome; the Video viewer relies on the\n * native `<video controls>` download menu, and the Pdf viewer\n * inherits the browser's built-in PDF download. Sibling-row Download\n * buttons on Pdf / File and the native `<audio>` controls expose\n * downloads outside the viewer too. The lightbox chrome is styled\n * with plain CSS (`.mes-media-viewer*`) so the package's shipped\n * stylesheet is enough to render the viewer correctly without a\n * Tailwind dependency in the consumer.\n *\n * # Lazy-loading defaults\n *\n * Media attachments bake in network-friendly defaults for long chat\n * histories and expose explicit escape hatches when a caller knows\n * better (e.g. a hero attachment that's already on-screen):\n *\n * - **Image** — every `<img>` rendered on the bubble surface\n * (Composer thumbnail, single + stacked tiles, `+N` overflow)\n * ships with `loading=\"lazy\" decoding=\"async\"`. Override via the\n * attachment's `loading` prop (or `ImageItem.loading` for per-tile\n * control). The opened `ImageViewer` always eager-loads the\n * active image so it appears immediately.\n * - **Video** — the `<video>` rendered inside the `VideoViewer`\n * defaults to `preload=\"none\"`, so no video bytes are fetched\n * until the user opens the viewer. Poster `<img>` thumbnails on\n * the bubble surface are `loading=\"lazy\" decoding=\"async\"`.\n * Override via the attachment's `preload` prop (or\n * `VideoItem.preload` per item). Once the viewer is open the\n * active item bumps to `preload=\"metadata\"` so duration / the\n * first frame appear immediately.\n * - **Audio** — a single audio bubble defaults to\n * `preload=\"metadata\"` so the native player surfaces duration\n * immediately. A stacked audio bubble (`items.length > 1`)\n * defaults to `preload=\"none\"` for every player so a thread of\n * voice memos doesn't fan out N parallel metadata requests on\n * first paint. Override via the attachment's `preload` prop\n * (or `AudioItem.preload` per track).\n * - **Pdf** / **File** — no inline media element to throttle; the\n * bubble renders compact rows that download / open lazily on\n * activation. No `loading` / `preload` props on these surfaces.\n */\nconst MessageAttachment = {\n Image: ImageAttachment,\n Video: VideoAttachment,\n Audio: AudioAttachment,\n Pdf: PdfAttachment,\n File: FileAttachment,\n}\n\nexport default MessageAttachment\n\nexport type {\n ImageComposerProps,\n ImageSentProps,\n ImageReceivedProps,\n VideoComposerProps,\n VideoSentProps,\n VideoReceivedProps,\n AudioComposerProps,\n AudioSentProps,\n AudioReceivedProps,\n PdfComposerProps,\n PdfSentProps,\n PdfReceivedProps,\n FileComposerProps,\n FileSentProps,\n FileReceivedProps,\n}\nexport type {\n ImageItem,\n ImageLoadingMode,\n VideoItem,\n PdfItem,\n AudioItem,\n FileItem,\n BubbleGroupPosition,\n MediaPreloadMode,\n MessageAttachmentBaseProps,\n MessageAttachmentState,\n} from './types'\nexport { bubbleGroupPositionFromStream } from './types'\nexport {\n formatFileSize,\n getFileExtensionLabel,\n buildCompactMetaLabel,\n} from './_shared/fileMeta'\n","import { createContext, useState } from 'react'\n\nimport type { BroadcastNameResolver } from '../../types'\n\n/** Live campaign names keyed by broadcast id — not the resolver function. */\nexport type BroadcastNamesById = Readonly<Record<string, string>>\n\nexport const BroadcastNameContext = createContext<\n BroadcastNamesById | undefined\n>(undefined)\n\nconst broadcastIdFromMessage = (message: {\n metadata?: { broadcast_id?: unknown }\n}): string | undefined => {\n const broadcastId = message.metadata?.broadcast_id\n return typeof broadcastId === 'string' ? broadcastId : undefined\n}\n\n/**\n * Resolve campaign names for the messages currently in view.\n *\n * Built outside memoized Stream rows so a host can keep `resolveBroadcastName`\n * referentially stable (ref/cache-backed) and still publish new strings when\n * ChannelView re-renders after the cache fills in.\n */\nexport const buildBroadcastNamesById = (\n messages: readonly { metadata?: { broadcast_id?: unknown } }[] | undefined,\n resolveBroadcastName: BroadcastNameResolver | undefined\n): BroadcastNamesById | undefined => {\n if (!resolveBroadcastName || !messages?.length) {\n return undefined\n }\n\n const seen = new Set<string>()\n let names: Record<string, string> | undefined\n\n for (const message of messages) {\n const broadcastId = broadcastIdFromMessage(message)\n if (!broadcastId || seen.has(broadcastId)) {\n continue\n }\n seen.add(broadcastId)\n\n const resolved = resolveBroadcastName(broadcastId)\n if (!resolved) {\n continue\n }\n\n names ??= {}\n names[broadcastId] = resolved\n }\n\n return names\n}\n\nconst areBroadcastNamesEqual = (\n previous: BroadcastNamesById | undefined,\n next: BroadcastNamesById | undefined\n): boolean => {\n if (previous === next) {\n return true\n }\n if (!previous || !next) {\n return false\n }\n\n const previousIds = Object.keys(previous)\n const nextIds = Object.keys(next)\n if (previousIds.length !== nextIds.length) {\n return false\n }\n\n return previousIds.every((id) => previous[id] === next[id])\n}\n\n/**\n * Re-invokes a (possibly stable) resolver on every render, but only returns a\n * new object when the resolved strings actually change — so context consumers\n * update for late-arriving campaign names without thrashing on unrelated\n * ChannelViewInner renders.\n */\nexport const useBroadcastNamesById = (\n messages: readonly { metadata?: { broadcast_id?: unknown } }[] | undefined,\n resolveBroadcastName: BroadcastNameResolver | undefined\n): BroadcastNamesById | undefined => {\n const names = buildBroadcastNamesById(messages, resolveBroadcastName)\n const [publishedNames, setPublishedNames] =\n useState<BroadcastNamesById | undefined>(names)\n\n if (!areBroadcastNamesEqual(publishedNames, names)) {\n setPublishedNames(names)\n return names\n }\n\n return publishedNames\n}\n","import type { Channel, LocalMessage } from 'stream-chat'\n\nimport type { PaymentStatus } from '../../../stream-custom-data'\n\nexport interface LockedAttachmentGalleryItem {\n /** Drives the per-item play/lock affordance. */\n mimeType: string\n /** Poster image, locked or unlocked. */\n thumbnailUrl?: string\n /** Media source, shown only when unlocked. */\n sourceUrl?: string\n}\n\nexport interface LockedAttachmentSource {\n /** Proxied URL for in-app playback. */\n sourceUrl: string\n /** Opened when the visitor clicks Download. */\n redeemUrl?: string\n /** Overrides the metadata thumbnail when present. */\n thumbnailUrl?: string\n}\n\nexport type { PaymentStatus }\n\n/** Fetches the underlying source; `void` return means none available. */\nexport type FetchSourceHandler = () => Promise<LockedAttachmentSource | void>\n\nexport interface LockedAttachmentContextValue {\n /** Whether the given message is mid-checkout. */\n isUnlocking: (id: string) => boolean\n /** Opens the checkout flow for a message. */\n onUnlockClick?: (message: LocalMessage, channel: Channel) => void\n /** Handles a Download click for a message. */\n onDownloadClick?: (message: LocalMessage, channel: Channel) => void\n /** Reveals the locked media's source. Unused for text — payment writes `message.text` directly. */\n onFetchSource?: (\n message: LocalMessage,\n channel: Channel\n ) => Promise<LockedAttachmentSource | void>\n}\n\nexport const defaultLockedAttachmentContextValue: LockedAttachmentContextValue = {\n isUnlocking: () => false,\n}\n","import { createContext, useContext } from 'react'\n\nimport { defaultLockedAttachmentContextValue, type LockedAttachmentContextValue } from './LockedAttachment/types'\n\nexport interface CustomMessageRegistry {\n LockedAttachment: LockedAttachmentContextValue\n}\n\nconst customMessageDefaults: CustomMessageRegistry = {\n LockedAttachment: defaultLockedAttachmentContextValue,\n}\n\nconst CustomMessageContext = createContext<Partial<CustomMessageRegistry>>({})\n\nexport const CustomMessageProvider = CustomMessageContext.Provider\n\nexport function useCustomMessage<K extends keyof CustomMessageRegistry>(key: K): CustomMessageRegistry[K] {\n const ctx = useContext(CustomMessageContext)\n return (ctx[key] ?? customMessageDefaults[key]) as CustomMessageRegistry[K]\n}\n","import React, { Suspense } from 'react'\n\nimport type {\n MediaCardDraftProps,\n MediaCardOtherProps,\n MediaCardOwnProps,\n MediaCardPreviewProps,\n} from './components/Media/types'\nimport type {\n TextCardOtherProps,\n TextCardOwnProps,\n} from './components/Text/types'\n\nconst TextCardLazy = React.lazy(() => import('./components/Text/Card'))\nconst MediaCardLazy = React.lazy(() => import('./components/Media/Card'))\n\nconst LockedAttachmentFallback = () => (\n <div\n className=\"w-[280px] min-h-[200px] animate-pulse rounded-md bg-black/[0.06] shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_1px_2px_rgba(0,0,0,0.04),0_8px_32px_rgba(0,0,0,0.1)]\"\n aria-hidden\n />\n)\n\nexport type DraftProps = MediaCardDraftProps & {\n /** Drafting is always the sender — doesn't apply here. */\n isMine?: never\n /**\n * \"text\" renders as a chat bubble showing the real draft `text` instead of\n * a media thumbnail card. Media-only fields below are ignored in text mode.\n * Defaults to `\"media\"`.\n */\n contentType?: 'text' | 'media'\n /** The message's own text, shown as-is (not redacted yet). Only used when `contentType` is `\"text\"`. */\n renderedText?: React.ReactNode\n}\n\nexport type PreviewProps = MediaCardPreviewProps & {\n /** Drafting is always the sender — doesn't apply here. */\n isMine?: never\n /**\n * \"text\" renders as a chat bubble instead of a media thumbnail card.\n * Media-only fields below are ignored in text mode. Defaults to `\"media\"`.\n */\n contentType?: 'text' | 'media'\n}\n\nexport type SentTextOwnProps = TextCardOwnProps & {\n contentType: 'text'\n /** Sender's view has no unlock flow — doesn't apply here. */\n onUnlockClick?: never\n isUnlocking?: never\n}\n\nexport type SentTextOtherProps = TextCardOtherProps & {\n contentType: 'text'\n}\n\nexport type SentMediaOwnProps = MediaCardOwnProps & {\n contentType?: 'media'\n /** Sender's view has no unlock/download flow — doesn't apply here. */\n onUnlockClick?: never\n isUnlocking?: never\n onDownloadClick?: never\n}\n\nexport type SentMediaOtherProps = MediaCardOtherProps & {\n contentType?: 'media'\n}\n\n/**\n * The card for a paid attachment — a still-drafting `isDraft` card, a static\n * receiver-facing `isPreview` mockup, or a sent text/media card discriminated\n * by `isMine` + `contentType`. Internally lazy-loads only the one underlying\n * implementation the resolved branch needs.\n */\nexport type LockedAttachmentProps =\n | DraftProps\n | PreviewProps\n | SentTextOwnProps\n | SentTextOtherProps\n | SentMediaOwnProps\n | SentMediaOtherProps\n\nconst LockedAttachment: React.FC<LockedAttachmentProps> = (props) => {\n return (\n <Suspense fallback={<LockedAttachmentFallback />}>\n {props.contentType === 'text' ? (\n <TextCardLazy {...props} />\n ) : (\n <MediaCardLazy {...props} />\n )}\n </Suspense>\n )\n}\n\nexport default LockedAttachment\nexport { default as PurchaseStatusBadge } from './components/_shared/PurchaseStatusBadge'\nexport type { PurchaseStatusBadgeProps } from './components/_shared/PurchaseStatusBadge'\nexport type {\n PaymentStatus,\n FetchSourceHandler,\n LockedAttachmentSource,\n LockedAttachmentGalleryItem,\n LockedAttachmentContextValue,\n} from './types'\n","import { MESSAGE_CUSTOM_TYPE } from '@linktr.ee/messaging-taxonomy'\nimport { GiftIcon } from '@phosphor-icons/react'\nimport { LocalMessage } from 'stream-chat'\n\ninterface MessageTagProps {\n message: LocalMessage\n /** When true, renders as a standalone bubble instead of a small tag */\n standalone?: boolean\n /** When true, renders sender-side chatbot variants */\n isMyMessage?: boolean\n /** Whether the message includes an attachment */\n hasAttachment?: boolean\n}\n\nconst SparkleIcon = ({ size = 15 }: { size?: number }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 15 15\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M12.003 9a.985.985 0 0 1-.652.934l-3.223 1.191-1.188 3.226a.995.995 0 0 1-1.867 0l-1.195-3.226L.65 9.937a.995.995 0 0 1 0-1.867l3.227-1.195 1.187-3.226a.995.995 0 0 1 1.868 0l1.195 3.226 3.226 1.187a.99.99 0 0 1 .649.938m3-5.83a.52.52 0 0 1-.344.492l-1.702.63-.627 1.703a.525.525 0 0 1-.986 0l-.63-1.704-1.704-.627a.525.525 0 0 1 0-.986l1.703-.63.627-1.704a.526.526 0 0 1 .986 0l.631 1.703 1.704.627a.52.52 0 0 1 .342.495\"\n fill=\"currentColor\"\n fillOpacity={0.55}\n />\n </svg>\n)\n\n/** Check if a message is a tip based on metadata */\nexport const isTipMessage = (message: LocalMessage): boolean => {\n return message.metadata?.custom_type === MESSAGE_CUSTOM_TYPE.TIP\n}\n\n/** Check if a message is a paid message based on metadata */\nexport const isPaidMessage = (message: LocalMessage): boolean => {\n return message.metadata?.custom_type === MESSAGE_CUSTOM_TYPE.PAID\n}\n\n/** Check if a message is a chatbot message based on metadata */\nexport const isChatbotMessage = (message: LocalMessage): boolean => {\n return message.metadata?.custom_type === MESSAGE_CUSTOM_TYPE.CHATBOT\n}\n\n/** Check if a message is a locked attachment */\nexport const isAttachmentMessage = (message: LocalMessage): boolean => {\n return message.metadata?.custom_type === MESSAGE_CUSTOM_TYPE.ATTACHMENT\n}\n\nexport const isTextAttachmentMessage = (message: LocalMessage): boolean => {\n return (\n isAttachmentMessage(message) &&\n message.metadata?.attachment_content_type === 'text'\n )\n}\n\nexport const isMediaAttachmentMessage = (message: LocalMessage): boolean => {\n return (\n isAttachmentMessage(message) &&\n message.metadata?.attachment_content_type !== 'text'\n )\n}\n\n/** Check if a message has a tip or paid tag (shared layout, distinct copy) */\nexport const isTipOrPaidMessage = (message: LocalMessage): boolean => {\n return isTipMessage(message) || isPaidMessage(message)\n}\n\n/** Check if a message is a tip/paid-only message (no text) */\nexport const isTipOnlyMessage = (message: LocalMessage): boolean => {\n return isTipOrPaidMessage(message) && !message.text?.trim()\n}\n\nexport const MessageTag = ({\n message,\n standalone = false,\n isMyMessage = false,\n hasAttachment = false,\n}: MessageTagProps) => {\n const isTipOrPaid = isTipOrPaidMessage(message)\n const isChatbot = isChatbotMessage(message)\n\n if (!isTipOrPaid && !isChatbot) {\n return null\n }\n\n if (isTipOrPaid) {\n const amountText = message.metadata?.amount_text\n if (!amountText) return null\n\n const className = standalone\n ? 'message-tip-standalone'\n : 'message-tag message-tag--tip'\n\n const amountLabel = isPaidMessage(message) ? 'message' : 'tip'\n const label = standalone\n ? `${amountText} ${amountLabel}`\n : `Delivered with ${amountText} ${amountLabel}`\n\n return (\n <div className={className}>\n <GiftIcon size={standalone ? 14 : 12} />\n <span>{label}</span>\n </div>\n )\n }\n\n const isSenderAttachmentVariant = isMyMessage && hasAttachment\n const chatbotLabel = isSenderAttachmentVariant\n ? 'Sent with AI'\n : 'Sent by AI Assistant'\n\n const chatbotClassName = [\n 'message-chatbot-indicator',\n isMyMessage\n ? 'message-chatbot-indicator--sender'\n : 'message-chatbot-indicator--receiver',\n isSenderAttachmentVariant\n ? 'message-chatbot-indicator--attachment'\n : 'message-chatbot-indicator--text',\n ].join(' ')\n\n const label = (\n <span className=\"message-chatbot-indicator__label\">{chatbotLabel}</span>\n )\n const icon = (\n <span className=\"message-chatbot-indicator__icon\">\n <SparkleIcon size={isSenderAttachmentVariant ? 12 : 15} />\n </span>\n )\n\n // Chatbot indicator variant\n return (\n <div className={chatbotClassName} data-testid=\"message-chatbot-indicator\">\n {isMyMessage && !isSenderAttachmentVariant ? (\n <>\n {label}\n {icon}\n </>\n ) : (\n <>\n {icon}\n {label}\n </>\n )}\n </div>\n )\n}\n","import { ThumbsUpIcon, ThumbsDownIcon } from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React from 'react'\n\nimport type { VoteSelection } from '../../hooks/useMessageVote'\n\ninterface MessageVoteButtonsProps {\n selected: VoteSelection\n onVoteUp: () => void\n onVoteDown: () => void\n}\n\nexport const MessageVoteButtons: React.FC<MessageVoteButtonsProps> = ({\n selected,\n onVoteUp,\n onVoteDown,\n}) => (\n <div className=\"message-vote-buttons\">\n <button\n type=\"button\"\n className={classNames('message-vote-button focus-ring', {\n 'message-vote-button--selected': selected === 'up',\n })}\n onClick={onVoteUp}\n aria-label=\"Good response\"\n aria-pressed={selected === 'up'}\n data-tooltip=\"Good response\"\n >\n <ThumbsUpIcon size={16} weight={selected === 'up' ? 'fill' : 'regular'} />\n </button>\n <button\n type=\"button\"\n className={classNames('message-vote-button focus-ring', {\n 'message-vote-button--selected': selected === 'down',\n })}\n onClick={onVoteDown}\n aria-label=\"Bad response\"\n aria-pressed={selected === 'down'}\n data-tooltip=\"Bad response\"\n >\n <ThumbsDownIcon size={16} weight={selected === 'down' ? 'fill' : 'regular'} />\n </button>\n </div>\n)\n","import {\n ChecksIcon,\n CircleNotchIcon,\n MegaphoneIcon,\n WarningCircleIcon,\n} from '@phosphor-icons/react'\nimport {\n MessageStatus,\n useChannelStateContext,\n useMessageContext,\n} from 'stream-chat-react'\n\n/**\n * Message status stamps for sending and terminal `MessageStatus` states\n * (sent / delivered / read), plus failed messages.\n *\n * Two reasons this is more than a static label:\n *\n * 1. `MessageStatus` picks its `delivered`/`read` branches ahead of `sent`\n * whenever Stream has `deliveredTo`/`readBy`, and — unlike `sent` — those\n * branches aren't gated to the last message. So we override all three\n * terminal slots with this same label (never Stream's default delivered\n * icon / read avatars — Read is out of scope) and re-apply the \"latest\n * message in the thread\" gate ourselves.\n *\n * 2. We derive \"latest message\" from **live channel state**, not the message\n * context's `lastOwnMessage`/`lastReceivedId`. Stream's `Message` is\n * memoised by `areMessagePropsEqual`, which does not compare those props;\n * a previous own row whose message/grouping props are unchanged (e.g.\n * after an intervening incoming message) never re-renders, so the old\n * bubble would keep showing \"Delivered\" beside the new one.\n * `useChannelStateContext` gets a fresh `messages` array on every new\n * message and, being a context, re-renders this leaf straight through the\n * stale `Message`/`MessageStatus` memos — so the label reliably clears\n * once a reply lands. We still skip non-participant rows (`system`,\n * `ephemeral`, `deleted`) when finding the last real message so a trailing\n * system event does not clear the label.\n *\n * Rendered inside stream's `.str-chat__message-status` span, which supplies\n * the flex layout; icon and copy are styled via that span in `styles.css`.\n */\nconst useIsLatestRealMessage = () => {\n const { message } = useMessageContext('SentMessageDeliveryStatus')\n const { messages } = useChannelStateContext('SentMessageDeliveryStatus')\n\n const lastMessageId = (() => {\n if (!messages) {\n return undefined\n }\n\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n const lastMessage = messages[index]\n\n if (\n lastMessage.type === 'system' ||\n lastMessage.type === 'ephemeral' ||\n lastMessage.type === 'deleted'\n ) {\n continue\n }\n\n return lastMessage.id\n }\n\n return undefined\n })()\n\n return message.id === lastMessageId\n}\n\nconst DeliveredStatus = () => {\n if (!useIsLatestRealMessage()) return null\n\n return (\n <>\n <ChecksIcon weight=\"bold\" aria-hidden=\"true\" />\n <span data-testid=\"sent-message-delivery-status\">Delivered</span>\n </>\n )\n}\n\nconst SendingStatus = () => {\n if (!useIsLatestRealMessage()) return null\n\n return (\n <>\n <CircleNotchIcon\n className=\"sent-message-status__spinner animate-spin\"\n weight=\"bold\"\n aria-hidden=\"true\"\n />\n <span data-testid=\"sent-message-sending-status\">Sending</span>\n </>\n )\n}\n\nconst BroadcastStatus = ({\n broadcastId,\n broadcastName,\n resolvedBroadcastName,\n onBroadcastClick,\n}: {\n broadcastId: string\n broadcastName?: string\n resolvedBroadcastName?: string\n onBroadcastClick?: (broadcast: { id: string; name?: string }) => void\n}) => {\n const campaignName = resolvedBroadcastName || broadcastName\n const name = campaignName || 'Broadcast'\n const content = (\n <>\n <span className=\"sent-message-broadcast-badge\" aria-hidden=\"true\">\n <MegaphoneIcon weight=\"fill\" />\n </span>\n <span\n className=\"sent-message-broadcast-name\"\n data-testid=\"sent-message-broadcast-status\"\n >\n {name}\n </span>\n </>\n )\n\n return onBroadcastClick ? (\n <button\n type=\"button\"\n className=\"sent-message-broadcast-link\"\n aria-label={`View broadcast ${name}`}\n onClick={() =>\n onBroadcastClick({\n id: broadcastId,\n ...(campaignName ? { name: campaignName } : {}),\n })\n }\n >\n {content}\n </button>\n ) : (\n content\n )\n}\n\nconst FailedStatus = () => (\n <span className=\"str-chat__message-status sent-message-status--failed\">\n <WarningCircleIcon weight=\"bold\" aria-hidden=\"true\" />\n <span data-testid=\"sent-message-failed-status\">Failed to send</span>\n </span>\n)\n\n/**\n * Delivery status beneath the viewer's most recent sent message (MES-1036):\n * a right-aligned \"✓✓ Delivered\" that appears once Stream confirms the\n * message is stored and updates live.\n *\n * Built on stream-chat-react's `MessageStatus`, which owns the own-message /\n * not-error gating and only surfaces a terminal (sending/sent/delivered/read)\n * state once the message is stored. Stream's `threadList` guard covers\n * sent/delivered/read only — not `sending` — so we suppress the whole stamp\n * (including failed) in thread lists ourselves. Sending uses the same\n * latest-message-in-thread gate; failed messages bypass `MessageStatus`\n * because it has no failed slot and are shown on every own, non-thread\n * failed message.\n */\nexport const SentMessageDeliveryStatus = ({\n onBroadcastClick,\n resolvedBroadcastName,\n}: {\n onBroadcastClick?: (broadcast: { id: string; name?: string }) => void\n resolvedBroadcastName?: string\n}) => {\n const { isMyMessage, message, threadList } = useMessageContext(\n 'SentMessageDeliveryStatus'\n )\n const isOwnMessage = isMyMessage()\n const isLatestRealMessage = useIsLatestRealMessage()\n\n // Stream's MessageStatus still mounts MessageSendingStatus when\n // threadList is true; keep all of our stamps out of thread replies.\n if (threadList) {\n return null\n }\n\n if (message.status === 'failed' && isOwnMessage && message.type !== 'error') {\n return <FailedStatus />\n }\n\n if (!isOwnMessage) {\n return null\n }\n\n const broadcastId = message.metadata?.broadcast_id\n const broadcastName = message.metadata?.broadcast_name\n const broadcastStatus =\n message.status !== 'sending' &&\n message.status !== 'failed' &&\n broadcastId ? (\n <BroadcastStatus\n broadcastId={broadcastId}\n broadcastName={broadcastName}\n resolvedBroadcastName={resolvedBroadcastName}\n onBroadcastClick={onBroadcastClick}\n />\n ) : null\n\n const messageStatus = (\n <MessageStatus\n MessageSentStatus={DeliveredStatus}\n MessageDeliveredStatus={DeliveredStatus}\n MessageReadStatus={DeliveredStatus}\n MessageSendingStatus={SendingStatus}\n />\n )\n\n if (!broadcastStatus) {\n return messageStatus\n }\n\n return (\n <span className=\"sent-message-status-row\">\n {messageStatus}\n {isLatestRealMessage && (\n <span\n className=\"sent-message-broadcast-separator\"\n aria-hidden=\"true\"\n >\n •\n </span>\n )}\n {broadcastStatus}\n </span>\n )\n}\n","/**\n * Scheme detector: `protocol:` per RFC 3986 — a letter followed by any\n * combination of letters, digits, `+`, `.`, or `-` then `:`.\n */\nconst SCHEME_PATTERN = /^([a-z][a-z0-9+.-]*):/i\n\n/**\n * Allowlist of schemes that are safe to forward into `<a href>` for\n * external navigation. `javascript:` / `data:` / `vbscript:` etc. are\n * intentionally **not** on this list — link-attachment data is\n * effectively user-controlled, so passing them through would let a\n * recipient click execute attacker-supplied code or markup.\n */\nconst SAFE_SCHEMES = new Set(['http', 'https', 'mailto', 'tel', 'sms'])\n\n/**\n * Normalize a user-supplied URL into something safe to assign to\n * `<a href>` for external navigation.\n *\n * Link attachments / link apps always point at external destinations\n * (Spotify, TikTok, FAQ links, bare-hostname Linktree URLs like\n * `tr.ee/briemix`, etc.). Without normalization, a bare hostname is\n * treated as a relative path by the browser and clicks navigate within\n * the host site (e.g. `https://linktr.ee/admin/tr.ee/briemix`) instead\n * of opening the intended destination.\n *\n * Rules:\n * - Empty / whitespace-only → returns `undefined` (no href).\n * - Explicit scheme in the safe allowlist (`http`, `https`, `mailto`,\n * `tel`, `sms`) → returned trimmed.\n * - Explicit scheme **not** on the allowlist (`javascript:`, `data:`,\n * `vbscript:`, custom protocols, …) → returns `undefined` so the\n * shell falls back to a non-navigational chrome instead of letting\n * an attacker-controlled URL execute on click.\n * - Protocol-relative (`//example.com/…`) → returned as-is; browsers\n * resolve these against the current page's scheme.\n * - Site-relative path (`/admin/…`) → returned as-is so consumers can\n * still opt into in-app navigation if they really want to.\n * - Bare hostname or anything else → `https://` is prepended so the\n * browser treats it as an external URL.\n */\nexport function normalizeExternalHref(value?: string): string | undefined {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n if (trimmed === '') return undefined\n\n const schemeMatch = SCHEME_PATTERN.exec(trimmed)\n if (schemeMatch) {\n const scheme = schemeMatch[1].toLowerCase()\n return SAFE_SCHEMES.has(scheme) ? trimmed : undefined\n }\n\n if (trimmed.startsWith('//')) return trimmed\n if (trimmed.startsWith('/')) return trimmed\n return `https://${trimmed}`\n}\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport type { LinkAttachmentCta } from '../../types'\n\nimport type { LinkAttachmentVariant } from './CardShell'\nimport { normalizeExternalHref } from './normalizeExternalHref'\n\nexport interface CardCtaProps {\n variant: LinkAttachmentVariant\n cta: LinkAttachmentCta\n}\n\nconst BUTTON_CLASS_BY_VARIANT: Record<LinkAttachmentVariant, string> = {\n dark: 'bg-white text-[#121110] hover:bg-white/90',\n light: 'bg-[#121110] text-white hover:bg-[#2a2928]',\n}\n\n/**\n * Pill-shaped CTA rendered below the description on Link App cards that\n * surface an action instead of a URL (e.g. FAQ \"View FAQs\", Form \"Complete form\").\n * Renders as `<a target=\"_blank\">` when `cta.href` is set, otherwise as a\n * plain `<button>`.\n */\nconst CardCta: React.FC<CardCtaProps> = ({ variant, cta }) => {\n const className = classNames(\n 'mt-2 inline-flex h-10 w-full items-center justify-center rounded-full px-4 text-sm font-medium leading-none transition-colors',\n BUTTON_CLASS_BY_VARIANT[variant]\n )\n\n // Mirror the URL normalization used by the shell anchor so bare\n // hostnames (e.g. `tr.ee/foo`) open as external links rather than\n // resolving against the current host.\n const normalizedHref = normalizeExternalHref(cta.href)\n\n if (normalizedHref) {\n return (\n <a\n href={normalizedHref}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n onClick={(e) => {\n // Stop the click from bubbling up to the card's anchor wrapper\n // (Received variant) so we don't navigate twice.\n e.stopPropagation()\n cta.onClick?.()\n }}\n className={`${className} no-underline`}\n >\n {cta.label}\n </a>\n )\n }\n\n return (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n cta.onClick?.()\n }}\n className={className}\n >\n {cta.label}\n </button>\n )\n}\n\nexport default CardCta\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport type { LinkAttachmentCta } from '../../types'\n\nimport CardCta from './CardCta'\nimport type { LinkAttachmentVariant } from './CardShell'\n\nexport interface CardBodyProps {\n variant: LinkAttachmentVariant\n title?: string\n /** Placeholder shown in the title slot when no title is set (dark variants only). */\n placeholderTitle?: string\n description?: string\n /** Footer URL shown below the description. Ignored when `cta` is set. */\n url?: string\n /**\n * Ink for both chin lines, from `chinContrast.inkFor` — measured against the\n * surface this card actually paints, which may be a derived accent, the audio\n * strip, or the variant fallback. Replaces the variant's own `text-*` classes\n * (including their opacity) on both lines, so a card whose surface is not the\n * variant default still reads (MES-1388).\n */\n chinTextColor?: string\n /**\n * Optional 16x16 brand badge rendered before the title (used by Link Apps:\n * Spotify, TikTok, FAQ, Form, etc.).\n */\n appIcon?: React.ReactNode\n /** Optional CTA rendered in place of the URL footer. */\n cta?: LinkAttachmentCta\n /** Trailing action rendered on the right of the title/description block. */\n trailingAction?: React.ReactNode\n /** Renders two neutral pulsing bars in place of the text. */\n isLoading?: boolean\n}\n\nconst TITLE_CLASS_BY_VARIANT: Record<LinkAttachmentVariant, string> = {\n dark: 'text-white',\n light: 'text-black/90',\n}\n\nconst TITLE_DIMMED_CLASS = 'text-white/30'\n\nconst SECONDARY_CLASS_BY_VARIANT: Record<LinkAttachmentVariant, string> = {\n dark: 'text-white/55',\n light: 'text-black/55',\n}\n\n// Skeleton bars, variant-aware for the same reason the placeholder hero is: a\n// fixed dark tint is invisible on the dark card's own dark fill. Values\n// match `SkeletonTextLines`, the toolkit's existing skeleton bars, which also\n// documents why these are explicit black/white rather than `bg-current/N`\n// (Tailwind emits nothing for an opacity modifier on `current`).\nconst SKELETON_BAR_CLASS_BY_VARIANT: Record<LinkAttachmentVariant, string> = {\n dark: 'bg-white/25',\n light: 'bg-black/15',\n}\n\n/**\n * Body of a `LinkAttachment.*` card — the \"chin\". Matches the Figma\n * `content > Labels` group: 16px horizontal padding, 12px vertical padding,\n * 2px gap between the title and the URL. `shrink-0` so it keeps its natural\n * height inside the shell's fixed-height column and the hero absorbs the\n * remainder.\n *\n * Returns `null` when there's nothing to render so plain image / file\n * attachments collapse to a thumbnail-only card — unless the card is still\n * loading, when the skeleton *is* the content.\n */\nconst CardBody: React.FC<CardBodyProps> = ({\n variant,\n chinTextColor,\n title,\n placeholderTitle,\n description,\n url,\n appIcon,\n cta,\n trailingAction,\n isLoading = false,\n}) => {\n const isDark = variant === 'dark'\n const displayTitle = title ?? (isDark ? placeholderTitle : undefined) ?? ''\n const hasTitle = displayTitle.trim() !== ''\n const hasDescription = description != null && description.trim() !== ''\n // Mirror the trimming applied by `ReceivedCard` so a whitespace-only\n // `url` collapses the body footer (and the whole body, for media-only\n // cards) instead of rendering an empty line.\n const trimmedUrl = typeof url === 'string' ? url.trim() : ''\n const hasUrl = trimmedUrl !== ''\n const hasCta = cta != null\n\n if (!isLoading && !hasTitle && !hasDescription && !hasUrl && !hasCta) {\n return null\n }\n\n const titleDimmed = isDark && !title\n\n const titleClass = classNames(\n 'line-clamp-2 text-[14px] font-medium leading-5 tracking-[0.28px]',\n chinTextColor == null &&\n (titleDimmed ? TITLE_DIMMED_CLASS : TITLE_CLASS_BY_VARIANT[variant])\n )\n\n const secondaryClass = classNames(\n 'truncate text-[12px] leading-4 tracking-[0.24px]',\n chinTextColor == null && SECONDARY_CLASS_BY_VARIANT[variant]\n )\n\n if (isLoading) {\n const barClass = classNames(\n 'animate-pulse rounded',\n SKELETON_BAR_CLASS_BY_VARIANT[variant]\n )\n\n return (\n <div className=\"shrink-0 px-4 py-3\">\n <div className=\"flex min-w-0 flex-col gap-[2px]\">\n {/* Sized to the lines they stand in for: 14/20 title, 12/16 URL. */}\n <div className={classNames('h-5 w-3/4', barClass)} aria-hidden />\n <div className={classNames('h-4 w-1/2', barClass)} aria-hidden />\n </div>\n </div>\n )\n }\n\n const chinTextStyle = chinTextColor ? { color: chinTextColor } : undefined\n\n return (\n <div className=\"shrink-0 px-4 py-3\">\n <div className=\"flex items-end gap-3\">\n <div className=\"flex min-w-0 flex-1 flex-col gap-[2px]\">\n {hasTitle && (\n <div className=\"flex min-w-0 items-center gap-2\">\n {appIcon ? <span className=\"shrink-0\">{appIcon}</span> : null}\n <p\n className={classNames('min-w-0', titleClass)}\n style={chinTextStyle}\n >\n {displayTitle}\n </p>\n </div>\n )}\n\n {hasDescription && (\n <p className={secondaryClass} style={chinTextStyle}>\n {description}\n </p>\n )}\n\n {!hasCta && hasUrl && (\n <p className={secondaryClass} style={chinTextStyle}>\n {trimmedUrl}\n </p>\n )}\n </div>\n\n {trailingAction && <div className=\"shrink-0\">{trailingAction}</div>}\n </div>\n\n {cta && <CardCta variant={variant} cta={cta} />}\n </div>\n )\n}\n\nexport default CardBody\n","import classNames from 'classnames'\nimport React from 'react'\n\nexport type LinkAttachmentVariant = 'dark' | 'light'\n\nexport interface CardShellProps {\n variant: LinkAttachmentVariant\n children: React.ReactNode\n /**\n * When provided, the entire card chrome is rendered as an anchor (used\n * by Sent / Received cards to open the link target on click). Falls\n * back to a `<div>` when omitted so Composer cards stay\n * non-navigational while drafting.\n */\n href?: string\n /**\n * Click handler for the card chrome. When `href` is set the shell is an\n * anchor and `onClick` is invoked in addition to navigation. When `href`\n * is omitted but `onClick` is set, the shell renders as a clickable\n * button (used by media-only Received cards to open an image preview).\n */\n onClick?: () => void\n /** Accessible label for the clickable variant (when `onClick` is set without `href`). */\n ariaLabel?: string\n rootRef?: React.Ref<HTMLElement>\n /**\n * Absolutely-positioned slot rendered in the top-right corner of the\n * shell. Used by the Composer card to surface its dismiss affordance\n * when there's no hero thumbnail to anchor it to.\n */\n topRight?: React.ReactNode\n /**\n * Overrides the variant-derived background colour (e.g. audio cards\n * use `bg-[#F2F3F4]` regardless of the dark/light variant).\n */\n bgClassName?: string\n /**\n * Inline background for the dynamic accent colour extracted from the\n * attachment image. Wins over `bgClassName` / the variant default when\n * set — Tailwind cannot express a runtime hex.\n */\n accentStyle?: React.CSSProperties\n /**\n * Locks the card to Figma's 250px box and makes it a flex column, so the\n * hero absorbs whatever height the chin leaves. Only the `featured` layout\n * is drawn at a fixed height — `classic` cards and the audio-player card\n * size to their content.\n */\n fixedHeight?: boolean\n /**\n * Renders the shell as a labelled busy region while the link preview is\n * still being fetched. `role=\"status\"` is what makes `aria-label` legal\n * (and announced) on an otherwise generic container.\n */\n busy?: boolean\n 'data-testid'?: string\n}\n\n/**\n * Accessible name for the loading skeleton. Hardcoded English, matching the\n * toolkit's existing convention (`aria-label=\"Dismiss attachment\"`) — there\n * is no i18n layer here.\n */\nexport const LOADING_LABEL = 'Loading link preview'\n\nconst SHELL_CLASS = classNames(\n 'relative w-[290px] select-none overflow-hidden',\n // 20px corners — no token exists for it in the component-library preset,\n // whose radius scale is sm .5rem / md 1rem / lg 1.5rem / xl 4rem.\n 'rounded-[20px]'\n)\n\n// The 290x250 lock: the chin takes the height its 1-2 line title needs\n// (82px at two lines, 62px at one) and the hero absorbs the remainder.\nconst FIXED_HEIGHT_CLASS = 'flex h-[250px] flex-col'\n\n/**\n * Outer chrome for every `LinkAttachment.*` card. Matches the 290px x 250px\n * box, 20px corner radius, and borderless / shadowless treatment of the\n * composer and sent instances in Figma.\n */\nconst CardShell: React.FC<CardShellProps> = ({\n variant,\n children,\n href,\n onClick,\n ariaLabel,\n rootRef,\n topRight,\n bgClassName,\n accentStyle,\n fixedHeight = false,\n busy = false,\n 'data-testid': dataTestId,\n}) => {\n const isInteractive = href != null || onClick != null\n const className = classNames(\n SHELL_CLASS,\n fixedHeight ? FIXED_HEIGHT_CLASS : 'block',\n // Kept underneath `accentStyle` rather than swapped out: the inline\n // background wins on specificity, and leaving the class in place means\n // an accent that somehow doesn't paint still lands on a sane surface.\n //\n // MUST be an arbitrary value, not a theme token. This package ships no\n // Tailwind utilities — `dist/assets/index.css` is only the hand-written\n // `.str-chat`/`.mes-*` CSS — so consumers generate our classes by scanning\n // `messaging-react/dist` against *their own* theme. `shade` comes from the\n // component-library preset that this package builds with; frontyard builds\n // on the Arbor preset and has no such colour, so `bg-shade` was silently\n // dropped, the chin rendered transparent, and the own-message `color: white`\n // left the title and URL invisible (MES-1388). An arbitrary value is\n // generated from the class name alone and cannot depend on consumer theme.\n //\n // Both values are the plain message bubble's own fill, so a card with no\n // usable accent matches the text bubbles around it: `#1e2330` is\n // `--str-chat__own-message-bubble-background-color` and `#f1f0ee` is\n // `--str-chat__message-bubble-background-color`. Mirrored in\n // `chinContrast.BUBBLE_BG_BY_VARIANT`, which the bubble tail reads.\n bgClassName ?? (variant === 'dark' ? 'bg-[#1e2330]' : 'bg-[#f1f0ee]'),\n // `focus-ring` is a design-system utility from the component-library\n // tailwind preset — outline-none + a black 2px focus-visible ring\n // with offset, so keyboard users can see the focused card.\n isInteractive ? 'cursor-pointer no-underline focus-ring' : null\n )\n\n const busyProps = busy\n ? { role: 'status', 'aria-busy': true, 'aria-label': LOADING_LABEL }\n : undefined\n\n const corner = topRight ? (\n <div className=\"pointer-events-auto absolute right-3 top-3 z-10\">\n {topRight}\n </div>\n ) : null\n\n if (href) {\n return (\n <a\n ref={rootRef as React.Ref<HTMLAnchorElement>}\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n onClick={onClick}\n data-testid={dataTestId}\n className={className}\n style={accentStyle}\n {...busyProps}\n >\n {children}\n {corner}\n </a>\n )\n }\n\n if (onClick) {\n return (\n <button\n ref={rootRef as React.Ref<HTMLButtonElement>}\n type=\"button\"\n onClick={onClick}\n aria-label={ariaLabel}\n data-testid={dataTestId}\n className={classNames(className, 'text-left')}\n style={accentStyle}\n {...busyProps}\n >\n {children}\n {corner}\n </button>\n )\n }\n\n return (\n <div\n ref={rootRef as React.Ref<HTMLDivElement>}\n data-testid={dataTestId}\n className={className}\n style={accentStyle}\n {...busyProps}\n >\n {children}\n {corner}\n </div>\n )\n}\n\nexport default CardShell\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport { optimizeMessagingAttachmentUrl } from '../../../../utils/cdnImageUrl'\nimport { renderTypeIcon } from '../../../AttachmentCard'\nimport { getSourceType } from '../../../AttachmentCard/utils/mimeType'\n\nimport type { LinkAttachmentVariant } from './CardShell'\n\nexport interface CardThumbnailProps {\n variant: LinkAttachmentVariant\n /** Source URL of the hero image (or poster for video). */\n thumbnailUrl?: string\n /**\n * Playable media URL. When provided alongside a video / audio `mimeType`,\n * the hero region renders a native HTML5 player with controls instead of\n * the static thumbnail / placeholder.\n */\n sourceUrl?: string\n /** Alt text — typically the card's title. */\n title?: string\n /**\n * Drives the placeholder type icon when no `thumbnailUrl` is provided,\n * and selects between image / video / audio rendering when `sourceUrl`\n * is set. Defaults to a generic image icon when unset.\n */\n mimeType?: string\n /** Optional decorations layered into the top corners of the thumbnail. */\n topLeft?: React.ReactNode\n topRight?: React.ReactNode\n /**\n * Renders a neutral pulsing block instead of the image while the link\n * preview is still being fetched.\n */\n isLoading?: boolean\n /**\n * Fired when the hero image fails to load. The owning card clears\n * `thumbnailUrl` (so the type-icon placeholder takes over) and drops the\n * accent colour, which was derived from an image the viewer cannot see.\n */\n onImageError?: () => void\n}\n\nconst PLACEHOLDER_BG: Record<LinkAttachmentVariant, string> = {\n dark: 'bg-white/10',\n light: 'bg-black/5',\n}\n\nconst PLACEHOLDER_ICON: Record<LinkAttachmentVariant, string> = {\n dark: 'size-16 text-white/25',\n light: 'size-16 text-black/25',\n}\n\n/** Mime + sourceUrl gives us a playable audio attachment. */\nexport const isPlayableAudio = (mimeType?: string, sourceUrl?: string) =>\n !!sourceUrl && !!mimeType && getSourceType(mimeType) === 'audio'\n\n/**\n * Mime + sourceUrl gives us a playable video or audio attachment. Used by\n * Received to skip wrapping the shell in an interactive `<button>` so the\n * native media controls remain operable.\n */\nexport const isPlayableMedia = (mimeType?: string, sourceUrl?: string) => {\n if (!sourceUrl || !mimeType) return false\n const source = getSourceType(mimeType)\n return source === 'video' || source === 'audio'\n}\n\n/**\n * Background colour the LinkAttachment cards switch to when the source is\n * audio — flat neutral around the native `<audio>` chrome regardless of\n * the dark / light variant.\n *\n * The hex is exported alongside the class because the card's ink is chosen by\n * measuring contrast against whatever surface it lands on, and contrast needs\n * channels rather than a class name. They are written out twice on purpose:\n * Tailwind only generates utilities it can find as complete literals when it\n * scans `dist`, so building the class from the constant\n * (`` `bg-[${AUDIO_BG}]` ``) would emit nothing at all. `chinContrast.test.ts`\n * asserts the two stay in step.\n */\nexport const AUDIO_BG = '#F2F3F4'\nexport const AUDIO_BG_CLASS = 'bg-[#F2F3F4]'\n\n/**\n * Hero region shown above the card body. Inside the `featured` card's fixed\n * 250px box it takes `flex-1`, absorbing whatever height the chin leaves.\n * Renders, in priority order: a loading placeholder, a native\n * `<video controls>` / `<audio controls>` when `sourceUrl` + mime say so, the\n * thumbnail image, then a type-icon placeholder.\n */\nconst CardThumbnail: React.FC<CardThumbnailProps> = ({\n variant,\n thumbnailUrl,\n sourceUrl,\n title,\n mimeType = 'image/*',\n topLeft,\n topRight,\n isLoading = false,\n onImageError,\n}) => {\n const sourceType = getSourceType(mimeType)\n const isPlayableVideo = !!sourceUrl && sourceType === 'video'\n const optimizedThumbnailUrl = optimizeMessagingAttachmentUrl(thumbnailUrl)\n\n // `!isLoading` first, deliberately: while the scrape is in flight we do not\n // yet know what the asset is, so honouring a `mimeType` the caller happens to\n // have set already would mount a live player next to `CardBody`'s skeleton\n // bars. The loading branch below owns every hero shape (MES-1349).\n if (!isLoading && isPlayableAudio(mimeType, sourceUrl)) {\n // Audio collapses the hero entirely — the native player sits inside\n // the card chrome with a bit of padding so the card background\n // (typically `bg-[#F2F3F4]`) is visible around it.\n return (\n <div className=\"p-3\">\n <audio\n src={sourceUrl}\n controls\n preload=\"metadata\"\n className=\"block w-full\"\n >\n <track kind=\"captions\" />\n </audio>\n </div>\n )\n }\n\n return (\n <div\n className={classNames(\n // `flex-1 min-h-0` inside the shell's 250px column: the hero takes\n // every pixel the chin doesn't, which is 168px at a two-line title\n // and 188px at one.\n 'relative min-h-0 w-full flex-1 overflow-hidden',\n isPlayableVideo && 'bg-black'\n )}\n >\n {isLoading ? (\n // Reuses the placeholder fill: a fixed `bg-black/[0.06]` would be\n // invisible on the dark card's dark surface. Stock Tailwind only\n // — `animate-shimmer` exists in this package's own tailwind config but\n // not in either consumer's, so it would compile to nothing in\n // frontyard and profiles while looking right in this Storybook.\n <div\n className={classNames(\n 'h-full w-full animate-pulse',\n PLACEHOLDER_BG[variant]\n )}\n aria-hidden\n />\n ) : isPlayableVideo ? (\n <>\n <video\n src={sourceUrl}\n poster={optimizedThumbnailUrl}\n controls\n playsInline\n preload=\"metadata\"\n className=\"absolute inset-0 h-full w-full object-contain\"\n >\n <track kind=\"captions\" />\n </video>\n {/*\n The poster *is* the hero on this branch, and `<video>` raises no\n event when one fails to load — its own `error` is about the media\n resource, not the poster — so the `<img>` below verifies it. A\n `display:none` image is still fetched and still fires `onError`\n (checked in a browser, not assumed), and it dedupes with the\n poster's own request for the same URL, so this costs a DOM node\n rather than a round trip. No `loading=\"lazy\"`: that would defer the\n probe while off screen. Without it a 404 poster left the card and\n its tail accent-painted over a bare `bg-black` box, which is the\n one thing `useChinPalette`'s rule exists to prevent (MES-1349).\n */}\n {optimizedThumbnailUrl && onImageError ? (\n <img\n src={optimizedThumbnailUrl}\n alt=\"\"\n aria-hidden\n onError={onImageError}\n className=\"hidden\"\n />\n ) : null}\n </>\n ) : thumbnailUrl ? (\n <img\n src={optimizedThumbnailUrl ?? thumbnailUrl}\n alt={title ?? ''}\n draggable={false}\n loading=\"lazy\"\n decoding=\"async\"\n onError={onImageError}\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n ) : (\n <div\n className={classNames(\n 'flex h-full w-full items-center justify-center',\n PLACEHOLDER_BG[variant]\n )}\n >\n {renderTypeIcon(mimeType, {\n className: PLACEHOLDER_ICON[variant],\n weight: 'regular',\n })}\n </div>\n )}\n\n {topLeft ? (\n <div className=\"pointer-events-auto absolute left-3 top-3 z-10\">\n {topLeft}\n </div>\n ) : null}\n {topRight ? (\n <div className=\"pointer-events-auto absolute right-3 top-3 z-10\">\n {topRight}\n </div>\n ) : null}\n </div>\n )\n}\n\nexport default CardThumbnail\n","const parseNumber = (color, len) => {\n\tif (typeof color !== 'number') return;\n\n\t// hex3: #c93 -> #cc9933\n\tif (len === 3) {\n\t\treturn {\n\t\t\tmode: 'rgb',\n\t\t\tr: (((color >> 8) & 0xf) | ((color >> 4) & 0xf0)) / 255,\n\t\t\tg: (((color >> 4) & 0xf) | (color & 0xf0)) / 255,\n\t\t\tb: ((color & 0xf) | ((color << 4) & 0xf0)) / 255\n\t\t};\n\t}\n\n\t// hex4: #c931 -> #cc993311\n\tif (len === 4) {\n\t\treturn {\n\t\t\tmode: 'rgb',\n\t\t\tr: (((color >> 12) & 0xf) | ((color >> 8) & 0xf0)) / 255,\n\t\t\tg: (((color >> 8) & 0xf) | ((color >> 4) & 0xf0)) / 255,\n\t\t\tb: (((color >> 4) & 0xf) | (color & 0xf0)) / 255,\n\t\t\talpha: ((color & 0xf) | ((color << 4) & 0xf0)) / 255\n\t\t};\n\t}\n\n\t// hex6: #f0f1f2\n\tif (len === 6) {\n\t\treturn {\n\t\t\tmode: 'rgb',\n\t\t\tr: ((color >> 16) & 0xff) / 255,\n\t\t\tg: ((color >> 8) & 0xff) / 255,\n\t\t\tb: (color & 0xff) / 255\n\t\t};\n\t}\n\n\t// hex8: #f0f1f2ff\n\tif (len === 8) {\n\t\treturn {\n\t\t\tmode: 'rgb',\n\t\t\tr: ((color >> 24) & 0xff) / 255,\n\t\t\tg: ((color >> 16) & 0xff) / 255,\n\t\t\tb: ((color >> 8) & 0xff) / 255,\n\t\t\talpha: (color & 0xff) / 255\n\t\t};\n\t}\n};\n\nexport default parseNumber;\n","const named = {\n\taliceblue: 0xf0f8ff,\n\tantiquewhite: 0xfaebd7,\n\taqua: 0x00ffff,\n\taquamarine: 0x7fffd4,\n\tazure: 0xf0ffff,\n\tbeige: 0xf5f5dc,\n\tbisque: 0xffe4c4,\n\tblack: 0x000000,\n\tblanchedalmond: 0xffebcd,\n\tblue: 0x0000ff,\n\tblueviolet: 0x8a2be2,\n\tbrown: 0xa52a2a,\n\tburlywood: 0xdeb887,\n\tcadetblue: 0x5f9ea0,\n\tchartreuse: 0x7fff00,\n\tchocolate: 0xd2691e,\n\tcoral: 0xff7f50,\n\tcornflowerblue: 0x6495ed,\n\tcornsilk: 0xfff8dc,\n\tcrimson: 0xdc143c,\n\tcyan: 0x00ffff,\n\tdarkblue: 0x00008b,\n\tdarkcyan: 0x008b8b,\n\tdarkgoldenrod: 0xb8860b,\n\tdarkgray: 0xa9a9a9,\n\tdarkgreen: 0x006400,\n\tdarkgrey: 0xa9a9a9,\n\tdarkkhaki: 0xbdb76b,\n\tdarkmagenta: 0x8b008b,\n\tdarkolivegreen: 0x556b2f,\n\tdarkorange: 0xff8c00,\n\tdarkorchid: 0x9932cc,\n\tdarkred: 0x8b0000,\n\tdarksalmon: 0xe9967a,\n\tdarkseagreen: 0x8fbc8f,\n\tdarkslateblue: 0x483d8b,\n\tdarkslategray: 0x2f4f4f,\n\tdarkslategrey: 0x2f4f4f,\n\tdarkturquoise: 0x00ced1,\n\tdarkviolet: 0x9400d3,\n\tdeeppink: 0xff1493,\n\tdeepskyblue: 0x00bfff,\n\tdimgray: 0x696969,\n\tdimgrey: 0x696969,\n\tdodgerblue: 0x1e90ff,\n\tfirebrick: 0xb22222,\n\tfloralwhite: 0xfffaf0,\n\tforestgreen: 0x228b22,\n\tfuchsia: 0xff00ff,\n\tgainsboro: 0xdcdcdc,\n\tghostwhite: 0xf8f8ff,\n\tgold: 0xffd700,\n\tgoldenrod: 0xdaa520,\n\tgray: 0x808080,\n\tgreen: 0x008000,\n\tgreenyellow: 0xadff2f,\n\tgrey: 0x808080,\n\thoneydew: 0xf0fff0,\n\thotpink: 0xff69b4,\n\tindianred: 0xcd5c5c,\n\tindigo: 0x4b0082,\n\tivory: 0xfffff0,\n\tkhaki: 0xf0e68c,\n\tlavender: 0xe6e6fa,\n\tlavenderblush: 0xfff0f5,\n\tlawngreen: 0x7cfc00,\n\tlemonchiffon: 0xfffacd,\n\tlightblue: 0xadd8e6,\n\tlightcoral: 0xf08080,\n\tlightcyan: 0xe0ffff,\n\tlightgoldenrodyellow: 0xfafad2,\n\tlightgray: 0xd3d3d3,\n\tlightgreen: 0x90ee90,\n\tlightgrey: 0xd3d3d3,\n\tlightpink: 0xffb6c1,\n\tlightsalmon: 0xffa07a,\n\tlightseagreen: 0x20b2aa,\n\tlightskyblue: 0x87cefa,\n\tlightslategray: 0x778899,\n\tlightslategrey: 0x778899,\n\tlightsteelblue: 0xb0c4de,\n\tlightyellow: 0xffffe0,\n\tlime: 0x00ff00,\n\tlimegreen: 0x32cd32,\n\tlinen: 0xfaf0e6,\n\tmagenta: 0xff00ff,\n\tmaroon: 0x800000,\n\tmediumaquamarine: 0x66cdaa,\n\tmediumblue: 0x0000cd,\n\tmediumorchid: 0xba55d3,\n\tmediumpurple: 0x9370db,\n\tmediumseagreen: 0x3cb371,\n\tmediumslateblue: 0x7b68ee,\n\tmediumspringgreen: 0x00fa9a,\n\tmediumturquoise: 0x48d1cc,\n\tmediumvioletred: 0xc71585,\n\tmidnightblue: 0x191970,\n\tmintcream: 0xf5fffa,\n\tmistyrose: 0xffe4e1,\n\tmoccasin: 0xffe4b5,\n\tnavajowhite: 0xffdead,\n\tnavy: 0x000080,\n\toldlace: 0xfdf5e6,\n\tolive: 0x808000,\n\tolivedrab: 0x6b8e23,\n\torange: 0xffa500,\n\torangered: 0xff4500,\n\torchid: 0xda70d6,\n\tpalegoldenrod: 0xeee8aa,\n\tpalegreen: 0x98fb98,\n\tpaleturquoise: 0xafeeee,\n\tpalevioletred: 0xdb7093,\n\tpapayawhip: 0xffefd5,\n\tpeachpuff: 0xffdab9,\n\tperu: 0xcd853f,\n\tpink: 0xffc0cb,\n\tplum: 0xdda0dd,\n\tpowderblue: 0xb0e0e6,\n\tpurple: 0x800080,\n\n\t// Added in CSS Colors Level 4:\n\t// https://drafts.csswg.org/css-color/#changes-from-3\n\trebeccapurple: 0x663399,\n\n\tred: 0xff0000,\n\trosybrown: 0xbc8f8f,\n\troyalblue: 0x4169e1,\n\tsaddlebrown: 0x8b4513,\n\tsalmon: 0xfa8072,\n\tsandybrown: 0xf4a460,\n\tseagreen: 0x2e8b57,\n\tseashell: 0xfff5ee,\n\tsienna: 0xa0522d,\n\tsilver: 0xc0c0c0,\n\tskyblue: 0x87ceeb,\n\tslateblue: 0x6a5acd,\n\tslategray: 0x708090,\n\tslategrey: 0x708090,\n\tsnow: 0xfffafa,\n\tspringgreen: 0x00ff7f,\n\tsteelblue: 0x4682b4,\n\ttan: 0xd2b48c,\n\tteal: 0x008080,\n\tthistle: 0xd8bfd8,\n\ttomato: 0xff6347,\n\tturquoise: 0x40e0d0,\n\tviolet: 0xee82ee,\n\twheat: 0xf5deb3,\n\twhite: 0xffffff,\n\twhitesmoke: 0xf5f5f5,\n\tyellow: 0xffff00,\n\tyellowgreen: 0x9acd32\n};\n\nexport default named;\n","import parseNumber from './parseNumber.js';\nimport named from '../colors/named.js';\n\n// Also supports the `transparent` color as defined in:\n// https://drafts.csswg.org/css-color/#transparent-black\nconst parseNamed = color => {\n\treturn parseNumber(named[color.toLowerCase()], 6);\n};\n\nexport default parseNamed;\n","import parseNumber from './parseNumber.js';\n\nconst hex = /^#?([0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{4}|[0-9a-f]{3})$/i;\n\nconst parseHex = color => {\n\tlet match;\n\t// eslint-disable-next-line no-cond-assign\n\treturn (match = color.match(hex))\n\t\t? parseNumber(parseInt(match[1], 16), match[1].length)\n\t\t: undefined;\n};\n\nexport default parseHex;\n","/*\n\tBasic building blocks for color regexes\n\t---------------------------------------\n\n\tThese regexes are expressed as strings\n\tto be interpolated in the color regexes.\n */\n\n// <number>\nexport const num = '([+-]?\\\\d*\\\\.?\\\\d+(?:[eE][+-]?\\\\d+)?)';\n\n// <number> or 'none'\nexport const num_none = `(?:${num}|none)`;\n\n// <percentage>\nexport const per = `${num}%`;\n\n// <percent> or 'none'\nexport const per_none = `(?:${num}%|none)`;\n\n// <number-percentage> (<alpha-value>)\nexport const num_per = `(?:${num}%|${num})`;\n\n// <number-percentage> (<alpha-value>) or 'none'\nexport const num_per_none = `(?:${num}%|${num}|none)`;\n\n// <hue>\nexport const hue = `(?:${num}(deg|grad|rad|turn)|${num})`;\n\n// <hue> or 'none'\nexport const hue_none = `(?:${num}(deg|grad|rad|turn)|${num}|none)`;\n\nexport const c = `\\\\s*,\\\\s*`; // comma\nexport const so = '\\\\s*'; // space, optional\nexport const s = `\\\\s+`; // space\n\nexport const rx_num_per_none = new RegExp('^' + num_per_none + '$');\n","import { num, per, num_per, c } from '../util/regex.js';\n\n/*\n\trgb() regular expressions for legacy format\n\tReference: https://drafts.csswg.org/css-color/#rgb-functions\n */\nconst rgb_num_old = new RegExp(\n\t`^rgba?\\\\(\\\\s*${num}${c}${num}${c}${num}\\\\s*(?:,\\\\s*${num_per}\\\\s*)?\\\\)$`\n);\n\nconst rgb_per_old = new RegExp(\n\t`^rgba?\\\\(\\\\s*${per}${c}${per}${c}${per}\\\\s*(?:,\\\\s*${num_per}\\\\s*)?\\\\)$`\n);\n\nconst parseRgbLegacy = color => {\n\tlet res = { mode: 'rgb' };\n\tlet match;\n\tif ((match = color.match(rgb_num_old))) {\n\t\tif (match[1] !== undefined) {\n\t\t\tres.r = match[1] / 255;\n\t\t}\n\t\tif (match[2] !== undefined) {\n\t\t\tres.g = match[2] / 255;\n\t\t}\n\t\tif (match[3] !== undefined) {\n\t\t\tres.b = match[3] / 255;\n\t\t}\n\t} else if ((match = color.match(rgb_per_old))) {\n\t\tif (match[1] !== undefined) {\n\t\t\tres.r = match[1] / 100;\n\t\t}\n\t\tif (match[2] !== undefined) {\n\t\t\tres.g = match[2] / 100;\n\t\t}\n\t\tif (match[3] !== undefined) {\n\t\t\tres.b = match[3] / 100;\n\t\t}\n\t} else {\n\t\treturn undefined;\n\t}\n\n\tif (match[4] !== undefined) {\n\t\tres.alpha = Math.max(0, Math.min(1, match[4] / 100));\n\t} else if (match[5] !== undefined) {\n\t\tres.alpha = Math.max(0, Math.min(1, +match[5]));\n\t}\n\n\treturn res;\n};\n\nexport default parseRgbLegacy;\n","import parse from './parse.js';\n\nconst prepare = (color, mode) =>\n\tcolor === undefined\n\t\t? undefined\n\t\t: typeof color !== 'object'\n\t\t? parse(color)\n\t\t: color.mode !== undefined\n\t\t? color\n\t\t: mode\n\t\t? { ...color, mode }\n\t\t: undefined;\n\nexport default prepare;\n","import { converters } from './modes.js';\nimport prepare from './_prepare.js';\n\nconst converter =\n\t(target_mode = 'rgb') =>\n\tcolor =>\n\t\t(color = prepare(color, target_mode)) !== undefined\n\t\t\t? // if the color's mode corresponds to our target mode\n\t\t\t color.mode === target_mode\n\t\t\t\t? // then just return the color\n\t\t\t\t color\n\t\t\t\t: // otherwise check to see if we have a dedicated\n\t\t\t\t// converter for the target mode\n\t\t\t\tconverters[color.mode][target_mode]\n\t\t\t\t? // and return its result...\n\t\t\t\t converters[color.mode][target_mode](color)\n\t\t\t\t: // ...otherwise pass through RGB as an intermediary step.\n\t\t\t\t// if the target mode is RGB...\n\t\t\t\ttarget_mode === 'rgb'\n\t\t\t\t? // just return the RGB\n\t\t\t\t converters[color.mode].rgb(color)\n\t\t\t\t: // otherwise convert color.mode -> RGB -> target_mode\n\t\t\t\t converters.rgb[target_mode](converters[color.mode].rgb(color))\n\t\t\t: undefined;\n\nexport default converter;\n","import converter from './converter.js';\n\nconst converters = {};\nconst modes = {};\n\nconst parsers = [];\nconst colorProfiles = {};\n\nconst identity = v => v;\n\nconst useMode = definition => {\n\tconverters[definition.mode] = {\n\t\t...converters[definition.mode],\n\t\t...definition.toMode\n\t};\n\n\tObject.keys(definition.fromMode || {}).forEach(k => {\n\t\tif (!converters[k]) {\n\t\t\tconverters[k] = {};\n\t\t}\n\t\tconverters[k][definition.mode] = definition.fromMode[k];\n\t});\n\n\t// Color space channel ranges\n\tif (!definition.ranges) {\n\t\tdefinition.ranges = {};\n\t}\n\n\tif (!definition.difference) {\n\t\tdefinition.difference = {};\n\t}\n\n\tdefinition.channels.forEach(channel => {\n\t\t// undefined channel ranges default to the [0, 1] interval\n\t\tif (definition.ranges[channel] === undefined) {\n\t\t\tdefinition.ranges[channel] = [0, 1];\n\t\t}\n\n\t\tif (!definition.interpolate[channel]) {\n\t\t\tthrow new Error(`Missing interpolator for: ${channel}`);\n\t\t}\n\n\t\tif (typeof definition.interpolate[channel] === 'function') {\n\t\t\tdefinition.interpolate[channel] = {\n\t\t\t\tuse: definition.interpolate[channel]\n\t\t\t};\n\t\t}\n\n\t\tif (!definition.interpolate[channel].fixup) {\n\t\t\tdefinition.interpolate[channel].fixup = identity;\n\t\t}\n\t});\n\n\tmodes[definition.mode] = definition;\n\t(definition.parse || []).forEach(parser => {\n\t\tuseParser(parser, definition.mode);\n\t});\n\n\treturn converter(definition.mode);\n};\n\nconst getMode = mode => modes[mode];\n\nconst useParser = (parser, mode) => {\n\tif (typeof parser === 'string') {\n\t\tif (!mode) {\n\t\t\tthrow new Error(`'mode' required when 'parser' is a string`);\n\t\t}\n\t\tcolorProfiles[parser] = mode;\n\t} else if (typeof parser === 'function') {\n\t\tif (parsers.indexOf(parser) < 0) {\n\t\t\tparsers.push(parser);\n\t\t}\n\t}\n};\n\nconst removeParser = parser => {\n\tif (typeof parser === 'string') {\n\t\tdelete colorProfiles[parser];\n\t} else if (typeof parser === 'function') {\n\t\tconst idx = parsers.indexOf(parser);\n\t\tif (idx > 0) {\n\t\t\tparsers.splice(idx, 1);\n\t\t}\n\t}\n};\n\nexport {\n\tuseMode,\n\tgetMode,\n\tuseParser,\n\tremoveParser,\n\tconverters,\n\tparsers,\n\tcolorProfiles\n};\n","import { parsers, colorProfiles, getMode } from './modes.js';\n\n/* eslint-disable-next-line no-control-regex */\nconst IdentStartCodePoint = /[^\\x00-\\x7F]|[a-zA-Z_]/;\n\n/* eslint-disable-next-line no-control-regex */\nconst IdentCodePoint = /[^\\x00-\\x7F]|[-\\w]/;\n\nexport const Tok = {\n\tFunction: 'function',\n\tIdent: 'ident',\n\tNumber: 'number',\n\tPercentage: 'percentage',\n\tParenClose: ')',\n\tNone: 'none',\n\tHue: 'hue',\n\tAlpha: 'alpha'\n};\n\nlet _i = 0;\n\n/*\n\t4.3.10. Check if three code points would start a number\n\thttps://drafts.csswg.org/css-syntax/#starts-with-a-number\n */\nfunction is_num(chars) {\n\tlet ch = chars[_i];\n\tlet ch1 = chars[_i + 1];\n\tif (ch === '-' || ch === '+') {\n\t\treturn /\\d/.test(ch1) || (ch1 === '.' && /\\d/.test(chars[_i + 2]));\n\t}\n\tif (ch === '.') {\n\t\treturn /\\d/.test(ch1);\n\t}\n\treturn /\\d/.test(ch);\n}\n\n/*\n\tCheck if the stream starts with an identifier.\n */\n\nfunction is_ident(chars) {\n\tif (_i >= chars.length) {\n\t\treturn false;\n\t}\n\tlet ch = chars[_i];\n\tif (IdentStartCodePoint.test(ch)) {\n\t\treturn true;\n\t}\n\tif (ch === '-') {\n\t\tif (chars.length - _i < 2) {\n\t\t\treturn false;\n\t\t}\n\t\tlet ch1 = chars[_i + 1];\n\t\tif (ch1 === '-' || IdentStartCodePoint.test(ch1)) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\treturn false;\n}\n\n/*\n\t4.3.3. Consume a numeric token\n\thttps://drafts.csswg.org/css-syntax/#consume-numeric-token\n */\n\nconst huenits = {\n\tdeg: 1,\n\trad: 180 / Math.PI,\n\tgrad: 9 / 10,\n\tturn: 360\n};\n\nfunction num(chars) {\n\tlet value = '';\n\tif (chars[_i] === '-' || chars[_i] === '+') {\n\t\tvalue += chars[_i++];\n\t}\n\tvalue += digits(chars);\n\tif (chars[_i] === '.' && /\\d/.test(chars[_i + 1])) {\n\t\tvalue += chars[_i++] + digits(chars);\n\t}\n\tif (chars[_i] === 'e' || chars[_i] === 'E') {\n\t\tif (\n\t\t\t(chars[_i + 1] === '-' || chars[_i + 1] === '+') &&\n\t\t\t/\\d/.test(chars[_i + 2])\n\t\t) {\n\t\t\tvalue += chars[_i++] + chars[_i++] + digits(chars);\n\t\t} else if (/\\d/.test(chars[_i + 1])) {\n\t\t\tvalue += chars[_i++] + digits(chars);\n\t\t}\n\t}\n\tif (is_ident(chars)) {\n\t\tlet id = ident(chars);\n\t\tif (id === 'deg' || id === 'rad' || id === 'turn' || id === 'grad') {\n\t\t\treturn { type: Tok.Hue, value: value * huenits[id] };\n\t\t}\n\t\treturn undefined;\n\t}\n\tif (chars[_i] === '%') {\n\t\t_i++;\n\t\treturn { type: Tok.Percentage, value: +value };\n\t}\n\treturn { type: Tok.Number, value: +value };\n}\n\n/*\n\tConsume digits.\n */\nfunction digits(chars) {\n\tlet v = '';\n\twhile (/\\d/.test(chars[_i])) {\n\t\tv += chars[_i++];\n\t}\n\treturn v;\n}\n\n/*\n\tConsume an identifier.\n */\nfunction ident(chars) {\n\tlet v = '';\n\twhile (_i < chars.length && IdentCodePoint.test(chars[_i])) {\n\t\tv += chars[_i++];\n\t}\n\treturn v;\n}\n\n/*\n\tConsume an ident-like token.\n */\nfunction identlike(chars) {\n\tlet v = ident(chars);\n\tif (chars[_i] === '(') {\n\t\t_i++;\n\t\treturn { type: Tok.Function, value: v };\n\t}\n\tif (v === 'none') {\n\t\treturn { type: Tok.None, value: undefined };\n\t}\n\treturn { type: Tok.Ident, value: v };\n}\n\nexport function tokenize(str = '') {\n\tlet chars = str.trim();\n\tlet tokens = [];\n\tlet ch;\n\n\t/* reset counter */\n\t_i = 0;\n\n\twhile (_i < chars.length) {\n\t\tch = chars[_i++];\n\n\t\t/*\n\t\t\tConsume whitespace without emitting it\n\t\t */\n\t\tif (ch === '\\n' || ch === '\\t' || ch === ' ') {\n\t\t\twhile (\n\t\t\t\t_i < chars.length &&\n\t\t\t\t(chars[_i] === '\\n' || chars[_i] === '\\t' || chars[_i] === ' ')\n\t\t\t) {\n\t\t\t\t_i++;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (ch === ',') {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (ch === ')') {\n\t\t\ttokens.push({ type: Tok.ParenClose });\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (ch === '+') {\n\t\t\t_i--;\n\t\t\tif (is_num(chars)) {\n\t\t\t\ttokens.push(num(chars));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (ch === '-') {\n\t\t\t_i--;\n\t\t\tif (is_num(chars)) {\n\t\t\t\ttokens.push(num(chars));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (is_ident(chars)) {\n\t\t\t\ttokens.push({ type: Tok.Ident, value: ident(chars) });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (ch === '.') {\n\t\t\t_i--;\n\t\t\tif (is_num(chars)) {\n\t\t\t\ttokens.push(num(chars));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (ch === '/') {\n\t\t\twhile (\n\t\t\t\t_i < chars.length &&\n\t\t\t\t(chars[_i] === '\\n' || chars[_i] === '\\t' || chars[_i] === ' ')\n\t\t\t) {\n\t\t\t\t_i++;\n\t\t\t}\n\t\t\tlet alpha;\n\t\t\tif (is_num(chars)) {\n\t\t\t\talpha = num(chars);\n\t\t\t\tif (alpha.type !== Tok.Hue) {\n\t\t\t\t\ttokens.push({ type: Tok.Alpha, value: alpha });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (is_ident(chars)) {\n\t\t\t\tif (ident(chars) === 'none') {\n\t\t\t\t\ttokens.push({\n\t\t\t\t\t\ttype: Tok.Alpha,\n\t\t\t\t\t\tvalue: { type: Tok.None, value: undefined }\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (/\\d/.test(ch)) {\n\t\t\t_i--;\n\t\t\ttokens.push(num(chars));\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (IdentStartCodePoint.test(ch)) {\n\t\t\t_i--;\n\t\t\ttokens.push(identlike(chars));\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t\tTreat everything not already handled as an error.\n\t\t */\n\t\treturn undefined;\n\t}\n\n\treturn tokens;\n}\n\nexport function parseColorSyntax(tokens) {\n\ttokens._i = 0;\n\tlet token = tokens[tokens._i++];\n\tif (!token || token.type !== Tok.Function || token.value !== 'color') {\n\t\treturn undefined;\n\t}\n\ttoken = tokens[tokens._i++];\n\tif (token.type !== Tok.Ident) {\n\t\treturn undefined;\n\t}\n\tconst mode = colorProfiles[token.value];\n\tif (!mode) {\n\t\treturn undefined;\n\t}\n\tconst res = { mode };\n\tconst coords = consumeCoords(tokens, false);\n\tif (!coords) {\n\t\treturn undefined;\n\t}\n\tconst channels = getMode(mode).channels;\n\tfor (let ii = 0, c, ch; ii < channels.length; ii++) {\n\t\tc = coords[ii];\n\t\tch = channels[ii];\n\t\tif (c.type !== Tok.None) {\n\t\t\tres[ch] = c.type === Tok.Number ? c.value : c.value / 100;\n\t\t\tif (ch === 'alpha') {\n\t\t\t\tres[ch] = Math.max(0, Math.min(1, res[ch]));\n\t\t\t}\n\t\t}\n\t}\n\treturn res;\n}\n\nfunction consumeCoords(tokens, includeHue) {\n\tconst coords = [];\n\tlet token;\n\twhile (tokens._i < tokens.length) {\n\t\ttoken = tokens[tokens._i++];\n\t\tif (\n\t\t\ttoken.type === Tok.None ||\n\t\t\ttoken.type === Tok.Number ||\n\t\t\ttoken.type === Tok.Alpha ||\n\t\t\ttoken.type === Tok.Percentage ||\n\t\t\t(includeHue && token.type === Tok.Hue)\n\t\t) {\n\t\t\tcoords.push(token);\n\t\t\tcontinue;\n\t\t}\n\t\tif (token.type === Tok.ParenClose) {\n\t\t\tif (tokens._i < tokens.length) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tif (coords.length < 3 || coords.length > 4) {\n\t\treturn undefined;\n\t}\n\n\tif (coords.length === 4) {\n\t\tif (coords[3].type !== Tok.Alpha) {\n\t\t\treturn undefined;\n\t\t}\n\t\tcoords[3] = coords[3].value;\n\t}\n\tif (coords.length === 3) {\n\t\tcoords.push({ type: Tok.None, value: undefined });\n\t}\n\n\treturn coords.every(c => c.type !== Tok.Alpha) ? coords : undefined;\n}\n\nexport function parseModernSyntax(tokens, includeHue) {\n\ttokens._i = 0;\n\tlet token = tokens[tokens._i++];\n\tif (!token || token.type !== Tok.Function) {\n\t\treturn undefined;\n\t}\n\tlet coords = consumeCoords(tokens, includeHue);\n\tif (!coords) {\n\t\treturn undefined;\n\t}\n\tcoords.unshift(token.value);\n\treturn coords;\n}\n\nconst parse = color => {\n\tif (typeof color !== 'string') {\n\t\treturn undefined;\n\t}\n\tconst tokens = tokenize(color);\n\tconst parsed = tokens ? parseModernSyntax(tokens, true) : undefined;\n\tlet result = undefined;\n\tlet i = 0;\n\tlet len = parsers.length;\n\twhile (i < len) {\n\t\tif ((result = parsers[i++](color, parsed)) !== undefined) {\n\t\t\treturn result;\n\t\t}\n\t}\n\treturn tokens ? parseColorSyntax(tokens) : undefined;\n};\n\nexport default parse;\n","import { Tok } from '../parse.js';\n\nfunction parseRgb(color, parsed) {\n\tif (!parsed || (parsed[0] !== 'rgb' && parsed[0] !== 'rgba')) {\n\t\treturn undefined;\n\t}\n\tconst res = { mode: 'rgb' };\n\tconst [, r, g, b, alpha] = parsed;\n\tif (r.type === Tok.Hue || g.type === Tok.Hue || b.type === Tok.Hue) {\n\t\treturn undefined;\n\t}\n\tif (r.type !== Tok.None) {\n\t\tres.r = r.type === Tok.Number ? r.value / 255 : r.value / 100;\n\t}\n\tif (g.type !== Tok.None) {\n\t\tres.g = g.type === Tok.Number ? g.value / 255 : g.value / 100;\n\t}\n\tif (b.type !== Tok.None) {\n\t\tres.b = b.type === Tok.Number ? b.value / 255 : b.value / 100;\n\t}\n\tif (alpha.type !== Tok.None) {\n\t\tres.alpha = Math.min(\n\t\t\t1,\n\t\t\tMath.max(\n\t\t\t\t0,\n\t\t\t\talpha.type === Tok.Number ? alpha.value : alpha.value / 100\n\t\t\t)\n\t\t);\n\t}\n\n\treturn res;\n}\n\nexport default parseRgb;\n","const parseTransparent = c =>\n\tc === 'transparent'\n\t\t? { mode: 'rgb', r: 0, g: 0, b: 0, alpha: 0 }\n\t\t: undefined;\n\nexport default parseTransparent;\n","const lerp = (a, b, t) => a + t * (b - a);\nconst unlerp = (a, b, v) => (v - a) / (b - a);\n\nconst blerp = (a00, a01, a10, a11, tx, ty) => {\n\treturn lerp(lerp(a00, a01, tx), lerp(a10, a11, tx), ty);\n};\n\nconst trilerp = (\n\ta000,\n\ta010,\n\ta100,\n\ta110,\n\ta001,\n\ta011,\n\ta101,\n\ta111,\n\ttx,\n\tty,\n\ttz\n) => {\n\treturn lerp(\n\t\tblerp(a000, a010, a100, a110, tx, ty),\n\t\tblerp(a001, a011, a101, a111, tx, ty),\n\t\ttz\n\t);\n};\n\nexport { lerp, blerp, trilerp, unlerp };\n","const get_classes = arr => {\n\tlet classes = [];\n\tfor (let i = 0; i < arr.length - 1; i++) {\n\t\tlet a = arr[i];\n\t\tlet b = arr[i + 1];\n\t\tif (a === undefined && b === undefined) {\n\t\t\tclasses.push(undefined);\n\t\t} else if (a !== undefined && b !== undefined) {\n\t\t\tclasses.push([a, b]);\n\t\t} else {\n\t\t\tclasses.push(a !== undefined ? [a, a] : [b, b]);\n\t\t}\n\t}\n\treturn classes;\n};\n\nconst interpolatorPiecewise = interpolator => arr => {\n\tlet classes = get_classes(arr);\n\treturn t => {\n\t\tlet cls = t * classes.length;\n\t\tlet idx = t >= 1 ? classes.length - 1 : Math.max(Math.floor(cls), 0);\n\t\tlet pair = classes[idx];\n\t\treturn pair === undefined\n\t\t\t? undefined\n\t\t\t: interpolator(pair[0], pair[1], cls - idx);\n\t};\n};\n\nexport { interpolatorPiecewise };\n","import { lerp } from './lerp.js';\nimport { interpolatorPiecewise } from './piecewise.js';\n\nexport const interpolatorLinear = interpolatorPiecewise(lerp);\n","const fixupAlpha = arr => {\n\tlet some_defined = false;\n\tlet res = arr.map(v => {\n\t\tif (v !== undefined) {\n\t\t\tsome_defined = true;\n\t\t\treturn v;\n\t\t}\n\t\treturn 1;\n\t});\n\treturn some_defined ? res : arr;\n};\n\nexport { fixupAlpha };\n","import parseNamed from './parseNamed.js';\nimport parseHex from './parseHex.js';\nimport parseRgbLegacy from './parseRgbLegacy.js';\nimport parseRgb from './parseRgb.js';\nimport parseTransparent from './parseTransparent.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\n\n/*\n\tsRGB color space\n */\n\nconst definition = {\n\tmode: 'rgb',\n\tchannels: ['r', 'g', 'b', 'alpha'],\n\tparse: [\n\t\tparseRgb,\n\t\tparseHex,\n\t\tparseRgbLegacy,\n\t\tparseNamed,\n\t\tparseTransparent,\n\t\t'srgb'\n\t],\n\tserialize: 'srgb',\n\tinterpolate: {\n\t\tr: interpolatorLinear,\n\t\tg: interpolatorLinear,\n\t\tb: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t},\n\tgamut: true,\n\twhite: { r: 1, g: 1, b: 1 },\n\tblack: { r: 0, g: 0, b: 0 }\n};\n\nexport default definition;\n","/*\n\tConvert A98 RGB values to CIE XYZ D65\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n\t\t* https://www.adobe.com/digitalimag/pdfs/AdobeRGB1998.pdf\n*/\n\nconst linearize = (v = 0) => Math.pow(Math.abs(v), 563 / 256) * Math.sign(v);\n\nconst convertA98ToXyz65 = a98 => {\n\tlet r = linearize(a98.r);\n\tlet g = linearize(a98.g);\n\tlet b = linearize(a98.b);\n\tlet res = {\n\t\tmode: 'xyz65',\n\t\tx:\n\t\t\t0.5766690429101305 * r +\n\t\t\t0.1855582379065463 * g +\n\t\t\t0.1882286462349947 * b,\n\t\ty:\n\t\t\t0.297344975250536 * r +\n\t\t\t0.6273635662554661 * g +\n\t\t\t0.0752914584939979 * b,\n\t\tz:\n\t\t\t0.0270313613864123 * r +\n\t\t\t0.0706888525358272 * g +\n\t\t\t0.9913375368376386 * b\n\t};\n\tif (a98.alpha !== undefined) {\n\t\tres.alpha = a98.alpha;\n\t}\n\treturn res;\n};\n\nexport default convertA98ToXyz65;\n","/*\n\tConvert CIE XYZ D65 values to A98 RGB\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n*/\n\nconst gamma = v => Math.pow(Math.abs(v), 256 / 563) * Math.sign(v);\n\nconst convertXyz65ToA98 = ({ x, y, z, alpha }) => {\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet res = {\n\t\tmode: 'a98',\n\t\tr: gamma(\n\t\t\tx * 2.0415879038107465 -\n\t\t\t\ty * 0.5650069742788597 -\n\t\t\t\t0.3447313507783297 * z\n\t\t),\n\t\tg: gamma(\n\t\t\tx * -0.9692436362808798 +\n\t\t\t\ty * 1.8759675015077206 +\n\t\t\t\t0.0415550574071756 * z\n\t\t),\n\t\tb: gamma(\n\t\t\tx * 0.0134442806320312 -\n\t\t\t\ty * 0.1183623922310184 +\n\t\t\t\t1.0151749943912058 * z\n\t\t)\n\t};\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertXyz65ToA98;\n","const fn = (c = 0) => {\n\tconst abs = Math.abs(c);\n\tif (abs <= 0.04045) {\n\t\treturn c / 12.92;\n\t}\n\treturn (Math.sign(c) || 1) * Math.pow((abs + 0.055) / 1.055, 2.4);\n};\n\nconst convertRgbToLrgb = ({ r, g, b, alpha }) => {\n\tlet res = {\n\t\tmode: 'lrgb',\n\t\tr: fn(r),\n\t\tg: fn(g),\n\t\tb: fn(b)\n\t};\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertRgbToLrgb;\n","/*\n\tConvert sRGB values to CIE XYZ D65\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n\t\t* https://observablehq.com/@danburzo/color-matrix-calculator\n*/\n\nimport convertRgbToLrgb from '../lrgb/convertRgbToLrgb.js';\n\nconst convertRgbToXyz65 = rgb => {\n\tlet { r, g, b, alpha } = convertRgbToLrgb(rgb);\n\tlet res = {\n\t\tmode: 'xyz65',\n\t\tx:\n\t\t\t0.4123907992659593 * r +\n\t\t\t0.357584339383878 * g +\n\t\t\t0.1804807884018343 * b,\n\t\ty:\n\t\t\t0.2126390058715102 * r +\n\t\t\t0.715168678767756 * g +\n\t\t\t0.0721923153607337 * b,\n\t\tz:\n\t\t\t0.0193308187155918 * r +\n\t\t\t0.119194779794626 * g +\n\t\t\t0.9505321522496607 * b\n\t};\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertRgbToXyz65;\n","const fn = (c = 0) => {\n\tconst abs = Math.abs(c);\n\tif (abs > 0.0031308) {\n\t\treturn (Math.sign(c) || 1) * (1.055 * Math.pow(abs, 1 / 2.4) - 0.055);\n\t}\n\treturn c * 12.92;\n};\n\nconst convertLrgbToRgb = ({ r, g, b, alpha }, mode = 'rgb') => {\n\tlet res = {\n\t\tmode,\n\t\tr: fn(r),\n\t\tg: fn(g),\n\t\tb: fn(b)\n\t};\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertLrgbToRgb;\n","/*\n\tCIE XYZ D65 values to sRGB.\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n\t\t* https://observablehq.com/@danburzo/color-matrix-calculator\n*/\n\nimport convertLrgbToRgb from '../lrgb/convertLrgbToRgb.js';\n\nconst convertXyz65ToRgb = ({ x, y, z, alpha }) => {\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet res = convertLrgbToRgb({\n\t\tr:\n\t\t\tx * 3.2409699419045226 -\n\t\t\ty * 1.5373831775700939 -\n\t\t\t0.4986107602930034 * z,\n\t\tg:\n\t\t\tx * -0.9692436362808796 +\n\t\t\ty * 1.8759675015077204 +\n\t\t\t0.0415550574071756 * z,\n\t\tb:\n\t\t\tx * 0.0556300796969936 -\n\t\t\ty * 0.2039769588889765 +\n\t\t\t1.0569715142428784 * z\n\t});\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertXyz65ToRgb;\n","import rgb from '../rgb/definition.js';\n\nimport convertA98ToXyz65 from './convertA98ToXyz65.js';\nimport convertXyz65ToA98 from './convertXyz65ToA98.js';\nimport convertRgbToXyz65 from '../xyz65/convertRgbToXyz65.js';\nimport convertXyz65ToRgb from '../xyz65/convertXyz65ToRgb.js';\n\nconst definition = {\n\t...rgb,\n\tmode: 'a98',\n\tparse: ['a98-rgb'],\n\tserialize: 'a98-rgb',\n\n\tfromMode: {\n\t\trgb: color => convertXyz65ToA98(convertRgbToXyz65(color)),\n\t\txyz65: convertXyz65ToA98\n\t},\n\n\ttoMode: {\n\t\trgb: color => convertXyz65ToRgb(convertA98ToXyz65(color)),\n\t\txyz65: convertA98ToXyz65\n\t}\n};\n\nexport default definition;\n","const normalizeHue = hue => ((hue = hue % 360) < 0 ? hue + 360 : hue);\n\nexport default normalizeHue;\n","import normalizeHue from '../util/normalizeHue.js';\n\nconst hue = (hues, fn) => {\n\treturn hues\n\t\t.map((hue, idx, arr) => {\n\t\t\tif (hue === undefined) {\n\t\t\t\treturn hue;\n\t\t\t}\n\t\t\tlet normalized = normalizeHue(hue);\n\t\t\tif (idx === 0 || hues[idx - 1] === undefined) {\n\t\t\t\treturn normalized;\n\t\t\t}\n\t\t\treturn fn(normalized - normalizeHue(arr[idx - 1]));\n\t\t})\n\t\t.reduce((acc, curr) => {\n\t\t\tif (\n\t\t\t\t!acc.length ||\n\t\t\t\tcurr === undefined ||\n\t\t\t\tacc[acc.length - 1] === undefined\n\t\t\t) {\n\t\t\t\tacc.push(curr);\n\t\t\t\treturn acc;\n\t\t\t}\n\t\t\tacc.push(curr + acc[acc.length - 1]);\n\t\t\treturn acc;\n\t\t}, []);\n};\n\nconst fixupHueShorter = arr =>\n\thue(arr, d => (Math.abs(d) <= 180 ? d : d - 360 * Math.sign(d)));\nconst fixupHueLonger = arr =>\n\thue(arr, d => (Math.abs(d) >= 180 || d === 0 ? d : d - 360 * Math.sign(d)));\nconst fixupHueIncreasing = arr => hue(arr, d => (d >= 0 ? d : d + 360));\nconst fixupHueDecreasing = arr => hue(arr, d => (d <= 0 ? d : d - 360));\n\nexport {\n\tfixupHueShorter,\n\tfixupHueLonger,\n\tfixupHueIncreasing,\n\tfixupHueDecreasing\n};\n","export const M = [-0.14861, 1.78277, -0.29227, -0.90649, 1.97294, 0];\n\nexport const degToRad = Math.PI / 180;\nexport const radToDeg = 180 / Math.PI;\n","/*\n\tConvert a RGB color to the Cubehelix HSL color space.\n\n\tThis computation is not present in Green's paper:\n\thttps://arxiv.org/pdf/1108.5083.pdf\n\n\t...but can be derived from the inverse, HSL to RGB conversion.\n\n\tIt matches the math in Mike Bostock's D3 implementation:\n\n\thttps://github.com/d3/d3-color/blob/master/src/cubehelix.js\n */\n\nimport { radToDeg, M } from './constants.js';\n\nlet DE = M[3] * M[4];\nlet BE = M[1] * M[4];\nlet BCAD = M[1] * M[2] - M[0] * M[3];\n\nconst convertRgbToCubehelix = ({ r, g, b, alpha }) => {\n\tif (r === undefined) r = 0;\n\tif (g === undefined) g = 0;\n\tif (b === undefined) b = 0;\n\tlet l = (BCAD * b + r * DE - g * BE) / (BCAD + DE - BE);\n\tlet x = b - l;\n\tlet y = (M[4] * (g - l) - M[2] * x) / M[3];\n\n\tlet res = {\n\t\tmode: 'cubehelix',\n\t\tl: l,\n\t\ts:\n\t\t\tl === 0 || l === 1\n\t\t\t\t? undefined\n\t\t\t\t: Math.sqrt(x * x + y * y) / (M[4] * l * (1 - l))\n\t};\n\n\tif (res.s) res.h = Math.atan2(y, x) * radToDeg - 120;\n\tif (alpha !== undefined) res.alpha = alpha;\n\n\treturn res;\n};\n\nexport default convertRgbToCubehelix;\n","import { degToRad, M } from './constants.js';\n\nconst convertCubehelixToRgb = ({ h, s, l, alpha }) => {\n\tlet res = { mode: 'rgb' };\n\n\th = (h === undefined ? 0 : h + 120) * degToRad;\n\tif (l === undefined) l = 0;\n\n\tlet amp = s === undefined ? 0 : s * l * (1 - l);\n\n\tlet cosh = Math.cos(h);\n\tlet sinh = Math.sin(h);\n\n\tres.r = l + amp * (M[0] * cosh + M[1] * sinh);\n\tres.g = l + amp * (M[2] * cosh + M[3] * sinh);\n\tres.b = l + amp * (M[4] * cosh + M[5] * sinh);\n\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertCubehelixToRgb;\n","import { getMode } from './modes.js';\nimport converter from './converter.js';\nimport normalizeHue from './util/normalizeHue.js';\n\nconst differenceHueSaturation = (std, smp) => {\n\tif (std.h === undefined || smp.h === undefined || !std.s || !smp.s) {\n\t\treturn 0;\n\t}\n\tlet std_h = normalizeHue(std.h);\n\tlet smp_h = normalizeHue(smp.h);\n\tlet dH = Math.sin((((smp_h - std_h + 360) / 2) * Math.PI) / 180);\n\treturn 2 * Math.sqrt(std.s * smp.s) * dH;\n};\n\nconst differenceHueNaive = (std, smp) => {\n\tif (std.h === undefined || smp.h === undefined) {\n\t\treturn 0;\n\t}\n\tlet std_h = normalizeHue(std.h);\n\tlet smp_h = normalizeHue(smp.h);\n\tif (Math.abs(smp_h - std_h) > 180) {\n\t\t// todo should this be normalized once again?\n\t\treturn std_h - (smp_h - 360 * Math.sign(smp_h - std_h));\n\t}\n\treturn smp_h - std_h;\n};\n\nconst differenceHueChroma = (std, smp) => {\n\tif (std.h === undefined || smp.h === undefined || !std.c || !smp.c) {\n\t\treturn 0;\n\t}\n\tlet std_h = normalizeHue(std.h);\n\tlet smp_h = normalizeHue(smp.h);\n\tlet dH = Math.sin((((smp_h - std_h + 360) / 2) * Math.PI) / 180);\n\treturn 2 * Math.sqrt(std.c * smp.c) * dH;\n};\n\nconst differenceEuclidean = (mode = 'rgb', weights = [1, 1, 1, 0]) => {\n\tlet def = getMode(mode);\n\tlet channels = def.channels;\n\tlet diffs = def.difference;\n\tlet conv = converter(mode);\n\treturn (std, smp) => {\n\t\tlet ConvStd = conv(std);\n\t\tlet ConvSmp = conv(smp);\n\t\treturn Math.sqrt(\n\t\t\tchannels.reduce((sum, k, idx) => {\n\t\t\t\tlet delta = diffs[k]\n\t\t\t\t\t? diffs[k](ConvStd, ConvSmp)\n\t\t\t\t\t: ConvStd[k] - ConvSmp[k];\n\t\t\t\treturn (\n\t\t\t\t\tsum +\n\t\t\t\t\t(weights[idx] || 0) * Math.pow(isNaN(delta) ? 0 : delta, 2)\n\t\t\t\t);\n\t\t\t}, 0)\n\t\t);\n\t};\n};\n\nconst differenceCie76 = () => differenceEuclidean('lab65');\n\nconst differenceCie94 = (kL = 1, K1 = 0.045, K2 = 0.015) => {\n\tlet lab = converter('lab65');\n\n\treturn (std, smp) => {\n\t\tlet LabStd = lab(std);\n\t\tlet LabSmp = lab(smp);\n\n\t\t// Extract Lab values, and compute Chroma\n\t\tlet lStd = LabStd.l;\n\t\tlet aStd = LabStd.a;\n\t\tlet bStd = LabStd.b;\n\t\tlet cStd = Math.sqrt(aStd * aStd + bStd * bStd);\n\n\t\tlet lSmp = LabSmp.l;\n\t\tlet aSmp = LabSmp.a;\n\t\tlet bSmp = LabSmp.b;\n\t\tlet cSmp = Math.sqrt(aSmp * aSmp + bSmp * bSmp);\n\n\t\tlet dL2 = Math.pow(lStd - lSmp, 2);\n\t\tlet dC2 = Math.pow(cStd - cSmp, 2);\n\t\tlet dH2 = Math.pow(aStd - aSmp, 2) + Math.pow(bStd - bSmp, 2) - dC2;\n\n\t\treturn Math.sqrt(\n\t\t\tdL2 / Math.pow(kL, 2) +\n\t\t\t\tdC2 / Math.pow(1 + K1 * cStd, 2) +\n\t\t\t\tdH2 / Math.pow(1 + K2 * cStd, 2)\n\t\t);\n\t};\n};\n\n/*\n\tCIEDE2000 color difference, original Matlab implementation by Gaurav Sharma\n\tBased on \"The CIEDE2000 Color-Difference Formula: Implementation Notes, Supplementary Test Data, and Mathematical Observations\" \n\tby Gaurav Sharma, Wencheng Wu, Edul N. Dalal in Color Research and Application, vol. 30. No. 1, pp. 21-30, February 2005.\n\thttp://www2.ece.rochester.edu/~gsharma/ciede2000/\n */\n\nconst differenceCiede2000 = (Kl = 1, Kc = 1, Kh = 1) => {\n\tlet lab = converter('lab65');\n\treturn (std, smp) => {\n\t\tlet LabStd = lab(std);\n\t\tlet LabSmp = lab(smp);\n\n\t\tlet lStd = LabStd.l;\n\t\tlet aStd = LabStd.a;\n\t\tlet bStd = LabStd.b;\n\t\tlet cStd = Math.sqrt(aStd * aStd + bStd * bStd);\n\n\t\tlet lSmp = LabSmp.l;\n\t\tlet aSmp = LabSmp.a;\n\t\tlet bSmp = LabSmp.b;\n\t\tlet cSmp = Math.sqrt(aSmp * aSmp + bSmp * bSmp);\n\n\t\tlet cAvg = (cStd + cSmp) / 2;\n\n\t\tlet G =\n\t\t\t0.5 *\n\t\t\t(1 -\n\t\t\t\tMath.sqrt(\n\t\t\t\t\tMath.pow(cAvg, 7) / (Math.pow(cAvg, 7) + Math.pow(25, 7))\n\t\t\t\t));\n\n\t\tlet apStd = aStd * (1 + G);\n\t\tlet apSmp = aSmp * (1 + G);\n\n\t\tlet cpStd = Math.sqrt(apStd * apStd + bStd * bStd);\n\t\tlet cpSmp = Math.sqrt(apSmp * apSmp + bSmp * bSmp);\n\n\t\tlet hpStd =\n\t\t\tMath.abs(apStd) + Math.abs(bStd) === 0\n\t\t\t\t? 0\n\t\t\t\t: Math.atan2(bStd, apStd);\n\t\thpStd += (hpStd < 0) * 2 * Math.PI;\n\n\t\tlet hpSmp =\n\t\t\tMath.abs(apSmp) + Math.abs(bSmp) === 0\n\t\t\t\t? 0\n\t\t\t\t: Math.atan2(bSmp, apSmp);\n\t\thpSmp += (hpSmp < 0) * 2 * Math.PI;\n\n\t\tlet dL = lSmp - lStd;\n\t\tlet dC = cpSmp - cpStd;\n\n\t\tlet dhp = cpStd * cpSmp === 0 ? 0 : hpSmp - hpStd;\n\t\tdhp -= (dhp > Math.PI) * 2 * Math.PI;\n\t\tdhp += (dhp < -Math.PI) * 2 * Math.PI;\n\n\t\tlet dH = 2 * Math.sqrt(cpStd * cpSmp) * Math.sin(dhp / 2);\n\n\t\tlet Lp = (lStd + lSmp) / 2;\n\t\tlet Cp = (cpStd + cpSmp) / 2;\n\n\t\tlet hp;\n\t\tif (cpStd * cpSmp === 0) {\n\t\t\thp = hpStd + hpSmp;\n\t\t} else {\n\t\t\thp = (hpStd + hpSmp) / 2;\n\t\t\thp -= (Math.abs(hpStd - hpSmp) > Math.PI) * Math.PI;\n\t\t\thp += (hp < 0) * 2 * Math.PI;\n\t\t}\n\n\t\tlet Lpm50 = Math.pow(Lp - 50, 2);\n\t\tlet T =\n\t\t\t1 -\n\t\t\t0.17 * Math.cos(hp - Math.PI / 6) +\n\t\t\t0.24 * Math.cos(2 * hp) +\n\t\t\t0.32 * Math.cos(3 * hp + Math.PI / 30) -\n\t\t\t0.2 * Math.cos(4 * hp - (63 * Math.PI) / 180);\n\n\t\tlet Sl = 1 + (0.015 * Lpm50) / Math.sqrt(20 + Lpm50);\n\t\tlet Sc = 1 + 0.045 * Cp;\n\t\tlet Sh = 1 + 0.015 * Cp * T;\n\n\t\tlet deltaTheta =\n\t\t\t((30 * Math.PI) / 180) *\n\t\t\tMath.exp(-1 * Math.pow(((180 / Math.PI) * hp - 275) / 25, 2));\n\t\tlet Rc =\n\t\t\t2 *\n\t\t\tMath.sqrt(Math.pow(Cp, 7) / (Math.pow(Cp, 7) + Math.pow(25, 7)));\n\n\t\tlet Rt = -1 * Math.sin(2 * deltaTheta) * Rc;\n\n\t\treturn Math.sqrt(\n\t\t\tMath.pow(dL / (Kl * Sl), 2) +\n\t\t\t\tMath.pow(dC / (Kc * Sc), 2) +\n\t\t\t\tMath.pow(dH / (Kh * Sh), 2) +\n\t\t\t\t(((Rt * dC) / (Kc * Sc)) * dH) / (Kh * Sh)\n\t\t);\n\t};\n};\n\n/*\n\tCMC (l:c) difference formula\n\n\tReferences:\n\t\thttps://en.wikipedia.org/wiki/Color_difference#CMC_l:c_(1984)\n\t\thttp://www.brucelindbloom.com/index.html?Eqn_DeltaE_CMC.html\n */\nconst differenceCmc = (l = 1, c = 1) => {\n\tlet lab = converter('lab65');\n\n\t/*\n\t\tComparte two colors:\n\t\tstd - standard (first) color\n\t\tsmp - sample (second) color\n\t */\n\treturn (std, smp) => {\n\t\t// convert standard color to Lab\n\t\tlet LabStd = lab(std);\n\t\tlet lStd = LabStd.l;\n\t\tlet aStd = LabStd.a;\n\t\tlet bStd = LabStd.b;\n\n\t\t// Obtain hue/chroma\n\t\tlet cStd = Math.sqrt(aStd * aStd + bStd * bStd);\n\t\tlet hStd = Math.atan2(bStd, aStd);\n\t\thStd = hStd + 2 * Math.PI * (hStd < 0);\n\n\t\t// convert sample color to Lab, obtain LCh\n\t\tlet LabSmp = lab(smp);\n\t\tlet lSmp = LabSmp.l;\n\t\tlet aSmp = LabSmp.a;\n\t\tlet bSmp = LabSmp.b;\n\n\t\t// Obtain chroma\n\t\tlet cSmp = Math.sqrt(aSmp * aSmp + bSmp * bSmp);\n\n\t\t// lightness delta squared\n\t\tlet dL2 = Math.pow(lStd - lSmp, 2);\n\n\t\t// chroma delta squared\n\t\tlet dC2 = Math.pow(cStd - cSmp, 2);\n\n\t\t// hue delta squared\n\t\tlet dH2 = Math.pow(aStd - aSmp, 2) + Math.pow(bStd - bSmp, 2) - dC2;\n\n\t\tlet F = Math.sqrt(Math.pow(cStd, 4) / (Math.pow(cStd, 4) + 1900));\n\t\tlet T =\n\t\t\thStd >= (164 / 180) * Math.PI && hStd <= (345 / 180) * Math.PI\n\t\t\t\t? 0.56 + Math.abs(0.2 * Math.cos(hStd + (168 / 180) * Math.PI))\n\t\t\t\t: 0.36 + Math.abs(0.4 * Math.cos(hStd + (35 / 180) * Math.PI));\n\n\t\tlet Sl = lStd < 16 ? 0.511 : (0.040975 * lStd) / (1 + 0.01765 * lStd);\n\t\tlet Sc = (0.0638 * cStd) / (1 + 0.0131 * cStd) + 0.638;\n\t\tlet Sh = Sc * (F * T + 1 - F);\n\n\t\treturn Math.sqrt(\n\t\t\tdL2 / Math.pow(l * Sl, 2) +\n\t\t\t\tdC2 / Math.pow(c * Sc, 2) +\n\t\t\t\tdH2 / Math.pow(Sh, 2)\n\t\t);\n\t};\n};\n\n/*\n\n\tHyAB color difference formula, introduced in:\n\n\t\tAbasi S, Amani Tehran M, Fairchild MD. \n\t\t\"Distance metrics for very large color differences.\"\n\t\tColor Res Appl. 2019; 1–16. \n\t\thttps://doi.org/10.1002/col.22451\n\n\tPDF available at:\n\t\n\t\thttp://markfairchild.org/PDFs/PAP40.pdf\n */\nconst differenceHyab = () => {\n\tlet lab = converter('lab65');\n\treturn (std, smp) => {\n\t\tlet LabStd = lab(std);\n\t\tlet LabSmp = lab(smp);\n\t\tlet dL = LabStd.l - LabSmp.l;\n\t\tlet dA = LabStd.a - LabSmp.a;\n\t\tlet dB = LabStd.b - LabSmp.b;\n\t\treturn Math.abs(dL) + Math.sqrt(dA * dA + dB * dB);\n\t};\n};\n\n/*\n\t\"Measuring perceived color difference using YIQ NTSC\n\ttransmission color space in mobile applications\"\n\t\t\n\t\tby Yuriy Kotsarenko, Fernando Ramos in:\n\t\tProgramación Matemática y Software (2010) \n\n\tAvailable at:\n\t\t\n\t\thttp://www.progmat.uaem.mx:8080/artVol2Num2/Articulo3Vol2Num2.pdf\n */\nconst differenceKotsarenkoRamos = () =>\n\tdifferenceEuclidean('yiq', [0.5053, 0.299, 0.1957]);\n\n/*\n\tΔE_ITP, as defined in Rec. ITU-R BT.2124:\n\n\thttps://www.itu.int/rec/R-REC-BT.2124/en\n*/\nconst differenceItp = () =>\n\tdifferenceEuclidean('itp', [518400, 129600, 518400]);\n\nexport {\n\tdifferenceHueChroma,\n\tdifferenceHueSaturation,\n\tdifferenceHueNaive,\n\tdifferenceEuclidean,\n\tdifferenceCie76,\n\tdifferenceCie94,\n\tdifferenceCiede2000,\n\tdifferenceCmc,\n\tdifferenceHyab,\n\tdifferenceKotsarenkoRamos,\n\tdifferenceItp\n};\n","import converter from './converter.js';\nimport { getMode } from './modes.js';\n\nconst averageAngle = val => {\n\t// See: https://en.wikipedia.org/wiki/Mean_of_circular_quantities\n\tlet sum = val.reduce(\n\t\t(sum, val) => {\n\t\t\tif (val !== undefined) {\n\t\t\t\tlet rad = (val * Math.PI) / 180;\n\t\t\t\tsum.sin += Math.sin(rad);\n\t\t\t\tsum.cos += Math.cos(rad);\n\t\t\t}\n\t\t\treturn sum;\n\t\t},\n\t\t{ sin: 0, cos: 0 }\n\t);\n\tlet angle = (Math.atan2(sum.sin, sum.cos) * 180) / Math.PI;\n\treturn angle < 0 ? 360 + angle : angle;\n};\n\nconst averageNumber = val => {\n\tlet a = val.filter(v => v !== undefined);\n\treturn a.length ? a.reduce((sum, v) => sum + v, 0) / a.length : undefined;\n};\n\nconst isfn = o => typeof o === 'function';\n\nfunction average(colors, mode = 'rgb', overrides) {\n\tlet def = getMode(mode);\n\tlet cc = colors.map(converter(mode));\n\treturn def.channels.reduce(\n\t\t(res, ch) => {\n\t\t\tlet arr = cc.map(c => c[ch]).filter(val => val !== undefined);\n\t\t\tif (arr.length) {\n\t\t\t\tlet fn;\n\t\t\t\tif (isfn(overrides)) {\n\t\t\t\t\tfn = overrides;\n\t\t\t\t} else if (overrides && isfn(overrides[ch])) {\n\t\t\t\t\tfn = overrides[ch];\n\t\t\t\t} else if (def.average && isfn(def.average[ch])) {\n\t\t\t\t\tfn = def.average[ch];\n\t\t\t\t} else {\n\t\t\t\t\tfn = averageNumber;\n\t\t\t\t}\n\t\t\t\tres[ch] = fn(arr, ch);\n\t\t\t}\n\t\t\treturn res;\n\t\t},\n\t\t{ mode }\n\t);\n}\n\nexport { average, averageAngle, averageNumber };\n","/* \n\tDave Green's Cubehelix\n\t----------------------\n\n\tGreen, D. A., 2011, \"A colour scheme for the display of astronomical intensity images\", \n\tBulletin of the Astronomical Society of India, 39, 289. (2011BASI...39..289G at ADS.) \n\n\thttps://www.mrao.cam.ac.uk/%7Edag/CUBEHELIX/\n\thttps://arxiv.org/pdf/1108.5083.pdf\n\n\tAlthough Cubehelix was defined to be a method to obtain a colour scheme,\n\tit actually contains a definition of a colour space, as identified by \n\tMike Bostock and implemented in D3.js.\n\n\tGreen's paper introduces the following terminology:\n\n\t* \ta `lightness` dimension in the interval [0, 1] \n\t\ton which we interpolate to obtain the colour scheme\n\t*\ta `start` colour that is analogous to a Hue in HSL space\n\t*\ta number of `rotations` around the Hue cylinder.\n\t*\ta `hue` parameter which should more appropriately be called `saturation`\n\t\n\tAs such, the original definition of the Cubehelix scheme is actually an\n\tinterpolation between two colors in the Cubehelix space:\n\n\tH: start \t\t\t\tH: start + 360 * rotations\n\tS: hue \t\t\t->\t\tS: hue\n\tL: 0\t\t\t\t\tL: 1\n\n\tWe can therefore extend the interpolation to any two colors in this space,\n\twith a variable Saturation and a Lightness interval other than the fixed 0 -> 1.\n*/\n\nimport { fixupHueShorter } from '../fixup/hue.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport convertRgbToCubehelix from './convertRgbToCubehelix.js';\nimport convertCubehelixToRgb from './convertCubehelixToRgb.js';\nimport { differenceHueSaturation } from '../difference.js';\nimport { averageAngle } from '../average.js';\n\nconst definition = {\n\tmode: 'cubehelix',\n\tchannels: ['h', 's', 'l', 'alpha'],\n\tparse: ['--cubehelix'],\n\tserialize: '--cubehelix',\n\n\tranges: {\n\t\th: [0, 360],\n\t\ts: [0, 4.614],\n\t\tl: [0, 1]\n\t},\n\n\tfromMode: {\n\t\trgb: convertRgbToCubehelix\n\t},\n\n\ttoMode: {\n\t\trgb: convertCubehelixToRgb\n\t},\n\n\tinterpolate: {\n\t\th: {\n\t\t\tuse: interpolatorLinear,\n\t\t\tfixup: fixupHueShorter\n\t\t},\n\t\ts: interpolatorLinear,\n\t\tl: interpolatorLinear,\n\t\talpha: {\n\t\t\tuse: interpolatorLinear,\n\t\t\tfixup: fixupAlpha\n\t\t}\n\t},\n\n\tdifference: {\n\t\th: differenceHueSaturation\n\t},\n\n\taverage: {\n\t\th: averageAngle\n\t}\n};\n\nexport default definition;\n","import normalizeHue from '../util/normalizeHue.js';\n\n/* \n\tReferences: \n\t\t* https://drafts.csswg.org/css-color/#lab-to-lch\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n*/\nconst convertLabToLch = ({ l, a, b, alpha }, mode = 'lch') => {\n\tif (a === undefined) a = 0;\n\tif (b === undefined) b = 0;\n\tlet c = Math.sqrt(a * a + b * b);\n\tlet res = { mode, l, c };\n\tif (c) res.h = normalizeHue((Math.atan2(b, a) * 180) / Math.PI);\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertLabToLch;\n","/* \n\tReferences: \n\t\t* https://drafts.csswg.org/css-color/#lch-to-lab\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n*/\nconst convertLchToLab = ({ l, c, h, alpha }, mode = 'lab') => {\n\tif (h === undefined) h = 0;\n\tlet res = {\n\t\tmode,\n\t\tl,\n\t\ta: c ? c * Math.cos((h / 180) * Math.PI) : 0,\n\t\tb: c ? c * Math.sin((h / 180) * Math.PI) : 0\n\t};\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertLchToLab;\n","export const k = Math.pow(29, 3) / Math.pow(3, 3);\nexport const e = Math.pow(6, 3) / Math.pow(29, 3);\n","/*\n\tThe XYZ tristimulus values (white point)\n\tof standard illuminants for the CIE 1931 2° \n\tstandard observer.\n\n\tSee: https://en.wikipedia.org/wiki/Standard_illuminant\n */\n\nexport const D50 = {\n\tX: 0.3457 / 0.3585,\n\tY: 1,\n\tZ: (1 - 0.3457 - 0.3585) / 0.3585\n};\n\nexport const D65 = {\n\tX: 0.3127 / 0.329,\n\tY: 1,\n\tZ: (1 - 0.3127 - 0.329) / 0.329\n};\n\nexport const k = Math.pow(29, 3) / Math.pow(3, 3);\nexport const e = Math.pow(6, 3) / Math.pow(29, 3);\n","import { k, e } from '../xyz65/constants.js';\nimport { D65 } from '../constants.js';\n\nlet fn = v => (Math.pow(v, 3) > e ? Math.pow(v, 3) : (116 * v - 16) / k);\n\nconst convertLab65ToXyz65 = ({ l, a, b, alpha }) => {\n\tif (l === undefined) l = 0;\n\tif (a === undefined) a = 0;\n\tif (b === undefined) b = 0;\n\n\tlet fy = (l + 16) / 116;\n\tlet fx = a / 500 + fy;\n\tlet fz = fy - b / 200;\n\n\tlet res = {\n\t\tmode: 'xyz65',\n\t\tx: fn(fx) * D65.X,\n\t\ty: fn(fy) * D65.Y,\n\t\tz: fn(fz) * D65.Z\n\t};\n\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertLab65ToXyz65;\n","import convertLab65ToXyz65 from './convertLab65ToXyz65.js';\nimport convertXyz65ToRgb from '../xyz65/convertXyz65ToRgb.js';\n\nconst convertLab65ToRgb = lab => convertXyz65ToRgb(convertLab65ToXyz65(lab));\n\nexport default convertLab65ToRgb;\n","import { k, e } from '../xyz65/constants.js';\nimport { D65 } from '../constants.js';\n\nconst f = value => (value > e ? Math.cbrt(value) : (k * value + 16) / 116);\n\nconst convertXyz65ToLab65 = ({ x, y, z, alpha }) => {\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet f0 = f(x / D65.X);\n\tlet f1 = f(y / D65.Y);\n\tlet f2 = f(z / D65.Z);\n\n\tlet res = {\n\t\tmode: 'lab65',\n\t\tl: 116 * f1 - 16,\n\t\ta: 500 * (f0 - f1),\n\t\tb: 200 * (f1 - f2)\n\t};\n\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertXyz65ToLab65;\n","import convertRgbToXyz65 from '../xyz65/convertRgbToXyz65.js';\nimport convertXyz65ToLab65 from './convertXyz65ToLab65.js';\n\nconst convertRgbToLab65 = rgb => {\n\tlet res = convertXyz65ToLab65(convertRgbToXyz65(rgb));\n\n\t// Fixes achromatic RGB colors having a _slight_ chroma due to floating-point errors\n\t// and approximated computations in sRGB <-> CIELab.\n\t// See: https://github.com/d3/d3-color/pull/46\n\tif (rgb.r === rgb.b && rgb.b === rgb.g) {\n\t\tres.a = res.b = 0;\n\t}\n\treturn res;\n};\n\nexport default convertRgbToLab65;\n","export const kE = 1;\nexport const kCH = 1;\nexport const θ = (26 / 180) * Math.PI;\nexport const cosθ = Math.cos(θ);\nexport const sinθ = Math.sin(θ);\nexport const factor = 100 / Math.log(139 / 100); // ~ 303.67\n","import { kCH, kE, sinθ, cosθ, θ, factor } from './constants.js';\n\n/*\n\tConvert DIN99o LCh to CIELab D65\n\t--------------------------------\n */\n\nconst convertDlchToLab65 = ({ l, c, h, alpha }) => {\n\tif (l === undefined) l = 0;\n\tif (c === undefined) c = 0;\n\tif (h === undefined) h = 0;\n\tlet res = {\n\t\tmode: 'lab65',\n\t\tl: (Math.exp((l * kE) / factor) - 1) / 0.0039\n\t};\n\n\tlet G = (Math.exp(0.0435 * c * kCH * kE) - 1) / 0.075;\n\tlet e = G * Math.cos((h / 180) * Math.PI - θ);\n\tlet f = G * Math.sin((h / 180) * Math.PI - θ);\n\tres.a = e * cosθ - (f / 0.83) * sinθ;\n\tres.b = e * sinθ + (f / 0.83) * cosθ;\n\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertDlchToLab65;\n","import { kCH, kE, sinθ, cosθ, θ, factor } from './constants.js';\nimport normalizeHue from '../util/normalizeHue.js';\n\n/*\n\tConvert CIELab D65 to DIN99o LCh\n\t================================\n */\n\nconst convertLab65ToDlch = ({ l, a, b, alpha }) => {\n\tif (l === undefined) l = 0;\n\tif (a === undefined) a = 0;\n\tif (b === undefined) b = 0;\n\tlet e = a * cosθ + b * sinθ;\n\tlet f = 0.83 * (b * cosθ - a * sinθ);\n\tlet G = Math.sqrt(e * e + f * f);\n\tlet res = {\n\t\tmode: 'dlch',\n\t\tl: (factor / kE) * Math.log(1 + 0.0039 * l),\n\t\tc: Math.log(1 + 0.075 * G) / (0.0435 * kCH * kE)\n\t};\n\n\tif (res.c) {\n\t\tres.h = normalizeHue(((Math.atan2(f, e) + θ) / Math.PI) * 180);\n\t}\n\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertLab65ToDlch;\n","import convertLabToLch from '../lch/convertLabToLch.js';\nimport convertLchToLab from '../lch/convertLchToLab.js';\nimport convertLab65ToRgb from '../lab65/convertLab65ToRgb.js';\nimport convertRgbToLab65 from '../lab65/convertRgbToLab65.js';\nimport convertDlchToLab65 from '../dlch/convertDlchToLab65.js';\nimport convertLab65ToDlch from '../dlch/convertLab65ToDlch.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\n\nconst convertDlabToLab65 = c => convertDlchToLab65(convertLabToLch(c, 'dlch'));\nconst convertLab65ToDlab = c => convertLchToLab(convertLab65ToDlch(c), 'dlab');\n\nconst definition = {\n\tmode: 'dlab',\n\n\tparse: ['--din99o-lab'],\n\tserialize: '--din99o-lab',\n\n\ttoMode: {\n\t\tlab65: convertDlabToLab65,\n\t\trgb: c => convertLab65ToRgb(convertDlabToLab65(c))\n\t},\n\n\tfromMode: {\n\t\tlab65: convertLab65ToDlab,\n\t\trgb: c => convertLab65ToDlab(convertRgbToLab65(c))\n\t},\n\n\tchannels: ['l', 'a', 'b', 'alpha'],\n\n\tranges: {\n\t\tl: [0, 100],\n\t\ta: [-40.09, 45.501],\n\t\tb: [-40.469, 44.344]\n\t},\n\n\tinterpolate: {\n\t\tl: interpolatorLinear,\n\t\ta: interpolatorLinear,\n\t\tb: interpolatorLinear,\n\t\talpha: {\n\t\t\tuse: interpolatorLinear,\n\t\t\tfixup: fixupAlpha\n\t\t}\n\t}\n};\n\nexport default definition;\n","import convertLabToLch from '../lch/convertLabToLch.js';\nimport convertLchToLab from '../lch/convertLchToLab.js';\nimport convertDlchToLab65 from './convertDlchToLab65.js';\nimport convertLab65ToDlch from './convertLab65ToDlch.js';\nimport convertLab65ToRgb from '../lab65/convertLab65ToRgb.js';\nimport convertRgbToLab65 from '../lab65/convertRgbToLab65.js';\n\nimport { fixupHueShorter } from '../fixup/hue.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { differenceHueChroma } from '../difference.js';\nimport { averageAngle } from '../average.js';\n\nconst definition = {\n\tmode: 'dlch',\n\n\tparse: ['--din99o-lch'],\n\tserialize: '--din99o-lch',\n\n\ttoMode: {\n\t\tlab65: convertDlchToLab65,\n\t\tdlab: c => convertLchToLab(c, 'dlab'),\n\t\trgb: c => convertLab65ToRgb(convertDlchToLab65(c))\n\t},\n\n\tfromMode: {\n\t\tlab65: convertLab65ToDlch,\n\t\tdlab: c => convertLabToLch(c, 'dlch'),\n\t\trgb: c => convertLab65ToDlch(convertRgbToLab65(c))\n\t},\n\n\tchannels: ['l', 'c', 'h', 'alpha'],\n\n\tranges: {\n\t\tl: [0, 100],\n\t\tc: [0, 51.484],\n\t\th: [0, 360]\n\t},\n\n\tinterpolate: {\n\t\tl: interpolatorLinear,\n\t\tc: interpolatorLinear,\n\t\th: {\n\t\t\tuse: interpolatorLinear,\n\t\t\tfixup: fixupHueShorter\n\t\t},\n\t\talpha: {\n\t\t\tuse: interpolatorLinear,\n\t\t\tfixup: fixupAlpha\n\t\t}\n\t},\n\n\tdifference: {\n\t\th: differenceHueChroma\n\t},\n\n\taverage: {\n\t\th: averageAngle\n\t}\n};\n\nexport default definition;\n","import normalizeHue from '../util/normalizeHue.js';\n\n// Based on: https://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB\n\nexport default function convertHsiToRgb({ h, s, i, alpha }) {\n\th = normalizeHue(h !== undefined ? h : 0);\n\tif (s === undefined) s = 0;\n\tif (i === undefined) i = 0;\n\tlet f = Math.abs(((h / 60) % 2) - 1);\n\tlet res;\n\tswitch (Math.floor(h / 60)) {\n\t\tcase 0:\n\t\t\tres = {\n\t\t\t\tr: i * (1 + s * (3 / (2 - f) - 1)),\n\t\t\t\tg: i * (1 + s * ((3 * (1 - f)) / (2 - f) - 1)),\n\t\t\t\tb: i * (1 - s)\n\t\t\t};\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tres = {\n\t\t\t\tr: i * (1 + s * ((3 * (1 - f)) / (2 - f) - 1)),\n\t\t\t\tg: i * (1 + s * (3 / (2 - f) - 1)),\n\t\t\t\tb: i * (1 - s)\n\t\t\t};\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tres = {\n\t\t\t\tr: i * (1 - s),\n\t\t\t\tg: i * (1 + s * (3 / (2 - f) - 1)),\n\t\t\t\tb: i * (1 + s * ((3 * (1 - f)) / (2 - f) - 1))\n\t\t\t};\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tres = {\n\t\t\t\tr: i * (1 - s),\n\t\t\t\tg: i * (1 + s * ((3 * (1 - f)) / (2 - f) - 1)),\n\t\t\t\tb: i * (1 + s * (3 / (2 - f) - 1))\n\t\t\t};\n\t\t\tbreak;\n\t\tcase 4:\n\t\t\tres = {\n\t\t\t\tr: i * (1 + s * ((3 * (1 - f)) / (2 - f) - 1)),\n\t\t\t\tg: i * (1 - s),\n\t\t\t\tb: i * (1 + s * (3 / (2 - f) - 1))\n\t\t\t};\n\t\t\tbreak;\n\t\tcase 5:\n\t\t\tres = {\n\t\t\t\tr: i * (1 + s * (3 / (2 - f) - 1)),\n\t\t\t\tg: i * (1 - s),\n\t\t\t\tb: i * (1 + s * ((3 * (1 - f)) / (2 - f) - 1))\n\t\t\t};\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tres = { r: i * (1 - s), g: i * (1 - s), b: i * (1 - s) };\n\t}\n\n\tres.mode = 'rgb';\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n}\n","// Based on: https://en.wikipedia.org/wiki/HSL_and_HSV#Formal_derivation\n\nexport default function convertRgbToHsi({ r, g, b, alpha }) {\n\tif (r === undefined) r = 0;\n\tif (g === undefined) g = 0;\n\tif (b === undefined) b = 0;\n\tlet M = Math.max(r, g, b),\n\t\tm = Math.min(r, g, b);\n\tlet res = {\n\t\tmode: 'hsi',\n\t\ts: r + g + b === 0 ? 0 : 1 - (3 * m) / (r + g + b),\n\t\ti: (r + g + b) / 3\n\t};\n\tif (M - m !== 0)\n\t\tres.h =\n\t\t\t(M === r\n\t\t\t\t? (g - b) / (M - m) + (g < b) * 6\n\t\t\t\t: M === g\n\t\t\t\t? (b - r) / (M - m) + 2\n\t\t\t\t: (r - g) / (M - m) + 4) * 60;\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n}\n","import convertHsiToRgb from './convertHsiToRgb.js';\nimport convertRgbToHsi from './convertRgbToHsi.js';\nimport { fixupHueShorter } from '../fixup/hue.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { differenceHueSaturation } from '../difference.js';\nimport { averageAngle } from '../average.js';\n\nconst definition = {\n\tmode: 'hsi',\n\n\ttoMode: {\n\t\trgb: convertHsiToRgb\n\t},\n\n\tparse: ['--hsi'],\n\tserialize: '--hsi',\n\n\tfromMode: {\n\t\trgb: convertRgbToHsi\n\t},\n\n\tchannels: ['h', 's', 'i', 'alpha'],\n\n\tranges: {\n\t\th: [0, 360]\n\t},\n\n\tgamut: 'rgb',\n\n\tinterpolate: {\n\t\th: { use: interpolatorLinear, fixup: fixupHueShorter },\n\t\ts: interpolatorLinear,\n\t\ti: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t},\n\n\tdifference: {\n\t\th: differenceHueSaturation\n\t},\n\n\taverage: {\n\t\th: averageAngle\n\t}\n};\n\nexport default definition;\n","import normalizeHue from '../util/normalizeHue.js';\n// Based on: https://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB\n\nexport default function convertHslToRgb({ h, s, l, alpha }) {\n\th = normalizeHue(h !== undefined ? h : 0);\n\tif (s === undefined) s = 0;\n\tif (l === undefined) l = 0;\n\tlet m1 = l + s * (l < 0.5 ? l : 1 - l);\n\tlet m2 = m1 - (m1 - l) * 2 * Math.abs(((h / 60) % 2) - 1);\n\tlet res;\n\tswitch (Math.floor(h / 60)) {\n\t\tcase 0:\n\t\t\tres = { r: m1, g: m2, b: 2 * l - m1 };\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tres = { r: m2, g: m1, b: 2 * l - m1 };\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tres = { r: 2 * l - m1, g: m1, b: m2 };\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tres = { r: 2 * l - m1, g: m2, b: m1 };\n\t\t\tbreak;\n\t\tcase 4:\n\t\t\tres = { r: m2, g: 2 * l - m1, b: m1 };\n\t\t\tbreak;\n\t\tcase 5:\n\t\t\tres = { r: m1, g: 2 * l - m1, b: m2 };\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tres = { r: 2 * l - m1, g: 2 * l - m1, b: 2 * l - m1 };\n\t}\n\tres.mode = 'rgb';\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n}\n","// Based on: https://en.wikipedia.org/wiki/HSL_and_HSV#Formal_derivation\n\nexport default function convertRgbToHsl({ r, g, b, alpha }) {\n\tif (r === undefined) r = 0;\n\tif (g === undefined) g = 0;\n\tif (b === undefined) b = 0;\n\tlet M = Math.max(r, g, b),\n\t\tm = Math.min(r, g, b);\n\tlet res = {\n\t\tmode: 'hsl',\n\t\ts: M === m ? 0 : (M - m) / (1 - Math.abs(M + m - 1)),\n\t\tl: 0.5 * (M + m)\n\t};\n\tif (M - m !== 0)\n\t\tres.h =\n\t\t\t(M === r\n\t\t\t\t? (g - b) / (M - m) + (g < b) * 6\n\t\t\t\t: M === g\n\t\t\t\t? (b - r) / (M - m) + 2\n\t\t\t\t: (r - g) / (M - m) + 4) * 60;\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n}\n","const hueToDeg = (val, unit) => {\n\tswitch (unit) {\n\t\tcase 'deg':\n\t\t\treturn +val;\n\t\tcase 'rad':\n\t\t\treturn (val / Math.PI) * 180;\n\t\tcase 'grad':\n\t\t\treturn (val / 10) * 9;\n\t\tcase 'turn':\n\t\t\treturn val * 360;\n\t}\n};\n\nexport default hueToDeg;\n","import hueToDeg from '../util/hue.js';\nimport { hue, per, num_per, c } from '../util/regex.js';\n\n/*\n\thsl() regular expressions for legacy format\n\tReference: https://drafts.csswg.org/css-color/#the-hsl-notation\n */\nconst hsl_old = new RegExp(\n\t`^hsla?\\\\(\\\\s*${hue}${c}${per}${c}${per}\\\\s*(?:,\\\\s*${num_per}\\\\s*)?\\\\)$`\n);\n\nconst parseHslLegacy = color => {\n\tlet match = color.match(hsl_old);\n\tif (!match) return;\n\tlet res = { mode: 'hsl' };\n\n\tif (match[3] !== undefined) {\n\t\tres.h = +match[3];\n\t} else if (match[1] !== undefined && match[2] !== undefined) {\n\t\tres.h = hueToDeg(match[1], match[2]);\n\t}\n\n\tif (match[4] !== undefined) {\n\t\tres.s = Math.min(Math.max(0, match[4] / 100), 1);\n\t}\n\n\tif (match[5] !== undefined) {\n\t\tres.l = Math.min(Math.max(0, match[5] / 100), 1);\n\t}\n\n\tif (match[6] !== undefined) {\n\t\tres.alpha = Math.max(0, Math.min(1, match[6] / 100));\n\t} else if (match[7] !== undefined) {\n\t\tres.alpha = Math.max(0, Math.min(1, +match[7]));\n\t}\n\treturn res;\n};\n\nexport default parseHslLegacy;\n","import { Tok } from '../parse.js';\n\nfunction parseHsl(color, parsed) {\n\tif (!parsed || (parsed[0] !== 'hsl' && parsed[0] !== 'hsla')) {\n\t\treturn undefined;\n\t}\n\tconst res = { mode: 'hsl' };\n\tconst [, h, s, l, alpha] = parsed;\n\n\tif (h.type !== Tok.None) {\n\t\tif (h.type === Tok.Percentage) {\n\t\t\treturn undefined;\n\t\t}\n\t\tres.h = h.value;\n\t}\n\n\tif (s.type !== Tok.None) {\n\t\tif (s.type === Tok.Hue) {\n\t\t\treturn undefined;\n\t\t}\n\t\tres.s = s.value / 100;\n\t}\n\n\tif (l.type !== Tok.None) {\n\t\tif (l.type === Tok.Hue) {\n\t\t\treturn undefined;\n\t\t}\n\t\tres.l = l.value / 100;\n\t}\n\n\tif (alpha.type !== Tok.None) {\n\t\tres.alpha = Math.min(\n\t\t\t1,\n\t\t\tMath.max(\n\t\t\t\t0,\n\t\t\t\talpha.type === Tok.Number ? alpha.value : alpha.value / 100\n\t\t\t)\n\t\t);\n\t}\n\n\treturn res;\n}\n\nexport default parseHsl;\n","import convertHslToRgb from './convertHslToRgb.js';\nimport convertRgbToHsl from './convertRgbToHsl.js';\nimport parseHslLegacy from './parseHslLegacy.js';\nimport parseHsl from './parseHsl.js';\nimport { fixupHueShorter } from '../fixup/hue.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { differenceHueSaturation } from '../difference.js';\nimport { averageAngle } from '../average.js';\n\nconst definition = {\n\tmode: 'hsl',\n\n\ttoMode: {\n\t\trgb: convertHslToRgb\n\t},\n\n\tfromMode: {\n\t\trgb: convertRgbToHsl\n\t},\n\n\tchannels: ['h', 's', 'l', 'alpha'],\n\n\tranges: {\n\t\th: [0, 360]\n\t},\n\n\tgamut: 'rgb',\n\n\tparse: [parseHsl, parseHslLegacy],\n\tserialize: c =>\n\t\t`hsl(${c.h !== undefined ? c.h : 'none'} ${\n\t\t\tc.s !== undefined ? c.s * 100 + '%' : 'none'\n\t\t} ${c.l !== undefined ? c.l * 100 + '%' : 'none'}${\n\t\t\tc.alpha < 1 ? ` / ${c.alpha}` : ''\n\t\t})`,\n\n\tinterpolate: {\n\t\th: { use: interpolatorLinear, fixup: fixupHueShorter },\n\t\ts: interpolatorLinear,\n\t\tl: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t},\n\n\tdifference: {\n\t\th: differenceHueSaturation\n\t},\n\n\taverage: {\n\t\th: averageAngle\n\t}\n};\n\nexport default definition;\n","import normalizeHue from '../util/normalizeHue.js';\n\n// Based on: https://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB\n\nexport default function convertHsvToRgb({ h, s, v, alpha }) {\n\th = normalizeHue(h !== undefined ? h : 0);\n\tif (s === undefined) s = 0;\n\tif (v === undefined) v = 0;\n\tlet f = Math.abs(((h / 60) % 2) - 1);\n\tlet res;\n\tswitch (Math.floor(h / 60)) {\n\t\tcase 0:\n\t\t\tres = { r: v, g: v * (1 - s * f), b: v * (1 - s) };\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tres = { r: v * (1 - s * f), g: v, b: v * (1 - s) };\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tres = { r: v * (1 - s), g: v, b: v * (1 - s * f) };\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tres = { r: v * (1 - s), g: v * (1 - s * f), b: v };\n\t\t\tbreak;\n\t\tcase 4:\n\t\t\tres = { r: v * (1 - s * f), g: v * (1 - s), b: v };\n\t\t\tbreak;\n\t\tcase 5:\n\t\t\tres = { r: v, g: v * (1 - s), b: v * (1 - s * f) };\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tres = { r: v * (1 - s), g: v * (1 - s), b: v * (1 - s) };\n\t}\n\tres.mode = 'rgb';\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n}\n","// Based on: https://en.wikipedia.org/wiki/HSL_and_HSV#Formal_derivation\n\nexport default function convertRgbToHsv({ r, g, b, alpha }) {\n\tif (r === undefined) r = 0;\n\tif (g === undefined) g = 0;\n\tif (b === undefined) b = 0;\n\tlet M = Math.max(r, g, b),\n\t\tm = Math.min(r, g, b);\n\tlet res = {\n\t\tmode: 'hsv',\n\t\ts: M === 0 ? 0 : 1 - m / M,\n\t\tv: M\n\t};\n\tif (M - m !== 0)\n\t\tres.h =\n\t\t\t(M === r\n\t\t\t\t? (g - b) / (M - m) + (g < b) * 6\n\t\t\t\t: M === g\n\t\t\t\t? (b - r) / (M - m) + 2\n\t\t\t\t: (r - g) / (M - m) + 4) * 60;\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n}\n","import convertHsvToRgb from './convertHsvToRgb.js';\nimport convertRgbToHsv from './convertRgbToHsv.js';\nimport { fixupHueShorter } from '../fixup/hue.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { differenceHueSaturation } from '../difference.js';\nimport { averageAngle } from '../average.js';\n\nconst definition = {\n\tmode: 'hsv',\n\n\ttoMode: {\n\t\trgb: convertHsvToRgb\n\t},\n\n\tparse: ['--hsv'],\n\tserialize: '--hsv',\n\n\tfromMode: {\n\t\trgb: convertRgbToHsv\n\t},\n\n\tchannels: ['h', 's', 'v', 'alpha'],\n\n\tranges: {\n\t\th: [0, 360]\n\t},\n\n\tgamut: 'rgb',\n\n\tinterpolate: {\n\t\th: { use: interpolatorLinear, fixup: fixupHueShorter },\n\t\ts: interpolatorLinear,\n\t\tv: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t},\n\n\tdifference: {\n\t\th: differenceHueSaturation\n\t},\n\n\taverage: {\n\t\th: averageAngle\n\t}\n};\n\nexport default definition;\n","/*\n\tHWB to RGB converter\n\t--------------------\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#hwb-to-rgb\n\t\t* https://en.wikipedia.org/wiki/HWB_color_model\n\t\t* http://alvyray.com/Papers/CG/HWB_JGTv208.pdf\n */\n\nimport convertHsvToRgb from '../hsv/convertHsvToRgb.js';\n\nexport default function convertHwbToRgb({ h, w, b, alpha }) {\n\tif (w === undefined) w = 0;\n\tif (b === undefined) b = 0;\n\t// normalize w + b to 1\n\tif (w + b > 1) {\n\t\tlet s = w + b;\n\t\tw /= s;\n\t\tb /= s;\n\t}\n\treturn convertHsvToRgb({\n\t\th: h,\n\t\ts: b === 1 ? 1 : 1 - w / (1 - b),\n\t\tv: 1 - b,\n\t\talpha: alpha\n\t});\n}\n","/*\n\tRGB to HWB converter\n\t--------------------\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#hwb-to-rgb\n\t\t* https://en.wikipedia.org/wiki/HWB_color_model\n\t\t* http://alvyray.com/Papers/CG/HWB_JGTv208.pdf\n */\n\nimport convertRgbToHsv from '../hsv/convertRgbToHsv.js';\n\nexport default function convertRgbToHwb(rgba) {\n\tlet hsv = convertRgbToHsv(rgba);\n\tif (hsv === undefined) return undefined;\n\tlet s = hsv.s !== undefined ? hsv.s : 0;\n\tlet v = hsv.v !== undefined ? hsv.v : 0;\n\tlet res = {\n\t\tmode: 'hwb',\n\t\tw: (1 - s) * v,\n\t\tb: 1 - v\n\t};\n\tif (hsv.h !== undefined) res.h = hsv.h;\n\tif (hsv.alpha !== undefined) res.alpha = hsv.alpha;\n\treturn res;\n}\n","import { Tok } from '../parse.js';\n\nfunction ParseHwb(color, parsed) {\n\tif (!parsed || parsed[0] !== 'hwb') {\n\t\treturn undefined;\n\t}\n\tconst res = { mode: 'hwb' };\n\tconst [, h, w, b, alpha] = parsed;\n\n\tif (h.type !== Tok.None) {\n\t\tif (h.type === Tok.Percentage) {\n\t\t\treturn undefined;\n\t\t}\n\t\tres.h = h.value;\n\t}\n\n\tif (w.type !== Tok.None) {\n\t\tif (w.type === Tok.Hue) {\n\t\t\treturn undefined;\n\t\t}\n\t\tres.w = w.value / 100;\n\t}\n\n\tif (b.type !== Tok.None) {\n\t\tif (b.type === Tok.Hue) {\n\t\t\treturn undefined;\n\t\t}\n\t\tres.b = b.value / 100;\n\t}\n\n\tif (alpha.type !== Tok.None) {\n\t\tres.alpha = Math.min(\n\t\t\t1,\n\t\t\tMath.max(\n\t\t\t\t0,\n\t\t\t\talpha.type === Tok.Number ? alpha.value : alpha.value / 100\n\t\t\t)\n\t\t);\n\t}\n\n\treturn res;\n}\n\nexport default ParseHwb;\n","import convertHwbToRgb from './convertHwbToRgb.js';\nimport convertRgbToHwb from './convertRgbToHwb.js';\nimport parseHwb from './parseHwb.js';\nimport { fixupHueShorter } from '../fixup/hue.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { differenceHueNaive } from '../difference.js';\nimport { averageAngle } from '../average.js';\n\nconst definition = {\n\tmode: 'hwb',\n\n\ttoMode: {\n\t\trgb: convertHwbToRgb\n\t},\n\n\tfromMode: {\n\t\trgb: convertRgbToHwb\n\t},\n\n\tchannels: ['h', 'w', 'b', 'alpha'],\n\n\tranges: {\n\t\th: [0, 360]\n\t},\n\n\tgamut: 'rgb',\n\n\tparse: [parseHwb],\n\tserialize: c =>\n\t\t`hwb(${c.h !== undefined ? c.h : 'none'} ${\n\t\t\tc.w !== undefined ? c.w * 100 + '%' : 'none'\n\t\t} ${c.b !== undefined ? c.b * 100 + '%' : 'none'}${\n\t\t\tc.alpha < 1 ? ` / ${c.alpha}` : ''\n\t\t})`,\n\n\tinterpolate: {\n\t\th: { use: interpolatorLinear, fixup: fixupHueShorter },\n\t\tw: interpolatorLinear,\n\t\tb: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t},\n\n\tdifference: {\n\t\th: differenceHueNaive\n\t},\n\n\taverage: {\n\t\th: averageAngle\n\t}\n};\n\nexport default definition;\n","/*\n\tRelative XYZ has Y=1 for media white,\n\tBT.2048 says media white Y=203 (at PQ 58).\n\tSee: https://www.itu.int/dms_pub/itu-r/opb/rep/R-REP-BT.2408-3-2019-PDF-E.pdf\n*/\nexport const YW = 203;\n","/*\n\thttps://en.wikipedia.org/wiki/Transfer_functions_in_imaging\n*/\n\nexport const M1 = 0.1593017578125;\nexport const M2 = 78.84375;\nexport const C1 = 0.8359375;\nexport const C2 = 18.8515625;\nexport const C3 = 18.6875;\n\n/*\n\tPerceptual Quantizer, as defined in Rec. BT 2100-2 (2018)\n\n\t* https://www.itu.int/rec/R-REC-BT.2100-2-201807-I/en\n\t* https://en.wikipedia.org/wiki/Perceptual_quantizer\n*/\n\n/* PQ EOTF, defined for `v` in [0,1]. */\nexport function transferPqDecode(v) {\n\tif (v < 0) return 0;\n\tconst c = Math.pow(v, 1 / M2);\n\treturn 1e4 * Math.pow(Math.max(0, c - C1) / (C2 - C3 * c), 1 / M1);\n}\n\n/* PQ EOTF^-1, defined for `v` in [0, 1e4]. */\nexport function transferPqEncode(v) {\n\tif (v < 0) return 0;\n\tconst c = Math.pow(v / 1e4, M1);\n\treturn Math.pow((C1 + C2 * c) / (1 + C3 * c), M2);\n}\n","import { YW } from '../hdr/constants.js';\nimport { transferPqDecode } from '../hdr/transfer.js';\n\nconst toRel = c => Math.max(c / YW, 0);\n\nconst convertItpToXyz65 = ({ i, t, p, alpha }) => {\n\tif (i === undefined) i = 0;\n\tif (t === undefined) t = 0;\n\tif (p === undefined) p = 0;\n\n\tconst l = transferPqDecode(\n\t\ti + 0.008609037037932761 * t + 0.11102962500302593 * p\n\t);\n\tconst m = transferPqDecode(\n\t\ti - 0.00860903703793275 * t - 0.11102962500302599 * p\n\t);\n\tconst s = transferPqDecode(\n\t\ti + 0.5600313357106791 * t - 0.32062717498731885 * p\n\t);\n\n\tconst res = {\n\t\tmode: 'xyz65',\n\t\tx: toRel(\n\t\t\t2.0701522183894219 * l -\n\t\t\t\t1.3263473389671556 * m +\n\t\t\t\t0.2066510476294051 * s\n\t\t),\n\t\ty: toRel(\n\t\t\t0.3647385209748074 * l +\n\t\t\t\t0.680566024947227 * m -\n\t\t\t\t0.0453045459220346 * s\n\t\t),\n\t\tz: toRel(\n\t\t\t-0.049747207535812 * l -\n\t\t\t\t0.0492609666966138 * m +\n\t\t\t\t1.1880659249923042 * s\n\t\t)\n\t};\n\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertItpToXyz65;\n","import { YW } from '../hdr/constants.js';\nimport { transferPqEncode } from '../hdr/transfer.js';\n\nconst toAbs = (c = 0) => Math.max(c * YW, 0);\n\nconst convertXyz65ToItp = ({ x, y, z, alpha }) => {\n\tconst absX = toAbs(x);\n\tconst absY = toAbs(y);\n\tconst absZ = toAbs(z);\n\tconst l = transferPqEncode(\n\t\t0.3592832590121217 * absX +\n\t\t\t0.6976051147779502 * absY -\n\t\t\t0.0358915932320289 * absZ\n\t);\n\tconst m = transferPqEncode(\n\t\t-0.1920808463704995 * absX +\n\t\t\t1.1004767970374323 * absY +\n\t\t\t0.0753748658519118 * absZ\n\t);\n\tconst s = transferPqEncode(\n\t\t0.0070797844607477 * absX +\n\t\t\t0.0748396662186366 * absY +\n\t\t\t0.8433265453898765 * absZ\n\t);\n\n\tconst i = 0.5 * l + 0.5 * m;\n\tconst t = 1.61376953125 * l - 3.323486328125 * m + 1.709716796875 * s;\n\tconst p = 4.378173828125 * l - 4.24560546875 * m - 0.132568359375 * s;\n\n\tconst res = { mode: 'itp', i, t, p };\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertXyz65ToItp;\n","import { interpolatorLinear } from '../interpolate/linear.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport convertItpToXyz65 from './convertItpToXyz65.js';\nimport convertXyz65ToItp from './convertXyz65ToItp.js';\nimport convertRgbToXyz65 from '../xyz65/convertRgbToXyz65.js';\nimport convertXyz65ToRgb from '../xyz65/convertXyz65ToRgb.js';\n\n/*\n ICtCp (or ITP) color space, as defined in ITU-R Recommendation BT.2100.\n\n ICtCp is drafted to be supported in CSS within\n [CSS Color HDR Module Level 1](https://drafts.csswg.org/css-color-hdr/#ICtCp) spec.\n*/\n\nconst definition = {\n\tmode: 'itp',\n\tchannels: ['i', 't', 'p', 'alpha'],\n\tparse: ['--ictcp'],\n\tserialize: '--ictcp',\n\n\ttoMode: {\n\t\txyz65: convertItpToXyz65,\n\t\trgb: color => convertXyz65ToRgb(convertItpToXyz65(color))\n\t},\n\n\tfromMode: {\n\t\txyz65: convertXyz65ToItp,\n\t\trgb: color => convertXyz65ToItp(convertRgbToXyz65(color))\n\t},\n\n\tranges: {\n\t\ti: [0, 0.581],\n\t\tt: [-0.369, 0.272],\n\t\tp: [-0.164, 0.331]\n\t},\n\n\tinterpolate: {\n\t\ti: interpolatorLinear,\n\t\tt: interpolatorLinear,\n\t\tp: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t}\n};\n\nexport default definition;\n","import { M1 as n, C1, C2, C3 } from '../hdr/transfer.js';\nconst p = 134.03437499999998; // = 1.7 * 2523 / Math.pow(2, 5);\nconst d0 = 1.6295499532821566e-11;\n\n/* \n\tThe encoding function is derived from Perceptual Quantizer.\n*/\nconst jabPqEncode = v => {\n\tif (v < 0) return 0;\n\tlet vn = Math.pow(v / 10000, n);\n\treturn Math.pow((C1 + C2 * vn) / (1 + C3 * vn), p);\n};\n\n// Convert to Absolute XYZ\nconst abs = (v = 0) => Math.max(v * 203, 0);\n\nconst convertXyz65ToJab = ({ x, y, z, alpha }) => {\n\tx = abs(x);\n\ty = abs(y);\n\tz = abs(z);\n\n\tlet xp = 1.15 * x - 0.15 * z;\n\tlet yp = 0.66 * y + 0.34 * x;\n\n\tlet l = jabPqEncode(0.41478972 * xp + 0.579999 * yp + 0.014648 * z);\n\tlet m = jabPqEncode(-0.20151 * xp + 1.120649 * yp + 0.0531008 * z);\n\tlet s = jabPqEncode(-0.0166008 * xp + 0.2648 * yp + 0.6684799 * z);\n\n\tlet i = (l + m) / 2;\n\n\tlet res = {\n\t\tmode: 'jab',\n\t\tj: (0.44 * i) / (1 - 0.56 * i) - d0,\n\t\ta: 3.524 * l - 4.066708 * m + 0.542708 * s,\n\t\tb: 0.199076 * l + 1.096799 * m - 1.295875 * s\n\t};\n\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertXyz65ToJab;\n","import { M1 as n, C1, C2, C3 } from '../hdr/transfer.js';\nconst p = 134.03437499999998; // = 1.7 * 2523 / Math.pow(2, 5);\nconst d0 = 1.6295499532821566e-11;\n\n/* \n\tThe encoding function is derived from Perceptual Quantizer.\n*/\nconst jabPqDecode = v => {\n\tif (v < 0) return 0;\n\tlet vp = Math.pow(v, 1 / p);\n\treturn 10000 * Math.pow((C1 - vp) / (C3 * vp - C2), 1 / n);\n};\n\nconst rel = v => v / 203;\n\nconst convertJabToXyz65 = ({ j, a, b, alpha }) => {\n\tif (j === undefined) j = 0;\n\tif (a === undefined) a = 0;\n\tif (b === undefined) b = 0;\n\tlet i = (j + d0) / (0.44 + 0.56 * (j + d0));\n\n\tlet l = jabPqDecode(i + 0.13860504 * a + 0.058047316 * b);\n\tlet m = jabPqDecode(i - 0.13860504 * a - 0.058047316 * b);\n\tlet s = jabPqDecode(i - 0.096019242 * a - 0.8118919 * b);\n\n\tlet res = {\n\t\tmode: 'xyz65',\n\t\tx: rel(\n\t\t\t1.661373024652174 * l -\n\t\t\t\t0.914523081304348 * m +\n\t\t\t\t0.23136208173913045 * s\n\t\t),\n\t\ty: rel(\n\t\t\t-0.3250758611844533 * l +\n\t\t\t\t1.571847026732543 * m -\n\t\t\t\t0.21825383453227928 * s\n\t\t),\n\t\tz: rel(-0.090982811 * l - 0.31272829 * m + 1.5227666 * s)\n\t};\n\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertJabToXyz65;\n","/*\n\tConvert sRGB to JzAzBz.\n\n\tFor achromatic sRGB colors, adjust the equivalent JzAzBz color\n\tto be achromatic as well, insteading of having a very slight chroma.\n */\n\nimport convertXyz65ToJab from './convertXyz65ToJab.js';\nimport convertRgbToXyz65 from '../xyz65/convertRgbToXyz65.js';\n\nconst convertRgbToJab = rgb => {\n\tlet res = convertXyz65ToJab(convertRgbToXyz65(rgb));\n\tif (rgb.r === rgb.b && rgb.b === rgb.g) {\n\t\tres.a = res.b = 0;\n\t}\n\treturn res;\n};\n\nexport default convertRgbToJab;\n","import convertXyz65ToRgb from '../xyz65/convertXyz65ToRgb.js';\nimport convertJabToXyz65 from './convertJabToXyz65.js';\n\nconst convertJabToRgb = color => convertXyz65ToRgb(convertJabToXyz65(color));\n\nexport default convertJabToRgb;\n","/*\n\tThe JzAzBz color space.\n\n\tBased on:\n\n\tMuhammad Safdar, Guihua Cui, Youn Jin Kim, and Ming Ronnier Luo, \n\t\"Perceptually uniform color space for image signals \n\tincluding high dynamic range and wide gamut,\" \n\tOpt. Express 25, 15131-15151 (2017) \n\n\thttps://doi.org/10.1364/OE.25.015131\n */\n\nimport convertXyz65ToJab from './convertXyz65ToJab.js';\nimport convertJabToXyz65 from './convertJabToXyz65.js';\nimport convertRgbToJab from './convertRgbToJab.js';\nimport convertJabToRgb from './convertJabToRgb.js';\n\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\n\nconst definition = {\n\tmode: 'jab',\n\tchannels: ['j', 'a', 'b', 'alpha'],\n\n\tparse: ['--jzazbz'],\n\tserialize: '--jzazbz',\n\n\tfromMode: {\n\t\trgb: convertRgbToJab,\n\t\txyz65: convertXyz65ToJab\n\t},\n\n\ttoMode: {\n\t\trgb: convertJabToRgb,\n\t\txyz65: convertJabToXyz65\n\t},\n\n\tranges: {\n\t\tj: [0, 0.222],\n\t\ta: [-0.109, 0.129],\n\t\tb: [-0.185, 0.134]\n\t},\n\n\tinterpolate: {\n\t\tj: interpolatorLinear,\n\t\ta: interpolatorLinear,\n\t\tb: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t}\n};\n\nexport default definition;\n","import normalizeHue from '../util/normalizeHue.js';\n\nconst convertJabToJch = ({ j, a, b, alpha }) => {\n\tif (a === undefined) a = 0;\n\tif (b === undefined) b = 0;\n\tlet c = Math.sqrt(a * a + b * b);\n\tlet res = {\n\t\tmode: 'jch',\n\t\tj,\n\t\tc\n\t};\n\tif (c) {\n\t\tres.h = normalizeHue((Math.atan2(b, a) * 180) / Math.PI);\n\t}\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertJabToJch;\n","const convertJchToJab = ({ j, c, h, alpha }) => {\n\tif (h === undefined) h = 0;\n\tlet res = {\n\t\tmode: 'jab',\n\t\tj,\n\t\ta: c ? c * Math.cos((h / 180) * Math.PI) : 0,\n\t\tb: c ? c * Math.sin((h / 180) * Math.PI) : 0\n\t};\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertJchToJab;\n","import convertJabToJch from './convertJabToJch.js';\nimport convertJchToJab from './convertJchToJab.js';\nimport convertJabToRgb from '../jab/convertJabToRgb.js';\nimport convertRgbToJab from '../jab/convertRgbToJab.js';\n\nimport { fixupHueShorter } from '../fixup/hue.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { differenceHueChroma } from '../difference.js';\nimport { averageAngle } from '../average.js';\n\nconst definition = {\n\tmode: 'jch',\n\n\tparse: ['--jzczhz'],\n\tserialize: '--jzczhz',\n\n\ttoMode: {\n\t\tjab: convertJchToJab,\n\t\trgb: c => convertJabToRgb(convertJchToJab(c))\n\t},\n\n\tfromMode: {\n\t\trgb: c => convertJabToJch(convertRgbToJab(c)),\n\t\tjab: convertJabToJch\n\t},\n\n\tchannels: ['j', 'c', 'h', 'alpha'],\n\n\tranges: {\n\t\tj: [0, 0.221],\n\t\tc: [0, 0.19],\n\t\th: [0, 360]\n\t},\n\n\tinterpolate: {\n\t\th: { use: interpolatorLinear, fixup: fixupHueShorter },\n\t\tc: interpolatorLinear,\n\t\tj: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t},\n\n\tdifference: {\n\t\th: differenceHueChroma\n\t},\n\n\taverage: {\n\t\th: averageAngle\n\t}\n};\n\nexport default definition;\n","export const k = Math.pow(29, 3) / Math.pow(3, 3);\nexport const e = Math.pow(6, 3) / Math.pow(29, 3);\n","import { k, e } from '../xyz50/constants.js';\nimport { D50 } from '../constants.js';\n\nlet fn = v => (Math.pow(v, 3) > e ? Math.pow(v, 3) : (116 * v - 16) / k);\n\nconst convertLabToXyz50 = ({ l, a, b, alpha }) => {\n\tif (l === undefined) l = 0;\n\tif (a === undefined) a = 0;\n\tif (b === undefined) b = 0;\n\tlet fy = (l + 16) / 116;\n\tlet fx = a / 500 + fy;\n\tlet fz = fy - b / 200;\n\n\tlet res = {\n\t\tmode: 'xyz50',\n\t\tx: fn(fx) * D50.X,\n\t\ty: fn(fy) * D50.Y,\n\t\tz: fn(fz) * D50.Z\n\t};\n\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertLabToXyz50;\n","/*\n\tCIE XYZ D50 values to sRGB.\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n*/\n\nimport convertLrgbToRgb from '../lrgb/convertLrgbToRgb.js';\n\nconst convertXyz50ToRgb = ({ x, y, z, alpha }) => {\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet res = convertLrgbToRgb({\n\t\tr:\n\t\t\tx * 3.1341359569958707 -\n\t\t\ty * 1.6173863321612538 -\n\t\t\t0.4906619460083532 * z,\n\t\tg:\n\t\t\tx * -0.978795502912089 +\n\t\t\ty * 1.916254567259524 +\n\t\t\t0.03344273116131949 * z,\n\t\tb:\n\t\t\tx * 0.07195537988411677 -\n\t\t\ty * 0.2289768264158322 +\n\t\t\t1.405386058324125 * z\n\t});\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertXyz50ToRgb;\n","import convertLabToXyz50 from './convertLabToXyz50.js';\nimport convertXyz50ToRgb from '../xyz50/convertXyz50ToRgb.js';\n\nconst convertLabToRgb = lab => convertXyz50ToRgb(convertLabToXyz50(lab));\n\nexport default convertLabToRgb;\n","/*\n\tConvert sRGB values to CIE XYZ D50\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n\t\n*/\n\nimport convertRgbToLrgb from '../lrgb/convertRgbToLrgb.js';\n\nconst convertRgbToXyz50 = rgb => {\n\tlet { r, g, b, alpha } = convertRgbToLrgb(rgb);\n\tlet res = {\n\t\tmode: 'xyz50',\n\t\tx:\n\t\t\t0.436065742824811 * r +\n\t\t\t0.3851514688337912 * g +\n\t\t\t0.14307845442264197 * b,\n\t\ty:\n\t\t\t0.22249319175623702 * r +\n\t\t\t0.7168870538238823 * g +\n\t\t\t0.06061979053616537 * b,\n\t\tz:\n\t\t\t0.013923904500943465 * r +\n\t\t\t0.09708128566574634 * g +\n\t\t\t0.7140993584005155 * b\n\t};\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertRgbToXyz50;\n","import { k, e } from '../xyz50/constants.js';\nimport { D50 } from '../constants.js';\n\nconst f = value => (value > e ? Math.cbrt(value) : (k * value + 16) / 116);\n\nconst convertXyz50ToLab = ({ x, y, z, alpha }) => {\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet f0 = f(x / D50.X);\n\tlet f1 = f(y / D50.Y);\n\tlet f2 = f(z / D50.Z);\n\n\tlet res = {\n\t\tmode: 'lab',\n\t\tl: 116 * f1 - 16,\n\t\ta: 500 * (f0 - f1),\n\t\tb: 200 * (f1 - f2)\n\t};\n\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertXyz50ToLab;\n","import convertRgbToXyz50 from '../xyz50/convertRgbToXyz50.js';\nimport convertXyz50ToLab from './convertXyz50ToLab.js';\n\nconst convertRgbToLab = rgb => {\n\tlet res = convertXyz50ToLab(convertRgbToXyz50(rgb));\n\n\t// Fixes achromatic RGB colors having a _slight_ chroma due to floating-point errors\n\t// and approximated computations in sRGB <-> CIELab.\n\t// See: https://github.com/d3/d3-color/pull/46\n\tif (rgb.r === rgb.b && rgb.b === rgb.g) {\n\t\tres.a = res.b = 0;\n\t}\n\treturn res;\n};\n\nexport default convertRgbToLab;\n","import { Tok } from '../parse.js';\n\nfunction parseLab(color, parsed) {\n\tif (!parsed || parsed[0] !== 'lab') {\n\t\treturn undefined;\n\t}\n\tconst res = { mode: 'lab' };\n\tconst [, l, a, b, alpha] = parsed;\n\tif (l.type === Tok.Hue || a.type === Tok.Hue || b.type === Tok.Hue) {\n\t\treturn undefined;\n\t}\n\tif (l.type !== Tok.None) {\n\t\tres.l = Math.min(Math.max(0, l.value), 100);\n\t}\n\tif (a.type !== Tok.None) {\n\t\tres.a = a.type === Tok.Number ? a.value : (a.value * 125) / 100;\n\t}\n\tif (b.type !== Tok.None) {\n\t\tres.b = b.type === Tok.Number ? b.value : (b.value * 125) / 100;\n\t}\n\tif (alpha.type !== Tok.None) {\n\t\tres.alpha = Math.min(\n\t\t\t1,\n\t\t\tMath.max(\n\t\t\t\t0,\n\t\t\t\talpha.type === Tok.Number ? alpha.value : alpha.value / 100\n\t\t\t)\n\t\t);\n\t}\n\n\treturn res;\n}\n\nexport default parseLab;\n","import convertLabToRgb from './convertLabToRgb.js';\nimport convertLabToXyz50 from './convertLabToXyz50.js';\nimport convertRgbToLab from './convertRgbToLab.js';\nimport convertXyz50ToLab from './convertXyz50ToLab.js';\nimport parseLab from './parseLab.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\n\nconst definition = {\n\tmode: 'lab',\n\n\ttoMode: {\n\t\txyz50: convertLabToXyz50,\n\t\trgb: convertLabToRgb\n\t},\n\n\tfromMode: {\n\t\txyz50: convertXyz50ToLab,\n\t\trgb: convertRgbToLab\n\t},\n\n\tchannels: ['l', 'a', 'b', 'alpha'],\n\n\tranges: {\n\t\tl: [0, 100],\n\t\ta: [-125, 125],\n\t\tb: [-125, 125]\n\t},\n\n\tparse: [parseLab],\n\tserialize: c =>\n\t\t`lab(${c.l !== undefined ? c.l : 'none'} ${\n\t\t\tc.a !== undefined ? c.a : 'none'\n\t\t} ${c.b !== undefined ? c.b : 'none'}${\n\t\t\tc.alpha < 1 ? ` / ${c.alpha}` : ''\n\t\t})`,\n\n\tinterpolate: {\n\t\tl: interpolatorLinear,\n\t\ta: interpolatorLinear,\n\t\tb: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t}\n};\n\nexport default definition;\n","import convertLab65ToRgb from './convertLab65ToRgb.js';\nimport convertLab65ToXyz65 from './convertLab65ToXyz65.js';\nimport convertRgbToLab65 from './convertRgbToLab65.js';\nimport convertXyz65ToLab65 from './convertXyz65ToLab65.js';\nimport lab from '../lab/definition.js';\n\nconst definition = {\n\t...lab,\n\tmode: 'lab65',\n\n\tparse: ['--lab-d65'],\n\tserialize: '--lab-d65',\n\n\ttoMode: {\n\t\txyz65: convertLab65ToXyz65,\n\t\trgb: convertLab65ToRgb\n\t},\n\n\tfromMode: {\n\t\txyz65: convertXyz65ToLab65,\n\t\trgb: convertRgbToLab65\n\t},\n\n\tranges: {\n\t\tl: [0, 100],\n\t\ta: [-125, 125],\n\t\tb: [-125, 125]\n\t}\n};\n\nexport default definition;\n","import { Tok } from '../parse.js';\n\nfunction parseLch(color, parsed) {\n\tif (!parsed || parsed[0] !== 'lch') {\n\t\treturn undefined;\n\t}\n\tconst res = { mode: 'lch' };\n\tconst [, l, c, h, alpha] = parsed;\n\tif (l.type !== Tok.None) {\n\t\tif (l.type === Tok.Hue) {\n\t\t\treturn undefined;\n\t\t}\n\t\tres.l = Math.min(Math.max(0, l.value), 100);\n\t}\n\tif (c.type !== Tok.None) {\n\t\tres.c = Math.max(\n\t\t\t0,\n\t\t\tc.type === Tok.Number ? c.value : (c.value * 150) / 100\n\t\t);\n\t}\n\tif (h.type !== Tok.None) {\n\t\tif (h.type === Tok.Percentage) {\n\t\t\treturn undefined;\n\t\t}\n\t\tres.h = h.value;\n\t}\n\tif (alpha.type !== Tok.None) {\n\t\tres.alpha = Math.min(\n\t\t\t1,\n\t\t\tMath.max(\n\t\t\t\t0,\n\t\t\t\talpha.type === Tok.Number ? alpha.value : alpha.value / 100\n\t\t\t)\n\t\t);\n\t}\n\n\treturn res;\n}\n\nexport default parseLch;\n","import convertLabToLch from './convertLabToLch.js';\nimport convertLchToLab from './convertLchToLab.js';\nimport convertLabToRgb from '../lab/convertLabToRgb.js';\nimport convertRgbToLab from '../lab/convertRgbToLab.js';\nimport parseLch from './parseLch.js';\nimport { fixupHueShorter } from '../fixup/hue.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { differenceHueChroma } from '../difference.js';\nimport { averageAngle } from '../average.js';\n\nconst definition = {\n\tmode: 'lch',\n\n\ttoMode: {\n\t\tlab: convertLchToLab,\n\t\trgb: c => convertLabToRgb(convertLchToLab(c))\n\t},\n\n\tfromMode: {\n\t\trgb: c => convertLabToLch(convertRgbToLab(c)),\n\t\tlab: convertLabToLch\n\t},\n\n\tchannels: ['l', 'c', 'h', 'alpha'],\n\n\tranges: {\n\t\tl: [0, 100],\n\t\tc: [0, 150],\n\t\th: [0, 360]\n\t},\n\n\tparse: [parseLch],\n\tserialize: c =>\n\t\t`lch(${c.l !== undefined ? c.l : 'none'} ${\n\t\t\tc.c !== undefined ? c.c : 'none'\n\t\t} ${c.h !== undefined ? c.h : 'none'}${\n\t\t\tc.alpha < 1 ? ` / ${c.alpha}` : ''\n\t\t})`,\n\n\tinterpolate: {\n\t\th: { use: interpolatorLinear, fixup: fixupHueShorter },\n\t\tc: interpolatorLinear,\n\t\tl: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t},\n\n\tdifference: {\n\t\th: differenceHueChroma\n\t},\n\n\taverage: {\n\t\th: averageAngle\n\t}\n};\n\nexport default definition;\n","import convertLabToLch from '../lch/convertLabToLch.js';\nimport convertLchToLab from '../lch/convertLchToLab.js';\nimport convertLab65ToRgb from '../lab65/convertLab65ToRgb.js';\nimport convertRgbToLab65 from '../lab65/convertRgbToLab65.js';\nimport lch from '../lch/definition.js';\n\nconst definition = {\n\t...lch,\n\tmode: 'lch65',\n\n\tparse: ['--lch-d65'],\n\tserialize: '--lch-d65',\n\n\ttoMode: {\n\t\tlab65: c => convertLchToLab(c, 'lab65'),\n\t\trgb: c => convertLab65ToRgb(convertLchToLab(c, 'lab65'))\n\t},\n\n\tfromMode: {\n\t\trgb: c => convertLabToLch(convertRgbToLab65(c), 'lch65'),\n\t\tlab65: c => convertLabToLch(c, 'lch65')\n\t},\n\n\tranges: {\n\t\tl: [0, 100],\n\t\tc: [0, 150],\n\t\th: [0, 360]\n\t}\n};\n\nexport default definition;\n","import normalizeHue from '../util/normalizeHue.js';\n\nconst convertLuvToLchuv = ({ l, u, v, alpha }) => {\n\tif (u === undefined) u = 0;\n\tif (v === undefined) v = 0;\n\tlet c = Math.sqrt(u * u + v * v);\n\tlet res = {\n\t\tmode: 'lchuv',\n\t\tl: l,\n\t\tc: c\n\t};\n\tif (c) {\n\t\tres.h = normalizeHue((Math.atan2(v, u) * 180) / Math.PI);\n\t}\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertLuvToLchuv;\n","const convertLchuvToLuv = ({ l, c, h, alpha }) => {\n\tif (h === undefined) h = 0;\n\tlet res = {\n\t\tmode: 'luv',\n\t\tl: l,\n\t\tu: c ? c * Math.cos((h / 180) * Math.PI) : 0,\n\t\tv: c ? c * Math.sin((h / 180) * Math.PI) : 0\n\t};\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertLchuvToLuv;\n","import { k, e } from '../xyz50/constants.js';\nimport { D50 } from '../constants.js';\n\nexport const u_fn = (x, y, z) => (4 * x) / (x + 15 * y + 3 * z);\nexport const v_fn = (x, y, z) => (9 * y) / (x + 15 * y + 3 * z);\n\nexport const un = u_fn(D50.X, D50.Y, D50.Z);\nexport const vn = v_fn(D50.X, D50.Y, D50.Z);\n\nconst l_fn = value => (value <= e ? k * value : 116 * Math.cbrt(value) - 16);\n\nconst convertXyz50ToLuv = ({ x, y, z, alpha }) => {\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet l = l_fn(y / D50.Y);\n\tlet u = u_fn(x, y, z);\n\tlet v = v_fn(x, y, z);\n\n\t// guard against NaNs produced by `xyz(0 0 0)` black\n\tif (!isFinite(u) || !isFinite(v)) {\n\t\tl = u = v = 0;\n\t} else {\n\t\tu = 13 * l * (u - un);\n\t\tv = 13 * l * (v - vn);\n\t}\n\n\tlet res = {\n\t\tmode: 'luv',\n\t\tl,\n\t\tu,\n\t\tv\n\t};\n\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertXyz50ToLuv;\n","import { k } from '../xyz50/constants.js';\nimport { D50 } from '../constants.js';\n\nexport const u_fn = (x, y, z) => (4 * x) / (x + 15 * y + 3 * z);\nexport const v_fn = (x, y, z) => (9 * y) / (x + 15 * y + 3 * z);\n\nexport const un = u_fn(D50.X, D50.Y, D50.Z);\nexport const vn = v_fn(D50.X, D50.Y, D50.Z);\n\nconst convertLuvToXyz50 = ({ l, u, v, alpha }) => {\n\tif (l === undefined) l = 0;\n\tif (l === 0) {\n\t\treturn { mode: 'xyz50', x: 0, y: 0, z: 0 };\n\t}\n\n\tif (u === undefined) u = 0;\n\tif (v === undefined) v = 0;\n\n\tlet up = u / (13 * l) + un;\n\tlet vp = v / (13 * l) + vn;\n\tlet y = D50.Y * (l <= 8 ? l / k : Math.pow((l + 16) / 116, 3));\n\tlet x = (y * (9 * up)) / (4 * vp);\n\tlet z = (y * (12 - 3 * up - 20 * vp)) / (4 * vp);\n\n\tlet res = { mode: 'xyz50', x, y, z };\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertLuvToXyz50;\n","/*\n\tCIELChuv color space\n\t--------------------\n\n\tReference: \n\n\t\thttps://en.wikipedia.org/wiki/CIELUV\n */\n\nimport convertLuvToLchuv from './convertLuvToLchuv.js';\nimport convertLchuvToLuv from './convertLchuvToLuv.js';\nimport convertXyz50ToLuv from '../luv/convertXyz50ToLuv.js';\nimport convertLuvToXyz50 from '../luv/convertLuvToXyz50.js';\nimport convertXyz50ToRgb from '../xyz50/convertXyz50ToRgb.js';\nimport convertRgbToXyz50 from '../xyz50/convertRgbToXyz50.js';\n\nimport { fixupHueShorter } from '../fixup/hue.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { differenceHueChroma } from '../difference.js';\nimport { averageAngle } from '../average.js';\n\nconst convertRgbToLchuv = rgb =>\n\tconvertLuvToLchuv(convertXyz50ToLuv(convertRgbToXyz50(rgb)));\nconst convertLchuvToRgb = lchuv =>\n\tconvertXyz50ToRgb(convertLuvToXyz50(convertLchuvToLuv(lchuv)));\n\nconst definition = {\n\tmode: 'lchuv',\n\n\ttoMode: {\n\t\tluv: convertLchuvToLuv,\n\t\trgb: convertLchuvToRgb\n\t},\n\n\tfromMode: {\n\t\trgb: convertRgbToLchuv,\n\t\tluv: convertLuvToLchuv\n\t},\n\n\tchannels: ['l', 'c', 'h', 'alpha'],\n\n\tparse: ['--lchuv'],\n\tserialize: '--lchuv',\n\n\tranges: {\n\t\tl: [0, 100],\n\t\tc: [0, 176.956],\n\t\th: [0, 360]\n\t},\n\n\tinterpolate: {\n\t\th: { use: interpolatorLinear, fixup: fixupHueShorter },\n\t\tc: interpolatorLinear,\n\t\tl: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t},\n\n\tdifference: {\n\t\th: differenceHueChroma\n\t},\n\n\taverage: {\n\t\th: averageAngle\n\t}\n};\n\nexport default definition;\n","import rgb from '../rgb/definition.js';\nimport convertRgbToLrgb from './convertRgbToLrgb.js';\nimport convertLrgbToRgb from './convertLrgbToRgb.js';\n\nconst definition = {\n\t...rgb,\n\tmode: 'lrgb',\n\n\ttoMode: {\n\t\trgb: convertLrgbToRgb\n\t},\n\n\tfromMode: {\n\t\trgb: convertRgbToLrgb\n\t},\n\n\tparse: ['srgb-linear'],\n\tserialize: 'srgb-linear'\n};\n\nexport default definition;\n","/*\n\tCIELUV color space\n\t------------------\n\n\tReference: \n\n\t\thttps://en.wikipedia.org/wiki/CIELUV\n */\n\nimport convertXyz50ToLuv from './convertXyz50ToLuv.js';\nimport convertLuvToXyz50 from './convertLuvToXyz50.js';\nimport convertXyz50ToRgb from '../xyz50/convertXyz50ToRgb.js';\nimport convertRgbToXyz50 from '../xyz50/convertRgbToXyz50.js';\n\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\n\nconst definition = {\n\tmode: 'luv',\n\n\ttoMode: {\n\t\txyz50: convertLuvToXyz50,\n\t\trgb: luv => convertXyz50ToRgb(convertLuvToXyz50(luv))\n\t},\n\n\tfromMode: {\n\t\txyz50: convertXyz50ToLuv,\n\t\trgb: rgb => convertXyz50ToLuv(convertRgbToXyz50(rgb))\n\t},\n\n\tchannels: ['l', 'u', 'v', 'alpha'],\n\n\tparse: ['--luv'],\n\tserialize: '--luv',\n\n\tranges: {\n\t\tl: [0, 100],\n\t\tu: [-84.936, 175.042],\n\t\tv: [-125.882, 87.243]\n\t},\n\n\tinterpolate: {\n\t\tl: interpolatorLinear,\n\t\tu: interpolatorLinear,\n\t\tv: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t}\n};\n\nexport default definition;\n","const convertLrgbToOklab = ({ r, g, b, alpha }) => {\n\tif (r === undefined) r = 0;\n\tif (g === undefined) g = 0;\n\tif (b === undefined) b = 0;\n\n\tlet L = Math.cbrt(\n\t\t0.412221469470763 * r + 0.5363325372617348 * g + 0.0514459932675022 * b\n\t);\n\tlet M = Math.cbrt(\n\t\t0.2119034958178252 * r + 0.6806995506452344 * g + 0.1073969535369406 * b\n\t);\n\tlet S = Math.cbrt(\n\t\t0.0883024591900564 * r + 0.2817188391361215 * g + 0.6299787016738222 * b\n\t);\n\n\tlet res = {\n\t\tmode: 'oklab',\n\t\tl:\n\t\t\t0.210454268309314 * L +\n\t\t\t0.7936177747023054 * M -\n\t\t\t0.0040720430116193 * S,\n\t\ta:\n\t\t\t1.9779985324311684 * L -\n\t\t\t2.4285922420485799 * M +\n\t\t\t0.450593709617411 * S,\n\t\tb:\n\t\t\t0.0259040424655478 * L +\n\t\t\t0.7827717124575296 * M -\n\t\t\t0.8086757549230774 * S\n\t};\n\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertLrgbToOklab;\n","import convertRgbToLrgb from '../lrgb/convertRgbToLrgb.js';\nimport convertLrgbToOklab from './convertLrgbToOklab.js';\n\nconst convertRgbToOklab = rgb => {\n\tlet res = convertLrgbToOklab(convertRgbToLrgb(rgb));\n\tif (rgb.r === rgb.b && rgb.b === rgb.g) {\n\t\tres.a = res.b = 0;\n\t}\n\treturn res;\n};\n\nexport default convertRgbToOklab;\n","const convertOklabToLrgb = ({ l, a, b, alpha }) => {\n\tif (l === undefined) l = 0;\n\tif (a === undefined) a = 0;\n\tif (b === undefined) b = 0;\n\n\tlet L = Math.pow(l + 0.3963377773761749 * a + 0.2158037573099136 * b, 3);\n\tlet M = Math.pow(l - 0.1055613458156586 * a - 0.0638541728258133 * b, 3);\n\tlet S = Math.pow(l - 0.0894841775298119 * a - 1.2914855480194092 * b, 3);\n\n\tlet res = {\n\t\tmode: 'lrgb',\n\t\tr:\n\t\t\t4.0767416360759574 * L -\n\t\t\t3.3077115392580616 * M +\n\t\t\t0.2309699031821044 * S,\n\t\tg:\n\t\t\t-1.2684379732850317 * L +\n\t\t\t2.6097573492876887 * M -\n\t\t\t0.3413193760026573 * S,\n\t\tb:\n\t\t\t-0.0041960761386756 * L -\n\t\t\t0.7034186179359362 * M +\n\t\t\t1.7076146940746117 * S\n\t};\n\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertOklabToLrgb;\n","import convertLrgbToRgb from '../lrgb/convertLrgbToRgb.js';\nimport convertOklabToLrgb from './convertOklabToLrgb.js';\n\nconst convertOklabToRgb = c => convertLrgbToRgb(convertOklabToLrgb(c));\n\nexport default convertOklabToRgb;\n","/*\n\tAdapted from code by Björn Ottosson,\n\treleased under the MIT license:\n\n\tCopyright (c) 2021 Björn Ottosson\n\n\tPermission is hereby granted, free of charge, to any person obtaining a copy of\n\tthis software and associated documentation files (the \"Software\"), to deal in\n\tthe Software without restriction, including without limitation the rights to\n\tuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n\tof the Software, and to permit persons to whom the Software is furnished to do\n\tso, subject to the following conditions:\n\n\tThe above copyright notice and this permission notice shall be included in all\n\tcopies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\tIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\tFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n\tAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n\tLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n\tOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n\tSOFTWARE.\n */\n\nimport convertOklabToLrgb from '../oklab/convertOklabToLrgb.js';\n\nexport function toe(x) {\n\tconst k_1 = 0.206;\n\tconst k_2 = 0.03;\n\tconst k_3 = (1 + k_1) / (1 + k_2);\n\treturn (\n\t\t0.5 *\n\t\t(k_3 * x -\n\t\t\tk_1 +\n\t\t\tMath.sqrt((k_3 * x - k_1) * (k_3 * x - k_1) + 4 * k_2 * k_3 * x))\n\t);\n}\n\nexport function toe_inv(x) {\n\tconst k_1 = 0.206;\n\tconst k_2 = 0.03;\n\tconst k_3 = (1 + k_1) / (1 + k_2);\n\treturn (x * x + k_1 * x) / (k_3 * (x + k_2));\n}\n\n// Finds the maximum saturation possible for a given hue that fits in sRGB\n// Saturation here is defined as S = C/L\n// a and b must be normalized so a^2 + b^2 == 1\nfunction compute_max_saturation(a, b) {\n\t// Max saturation will be when one of r, g or b goes below zero.\n\n\t// Select different coefficients depending on which component goes below zero first\n\tlet k0, k1, k2, k3, k4, wl, wm, ws;\n\n\tif (-1.88170328 * a - 0.80936493 * b > 1) {\n\t\t// Red component\n\t\tk0 = +1.19086277;\n\t\tk1 = +1.76576728;\n\t\tk2 = +0.59662641;\n\t\tk3 = +0.75515197;\n\t\tk4 = +0.56771245;\n\t\twl = +4.0767416621;\n\t\twm = -3.3077115913;\n\t\tws = +0.2309699292;\n\t} else if (1.81444104 * a - 1.19445276 * b > 1) {\n\t\t// Green component\n\t\tk0 = +0.73956515;\n\t\tk1 = -0.45954404;\n\t\tk2 = +0.08285427;\n\t\tk3 = +0.1254107;\n\t\tk4 = +0.14503204;\n\t\twl = -1.2684380046;\n\t\twm = +2.6097574011;\n\t\tws = -0.3413193965;\n\t} else {\n\t\t// Blue component\n\t\tk0 = +1.35733652;\n\t\tk1 = -0.00915799;\n\t\tk2 = -1.1513021;\n\t\tk3 = -0.50559606;\n\t\tk4 = +0.00692167;\n\t\twl = -0.0041960863;\n\t\twm = -0.7034186147;\n\t\tws = +1.707614701;\n\t}\n\n\t// Approximate max saturation using a polynomial:\n\tlet S = k0 + k1 * a + k2 * b + k3 * a * a + k4 * a * b;\n\n\t// Do one step Halley's method to get closer\n\t// this gives an error less than 10e6, except for some blue hues where the dS/dh is close to infinite\n\t// this should be sufficient for most applications, otherwise do two/three steps\n\n\tlet k_l = +0.3963377774 * a + 0.2158037573 * b;\n\tlet k_m = -0.1055613458 * a - 0.0638541728 * b;\n\tlet k_s = -0.0894841775 * a - 1.291485548 * b;\n\n\t{\n\t\tlet l_ = 1 + S * k_l;\n\t\tlet m_ = 1 + S * k_m;\n\t\tlet s_ = 1 + S * k_s;\n\n\t\tlet l = l_ * l_ * l_;\n\t\tlet m = m_ * m_ * m_;\n\t\tlet s = s_ * s_ * s_;\n\n\t\tlet l_dS = 3 * k_l * l_ * l_;\n\t\tlet m_dS = 3 * k_m * m_ * m_;\n\t\tlet s_dS = 3 * k_s * s_ * s_;\n\n\t\tlet l_dS2 = 6 * k_l * k_l * l_;\n\t\tlet m_dS2 = 6 * k_m * k_m * m_;\n\t\tlet s_dS2 = 6 * k_s * k_s * s_;\n\n\t\tlet f = wl * l + wm * m + ws * s;\n\t\tlet f1 = wl * l_dS + wm * m_dS + ws * s_dS;\n\t\tlet f2 = wl * l_dS2 + wm * m_dS2 + ws * s_dS2;\n\n\t\tS = S - (f * f1) / (f1 * f1 - 0.5 * f * f2);\n\t}\n\n\treturn S;\n}\n\nexport function find_cusp(a, b) {\n\t// First, find the maximum saturation (saturation S = C/L)\n\tlet S_cusp = compute_max_saturation(a, b);\n\n\t// Convert to linear sRGB to find the first point where at least one of r,g or b >= 1:\n\tlet rgb = convertOklabToLrgb({ l: 1, a: S_cusp * a, b: S_cusp * b });\n\tlet L_cusp = Math.cbrt(1 / Math.max(rgb.r, rgb.g, rgb.b));\n\tlet C_cusp = L_cusp * S_cusp;\n\n\treturn [L_cusp, C_cusp];\n}\n\n// Finds intersection of the line defined by\n// L = L0 * (1 - t) + t * L1;\n// C = t * C1;\n// a and b must be normalized so a^2 + b^2 == 1\nfunction find_gamut_intersection(a, b, L1, C1, L0, cusp = null) {\n\tif (!cusp) {\n\t\t// Find the cusp of the gamut triangle\n\t\tcusp = find_cusp(a, b);\n\t}\n\n\t// Find the intersection for upper and lower half seprately\n\tlet t;\n\tif ((L1 - L0) * cusp[1] - (cusp[0] - L0) * C1 <= 0) {\n\t\t// Lower half\n\n\t\tt = (cusp[1] * L0) / (C1 * cusp[0] + cusp[1] * (L0 - L1));\n\t} else {\n\t\t// Upper half\n\n\t\t// First intersect with triangle\n\t\tt = (cusp[1] * (L0 - 1)) / (C1 * (cusp[0] - 1) + cusp[1] * (L0 - L1));\n\n\t\t// Then one step Halley's method\n\t\t{\n\t\t\tlet dL = L1 - L0;\n\t\t\tlet dC = C1;\n\n\t\t\tlet k_l = +0.3963377774 * a + 0.2158037573 * b;\n\t\t\tlet k_m = -0.1055613458 * a - 0.0638541728 * b;\n\t\t\tlet k_s = -0.0894841775 * a - 1.291485548 * b;\n\n\t\t\tlet l_dt = dL + dC * k_l;\n\t\t\tlet m_dt = dL + dC * k_m;\n\t\t\tlet s_dt = dL + dC * k_s;\n\n\t\t\t// If higher accuracy is required, 2 or 3 iterations of the following block can be used:\n\t\t\t{\n\t\t\t\tlet L = L0 * (1 - t) + t * L1;\n\t\t\t\tlet C = t * C1;\n\n\t\t\t\tlet l_ = L + C * k_l;\n\t\t\t\tlet m_ = L + C * k_m;\n\t\t\t\tlet s_ = L + C * k_s;\n\n\t\t\t\tlet l = l_ * l_ * l_;\n\t\t\t\tlet m = m_ * m_ * m_;\n\t\t\t\tlet s = s_ * s_ * s_;\n\n\t\t\t\tlet ldt = 3 * l_dt * l_ * l_;\n\t\t\t\tlet mdt = 3 * m_dt * m_ * m_;\n\t\t\t\tlet sdt = 3 * s_dt * s_ * s_;\n\n\t\t\t\tlet ldt2 = 6 * l_dt * l_dt * l_;\n\t\t\t\tlet mdt2 = 6 * m_dt * m_dt * m_;\n\t\t\t\tlet sdt2 = 6 * s_dt * s_dt * s_;\n\n\t\t\t\tlet r =\n\t\t\t\t\t4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s - 1;\n\t\t\t\tlet r1 =\n\t\t\t\t\t4.0767416621 * ldt -\n\t\t\t\t\t3.3077115913 * mdt +\n\t\t\t\t\t0.2309699292 * sdt;\n\t\t\t\tlet r2 =\n\t\t\t\t\t4.0767416621 * ldt2 -\n\t\t\t\t\t3.3077115913 * mdt2 +\n\t\t\t\t\t0.2309699292 * sdt2;\n\n\t\t\t\tlet u_r = r1 / (r1 * r1 - 0.5 * r * r2);\n\t\t\t\tlet t_r = -r * u_r;\n\n\t\t\t\tlet g =\n\t\t\t\t\t-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s - 1;\n\t\t\t\tlet g1 =\n\t\t\t\t\t-1.2684380046 * ldt +\n\t\t\t\t\t2.6097574011 * mdt -\n\t\t\t\t\t0.3413193965 * sdt;\n\t\t\t\tlet g2 =\n\t\t\t\t\t-1.2684380046 * ldt2 +\n\t\t\t\t\t2.6097574011 * mdt2 -\n\t\t\t\t\t0.3413193965 * sdt2;\n\n\t\t\t\tlet u_g = g1 / (g1 * g1 - 0.5 * g * g2);\n\t\t\t\tlet t_g = -g * u_g;\n\n\t\t\t\tlet b =\n\t\t\t\t\t-0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s - 1;\n\t\t\t\tlet b1 =\n\t\t\t\t\t-0.0041960863 * ldt -\n\t\t\t\t\t0.7034186147 * mdt +\n\t\t\t\t\t1.707614701 * sdt;\n\t\t\t\tlet b2 =\n\t\t\t\t\t-0.0041960863 * ldt2 -\n\t\t\t\t\t0.7034186147 * mdt2 +\n\t\t\t\t\t1.707614701 * sdt2;\n\n\t\t\t\tlet u_b = b1 / (b1 * b1 - 0.5 * b * b2);\n\t\t\t\tlet t_b = -b * u_b;\n\n\t\t\t\tt_r = u_r >= 0 ? t_r : 10e5;\n\t\t\t\tt_g = u_g >= 0 ? t_g : 10e5;\n\t\t\t\tt_b = u_b >= 0 ? t_b : 10e5;\n\n\t\t\t\tt += Math.min(t_r, Math.min(t_g, t_b));\n\t\t\t}\n\t\t}\n\t}\n\n\treturn t;\n}\n\nexport function get_ST_max(a_, b_, cusp = null) {\n\tif (!cusp) {\n\t\tcusp = find_cusp(a_, b_);\n\t}\n\tlet L = cusp[0];\n\tlet C = cusp[1];\n\treturn [C / L, C / (1 - L)];\n}\n\nexport function get_ST_mid(a_, b_) {\n\tlet S =\n\t\t0.11516993 +\n\t\t1 /\n\t\t\t(+7.4477897 +\n\t\t\t\t4.1590124 * b_ +\n\t\t\t\ta_ *\n\t\t\t\t\t(-2.19557347 +\n\t\t\t\t\t\t1.75198401 * b_ +\n\t\t\t\t\t\ta_ *\n\t\t\t\t\t\t\t(-2.13704948 -\n\t\t\t\t\t\t\t\t10.02301043 * b_ +\n\t\t\t\t\t\t\t\ta_ *\n\t\t\t\t\t\t\t\t\t(-4.24894561 +\n\t\t\t\t\t\t\t\t\t\t5.38770819 * b_ +\n\t\t\t\t\t\t\t\t\t\t4.69891013 * a_))));\n\n\tlet T =\n\t\t0.11239642 +\n\t\t1 /\n\t\t\t(+1.6132032 -\n\t\t\t\t0.68124379 * b_ +\n\t\t\t\ta_ *\n\t\t\t\t\t(+0.40370612 +\n\t\t\t\t\t\t0.90148123 * b_ +\n\t\t\t\t\t\ta_ *\n\t\t\t\t\t\t\t(-0.27087943 +\n\t\t\t\t\t\t\t\t0.6122399 * b_ +\n\t\t\t\t\t\t\t\ta_ *\n\t\t\t\t\t\t\t\t\t(+0.00299215 -\n\t\t\t\t\t\t\t\t\t\t0.45399568 * b_ -\n\t\t\t\t\t\t\t\t\t\t0.14661872 * a_))));\n\n\treturn [S, T];\n}\n\nexport function get_Cs(L, a_, b_) {\n\tlet cusp = find_cusp(a_, b_);\n\n\tlet C_max = find_gamut_intersection(a_, b_, L, 1, L, cusp);\n\tlet ST_max = get_ST_max(a_, b_, cusp);\n\n\tlet S_mid =\n\t\t0.11516993 +\n\t\t1 /\n\t\t\t(+7.4477897 +\n\t\t\t\t4.1590124 * b_ +\n\t\t\t\ta_ *\n\t\t\t\t\t(-2.19557347 +\n\t\t\t\t\t\t1.75198401 * b_ +\n\t\t\t\t\t\ta_ *\n\t\t\t\t\t\t\t(-2.13704948 -\n\t\t\t\t\t\t\t\t10.02301043 * b_ +\n\t\t\t\t\t\t\t\ta_ *\n\t\t\t\t\t\t\t\t\t(-4.24894561 +\n\t\t\t\t\t\t\t\t\t\t5.38770819 * b_ +\n\t\t\t\t\t\t\t\t\t\t4.69891013 * a_))));\n\n\tlet T_mid =\n\t\t0.11239642 +\n\t\t1 /\n\t\t\t(+1.6132032 -\n\t\t\t\t0.68124379 * b_ +\n\t\t\t\ta_ *\n\t\t\t\t\t(+0.40370612 +\n\t\t\t\t\t\t0.90148123 * b_ +\n\t\t\t\t\t\ta_ *\n\t\t\t\t\t\t\t(-0.27087943 +\n\t\t\t\t\t\t\t\t0.6122399 * b_ +\n\t\t\t\t\t\t\t\ta_ *\n\t\t\t\t\t\t\t\t\t(+0.00299215 -\n\t\t\t\t\t\t\t\t\t\t0.45399568 * b_ -\n\t\t\t\t\t\t\t\t\t\t0.14661872 * a_))));\n\n\tlet k = C_max / Math.min(L * ST_max[0], (1 - L) * ST_max[1]);\n\n\tlet C_a = L * S_mid;\n\tlet C_b = (1 - L) * T_mid;\n\tlet C_mid =\n\t\t0.9 *\n\t\tk *\n\t\tMath.sqrt(\n\t\t\tMath.sqrt(\n\t\t\t\t1 / (1 / (C_a * C_a * C_a * C_a) + 1 / (C_b * C_b * C_b * C_b))\n\t\t\t)\n\t\t);\n\n\tC_a = L * 0.4;\n\tC_b = (1 - L) * 0.8;\n\tlet C_0 = Math.sqrt(1 / (1 / (C_a * C_a) + 1 / (C_b * C_b)));\n\treturn [C_0, C_mid, C_max];\n}\n","/*\n\tAdapted from code by Björn Ottosson,\n\treleased under the MIT license:\n\n\tCopyright (c) 2021 Björn Ottosson\n\n\tPermission is hereby granted, free of charge, to any person obtaining a copy of\n\tthis software and associated documentation files (the \"Software\"), to deal in\n\tthe Software without restriction, including without limitation the rights to\n\tuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n\tof the Software, and to permit persons to whom the Software is furnished to do\n\tso, subject to the following conditions:\n\n\tThe above copyright notice and this permission notice shall be included in all\n\tcopies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\tIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\tFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n\tAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n\tLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n\tOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n\tSOFTWARE.\n */\n\nimport normalizeHue from '../util/normalizeHue.js';\nimport { get_Cs, toe } from './helpers.js';\n\nexport default function convertOklabToOkhsl(lab) {\n\tconst l = lab.l !== undefined ? lab.l : 0;\n\tconst a = lab.a !== undefined ? lab.a : 0;\n\tconst b = lab.b !== undefined ? lab.b : 0;\n\n\tconst ret = { mode: 'okhsl', l: toe(l) };\n\n\tif (lab.alpha !== undefined) {\n\t\tret.alpha = lab.alpha;\n\t}\n\tlet c = Math.sqrt(a * a + b * b);\n\tif (!c) {\n\t\tret.s = 0;\n\t\treturn ret;\n\t}\n\tlet [C_0, C_mid, C_max] = get_Cs(l, a / c, b / c);\n\tlet s;\n\tif (c < C_mid) {\n\t\tlet k_0 = 0;\n\t\tlet k_1 = 0.8 * C_0;\n\t\tlet k_2 = 1 - k_1 / C_mid;\n\t\tlet t = (c - k_0) / (k_1 + k_2 * (c - k_0));\n\t\ts = t * 0.8;\n\t} else {\n\t\tlet k_0 = C_mid;\n\t\tlet k_1 = (0.2 * C_mid * C_mid * 1.25 * 1.25) / C_0;\n\t\tlet k_2 = 1 - k_1 / (C_max - C_mid);\n\t\tlet t = (c - k_0) / (k_1 + k_2 * (c - k_0));\n\t\ts = 0.8 + 0.2 * t;\n\t}\n\tif (s) {\n\t\tret.s = s;\n\t\tret.h = normalizeHue((Math.atan2(b, a) * 180) / Math.PI);\n\t}\n\treturn ret;\n}\n","/*\n\tAdapted from code by Björn Ottosson,\n\treleased under the MIT license:\n\n\tCopyright (c) 2021 Björn Ottosson\n\n\tPermission is hereby granted, free of charge, to any person obtaining a copy of\n\tthis software and associated documentation files (the \"Software\"), to deal in\n\tthe Software without restriction, including without limitation the rights to\n\tuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n\tof the Software, and to permit persons to whom the Software is furnished to do\n\tso, subject to the following conditions:\n\n\tThe above copyright notice and this permission notice shall be included in all\n\tcopies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\tIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\tFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n\tAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n\tLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n\tOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n\tSOFTWARE.\n */\n\nimport { toe_inv, get_Cs } from './helpers.js';\n\nexport default function convertOkhslToOklab(hsl) {\n\tlet h = hsl.h !== undefined ? hsl.h : 0;\n\tlet s = hsl.s !== undefined ? hsl.s : 0;\n\tlet l = hsl.l !== undefined ? hsl.l : 0;\n\n\tconst ret = { mode: 'oklab', l: toe_inv(l) };\n\n\tif (hsl.alpha !== undefined) {\n\t\tret.alpha = hsl.alpha;\n\t}\n\n\tif (!s || l === 1) {\n\t\tret.a = ret.b = 0;\n\t\treturn ret;\n\t}\n\n\tlet a_ = Math.cos((h / 180) * Math.PI);\n\tlet b_ = Math.sin((h / 180) * Math.PI);\n\tlet [C_0, C_mid, C_max] = get_Cs(ret.l, a_, b_);\n\tlet t, k_0, k_1, k_2;\n\tif (s < 0.8) {\n\t\tt = 1.25 * s;\n\t\tk_0 = 0;\n\t\tk_1 = 0.8 * C_0;\n\t\tk_2 = 1 - k_1 / C_mid;\n\t} else {\n\t\tt = 5 * (s - 0.8);\n\t\tk_0 = C_mid;\n\t\tk_1 = (0.2 * C_mid * C_mid * 1.25 * 1.25) / C_0;\n\t\tk_2 = 1 - k_1 / (C_max - C_mid);\n\t}\n\tlet C = k_0 + (t * k_1) / (1 - k_2 * t);\n\tret.a = C * a_;\n\tret.b = C * b_;\n\n\treturn ret;\n}\n","import convertRgbToOklab from '../oklab/convertRgbToOklab.js';\nimport convertOklabToRgb from '../oklab/convertOklabToRgb.js';\nimport convertOklabToOkhsl from './convertOklabToOkhsl.js';\nimport convertOkhslToOklab from './convertOkhslToOklab.js';\n\nimport modeHsl from '../hsl/definition.js';\n\nconst modeOkhsl = {\n\t...modeHsl,\n\tmode: 'okhsl',\n\tchannels: ['h', 's', 'l', 'alpha'],\n\tparse: ['--okhsl'],\n\tserialize: '--okhsl',\n\tfromMode: {\n\t\toklab: convertOklabToOkhsl,\n\t\trgb: c => convertOklabToOkhsl(convertRgbToOklab(c))\n\t},\n\ttoMode: {\n\t\toklab: convertOkhslToOklab,\n\t\trgb: c => convertOklabToRgb(convertOkhslToOklab(c))\n\t}\n};\n\nexport default modeOkhsl;\n","/*\n\tAdapted from code by Björn Ottosson,\n\treleased under the MIT license:\n\n\tCopyright (c) 2021 Björn Ottosson\n\n\tPermission is hereby granted, free of charge, to any person obtaining a copy of\n\tthis software and associated documentation files (the \"Software\"), to deal in\n\tthe Software without restriction, including without limitation the rights to\n\tuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n\tof the Software, and to permit persons to whom the Software is furnished to do\n\tso, subject to the following conditions:\n\n\tThe above copyright notice and this permission notice shall be included in all\n\tcopies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\tIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\tFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n\tAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n\tLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n\tOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n\tSOFTWARE.\n */\n\nimport normalizeHue from '../util/normalizeHue.js';\nimport convertOklabToLrgb from '../oklab/convertOklabToLrgb.js';\nimport { get_ST_max, toe_inv, toe } from '../okhsl/helpers.js';\n\nexport default function convertOklabToOkhsv(lab) {\n\tlet l = lab.l !== undefined ? lab.l : 0;\n\tlet a = lab.a !== undefined ? lab.a : 0;\n\tlet b = lab.b !== undefined ? lab.b : 0;\n\n\tlet c = Math.sqrt(a * a + b * b);\n\n\t// TODO: c = 0\n\tlet a_ = c ? a / c : 1;\n\tlet b_ = c ? b / c : 1;\n\n\tlet [S_max, T] = get_ST_max(a_, b_);\n\tlet S_0 = 0.5;\n\tlet k = 1 - S_0 / S_max;\n\n\tlet t = T / (c + l * T);\n\tlet L_v = t * l;\n\tlet C_v = t * c;\n\n\tlet L_vt = toe_inv(L_v);\n\tlet C_vt = (C_v * L_vt) / L_v;\n\n\tlet rgb_scale = convertOklabToLrgb({ l: L_vt, a: a_ * C_vt, b: b_ * C_vt });\n\tlet scale_L = Math.cbrt(\n\t\t1 / Math.max(rgb_scale.r, rgb_scale.g, rgb_scale.b, 0)\n\t);\n\n\tl = l / scale_L;\n\tc = ((c / scale_L) * toe(l)) / l;\n\tl = toe(l);\n\n\tconst ret = {\n\t\tmode: 'okhsv',\n\t\ts: c ? ((S_0 + T) * C_v) / (T * S_0 + T * k * C_v) : 0,\n\t\tv: l ? l / L_v : 0\n\t};\n\tif (ret.s) {\n\t\tret.h = normalizeHue((Math.atan2(b, a) * 180) / Math.PI);\n\t}\n\tif (lab.alpha !== undefined) {\n\t\tret.alpha = lab.alpha;\n\t}\n\treturn ret;\n}\n","/*\n\tCopyright (c) 2021 Björn Ottosson\n\n\tPermission is hereby granted, free of charge, to any person obtaining a copy of\n\tthis software and associated documentation files (the \"Software\"), to deal in\n\tthe Software without restriction, including without limitation the rights to\n\tuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n\tof the Software, and to permit persons to whom the Software is furnished to do\n\tso, subject to the following conditions:\n\n\tThe above copyright notice and this permission notice shall be included in all\n\tcopies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\tIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\tFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n\tAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n\tLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n\tOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n\tSOFTWARE.\n */\n\nimport convertOklabToLrgb from '../oklab/convertOklabToLrgb.js';\nimport { get_ST_max, toe_inv } from '../okhsl/helpers.js';\n\nexport default function convertOkhsvToOklab(hsv) {\n\tconst ret = { mode: 'oklab' };\n\tif (hsv.alpha !== undefined) {\n\t\tret.alpha = hsv.alpha;\n\t}\n\n\tconst h = hsv.h !== undefined ? hsv.h : 0;\n\tconst s = hsv.s !== undefined ? hsv.s : 0;\n\tconst v = hsv.v !== undefined ? hsv.v : 0;\n\n\tconst a_ = Math.cos((h / 180) * Math.PI);\n\tconst b_ = Math.sin((h / 180) * Math.PI);\n\n\tconst [S_max, T] = get_ST_max(a_, b_);\n\tconst S_0 = 0.5;\n\tconst k = 1 - S_0 / S_max;\n\tconst L_v = 1 - (s * S_0) / (S_0 + T - T * k * s);\n\tconst C_v = (s * T * S_0) / (S_0 + T - T * k * s);\n\n\tconst L_vt = toe_inv(L_v);\n\tconst C_vt = (C_v * L_vt) / L_v;\n\tconst rgb_scale = convertOklabToLrgb({\n\t\tl: L_vt,\n\t\ta: a_ * C_vt,\n\t\tb: b_ * C_vt\n\t});\n\tconst scale_L = Math.cbrt(\n\t\t1 / Math.max(rgb_scale.r, rgb_scale.g, rgb_scale.b, 0)\n\t);\n\n\tconst L_new = toe_inv(v * L_v);\n\tconst C = (C_v * L_new) / L_v;\n\n\tret.l = L_new * scale_L;\n\tret.a = C * a_ * scale_L;\n\tret.b = C * b_ * scale_L;\n\n\treturn ret;\n}\n","import convertRgbToOklab from '../oklab/convertRgbToOklab.js';\nimport convertOklabToRgb from '../oklab/convertOklabToRgb.js';\nimport convertOklabToOkhsv from './convertOklabToOkhsv.js';\nimport convertOkhsvToOklab from './convertOkhsvToOklab.js';\n\nimport modeHsv from '../hsv/definition.js';\n\nconst modeOkhsv = {\n\t...modeHsv,\n\tmode: 'okhsv',\n\tchannels: ['h', 's', 'v', 'alpha'],\n\tparse: ['--okhsv'],\n\tserialize: '--okhsv',\n\tfromMode: {\n\t\toklab: convertOklabToOkhsv,\n\t\trgb: c => convertOklabToOkhsv(convertRgbToOklab(c))\n\t},\n\ttoMode: {\n\t\toklab: convertOkhsvToOklab,\n\t\trgb: c => convertOklabToRgb(convertOkhsvToOklab(c))\n\t}\n};\n\nexport default modeOkhsv;\n","import { Tok } from '../parse.js';\n\nfunction parseOklab(color, parsed) {\n\tif (!parsed || parsed[0] !== 'oklab') {\n\t\treturn undefined;\n\t}\n\tconst res = { mode: 'oklab' };\n\tconst [, l, a, b, alpha] = parsed;\n\tif (l.type === Tok.Hue || a.type === Tok.Hue || b.type === Tok.Hue) {\n\t\treturn undefined;\n\t}\n\tif (l.type !== Tok.None) {\n\t\tres.l = Math.min(\n\t\t\tMath.max(0, l.type === Tok.Number ? l.value : l.value / 100),\n\t\t\t1\n\t\t);\n\t}\n\tif (a.type !== Tok.None) {\n\t\tres.a = a.type === Tok.Number ? a.value : (a.value * 0.4) / 100;\n\t}\n\tif (b.type !== Tok.None) {\n\t\tres.b = b.type === Tok.Number ? b.value : (b.value * 0.4) / 100;\n\t}\n\tif (alpha.type !== Tok.None) {\n\t\tres.alpha = Math.min(\n\t\t\t1,\n\t\t\tMath.max(\n\t\t\t\t0,\n\t\t\t\talpha.type === Tok.Number ? alpha.value : alpha.value / 100\n\t\t\t)\n\t\t);\n\t}\n\n\treturn res;\n}\n\nexport default parseOklab;\n","import convertOklabToLrgb from './convertOklabToLrgb.js';\nimport convertLrgbToOklab from './convertLrgbToOklab.js';\nimport convertRgbToOklab from './convertRgbToOklab.js';\nimport convertOklabToRgb from './convertOklabToRgb.js';\nimport parseOklab from './parseOklab.js';\n\nimport lab from '../lab/definition.js';\n\n/*\n\tOklab, a perceptual color space for image processing by Björn Ottosson\n\tReference: https://bottosson.github.io/posts/oklab/\n */\n\nconst definition = {\n\t...lab,\n\tmode: 'oklab',\n\n\ttoMode: {\n\t\tlrgb: convertOklabToLrgb,\n\t\trgb: convertOklabToRgb\n\t},\n\n\tfromMode: {\n\t\tlrgb: convertLrgbToOklab,\n\t\trgb: convertRgbToOklab\n\t},\n\n\tranges: {\n\t\tl: [0, 1],\n\t\ta: [-0.4, 0.4],\n\t\tb: [-0.4, 0.4]\n\t},\n\n\tparse: [parseOklab],\n\tserialize: c =>\n\t\t`oklab(${c.l !== undefined ? c.l : 'none'} ${\n\t\t\tc.a !== undefined ? c.a : 'none'\n\t\t} ${c.b !== undefined ? c.b : 'none'}${\n\t\t\tc.alpha < 1 ? ` / ${c.alpha}` : ''\n\t\t})`\n};\n\nexport default definition;\n","import { Tok } from '../parse.js';\n\nfunction parseOklch(color, parsed) {\n\tif (!parsed || parsed[0] !== 'oklch') {\n\t\treturn undefined;\n\t}\n\tconst res = { mode: 'oklch' };\n\tconst [, l, c, h, alpha] = parsed;\n\tif (l.type !== Tok.None) {\n\t\tif (l.type === Tok.Hue) {\n\t\t\treturn undefined;\n\t\t}\n\t\tres.l = Math.min(\n\t\t\tMath.max(0, l.type === Tok.Number ? l.value : l.value / 100),\n\t\t\t1\n\t\t);\n\t}\n\tif (c.type !== Tok.None) {\n\t\tres.c = Math.max(\n\t\t\t0,\n\t\t\tc.type === Tok.Number ? c.value : (c.value * 0.4) / 100\n\t\t);\n\t}\n\tif (h.type !== Tok.None) {\n\t\tif (h.type === Tok.Percentage) {\n\t\t\treturn undefined;\n\t\t}\n\t\tres.h = h.value;\n\t}\n\tif (alpha.type !== Tok.None) {\n\t\tres.alpha = Math.min(\n\t\t\t1,\n\t\t\tMath.max(\n\t\t\t\t0,\n\t\t\t\talpha.type === Tok.Number ? alpha.value : alpha.value / 100\n\t\t\t)\n\t\t);\n\t}\n\n\treturn res;\n}\n\nexport default parseOklch;\n","import lch from '../lch/definition.js';\nimport convertLabToLch from '../lch/convertLabToLch.js';\nimport convertLchToLab from '../lch/convertLchToLab.js';\nimport convertOklabToRgb from '../oklab/convertOklabToRgb.js';\nimport convertRgbToOklab from '../oklab/convertRgbToOklab.js';\nimport parseOklch from './parseOklch.js';\n\nconst definition = {\n\t...lch,\n\tmode: 'oklch',\n\n\ttoMode: {\n\t\toklab: c => convertLchToLab(c, 'oklab'),\n\t\trgb: c => convertOklabToRgb(convertLchToLab(c, 'oklab'))\n\t},\n\n\tfromMode: {\n\t\trgb: c => convertLabToLch(convertRgbToOklab(c), 'oklch'),\n\t\toklab: c => convertLabToLch(c, 'oklch')\n\t},\n\n\tparse: [parseOklch],\n\tserialize: c =>\n\t\t`oklch(${c.l !== undefined ? c.l : 'none'} ${\n\t\t\tc.c !== undefined ? c.c : 'none'\n\t\t} ${c.h !== undefined ? c.h : 'none'}${\n\t\t\tc.alpha < 1 ? ` / ${c.alpha}` : ''\n\t\t})`,\n\n\tranges: {\n\t\tl: [0, 1],\n\t\tc: [0, 0.4],\n\t\th: [0, 360]\n\t}\n};\n\nexport default definition;\n","/*\n\tConvert Display P3 values to CIE XYZ D65\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n*/\n\nimport convertRgbToLrgb from '../lrgb/convertRgbToLrgb.js';\n\nconst convertP3ToXyz65 = rgb => {\n\tlet { r, g, b, alpha } = convertRgbToLrgb(rgb);\n\tlet res = {\n\t\tmode: 'xyz65',\n\t\tx:\n\t\t\t0.486570948648216 * r +\n\t\t\t0.265667693169093 * g +\n\t\t\t0.1982172852343625 * b,\n\t\ty:\n\t\t\t0.2289745640697487 * r +\n\t\t\t0.6917385218365062 * g +\n\t\t\t0.079286914093745 * b,\n\t\tz: 0.0 * r + 0.0451133818589026 * g + 1.043944368900976 * b\n\t};\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertP3ToXyz65;\n","/*\n\tCIE XYZ D65 values to Display P3.\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n*/\n\nimport convertLrgbToRgb from '../lrgb/convertLrgbToRgb.js';\n\nconst convertXyz65ToP3 = ({ x, y, z, alpha }) => {\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet res = convertLrgbToRgb(\n\t\t{\n\t\t\tr:\n\t\t\t\tx * 2.4934969119414263 -\n\t\t\t\ty * 0.9313836179191242 -\n\t\t\t\t0.402710784450717 * z,\n\t\t\tg:\n\t\t\t\tx * -0.8294889695615749 +\n\t\t\t\ty * 1.7626640603183465 +\n\t\t\t\t0.0236246858419436 * z,\n\t\t\tb:\n\t\t\t\tx * 0.0358458302437845 -\n\t\t\t\ty * 0.0761723892680418 +\n\t\t\t\t0.9568845240076871 * z\n\t\t},\n\t\t'p3'\n\t);\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertXyz65ToP3;\n","import rgb from '../rgb/definition.js';\nimport convertP3ToXyz65 from './convertP3ToXyz65.js';\nimport convertXyz65ToP3 from './convertXyz65ToP3.js';\nimport convertRgbToXyz65 from '../xyz65/convertRgbToXyz65.js';\nimport convertXyz65ToRgb from '../xyz65/convertXyz65ToRgb.js';\n\nconst definition = {\n\t...rgb,\n\tmode: 'p3',\n\tparse: ['display-p3'],\n\tserialize: 'display-p3',\n\n\tfromMode: {\n\t\trgb: color => convertXyz65ToP3(convertRgbToXyz65(color)),\n\t\txyz65: convertXyz65ToP3\n\t},\n\n\ttoMode: {\n\t\trgb: color => convertXyz65ToRgb(convertP3ToXyz65(color)),\n\t\txyz65: convertP3ToXyz65\n\t}\n};\n\nexport default definition;\n","/*\n\tConvert CIE XYZ D50 values to ProPhoto RGB\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n*/\n\nconst gamma = v => {\n\tlet abs = Math.abs(v);\n\tif (abs >= 1 / 512) {\n\t\treturn Math.sign(v) * Math.pow(abs, 1 / 1.8);\n\t}\n\treturn 16 * v;\n};\n\nconst convertXyz50ToProphoto = ({ x, y, z, alpha }) => {\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet res = {\n\t\tmode: 'prophoto',\n\t\tr: gamma(\n\t\t\tx * 1.3457868816471585 -\n\t\t\t\ty * 0.2555720873797946 -\n\t\t\t\t0.0511018649755453 * z\n\t\t),\n\t\tg: gamma(\n\t\t\tx * -0.5446307051249019 +\n\t\t\t\ty * 1.5082477428451466 +\n\t\t\t\t0.0205274474364214 * z\n\t\t),\n\t\tb: gamma(x * 0.0 + y * 0.0 + 1.2119675456389452 * z)\n\t};\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertXyz50ToProphoto;\n","/*\n\tConvert ProPhoto RGB values to CIE XYZ D50\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n*/\n\nconst linearize = (v = 0) => {\n\tlet abs = Math.abs(v);\n\tif (abs >= 16 / 512) {\n\t\treturn Math.sign(v) * Math.pow(abs, 1.8);\n\t}\n\treturn v / 16;\n};\n\nconst convertProphotoToXyz50 = prophoto => {\n\tlet r = linearize(prophoto.r);\n\tlet g = linearize(prophoto.g);\n\tlet b = linearize(prophoto.b);\n\tlet res = {\n\t\tmode: 'xyz50',\n\t\tx:\n\t\t\t0.7977666449006423 * r +\n\t\t\t0.1351812974005331 * g +\n\t\t\t0.0313477341283922 * b,\n\t\ty:\n\t\t\t0.2880748288194013 * r +\n\t\t\t0.7118352342418731 * g +\n\t\t\t0.0000899369387256 * b,\n\t\tz: 0 * r + 0 * g + 0.8251046025104602 * b\n\t};\n\tif (prophoto.alpha !== undefined) {\n\t\tres.alpha = prophoto.alpha;\n\t}\n\treturn res;\n};\n\nexport default convertProphotoToXyz50;\n","import rgb from '../rgb/definition.js';\n\nimport convertXyz50ToProphoto from './convertXyz50ToProphoto.js';\nimport convertProphotoToXyz50 from './convertProphotoToXyz50.js';\n\nimport convertXyz50ToRgb from '../xyz50/convertXyz50ToRgb.js';\nimport convertRgbToXyz50 from '../xyz50/convertRgbToXyz50.js';\n\n/*\n\tProPhoto RGB Color space\n\n\tReferences:\n\t\t* https://en.wikipedia.org/wiki/ProPhoto_RGB_color_space\n */\n\nconst definition = {\n\t...rgb,\n\tmode: 'prophoto',\n\tparse: ['prophoto-rgb'],\n\tserialize: 'prophoto-rgb',\n\n\tfromMode: {\n\t\txyz50: convertXyz50ToProphoto,\n\t\trgb: color => convertXyz50ToProphoto(convertRgbToXyz50(color))\n\t},\n\n\ttoMode: {\n\t\txyz50: convertProphotoToXyz50,\n\t\trgb: color => convertXyz50ToRgb(convertProphotoToXyz50(color))\n\t}\n};\n\nexport default definition;\n","/*\n\tConvert CIE XYZ D65 values to Rec. 2020\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n\t\t* https://www.itu.int/rec/R-REC-BT.2020/en\n*/\n\nconst α = 1.09929682680944;\nconst β = 0.018053968510807;\nconst gamma = v => {\n\tconst abs = Math.abs(v);\n\tif (abs > β) {\n\t\treturn (Math.sign(v) || 1) * (α * Math.pow(abs, 0.45) - (α - 1));\n\t}\n\treturn 4.5 * v;\n};\n\nconst convertXyz65ToRec2020 = ({ x, y, z, alpha }) => {\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet res = {\n\t\tmode: 'rec2020',\n\t\tr: gamma(\n\t\t\tx * 1.7166511879712683 -\n\t\t\t\ty * 0.3556707837763925 -\n\t\t\t\t0.2533662813736599 * z\n\t\t),\n\t\tg: gamma(\n\t\t\tx * -0.6666843518324893 +\n\t\t\t\ty * 1.6164812366349395 +\n\t\t\t\t0.0157685458139111 * z\n\t\t),\n\t\tb: gamma(\n\t\t\tx * 0.0176398574453108 -\n\t\t\t\ty * 0.0427706132578085 +\n\t\t\t\t0.9421031212354739 * z\n\t\t)\n\t};\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertXyz65ToRec2020;\n","/*\n\tConvert Rec. 2020 values to CIE XYZ D65\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n\t\t* https://www.itu.int/rec/R-REC-BT.2020/en\n*/\n\nconst α = 1.09929682680944;\nconst β = 0.018053968510807;\n\nconst linearize = (v = 0) => {\n\tlet abs = Math.abs(v);\n\tif (abs < β * 4.5) {\n\t\treturn v / 4.5;\n\t}\n\treturn (Math.sign(v) || 1) * Math.pow((abs + α - 1) / α, 1 / 0.45);\n};\n\nconst convertRec2020ToXyz65 = rec2020 => {\n\tlet r = linearize(rec2020.r);\n\tlet g = linearize(rec2020.g);\n\tlet b = linearize(rec2020.b);\n\tlet res = {\n\t\tmode: 'xyz65',\n\t\tx:\n\t\t\t0.6369580483012911 * r +\n\t\t\t0.1446169035862083 * g +\n\t\t\t0.1688809751641721 * b,\n\t\ty:\n\t\t\t0.262700212011267 * r +\n\t\t\t0.6779980715188708 * g +\n\t\t\t0.059301716469862 * b,\n\t\tz: 0 * r + 0.0280726930490874 * g + 1.0609850577107909 * b\n\t};\n\tif (rec2020.alpha !== undefined) {\n\t\tres.alpha = rec2020.alpha;\n\t}\n\treturn res;\n};\n\nexport default convertRec2020ToXyz65;\n","import rgb from '../rgb/definition.js';\n\nimport convertXyz65ToRec2020 from './convertXyz65ToRec2020.js';\nimport convertRec2020ToXyz65 from './convertRec2020ToXyz65.js';\n\nimport convertRgbToXyz65 from '../xyz65/convertRgbToXyz65.js';\nimport convertXyz65ToRgb from '../xyz65/convertXyz65ToRgb.js';\n\nconst definition = {\n\t...rgb,\n\tmode: 'rec2020',\n\n\tfromMode: {\n\t\txyz65: convertXyz65ToRec2020,\n\t\trgb: color => convertXyz65ToRec2020(convertRgbToXyz65(color))\n\t},\n\n\ttoMode: {\n\t\txyz65: convertRec2020ToXyz65,\n\t\trgb: color => convertXyz65ToRgb(convertRec2020ToXyz65(color))\n\t},\n\n\tparse: ['rec2020'],\n\tserialize: 'rec2020'\n};\n\nexport default definition;\n","export const bias = 0.00379307325527544933;\nexport const bias_cbrt = Math.cbrt(bias);\n","import convertRgbToLrgb from '../lrgb/convertRgbToLrgb.js';\nimport { bias, bias_cbrt } from './constants.js';\n\nconst transfer = v => Math.cbrt(v) - bias_cbrt;\n\nconst convertRgbToXyb = color => {\n\tconst { r, g, b, alpha } = convertRgbToLrgb(color);\n\tconst l = transfer(0.3 * r + 0.622 * g + 0.078 * b + bias);\n\tconst m = transfer(0.23 * r + 0.692 * g + 0.078 * b + bias);\n\tconst s = transfer(\n\t\t0.24342268924547819 * r +\n\t\t\t0.20476744424496821 * g +\n\t\t\t0.5518098665095536 * b +\n\t\t\tbias\n\t);\n\tconst res = {\n\t\tmode: 'xyb',\n\t\tx: (l - m) / 2,\n\t\ty: (l + m) / 2,\n\t\t/* Apply default chroma from luma (subtract Y from B) */\n\t\tb: s - (l + m) / 2\n\t};\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertRgbToXyb;\n","import convertLrgbToRgb from '../lrgb/convertLrgbToRgb.js';\nimport { bias, bias_cbrt } from './constants.js';\n\nconst transfer = v => Math.pow(v + bias_cbrt, 3);\n\nconst convertXybToRgb = ({ x, y, b, alpha }) => {\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (b === undefined) b = 0;\n\tconst l = transfer(x + y) - bias;\n\tconst m = transfer(y - x) - bias;\n\t/* Account for chroma from luma: add Y back to B */\n\tconst s = transfer(b + y) - bias;\n\n\tconst res = convertLrgbToRgb({\n\t\tr:\n\t\t\t11.031566904639861 * l -\n\t\t\t9.866943908131562 * m -\n\t\t\t0.16462299650829934 * s,\n\t\tg:\n\t\t\t-3.2541473810744237 * l +\n\t\t\t4.418770377582723 * m -\n\t\t\t0.16462299650829934 * s,\n\t\tb:\n\t\t\t-3.6588512867136815 * l +\n\t\t\t2.7129230459360922 * m +\n\t\t\t1.9459282407775895 * s\n\t});\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertXybToRgb;\n","import { interpolatorLinear } from '../interpolate/linear.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport convertRgbToXyb from './convertRgbToXyb.js';\nimport convertXybToRgb from './convertXybToRgb.js';\n\n/*\n\tThe XYB color space, used in JPEG XL.\n\tReference: https://ds.jpeg.org/whitepapers/jpeg-xl-whitepaper.pdf\n*/\n\nconst definition = {\n\tmode: 'xyb',\n\tchannels: ['x', 'y', 'b', 'alpha'],\n\tparse: ['--xyb'],\n\tserialize: '--xyb',\n\n\ttoMode: {\n\t\trgb: convertXybToRgb\n\t},\n\n\tfromMode: {\n\t\trgb: convertRgbToXyb\n\t},\n\n\tranges: {\n\t\tx: [-0.0154, 0.0281],\n\t\ty: [0, 0.8453],\n\t\tb: [-0.2778, 0.388]\n\t},\n\n\tinterpolate: {\n\t\tx: interpolatorLinear,\n\t\ty: interpolatorLinear,\n\t\tb: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t}\n};\n\nexport default definition;\n","/*\n\tThe XYZ D50 color space\n\t-----------------------\n */\n\nimport convertXyz50ToRgb from './convertXyz50ToRgb.js';\nimport convertXyz50ToLab from '../lab/convertXyz50ToLab.js';\nimport convertRgbToXyz50 from './convertRgbToXyz50.js';\nimport convertLabToXyz50 from '../lab/convertLabToXyz50.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\n\nconst definition = {\n\tmode: 'xyz50',\n\tparse: ['xyz-d50'],\n\tserialize: 'xyz-d50',\n\n\ttoMode: {\n\t\trgb: convertXyz50ToRgb,\n\t\tlab: convertXyz50ToLab\n\t},\n\n\tfromMode: {\n\t\trgb: convertRgbToXyz50,\n\t\tlab: convertLabToXyz50\n\t},\n\n\tchannels: ['x', 'y', 'z', 'alpha'],\n\n\tranges: {\n\t\tx: [0, 0.964],\n\t\ty: [0, 0.999],\n\t\tz: [0, 0.825]\n\t},\n\n\tinterpolate: {\n\t\tx: interpolatorLinear,\n\t\ty: interpolatorLinear,\n\t\tz: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t}\n};\n\nexport default definition;\n","/*\n\tChromatic adaptation of CIE XYZ from D65 to D50 white point\n\tusing the Bradford method.\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html\t\n*/\n\nconst convertXyz65ToXyz50 = xyz65 => {\n\tlet { x, y, z, alpha } = xyz65;\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet res = {\n\t\tmode: 'xyz50',\n\t\tx:\n\t\t\t1.0479298208405488 * x +\n\t\t\t0.0229467933410191 * y -\n\t\t\t0.0501922295431356 * z,\n\t\ty:\n\t\t\t0.0296278156881593 * x +\n\t\t\t0.990434484573249 * y -\n\t\t\t0.0170738250293851 * z,\n\t\tz:\n\t\t\t-0.0092430581525912 * x +\n\t\t\t0.0150551448965779 * y +\n\t\t\t0.7518742899580008 * z\n\t};\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertXyz65ToXyz50;\n","/*\n\tChromatic adaptation of CIE XYZ from D50 to D65 white point\n\tusing the Bradford method.\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html\t\n*/\n\nconst convertXyz50ToXyz65 = xyz50 => {\n\tlet { x, y, z, alpha } = xyz50;\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet res = {\n\t\tmode: 'xyz65',\n\t\tx:\n\t\t\t0.9554734527042182 * x -\n\t\t\t0.0230985368742614 * y +\n\t\t\t0.0632593086610217 * z,\n\t\ty:\n\t\t\t-0.0283697069632081 * x +\n\t\t\t1.0099954580058226 * y +\n\t\t\t0.021041398966943 * z,\n\t\tz:\n\t\t\t0.0123140016883199 * x -\n\t\t\t0.0205076964334779 * y +\n\t\t\t1.3303659366080753 * z\n\t};\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertXyz50ToXyz65;\n","/*\n\tThe XYZ D65 color space\n\t-----------------------\n */\n\nimport convertXyz65ToRgb from './convertXyz65ToRgb.js';\nimport convertRgbToXyz65 from './convertRgbToXyz65.js';\n\nimport convertXyz65ToXyz50 from './convertXyz65ToXyz50.js';\nimport convertXyz50ToXyz65 from './convertXyz50ToXyz65.js';\n\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\n\nconst definition = {\n\tmode: 'xyz65',\n\n\ttoMode: {\n\t\trgb: convertXyz65ToRgb,\n\t\txyz50: convertXyz65ToXyz50\n\t},\n\n\tfromMode: {\n\t\trgb: convertRgbToXyz65,\n\t\txyz50: convertXyz50ToXyz65\n\t},\n\n\tranges: {\n\t\tx: [0, 0.95],\n\t\ty: [0, 1],\n\t\tz: [0, 1.088]\n\t},\n\n\tchannels: ['x', 'y', 'z', 'alpha'],\n\n\tparse: ['xyz', 'xyz-d65'],\n\tserialize: 'xyz-d65',\n\n\tinterpolate: {\n\t\tx: interpolatorLinear,\n\t\ty: interpolatorLinear,\n\t\tz: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t}\n};\n\nexport default definition;\n","const convertRgbToYiq = ({ r, g, b, alpha }) => {\n\tif (r === undefined) r = 0;\n\tif (g === undefined) g = 0;\n\tif (b === undefined) b = 0;\n\tconst res = {\n\t\tmode: 'yiq',\n\t\ty: 0.29889531 * r + 0.58662247 * g + 0.11448223 * b,\n\t\ti: 0.59597799 * r - 0.2741761 * g - 0.32180189 * b,\n\t\tq: 0.21147017 * r - 0.52261711 * g + 0.31114694 * b\n\t};\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertRgbToYiq;\n","const convertYiqToRgb = ({ y, i, q, alpha }) => {\n\tif (y === undefined) y = 0;\n\tif (i === undefined) i = 0;\n\tif (q === undefined) q = 0;\n\tconst res = {\n\t\tmode: 'rgb',\n\t\tr: y + 0.95608445 * i + 0.6208885 * q,\n\t\tg: y - 0.27137664 * i - 0.6486059 * q,\n\t\tb: y - 1.10561724 * i + 1.70250126 * q\n\t};\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertYiqToRgb;\n","import convertRgbToYiq from './convertRgbToYiq.js';\nimport convertYiqToRgb from './convertYiqToRgb.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\n\n/*\n\tYIQ Color Space\n\n\tReferences\n\t----------\n\n\tWikipedia:\n\t\thttps://en.wikipedia.org/wiki/YIQ\n\n\t\"Measuring perceived color difference using YIQ NTSC\n\ttransmission color space in mobile applications\"\n\t\t\n\t\tby Yuriy Kotsarenko, Fernando Ramos in:\n\t\tProgramación Matemática y Software (2010) \n\n\tAvailable at:\n\t\t\n\t\thttp://www.progmat.uaem.mx:8080/artVol2Num2/Articulo3Vol2Num2.pdf\n */\n\nconst definition = {\n\tmode: 'yiq',\n\n\ttoMode: {\n\t\trgb: convertYiqToRgb\n\t},\n\n\tfromMode: {\n\t\trgb: convertRgbToYiq\n\t},\n\n\tchannels: ['y', 'i', 'q', 'alpha'],\n\n\tparse: ['--yiq'],\n\tserialize: '--yiq',\n\n\tranges: {\n\t\ti: [-0.595, 0.595],\n\t\tq: [-0.522, 0.522]\n\t},\n\n\tinterpolate: {\n\t\ty: interpolatorLinear,\n\t\ti: interpolatorLinear,\n\t\tq: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t}\n};\n\nexport default definition;\n","import converter from './converter.js';\nimport round from './round.js';\nimport prepare from './_prepare.js';\nimport { getMode } from './modes.js';\n\nlet twoDecimals = round(2);\n\nconst clamp = value => Math.max(0, Math.min(1, value || 0));\nconst fixup = value => Math.round(clamp(value) * 255);\n\nconst rgb = converter('rgb');\nconst hsl = converter('hsl');\n\nexport const serializeHex = color => {\n\tif (color === undefined) {\n\t\treturn undefined;\n\t}\n\n\tlet r = fixup(color.r);\n\tlet g = fixup(color.g);\n\tlet b = fixup(color.b);\n\n\treturn '#' + ((1 << 24) | (r << 16) | (g << 8) | b).toString(16).slice(1);\n};\n\nexport const serializeHex8 = color => {\n\tif (color === undefined) {\n\t\treturn undefined;\n\t}\n\n\tlet a = fixup(color.alpha !== undefined ? color.alpha : 1);\n\treturn serializeHex(color) + ((1 << 8) | a).toString(16).slice(1);\n};\n\nexport const serializeRgb = color => {\n\tif (color === undefined) {\n\t\treturn undefined;\n\t}\n\n\tlet r = fixup(color.r);\n\tlet g = fixup(color.g);\n\tlet b = fixup(color.b);\n\n\tif (color.alpha === undefined || color.alpha === 1) {\n\t\t// opaque color\n\t\treturn `rgb(${r}, ${g}, ${b})`;\n\t} else {\n\t\t// transparent color\n\t\treturn `rgba(${r}, ${g}, ${b}, ${twoDecimals(clamp(color.alpha))})`;\n\t}\n};\n\nexport const serializeHsl = color => {\n\tif (color === undefined) {\n\t\treturn undefined;\n\t}\n\n\tconst h = twoDecimals(color.h || 0);\n\tconst s = twoDecimals(clamp(color.s) * 100) + '%';\n\tconst l = twoDecimals(clamp(color.l) * 100) + '%';\n\n\tif (color.alpha === undefined || color.alpha === 1) {\n\t\t// opaque color\n\t\treturn `hsl(${h}, ${s}, ${l})`;\n\t} else {\n\t\t// transparent color\n\t\treturn `hsla(${h}, ${s}, ${l}, ${twoDecimals(clamp(color.alpha))})`;\n\t}\n};\n\nexport const formatCss = c => {\n\tconst color = prepare(c);\n\tif (!color) {\n\t\treturn undefined;\n\t}\n\tconst def = getMode(color.mode);\n\tif (!def.serialize || typeof def.serialize === 'string') {\n\t\tlet res = `color(${def.serialize || `--${color.mode}`} `;\n\t\tdef.channels.forEach((ch, i) => {\n\t\t\tif (ch !== 'alpha') {\n\t\t\t\tres +=\n\t\t\t\t\t(i ? ' ' : '') +\n\t\t\t\t\t(color[ch] !== undefined ? color[ch] : 'none');\n\t\t\t}\n\t\t});\n\t\tif (color.alpha !== undefined && color.alpha < 1) {\n\t\t\tres += ` / ${color.alpha}`;\n\t\t}\n\t\treturn res + ')';\n\t}\n\tif (typeof def.serialize === 'function') {\n\t\treturn def.serialize(color);\n\t}\n\treturn undefined;\n};\n\nexport const formatHex = c => serializeHex(rgb(c));\nexport const formatHex8 = c => serializeHex8(rgb(c));\nexport const formatRgb = c => serializeRgb(rgb(c));\nexport const formatHsl = c => serializeHsl(hsl(c));\n","import converter from './converter.js';\nimport prepare from './_prepare.js';\nimport { getMode } from './modes.js';\nimport { differenceEuclidean } from './difference.js';\n\nconst rgb = converter('rgb');\nconst fixup_rgb = c => {\n\tconst res = {\n\t\tmode: c.mode,\n\t\tr: Math.max(0, Math.min(c.r !== undefined ? c.r : 0, 1)),\n\t\tg: Math.max(0, Math.min(c.g !== undefined ? c.g : 0, 1)),\n\t\tb: Math.max(0, Math.min(c.b !== undefined ? c.b : 0, 1))\n\t};\n\tif (c.alpha !== undefined) {\n\t\tres.alpha = c.alpha;\n\t}\n\treturn res;\n};\n\nconst to_displayable_srgb = c => fixup_rgb(rgb(c));\n\nconst inrange_rgb = c => {\n\treturn (\n\t\tc !== undefined &&\n\t\t(c.r === undefined || (c.r >= 0 && c.r <= 1)) &&\n\t\t(c.g === undefined || (c.g >= 0 && c.g <= 1)) &&\n\t\t(c.b === undefined || (c.b >= 0 && c.b <= 1))\n\t);\n};\n\n/*\n\tReturns whether the color is in the sRGB gamut.\n */\nexport function displayable(color) {\n\treturn inrange_rgb(rgb(color));\n}\n\n/*\n\tGiven a color space `mode`, returns a function\n\twith which to check whether a color is \n\tin that color space's gamut.\n */\nexport function inGamut(mode = 'rgb') {\n\tconst { gamut } = getMode(mode);\n\tif (!gamut) {\n\t\treturn color => true;\n\t}\n\tconst conv = converter(typeof gamut === 'string' ? gamut : mode);\n\treturn color => inrange_rgb(conv(color));\n}\n\n/*\n\tObtain a color that's in the sRGB gamut\n\tby converting it to sRGB and clipping the channel values\n\tso that they're within the [0, 1] range.\n\n\tThe result is returned in the color's original color space.\n */\nexport function clampRgb(color) {\n\tcolor = prepare(color);\n\n\t// if the color is undefined or displayable, return it directly\n\tif (color === undefined || displayable(color)) return color;\n\n\t// keep track of color's original mode\n\tlet conv = converter(color.mode);\n\n\treturn conv(to_displayable_srgb(color));\n}\n\n/*\n\tGiven the `mode` color space, returns a function\n\twith which to obtain a color that's in gamut for\n\tthe `mode` color space by clipping the channel values\n\tso that they fit in their respective ranges.\n\n\tIt's similar to `clampRgb`, but works for any \n\tbounded color space (RGB or not) for which \n\tany combination of in-range channel values\n\tproduces an in-gamut color.\n */\nexport function clampGamut(mode = 'rgb') {\n\tconst { gamut } = getMode(mode);\n\tif (!gamut) {\n\t\treturn color => prepare(color);\n\t}\n\tconst destMode = typeof gamut === 'string' ? gamut : mode;\n\tconst destConv = converter(destMode);\n\tconst inDestGamut = inGamut(destMode);\n\treturn color => {\n\t\tconst original = prepare(color);\n\t\tif (!original) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst converted = destConv(original);\n\t\tif (inDestGamut(converted)) {\n\t\t\treturn original;\n\t\t}\n\t\tconst clamped = fixup_rgb(converted);\n\t\tif (original.mode === clamped.mode) {\n\t\t\treturn clamped;\n\t\t}\n\t\treturn converter(original.mode)(clamped);\n\t};\n}\n\n/*\n\tObtain a color that’s in a RGB gamut (by default sRGB)\n\tby first converting it to `mode` and then finding \n\tthe greatest chroma value that fits the gamut.\n\n\tBy default, the CIELCh color space is used,\n\tbut any color that has a chroma component will do.\n\n\tThe result is returned in the color's original color space.\n */\nexport function clampChroma(color, mode = 'lch', rgbGamut = 'rgb') {\n\tcolor = prepare(color);\n\n\tlet inDestinationGamut =\n\t\trgbGamut === 'rgb' ? displayable : inGamut(rgbGamut);\n\tlet clipToGamut =\n\t\trgbGamut === 'rgb' ? to_displayable_srgb : clampGamut(rgbGamut);\n\n\t// if the color is undefined or displayable, return it directly\n\tif (color === undefined || inDestinationGamut(color)) return color;\n\n\t// keep track of color's original mode\n\tlet conv = converter(color.mode);\n\n\t// convert to the provided `mode` for clamping\n\tcolor = converter(mode)(color);\n\n\t// try with chroma = 0\n\tlet clamped = { ...color, c: 0 };\n\n\t// if not even chroma = 0 is displayable\n\t// fall back to RGB clamping\n\tif (!inDestinationGamut(clamped)) {\n\t\treturn conv(clipToGamut(clamped));\n\t}\n\n\t// By this time we know chroma = 0 is displayable and our current chroma is not.\n\t// Find the displayable chroma through the bisection method.\n\tlet start = 0;\n\tlet end = color.c !== undefined ? color.c : 0;\n\tlet range = getMode(mode).ranges.c;\n\tlet resolution = (range[1] - range[0]) / Math.pow(2, 13);\n\tlet _last_good_c = clamped.c;\n\n\twhile (end - start > resolution) {\n\t\tclamped.c = start + (end - start) * 0.5;\n\t\tif (inDestinationGamut(clamped)) {\n\t\t\t_last_good_c = clamped.c;\n\t\t\tstart = clamped.c;\n\t\t} else {\n\t\t\tend = clamped.c;\n\t\t}\n\t}\n\n\treturn conv(\n\t\tinDestinationGamut(clamped) ? clamped : { ...clamped, c: _last_good_c }\n\t);\n}\n\n/*\n\tObtain a color that's in the `dest` gamut,\n\tby first converting it to the `mode` color space\n\tand then finding the largest chroma that's in gamut,\n\tsimilar to `clampChroma`. \n\n\tThe color returned is in the `dest` color space.\n\n\tTo address the shortcomings of `clampChroma`, which can\n\tsometimes produce colors more desaturated than necessary,\n\tthe test used in the binary search is replaced with\n\t\"is color is roughly in gamut\", by comparing the candidate \n\tto the clipped version (obtained with `clampGamut`).\n\tThe test passes if the colors are not too dissimilar, \n\tjudged by the `delta` color difference function \n\tand an associated `jnd` just-noticeable difference value.\n\n\tThe default arguments for this function correspond to the\n\tgamut mapping algorithm defined in CSS Color Level 4:\n\thttps://drafts.csswg.org/css-color/#css-gamut-mapping\n\n\tTo disable the “roughly in gamut” part, pass either\n\t`null` for the `delta` parameter, or zero for `jnd`.\n */\nexport function toGamut(\n\tdest = 'rgb',\n\tmode = 'oklch',\n\tdelta = differenceEuclidean('oklch'),\n\tjnd = 0.02\n) {\n\tconst destConv = converter(dest);\n\tconst destMode = getMode(dest);\n\n\tif (!destMode.gamut) {\n\t\treturn color => destConv(color);\n\t}\n\n\tconst inDestinationGamut = inGamut(dest);\n\tconst clipToGamut = clampGamut(dest);\n\n\tconst ucs = converter(mode);\n\tconst { ranges } = getMode(mode);\n\n\tif (!ranges.l || !ranges.c) {\n\t\tthrow new Error('LCH-like space expected');\n\t}\n\n\treturn color => {\n\t\tcolor = prepare(color);\n\t\tif (color === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst candidate = { ...ucs(color) };\n\n\t\t// account for missing components\n\t\tif (candidate.l === undefined) candidate.l = 0;\n\t\tif (candidate.c === undefined) candidate.c = 0;\n\n\t\tif (candidate.l >= ranges.l[1]) {\n\t\t\tconst res = { ...destMode.white, mode: dest };\n\t\t\tif (color.alpha !== undefined) {\n\t\t\t\tres.alpha = color.alpha;\n\t\t\t}\n\t\t\treturn res;\n\t\t}\n\t\tif (candidate.l <= ranges.l[0]) {\n\t\t\tconst res = { ...destMode.black, mode: dest };\n\t\t\tif (color.alpha !== undefined) {\n\t\t\t\tres.alpha = color.alpha;\n\t\t\t}\n\t\t\treturn res;\n\t\t}\n\t\tif (inDestinationGamut(candidate)) {\n\t\t\treturn destConv(candidate);\n\t\t}\n\t\tlet start = 0;\n\t\tlet end = candidate.c;\n\t\tlet epsilon = (ranges.c[1] - ranges.c[0]) / 4000; // 0.0001 for oklch()\n\t\tlet clipped = clipToGamut(candidate);\n\t\twhile (end - start > epsilon) {\n\t\t\tcandidate.c = (start + end) * 0.5;\n\t\t\tclipped = clipToGamut(candidate);\n\t\t\tif (\n\t\t\t\tinDestinationGamut(candidate) ||\n\t\t\t\t(delta && jnd > 0 && delta(candidate, clipped) <= jnd)\n\t\t\t) {\n\t\t\t\tstart = candidate.c;\n\t\t\t} else {\n\t\t\t\tend = candidate.c;\n\t\t\t}\n\t\t}\n\t\treturn destConv(inDestinationGamut(candidate) ? candidate : clipped);\n\t};\n}\n","import converter from './converter.js';\n\n/*\n\tWCAG luminance\n\tReferences: \n\n\thttps://en.wikipedia.org/wiki/Relative_luminance\n\thttps://github.com/w3c/wcag/issues/236#issuecomment-379526596\n */\nexport function luminance(color) {\n\tlet c = converter('lrgb')(color);\n\treturn 0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b;\n}\n\n/*\n\tWCAG contrast\n */\nexport function contrast(a, b) {\n\tlet L1 = luminance(a);\n\tlet L2 = luminance(b);\n\treturn (Math.max(L1, L2) + 0.05) / (Math.min(L1, L2) + 0.05);\n}\n","// Color space definitions\nimport modeA98 from './a98/definition.js';\nimport modeCubehelix from './cubehelix/definition.js';\nimport modeDlab from './dlab/definition.js';\nimport modeDlch from './dlch/definition.js';\nimport modeHsi from './hsi/definition.js';\nimport modeHsl from './hsl/definition.js';\nimport modeHsv from './hsv/definition.js';\nimport modeHwb from './hwb/definition.js';\nimport modeItp from './itp/definition.js';\nimport modeJab from './jab/definition.js';\nimport modeJch from './jch/definition.js';\nimport modeLab from './lab/definition.js';\nimport modeLab65 from './lab65/definition.js';\nimport modeLch from './lch/definition.js';\nimport modeLch65 from './lch65/definition.js';\nimport modeLchuv from './lchuv/definition.js';\nimport modeLrgb from './lrgb/definition.js';\nimport modeLuv from './luv/definition.js';\nimport modeOkhsl from './okhsl/modeOkhsl.js';\nimport modeOkhsv from './okhsv/modeOkhsv.js';\nimport modeOklab from './oklab/definition.js';\nimport modeOklch from './oklch/definition.js';\nimport modeP3 from './p3/definition.js';\nimport modeProphoto from './prophoto/definition.js';\nimport modeRec2020 from './rec2020/definition.js';\nimport modeRgb from './rgb/definition.js';\nimport modeXyb from './xyb/definition.js';\nimport modeXyz50 from './xyz50/definition.js';\nimport modeXyz65 from './xyz65/definition.js';\nimport modeYiq from './yiq/definition.js';\nimport { useMode } from './modes.js';\n\nexport { default as converter } from './converter.js';\n\nexport {\n\tserializeHex,\n\tserializeHex8,\n\tserializeRgb,\n\tserializeHsl,\n\tformatHex,\n\tformatHex8,\n\tformatRgb,\n\tformatHsl,\n\tformatCss\n} from './formatter.js';\n\nexport { default as colorsNamed } from './colors/named.js';\nexport { default as blend } from './blend.js';\nexport { default as random } from './random.js';\n\nexport {\n\tfixupHueShorter,\n\tfixupHueLonger,\n\tfixupHueIncreasing,\n\tfixupHueDecreasing\n} from './fixup/hue.js';\n\nexport { fixupAlpha } from './fixup/alpha.js';\n\nexport {\n\tmapper,\n\tmapAlphaMultiply,\n\tmapAlphaDivide,\n\tmapTransferLinear,\n\tmapTransferGamma\n} from './map.js';\n\nexport { average, averageAngle, averageNumber } from './average.js';\n\nexport { default as round } from './round.js';\nexport {\n\tinterpolate,\n\tinterpolateWith,\n\tinterpolateWithPremultipliedAlpha\n} from './interpolate/interpolate.js';\n\nexport { interpolatorLinear } from './interpolate/linear.js';\n\nexport { interpolatorPiecewise } from './interpolate/piecewise.js';\n\nexport {\n\tinterpolatorSplineBasis,\n\tinterpolatorSplineBasisClosed\n} from './interpolate/splineBasis.js';\n\nexport {\n\tinterpolatorSplineNatural,\n\tinterpolatorSplineNaturalClosed\n} from './interpolate/splineNatural.js';\n\nexport {\n\tinterpolatorSplineMonotone,\n\tinterpolatorSplineMonotone2,\n\tinterpolatorSplineMonotoneClosed\n} from './interpolate/splineMonotone.js';\n\nexport { lerp, unlerp, blerp, trilerp } from './interpolate/lerp.js';\nexport { default as samples } from './samples.js';\nexport {\n\tdisplayable,\n\tinGamut,\n\tclampRgb,\n\tclampChroma,\n\tclampGamut,\n\ttoGamut\n} from './clamp.js';\nexport { default as nearest } from './nearest.js';\nexport { useMode, getMode, useParser, removeParser } from './modes.js';\nexport { default as parse } from './parse.js';\n\nexport {\n\tdifferenceEuclidean,\n\tdifferenceCie76,\n\tdifferenceCie94,\n\tdifferenceCiede2000,\n\tdifferenceCmc,\n\tdifferenceHyab,\n\tdifferenceHueSaturation,\n\tdifferenceHueChroma,\n\tdifferenceHueNaive,\n\tdifferenceKotsarenkoRamos,\n\tdifferenceItp\n} from './difference.js';\n\nexport {\n\tfilterBrightness,\n\tfilterContrast,\n\tfilterSepia,\n\tfilterInvert,\n\tfilterSaturate,\n\tfilterGrayscale,\n\tfilterHueRotate\n} from './filter.js';\n\nexport {\n\tfilterDeficiencyProt,\n\tfilterDeficiencyDeuter,\n\tfilterDeficiencyTrit\n} from './deficiency.js';\n\n// Easings\nexport { default as easingMidpoint } from './easing/midpoint.js';\nexport {\n\teasingSmoothstep,\n\teasingSmoothstepInverse\n} from './easing/smoothstep.js';\nexport { default as easingSmootherstep } from './easing/smootherstep.js';\nexport { default as easingInOutSine } from './easing/inOutSine.js';\nexport { default as easingGamma } from './easing/gamma.js';\n\nexport {\n\tluminance as wcagLuminance,\n\tcontrast as wcagContrast\n} from './wcag.js';\n\nexport { default as parseHsl } from './hsl/parseHsl.js';\nexport { default as parseHwb } from './hwb/parseHwb.js';\nexport { default as parseLab } from './lab/parseLab.js';\nexport { default as parseLch } from './lch/parseLch.js';\nexport { default as parseNamed } from './rgb/parseNamed.js';\nexport { default as parseTransparent } from './rgb/parseTransparent.js';\nexport { default as parseHex } from './rgb/parseHex.js';\nexport { default as parseRgb } from './rgb/parseRgb.js';\nexport { default as parseHslLegacy } from './hsl/parseHslLegacy.js';\nexport { default as parseRgbLegacy } from './rgb/parseRgbLegacy.js';\nexport { default as parseOklab } from './oklab/parseOklab.js';\nexport { default as parseOklch } from './oklch/parseOklch.js';\n\nexport { default as convertA98ToXyz65 } from './a98/convertA98ToXyz65.js';\nexport { default as convertCubehelixToRgb } from './cubehelix/convertCubehelixToRgb.js';\nexport { default as convertDlchToLab65 } from './dlch/convertDlchToLab65.js';\nexport { default as convertHsiToRgb } from './hsi/convertHsiToRgb.js';\nexport { default as convertHslToRgb } from './hsl/convertHslToRgb.js';\nexport { default as convertHsvToRgb } from './hsv/convertHsvToRgb.js';\nexport { default as convertHwbToRgb } from './hwb/convertHwbToRgb.js';\nexport { default as convertItpToXyz65 } from './itp/convertItpToXyz65.js';\nexport { default as convertJabToJch } from './jch/convertJabToJch.js';\nexport { default as convertJabToRgb } from './jab/convertJabToRgb.js';\nexport { default as convertJabToXyz65 } from './jab/convertJabToXyz65.js';\nexport { default as convertJchToJab } from './jch/convertJchToJab.js';\nexport { default as convertLab65ToDlch } from './dlch/convertLab65ToDlch.js';\nexport { default as convertLab65ToRgb } from './lab65/convertLab65ToRgb.js';\nexport { default as convertLab65ToXyz65 } from './lab65/convertLab65ToXyz65.js';\nexport { default as convertLabToLch } from './lch/convertLabToLch.js';\nexport { default as convertLabToRgb } from './lab/convertLabToRgb.js';\nexport { default as convertLabToXyz50 } from './lab/convertLabToXyz50.js';\nexport { default as convertLchToLab } from './lch/convertLchToLab.js';\nexport { default as convertLchuvToLuv } from './lchuv/convertLchuvToLuv.js';\nexport { default as convertLrgbToOklab } from './oklab/convertLrgbToOklab.js';\nexport { default as convertLrgbToRgb } from './lrgb/convertLrgbToRgb.js';\nexport { default as convertLuvToLchuv } from './lchuv/convertLuvToLchuv.js';\nexport { default as convertLuvToXyz50 } from './luv/convertLuvToXyz50.js';\nexport { default as convertOkhslToOklab } from './okhsl/convertOkhslToOklab.js';\nexport { default as convertOkhsvToOklab } from './okhsv/convertOkhsvToOklab.js';\nexport { default as convertOklabToLrgb } from './oklab/convertOklabToLrgb.js';\nexport { default as convertOklabToOkhsl } from './okhsl/convertOklabToOkhsl.js';\nexport { default as convertOklabToOkhsv } from './okhsv/convertOklabToOkhsv.js';\nexport { default as convertOklabToRgb } from './oklab/convertOklabToRgb.js';\nexport { default as convertP3ToXyz65 } from './p3/convertP3ToXyz65.js';\nexport { default as convertProphotoToXyz50 } from './prophoto/convertProphotoToXyz50.js';\nexport { default as convertRec2020ToXyz65 } from './rec2020/convertRec2020ToXyz65.js';\nexport { default as convertRgbToCubehelix } from './cubehelix/convertRgbToCubehelix.js';\nexport { default as convertRgbToHsi } from './hsi/convertRgbToHsi.js';\nexport { default as convertRgbToHsl } from './hsl/convertRgbToHsl.js';\nexport { default as convertRgbToHsv } from './hsv/convertRgbToHsv.js';\nexport { default as convertRgbToHwb } from './hwb/convertRgbToHwb.js';\nexport { default as convertRgbToJab } from './jab/convertRgbToJab.js';\nexport { default as convertRgbToLab } from './lab/convertRgbToLab.js';\nexport { default as convertRgbToLab65 } from './lab65/convertRgbToLab65.js';\nexport { default as convertRgbToLrgb } from './lrgb/convertRgbToLrgb.js';\nexport { default as convertRgbToOklab } from './oklab/convertRgbToOklab.js';\nexport { default as convertRgbToXyb } from './xyb/convertRgbToXyb.js';\nexport { default as convertRgbToXyz50 } from './xyz50/convertRgbToXyz50.js';\nexport { default as convertRgbToXyz65 } from './xyz65/convertRgbToXyz65.js';\nexport { default as convertRgbToYiq } from './yiq/convertRgbToYiq.js';\nexport { default as convertXybToRgb } from './xyb/convertXybToRgb.js';\nexport { default as convertXyz50ToLab } from './lab/convertXyz50ToLab.js';\nexport { default as convertXyz50ToLuv } from './luv/convertXyz50ToLuv.js';\nexport { default as convertXyz50ToProphoto } from './prophoto/convertXyz50ToProphoto.js';\nexport { default as convertXyz50ToRgb } from './xyz50/convertXyz50ToRgb.js';\nexport { default as convertXyz50ToXyz65 } from './xyz65/convertXyz50ToXyz65.js';\nexport { default as convertXyz65ToA98 } from './a98/convertXyz65ToA98.js';\nexport { default as convertXyz65ToItp } from './itp/convertXyz65ToItp.js';\nexport { default as convertXyz65ToJab } from './jab/convertXyz65ToJab.js';\nexport { default as convertXyz65ToLab65 } from './lab65/convertXyz65ToLab65.js';\nexport { default as convertXyz65ToP3 } from './p3/convertXyz65ToP3.js';\nexport { default as convertXyz65ToRec2020 } from './rec2020/convertXyz65ToRec2020.js';\nexport { default as convertXyz65ToRgb } from './xyz65/convertXyz65ToRgb.js';\nexport { default as convertXyz65ToXyz50 } from './xyz65/convertXyz65ToXyz50.js';\nexport { default as convertYiqToRgb } from './yiq/convertYiqToRgb.js';\n\nexport {\n\tmodeA98,\n\tmodeCubehelix,\n\tmodeDlab,\n\tmodeDlch,\n\tmodeHsi,\n\tmodeHsl,\n\tmodeHsv,\n\tmodeHwb,\n\tmodeItp,\n\tmodeJab,\n\tmodeJch,\n\tmodeLab,\n\tmodeLab65,\n\tmodeLch,\n\tmodeLch65,\n\tmodeLchuv,\n\tmodeLrgb,\n\tmodeLuv,\n\tmodeOkhsl,\n\tmodeOkhsv,\n\tmodeOklab,\n\tmodeOklch,\n\tmodeP3,\n\tmodeProphoto,\n\tmodeRec2020,\n\tmodeRgb,\n\tmodeXyb,\n\tmodeXyz50,\n\tmodeXyz65,\n\tmodeYiq\n};\n\nexport const a98 = useMode(modeA98);\nexport const cubehelix = useMode(modeCubehelix);\nexport const dlab = useMode(modeDlab);\nexport const dlch = useMode(modeDlch);\nexport const hsi = useMode(modeHsi);\nexport const hsl = useMode(modeHsl);\nexport const hsv = useMode(modeHsv);\nexport const hwb = useMode(modeHwb);\nexport const itp = useMode(modeItp);\nexport const jab = useMode(modeJab);\nexport const jch = useMode(modeJch);\nexport const lab = useMode(modeLab);\nexport const lab65 = useMode(modeLab65);\nexport const lch = useMode(modeLch);\nexport const lch65 = useMode(modeLch65);\nexport const lchuv = useMode(modeLchuv);\nexport const lrgb = useMode(modeLrgb);\nexport const luv = useMode(modeLuv);\nexport const okhsl = useMode(modeOkhsl);\nexport const okhsv = useMode(modeOkhsv);\nexport const oklab = useMode(modeOklab);\nexport const oklch = useMode(modeOklch);\nexport const p3 = useMode(modeP3);\nexport const prophoto = useMode(modeProphoto);\nexport const rec2020 = useMode(modeRec2020);\nexport const rgb = useMode(modeRgb);\nexport const xyb = useMode(modeXyb);\nexport const xyz50 = useMode(modeXyz50);\nexport const xyz65 = useMode(modeXyz65);\nexport const yiq = useMode(modeYiq);\n","/**\n * The hex contract shared by `chinContrast` and `accentSurface`.\n *\n * `culori` does the parsing, and it accepts every CSS colour — including names\n * like `rebeccapurple` and formats with alpha. Every colour reaching these two\n * modules comes from `getDominantColorFromImageUrl` via a Stream attachment\n * field, or from a constant in this directory, so both narrow the input to a hex\n * before handing it over rather than widening their contract by accident.\n */\n\n/**\n * `#abc`, `#aabbcc`, or either without the leading `#`.\n *\n * The missing hash is deliberate: the extractor returns bare hexes often enough\n * that rejecting them would silently drop the colour. It is also why `toCssHex`\n * exists — `background-color: 738883` is invalid and the DOM drops it, which is\n * how a card once rendered unaccented while every calculation behind it had\n * succeeded (MES-1349).\n */\nexport const HEX_PATTERN = /^#?(?:[0-9a-f]{3}|[0-9a-f]{6})$/i\n\n/** Normalizes a hex for CSS and for culori, adding the `#` the extractor omits. */\nexport function toCssHex(hex: string): string {\n const trimmed = hex.trim()\n return trimmed.startsWith('#') ? trimmed : `#${trimmed}`\n}\n","/**\n * Ink and fallback fills for the `LinkAttachment` card, whose background is a\n * colour derived from the attachment image (see `accentSurface`).\n *\n * The card's text is chosen by measuring contrast against whatever surface the\n * card actually paints. Ink used to be fixed per variant, which left any\n * background the card imposed on *itself* unchecked: `AUDIO_BG_CLASS`\n * (`#F2F3F4`) is applied on either variant, so a sent audio card drew white ink\n * on near-white at 1.13:1 and the title was invisible (MES-1388).\n *\n * The ratio itself is `culori`'s `wcagContrast`. A previous revision computed\n * relative luminance here by hand; the only thing this module adds now is the\n * decision of *which* ink, and the hex validation that keeps the surface a hex\n * rather than any CSS colour.\n */\nimport { wcagContrast } from 'culori'\n\nimport type { LinkAttachmentVariant } from './CardShell'\nimport { HEX_PATTERN, toCssHex } from './hex'\n\n/** WCAG 2.1 SC 1.4.3 (AA), normal text. Both chin lines are normal text. */\nexport const WCAG_AA_NORMAL_TEXT = 4.5\n\n/**\n * Fill each side falls back to when no accent is paintable: the plain message\n * bubble's own background, so a link card without a usable colour is indistinct\n * from the text bubbles around it rather than a third colour nobody chose.\n *\n * These are the literal values behind `--str-chat__own-message-bubble-background-color`\n * and `--str-chat__message-bubble-background-color` in `styles.css`. Duplicated\n * as hex because the bubble tail paints *outside* the shell's box via an inline\n * style, and because the contrast arithmetic needs a colour, not a `var()`.\n * Keep in sync with those two custom properties.\n */\nexport const BUBBLE_BG_BY_VARIANT: Record<LinkAttachmentVariant, string> = {\n dark: '#1e2330',\n light: '#f1f0ee',\n}\n\n/** Ink candidates for a surface the card cannot refuse. */\nexport const INK_ON_DARK = '#FFFFFF'\n/** The near-black used across the Figma frames. */\nexport const INK_ON_LIGHT = '#040403'\n\n/**\n * WCAG contrast ratio between two hex colours, or `NaN` if either is not a hex.\n *\n * The hex guard is deliberate: `culori` resolves any CSS colour, and every\n * colour reaching this module comes from an image extractor or from the two\n * constants above. `NaN` rather than a throw so callers can branch on\n * `Number.isNaN` and fall back.\n */\nexport function contrastRatio(a: string, b: string): number {\n if (typeof a !== 'string' || typeof b !== 'string') return Number.NaN\n if (!HEX_PATTERN.test(a.trim()) || !HEX_PATTERN.test(b.trim())) {\n return Number.NaN\n }\n\n return wcagContrast(toCssHex(a), toCssHex(b))\n}\n\n/**\n * Ink for a surface the card did not choose — the audio strip's flat neutral, or\n * a variant fallback fill — picking whichever candidate scores the higher ratio\n * against it. `undefined` when the surface is not a hex, so callers keep the\n * variant's own `text-*` classes.\n *\n * This is the rule the accent derivation cannot cover. A derived accent suits\n * its side's ink by construction; an imposed background has to be met the other\n * way round, by moving the ink. Only decoration can be refused (MES-1388).\n */\nexport function inkFor(background: string): string | undefined {\n const againstDarkInk = contrastRatio(background, INK_ON_LIGHT)\n if (Number.isNaN(againstDarkInk)) return undefined\n\n return againstDarkInk >= contrastRatio(background, INK_ON_DARK)\n ? INK_ON_LIGHT\n : INK_ON_DARK\n}\n","/**\n * Turns the colour extracted from an attachment image into a card surface that\n * the card's own text can survive.\n *\n * `ugc-kit`'s `ImageAnalysis` (`getDominantColorFromImageUrl`) answers only\n * \"what colour is this image?\" — it has no notion of contrast or readability.\n * Painting that colour straight onto the card is what broke: the extracted\n * colour is whatever the photo happened to be, so roughly half of them left the\n * title illegible against the side's ink, and refusing those threw away the\n * colour the feature exists to add (MES-1349, MES-1388).\n *\n * So the hue is kept and the *lightness* is replaced with a fixed stop chosen\n * per side — dark behind the sender's white ink, pale behind the receiver's\n * near-black. This is the approach already used in `linktr.ee-profiles`\n * (`ui/src/utils/rgbToTheme.ts`), whose `getPaletteFromColor` generates a\n * 16-stop OKLCH ramp from one colour and has callers pick a background stop and\n * a text stop from it. We need exactly one stop per side rather than a whole\n * theme, so the ramp is collapsed to a single lightness target.\n *\n * OKLCH rather than HSL because its lightness axis is perceptually uniform: one\n * L value gives the same *apparent* lightness — and therefore the same contrast\n * — across every hue. In HSL, `50%` lightness yellow and `50%` blue differ by\n * several stops of contrast, so no single target would hold.\n *\n * The conversion, the sRGB gamut mapping and the WCAG ratio are all `culori`'s.\n * An earlier revision of this module hand-rolled them (~90 lines of OKLab\n * matrices and a bisecting chroma search); `culori` is zero-dependency and ships\n * a real CJS build, so it is safe for both frontyard's Jest and profiles' build.\n */\nimport { clampChroma, converter, formatHex, wcagContrast } from 'culori'\n\nimport type { LinkAttachmentVariant } from './CardShell'\nimport { INK_ON_DARK, INK_ON_LIGHT, WCAG_AA_NORMAL_TEXT } from './chinContrast'\nimport { HEX_PATTERN, toCssHex } from './hex'\n\n/**\n * Perceived-lightness stop each side paints at, in OKLCH L (0..1) — profiles'\n * `color12` / `color2` equivalent. Both sit far enough from their ink to clear\n * AA at any hue and chroma: swept across every hue at maximum chroma the worst\n * case is comfortably above the 4.5:1 floor (see `accentSurface.test.ts`).\n */\nconst SURFACE_LIGHTNESS: Record<LinkAttachmentVariant, number> = {\n dark: 0.3,\n light: 0.9,\n}\n\n/** Ink each side draws, so the derived surface can be checked against it. */\nconst INK_BY_VARIANT: Record<LinkAttachmentVariant, string> = {\n dark: INK_ON_DARK,\n light: INK_ON_LIGHT,\n}\n\nconst toOklch = converter('oklch')\n\n/**\n * The card surface for an extracted colour: the image's hue at this side's\n * lightness stop, or `undefined` when there was no colour to work from.\n *\n * The input is validated as a hex rather than handed to `culori` directly.\n * `culori` accepts every CSS colour, including names like `rebeccapurple`, and\n * `accent_color` is always a hex from `getDominantColorFromImageUrl` — widening\n * that contract by accident would let a caller pass something no other part of\n * this module can reason about. The bare-hex case *is* supported, because the\n * extractor omits the `#` often enough that dropping it would silently lose the\n * colour (MES-1349).\n *\n * The AA check at the end is a guard, not a branch anyone expects to take: the\n * lightness stops were chosen to clear it everywhere. It exists so that a future\n * change to `SURFACE_LIGHTNESS` or to the ink cannot quietly reintroduce an\n * illegible card — it degrades to the plain bubble fill instead.\n */\nexport function accentSurface(\n accentColor: string | undefined,\n variant: LinkAttachmentVariant\n): string | undefined {\n if (accentColor == null || !HEX_PATTERN.test(accentColor.trim())) {\n return undefined\n }\n\n const base = toOklch(toCssHex(accentColor))\n if (!base) return undefined\n\n // `clampChroma`, not `toGamut`: both bring an out-of-sRGB colour back into\n // range, but `toGamut` follows the CSS Color 4 path and drifts hue by up to\n // 12° on saturated bases, while `clampChroma` reduces chroma at constant hue\n // and lightness — 2.8° worst case. Vivid hues desaturate rather than shift,\n // which is what keeps the card recognisably the image's colour.\n const surface = formatHex(\n clampChroma({ ...base, l: SURFACE_LIGHTNESS[variant] }, 'oklch')\n )\n\n return wcagContrast(surface, INK_BY_VARIANT[variant]) >= WCAG_AA_NORMAL_TEXT\n ? surface\n : undefined\n}\n","/* eslint-disable react-hooks/set-state-in-effect -- pre-existing pattern flagged by the React\n Compiler rules added in eslint-plugin-react-hooks v7; refactoring it is\n out of scope for the lint toolchain upgrade. */\nimport React from 'react'\n\nimport type { LinkAttachmentLayout, LinkAttachmentStatus } from '../../types'\n\nimport { accentSurface } from './accentSurface'\nimport type { LinkAttachmentVariant } from './CardShell'\nimport { AUDIO_BG, isPlayableAudio } from './CardThumbnail'\nimport { BUBBLE_BG_BY_VARIANT, inkFor } from './chinContrast'\n\nexport interface ChinPaletteInput {\n variant: LinkAttachmentVariant\n accentColor?: string\n status?: LinkAttachmentStatus\n layout?: LinkAttachmentLayout\n thumbnailUrl?: string\n /**\n * Together with `sourceUrl`, identifies the playable-audio card whose hero\n * region is the native player rather than an image. See `hasHero` below.\n */\n mimeType?: string\n sourceUrl?: string\n}\n\nexport interface ChinPalette {\n /**\n * Hero URL to render. Cleared once the image has errored so `CardThumbnail`\n * falls through to its type-icon placeholder instead of a broken `<img>`.\n */\n thumbnailUrl?: string\n /**\n * Inline background for the card shell, or `undefined` to keep the variant's\n * own `bg-*` class.\n */\n accentStyle?: React.CSSProperties\n /**\n * Ink for both chin lines, chosen against the surface the card actually\n * paints — the derived accent, the audio strip, or the fallback fill. Always\n * defined for a parseable surface.\n */\n chinTextColor?: string\n /**\n * Colour the bubble tail paints in, always defined: the accent when one is\n * paintable, otherwise this side's plain bubble fill.\n */\n tailColor: string\n /** True while the card renders as a skeleton. */\n isLoading: boolean\n /** Hand to `CardThumbnail` so a broken hero drops the accent with it. */\n onImageError: () => void\n}\n\n/**\n * Resolves a link card's accent-derived colours and tracks hero-image failure.\n *\n * The accent is a claim about an image the viewer can see, so it only paints\n * when `CardThumbnail` actually mounts that image. Mirroring its branches\n * (`CardThumbnail.tsx:98-160`), the hero is *not* the accent's source when:\n *\n * - `layout: 'classic'` — there is no hero region at all;\n * - `status` is not `'ready'` — the hero is the pulsing skeleton and there is\n * no image yet;\n * - `thumbnailUrl` is absent — the hero is the type-icon placeholder, or for a\n * playable video a bare `bg-black` box with no poster;\n * - the attachment is playable audio — the hero collapses to the native\n * `<audio>` player and the `<img>` never mounts *even though `thumbnailUrl`\n * is set*, so `onImageError` can never rescue this one. Left ungated, an\n * artwork-backed audio link preview shipped a coloured card with no visible\n * source image, and the accent beat `AUDIO_BG_CLASS` on Sent / Received\n * because `CardShell` applies it as an inline `style`, which outranks any\n * `bg-*` class. `ComposerCard` already dodged that by returning early before\n * it passes `accentStyle`; this is that same rule, stated once instead of\n * three times (MES-1349);\n * - the image 404s — an accent extracted from something the viewer cannot see.\n * `onImageError` covers both hero shapes: the `<img>` reports directly, and a\n * playable video's `poster` (which raises no event of its own) is verified by\n * the hidden probe image in `CardThumbnail`.\n *\n * Every case falls back to the variant's own fill, which already pairs with\n * the variant's own text colours.\n */\nexport function useChinPalette({\n variant,\n accentColor,\n status = 'ready',\n layout = 'featured',\n thumbnailUrl,\n mimeType,\n sourceUrl,\n}: ChinPaletteInput): ChinPalette {\n const [heroFailed, setHeroFailed] = React.useState(false)\n\n // A new hero URL is a new chance to load — otherwise a card that recycles\n // (same element, different attachment) would stay stuck on the placeholder.\n React.useEffect(() => {\n setHeroFailed(false)\n }, [thumbnailUrl])\n\n const onImageError = React.useCallback(() => {\n setHeroFailed(true)\n }, [])\n\n // Truthiness rather than `!= null` so this tracks `CardThumbnail`'s own\n // `thumbnailUrl ?` branch, which renders the placeholder for `''` too.\n //\n // Playable audio stays excluded, as MES-1349 decided: its hero collapses to\n // the native `<audio>` player, so the artwork never appears and an accent\n // taken from it would be a claim about an image the viewer cannot see. The\n // `<img>` never mounts either, so `onImageError` could not withdraw the colour\n // if the artwork 404'd. Colouring audio cards from their artwork is a change\n // to the audio tickets (MES-1360 / MES-1361), not to this one.\n const isAudio = isPlayableAudio(mimeType, sourceUrl)\n const hasHero =\n layout === 'featured' && !!thumbnailUrl && !isAudio && !heroFailed\n const surface =\n hasHero && status === 'ready'\n ? accentSurface(accentColor, variant)\n : undefined\n\n // Whatever the card ends up painted with, legible or not, the ink is chosen\n // against it. The accent is derived to suit this side's ink, but the audio\n // strip and the fallback fill are imposed and cannot be refused — a sent\n // audio card put white ink on `AUDIO_BG`'s near-white at 1.13:1 (MES-1388).\n const painted =\n surface ?? (isAudio ? AUDIO_BG : BUBBLE_BG_BY_VARIANT[variant])\n\n return {\n thumbnailUrl: heroFailed ? undefined : thumbnailUrl,\n accentStyle: surface ? { backgroundColor: surface } : undefined,\n chinTextColor: inkFor(painted),\n tailColor: painted,\n isLoading: status === 'loading',\n onImageError,\n }\n}\n","import { PencilSimpleIcon, XIcon } from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React from 'react'\n\nimport type { LinkAttachmentBaseProps } from '../../types'\nimport CardBody from '../_shared/CardBody'\nimport CardShell from '../_shared/CardShell'\nimport CardThumbnail, {\n AUDIO_BG_CLASS,\n isPlayableAudio,\n} from '../_shared/CardThumbnail'\nimport { useChinPalette } from '../_shared/useChinPalette'\n\nexport interface ComposerCardProps extends LinkAttachmentBaseProps {\n /**\n * When provided, renders a dismiss X in the thumbnail corner. Called when\n * the composer clicks it to remove the attachment.\n */\n onDismiss?: () => void\n /**\n * When provided, renders a pencil button to the right of the description\n * that the composer can use to edit the attachment metadata.\n */\n onEditClick?: () => void\n /**\n * Accessible name for the dismiss button. Defaults to English because the\n * toolkit has no i18n layer; consumers that do (frontyard passes\n * `ComposerLinkPreviewList.closeLinkPreview`) should supply their own.\n */\n dismissLabel?: string\n}\n\n// 24x24 circle with a 12x12 white X — already Figma-exact.\nconst DISMISS_CLASS =\n 'flex size-6 items-center justify-center rounded-full bg-[#121110] text-white focus-ring'\n\n// Grows only the *clickable* area to 44x44 (24 + 10 + 10) for the platform\n// touch minimum (MES-1350 / MES-1358), leaving the visual box alone — this\n// same card renders in profiles' touch-first visitor composer, so a\n// consumer-scoped fix could not reach it. Same idiom as the send button in\n// `CustomMessageInput/index.tsx`. Not applied on the audio variant, where the\n// button is an inline sibling of the native controls rather than an overlay\n// and the halo would sit on top of them.\nconst DISMISS_TOUCH_TARGET_CLASS =\n \"relative before:absolute before:-inset-[10px] before:content-['']\"\n\n/**\n * The card the composer sees while drafting a link attachment.\n * Matches the Composer column of the messaging design system in Figma.\n */\nconst ComposerCard: React.FC<ComposerCardProps> = ({\n title,\n placeholderTitle,\n description,\n url,\n mimeType,\n thumbnailUrl,\n sourceUrl,\n layout = 'featured',\n appIcon,\n cta,\n accentColor,\n status = 'ready',\n onDismiss,\n onEditClick,\n dismissLabel = 'Dismiss attachment',\n}) => {\n const isClassic = layout === 'classic'\n const isAudio = isPlayableAudio(mimeType, sourceUrl)\n const chin = useChinPalette({\n variant: 'dark',\n accentColor,\n status,\n layout,\n thumbnailUrl,\n mimeType,\n sourceUrl,\n })\n\n const dismissButton = onDismiss ? (\n <button\n type=\"button\"\n onClick={onDismiss}\n aria-label={dismissLabel}\n className={classNames(\n DISMISS_CLASS,\n !isAudio && DISMISS_TOUCH_TARGET_CLASS\n )}\n >\n <XIcon className=\"size-3\" weight=\"bold\" />\n </button>\n ) : undefined\n\n const editButton = onEditClick ? (\n <button\n type=\"button\"\n onClick={onEditClick}\n aria-label=\"Edit attachment\"\n className=\"flex size-10 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/15\"\n >\n <PencilSimpleIcon className=\"size-5\" weight=\"regular\" />\n </button>\n ) : undefined\n\n // Audio cards collapse to just the native player — render the dismiss\n // button as an inline sibling so it always has its own space and never\n // overlaps the audio control's volume/menu buttons. Skipped while loading:\n // this path has no `CardBody` and no `busy`, so taking it during a scrape\n // would drop the skeleton and its `aria-busy` region entirely, and we do not\n // yet know the asset is audio anyway.\n if (isAudio && !chin.isLoading) {\n return (\n <CardShell variant=\"dark\" bgClassName={AUDIO_BG_CLASS}>\n <div className=\"flex items-center gap-2 pr-3\">\n <div className=\"min-w-0 flex-1\">\n <CardThumbnail\n variant=\"dark\"\n sourceUrl={sourceUrl}\n title={title}\n mimeType={mimeType}\n />\n </div>\n {dismissButton && <div className=\"shrink-0\">{dismissButton}</div>}\n </div>\n </CardShell>\n )\n }\n\n return (\n <CardShell\n variant=\"dark\"\n fixedHeight={!isClassic}\n accentStyle={chin.accentStyle}\n busy={chin.isLoading}\n topRight={isClassic ? dismissButton : undefined}\n >\n {!isClassic && (\n <CardThumbnail\n variant=\"dark\"\n thumbnailUrl={chin.thumbnailUrl}\n sourceUrl={sourceUrl}\n title={title}\n mimeType={mimeType}\n topRight={dismissButton}\n isLoading={chin.isLoading}\n onImageError={chin.onImageError}\n />\n )}\n <CardBody\n chinTextColor={chin.chinTextColor}\n variant=\"dark\"\n title={title}\n placeholderTitle={placeholderTitle}\n description={description}\n url={url}\n appIcon={appIcon}\n cta={cta}\n trailingAction={editButton}\n isLoading={chin.isLoading}\n />\n </CardShell>\n )\n}\n\nexport default ComposerCard\n","import classNames from 'classnames'\nimport React from 'react'\n\nexport interface BubbleTailProps {\n /**\n * Hex the tail paints in — the card's accent colour, or its variant\n * fallback fill. Inline rather than a class because the accent is a\n * runtime value extracted from the attachment image.\n */\n color: string\n /** Sender tails hang off the right edge, receiver tails mirror to the left. */\n side: 'sender' | 'receiver'\n /**\n * `false` renders `children` untouched — a card mid-run has no tail because\n * a later bubble in the run owns it.\n */\n visible: boolean\n children: React.ReactNode\n}\n\n/**\n * Wraps a `LinkAttachment` card in the chat bubble tail from the messaging\n * design system, painted to match the card's own bottom edge.\n *\n * The geometry and mask live in `styles.css` alongside the text-bubble tails\n * they mirror. They cannot be reused directly: those rules key off\n * `.str-chat__message-bubble:last-child`, which only exists when the card is\n * rendered inside a Stream thread — and `StreamAttachmentMessage` marks that\n * bubble `data-attachment-bubble` precisely to opt out of them, since a tail\n * tinted from the text-bubble surface would clash with a coloured card.\n */\nconst BubbleTail: React.FC<BubbleTailProps> = ({\n color,\n side,\n visible,\n children,\n}) => {\n if (!visible) return <>{children}</>\n\n return (\n // `isolate` keeps the tail's negative z-index from escaping behind the\n // thread background; `w-fit` stops the wrapper from stretching in the\n // composer's flex list.\n <div className=\"relative isolate w-fit\">\n {children}\n <span\n aria-hidden\n data-testid=\"link-card-tail\"\n style={{ backgroundColor: color }}\n className={classNames(\n 'messaging-link-card-tail',\n side === 'receiver' && 'messaging-link-card-tail--received'\n )}\n />\n </div>\n )\n}\n\nexport default BubbleTail\n","import React from 'react'\n\nimport type { BubbleGroupPosition } from '../../../MessageAttachment/types'\nimport type { LinkAttachmentBaseProps } from '../../types'\nimport BubbleTail from '../_shared/BubbleTail'\nimport CardBody from '../_shared/CardBody'\nimport CardShell from '../_shared/CardShell'\nimport CardThumbnail, {\n AUDIO_BG_CLASS,\n isPlayableAudio,\n isPlayableMedia,\n} from '../_shared/CardThumbnail'\nimport { normalizeExternalHref } from '../_shared/normalizeExternalHref'\nimport { useChinPalette } from '../_shared/useChinPalette'\n\nexport interface ReceivedCardProps extends LinkAttachmentBaseProps {\n /**\n * Fired when the recipient activates the card. Behavior depends on how\n * the card is configured:\n * - **Link app with a CTA** (FAQ / Form): the CTA owns navigation;\n * `onClick` fires when the recipient taps the CTA itself, alongside\n * `cta.onClick` (use for analytics).\n * - **Link app with a URL** (Spotify / TikTok / generic link): the card\n * chrome is an `<a target=\"_blank\">` opening `url` — `onClick` fires\n * alongside the navigation (use for analytics).\n * - **Hero-image only card**: the card has no URL, so it renders as\n * a button. `onClick` is the consumer's hook for opening a preview.\n * - **Video / audio link previews**: the shell stays non-interactive\n * so the native media controls remain operable — `onClick` is\n * ignored in this configuration.\n */\n onClick?: () => void\n /**\n * Position of this card inside its same-author run. `'single'` / `'end'`\n * paint the accent-coloured tail, mirrored to the card's left edge;\n * `'first'` / `'middle'` omit it because a later bubble in the run owns it.\n * Defaults to `'single'`.\n */\n groupPosition?: BubbleGroupPosition\n}\n\n/**\n * The card the recipient sees in chat for a link attachment. Matches the\n * Received column of the messaging design system in Figma.\n */\nconst ReceivedCard: React.FC<ReceivedCardProps> = ({\n title,\n description,\n url,\n mimeType,\n thumbnailUrl,\n sourceUrl,\n layout = 'featured',\n appIcon,\n cta,\n accentColor,\n status = 'ready',\n onClick,\n groupPosition = 'single',\n}) => {\n // Video / audio link previews wrap the native media element — render a\n // plain non-interactive shell and let the media controls own clicks so\n // taps on play/pause/scrubber don't fire the outer card action.\n const isPlayingMedia = isPlayableMedia(mimeType, sourceUrl)\n // Normalize the URL so a bare hostname like `tr.ee/briemix` (used in\n // our own docs / stories) is treated as an external link instead of a\n // relative path. Returns `undefined` for empty / whitespace-only\n // values, so those fall through to the preview path instead of\n // producing an empty `href` on the shell anchor.\n const normalizedUrl = normalizeExternalHref(url)\n const shellHref =\n cta == null && normalizedUrl != null && !isPlayingMedia\n ? normalizedUrl\n : undefined\n const shellOnClick = cta == null && !isPlayingMedia ? onClick : undefined\n // A loading card is not yet an audio card: the scrape that would tell us has\n // not returned, so it keeps the ordinary 250px skeleton rather than the\n // intrinsic-height audio shell (whose `flex-1` hero would collapse to 0).\n const audioBg =\n status !== 'loading' && isPlayableAudio(mimeType, sourceUrl)\n ? AUDIO_BG_CLASS\n : undefined\n\n // When a CTA is set the shell isn't interactive — the CTA owns the\n // click target. Forward the card-level `onClick` to the CTA so\n // analytics / side-effect consumers still fire on activation while\n // preserving the CTA's own `onClick` callback.\n const wrappedCta =\n cta && onClick\n ? {\n ...cta,\n onClick: () => {\n onClick()\n cta.onClick?.()\n },\n }\n : cta\n\n const chin = useChinPalette({\n variant: 'light',\n accentColor,\n status,\n layout,\n thumbnailUrl,\n mimeType,\n sourceUrl,\n })\n\n return (\n <BubbleTail\n color={chin.tailColor}\n side=\"receiver\"\n // Only the last card in a same-author run carries the tail; the audio\n // player card is not a bubble, so it never does.\n visible={\n audioBg == null &&\n (groupPosition === 'single' || groupPosition === 'end')\n }\n >\n <CardShell\n variant=\"light\"\n href={shellHref}\n onClick={shellOnClick}\n ariaLabel={title ?? 'Open attachment preview'}\n fixedHeight={layout === 'featured' && audioBg == null}\n accentStyle={chin.accentStyle}\n busy={chin.isLoading}\n bgClassName={audioBg}\n data-testid=\"link-attachment\"\n >\n {layout === 'featured' && (\n <CardThumbnail\n variant=\"light\"\n thumbnailUrl={chin.thumbnailUrl}\n sourceUrl={sourceUrl}\n title={title}\n mimeType={mimeType}\n isLoading={chin.isLoading}\n onImageError={chin.onImageError}\n />\n )}\n <CardBody\n chinTextColor={chin.chinTextColor}\n variant=\"light\"\n title={title}\n description={description}\n url={url}\n appIcon={appIcon}\n cta={wrappedCta}\n isLoading={chin.isLoading}\n />\n </CardShell>\n </BubbleTail>\n )\n}\n\nexport default ReceivedCard\n","import React from 'react'\n\nimport type { BubbleGroupPosition } from '../../../MessageAttachment/types'\nimport type { LinkAttachmentBaseProps } from '../../types'\nimport BubbleTail from '../_shared/BubbleTail'\nimport CardBody from '../_shared/CardBody'\nimport CardShell from '../_shared/CardShell'\nimport CardThumbnail, {\n AUDIO_BG_CLASS,\n isPlayableAudio,\n isPlayableMedia,\n} from '../_shared/CardThumbnail'\nimport { normalizeExternalHref } from '../_shared/normalizeExternalHref'\nimport { useChinPalette } from '../_shared/useChinPalette'\n\nexport interface SentCardProps extends LinkAttachmentBaseProps {\n /**\n * Fired when the sender activates their own posted card. Mirrors the\n * `Received` variant so analytics fires symmetrically on both sides\n * of the conversation. Behavior depends on configuration:\n * - **Link app with a URL**: the card chrome is an `<a target=\"_blank\">`\n * opening `url`; `onClick` fires alongside the navigation.\n * - **Link app with a CTA**: the CTA owns navigation; `onClick` is\n * ignored (the CTA's own `onClick` is the analytics hook).\n * - **Video / audio link previews**: the shell stays non-interactive\n * so the native media controls remain operable; `onClick` is ignored.\n */\n onClick?: () => void\n /**\n * Position of this card inside its same-author run. `'single'` / `'end'`\n * paint the accent-coloured tail; `'first'` / `'middle'` omit it because a\n * later bubble in the run owns it. Defaults to `'single'`.\n */\n groupPosition?: BubbleGroupPosition\n}\n\n/**\n * The card the sender sees in chat after a link attachment has been posted.\n * Matches the Sent column of the messaging design system in Figma — same\n * dark chrome as the Composer card minus the dismiss / edit affordances.\n *\n * The sender's own copy is clickable when a `url` is set so they can open\n * the link they just sent — symmetric with `LinkAttachment.Received`.\n */\nconst SentCard: React.FC<SentCardProps> = ({\n title,\n placeholderTitle,\n description,\n url,\n mimeType,\n thumbnailUrl,\n sourceUrl,\n layout = 'featured',\n appIcon,\n cta,\n accentColor,\n status = 'ready',\n onClick,\n groupPosition = 'single',\n}) => {\n // Video / audio link previews wrap the native media element — render a\n // plain non-interactive shell and let the media controls own clicks so\n // taps on play/pause/scrubber don't fire the outer card action. Same\n // rationale as `ReceivedCard`.\n const isPlayingMedia = isPlayableMedia(mimeType, sourceUrl)\n // Normalize the URL so a bare hostname like `tr.ee/briemix` is treated\n // as an external link instead of resolving against the current host.\n // Returns `undefined` for empty / whitespace-only values, so those fall\n // through to a non-navigational shell instead of producing an empty\n // `href` on the anchor.\n const normalizedUrl = normalizeExternalHref(url)\n const shellHref =\n cta == null && normalizedUrl != null && !isPlayingMedia\n ? normalizedUrl\n : undefined\n const shellOnClick =\n cta == null && !isPlayingMedia && shellHref != null ? onClick : undefined\n\n // A loading card is not yet an audio card: the scrape that would tell us has\n // not returned, so it keeps the ordinary 250px skeleton rather than the\n // intrinsic-height audio shell (whose `flex-1` hero would collapse to 0).\n const isAudio = status !== 'loading' && isPlayableAudio(mimeType, sourceUrl)\n const chin = useChinPalette({\n variant: 'dark',\n accentColor,\n status,\n layout,\n thumbnailUrl,\n mimeType,\n sourceUrl,\n })\n\n return (\n <BubbleTail\n color={chin.tailColor}\n side=\"sender\"\n // Only the last card in a same-author run carries the tail; the audio\n // player card is not a bubble, so it never does.\n visible={\n !isAudio && (groupPosition === 'single' || groupPosition === 'end')\n }\n >\n <CardShell\n variant=\"dark\"\n href={shellHref}\n onClick={shellOnClick}\n fixedHeight={layout === 'featured' && !isAudio}\n accentStyle={chin.accentStyle}\n busy={chin.isLoading}\n bgClassName={isAudio ? AUDIO_BG_CLASS : undefined}\n >\n {layout === 'featured' && (\n <CardThumbnail\n variant=\"dark\"\n thumbnailUrl={chin.thumbnailUrl}\n sourceUrl={sourceUrl}\n title={title}\n mimeType={mimeType}\n isLoading={chin.isLoading}\n onImageError={chin.onImageError}\n />\n )}\n <CardBody\n chinTextColor={chin.chinTextColor}\n variant=\"dark\"\n title={title}\n placeholderTitle={placeholderTitle}\n description={description}\n url={url}\n appIcon={appIcon}\n cta={cta}\n isLoading={chin.isLoading}\n />\n </CardShell>\n </BubbleTail>\n )\n}\n\nexport default SentCard\n","import ComposerCard, {\n type ComposerCardProps,\n} from './components/Composer/Card'\nimport ReceivedCard, {\n type ReceivedCardProps,\n} from './components/Received/Card'\nimport SentCard, { type SentCardProps } from './components/Sent/Card'\n\n/**\n * Link previews (1P / 3P Link Apps) shown in the chat thread. Mirrors\n * the `LockedAttachment` API — render `LinkAttachment.Composer` while\n * drafting, `LinkAttachment.Sent` after posting, and\n * `LinkAttachment.Received` in the recipient's thread. Maps to the\n * \"LinkApps\" section of the messaging design system.\n *\n * Two visual layouts via the `layout` prop:\n * - **Featured** (default) — a hero thumbnail filling the card above the\n * chin, inside a fixed 290x250 box. Used by hero-image LinkApps\n * (Spotify with cover art, TikTok with a frame, etc.) and by link\n * previews carrying OG imagery.\n * - **Classic** — compact card with no hero thumbnail; title /\n * description / URL / CTA only, sized to its content. Used for LinkApp\n * embeds without artwork (FAQ, Form) and any link preview that lacks\n * OG imagery.\n *\n * Pass `accentColor` (a hex extracted from the thumbnail) to paint the card\n * and its bubble tail; the card derives its own WCAG AA text colour.\n *\n * For chat **document / image / video / audio attachments**, reach for\n * `MessageAttachment.{Image,Video,Audio,Pdf,File}` instead — those\n * render as bubbles with built-in viewers (zoom-capable image\n * lightbox, native PDF viewer, video / audio with download) and a\n * caption slot for accompanying text.\n */\nconst LinkAttachment = {\n Composer: ComposerCard,\n Sent: SentCard,\n Received: ReceivedCard,\n}\n\nexport default LinkAttachment\nexport type { ComposerCardProps, SentCardProps, ReceivedCardProps }\nexport type {\n LinkAttachmentBaseProps,\n LinkAttachmentCta,\n LinkAttachmentLayout,\n LinkAttachmentStatus,\n} from './types'\n","import React from 'react'\nimport type { Attachment, LocalMessage } from 'stream-chat'\nimport {\n MessageErrorIcon,\n MessageText,\n type MessageContextValue,\n} from 'stream-chat-react'\n\nimport { optimizeMessagingAttachmentUrl } from '../../utils/cdnImageUrl'\nimport LinkAttachment from '../LinkAttachment'\nimport { isPlayableMedia } from '../LinkAttachment/components/_shared/CardThumbnail'\nimport MessageAttachment from '../MessageAttachment'\nimport type { BubbleGroupPosition } from '../MessageAttachment/types'\n\ntype StreamMediaKind = 'image' | 'video' | 'audio' | 'pdf' | 'file'\n\nexport type AttachmentSegment =\n | { type: 'link'; attachments: Attachment[] }\n | { type: 'media'; kind: StreamMediaKind; attachments: Attachment[] }\n\nfunction trimToUndefined(value?: string | null): string | undefined {\n const trimmed = value?.trim()\n return trimmed ? trimmed : undefined\n}\n\nexport function normalizeLinkUrl(url: string): string {\n return url\n .trim()\n .replace(/^https?:\\/\\//i, '')\n .replace(/\\/+$/, '')\n .toLowerCase()\n}\n\nexport function linkCaptionDuplicatesAttachmentUrl(\n caption: string | undefined,\n attachmentUrl?: string\n): boolean {\n if (!caption?.trim() || !attachmentUrl?.trim()) {\n return false\n }\n\n const normalizedCaption = normalizeLinkUrl(caption)\n const normalizedUrl = normalizeLinkUrl(attachmentUrl)\n\n if (normalizedCaption === normalizedUrl) {\n return true\n }\n\n if (!normalizedCaption.includes(normalizedUrl)) {\n return false\n }\n\n const remainder = normalizedCaption.split(normalizedUrl).join('')\n return !/[^\\p{P}\\p{Z}\\p{C}]/u.test(remainder)\n}\n\nexport function linkCardPropsFromStreamAttachment(a: Attachment) {\n const url = trimToUndefined(a.og_scrape_url) ?? trimToUndefined(a.title_link)\n const thumbnailUrl =\n trimToUndefined((a as { image_url?: string }).image_url) ??\n trimToUndefined((a as { thumb_url?: string }).thumb_url)\n const sourceUrl = trimToUndefined(a.asset_url)\n const mimeType = trimToUndefined(a.mime_type)\n\n return {\n title: trimToUndefined((a as { title?: string }).title),\n description: trimToUndefined((a as { text?: string }).text),\n url,\n thumbnailUrl: optimizeMessagingAttachmentUrl(thumbnailUrl),\n // Playable clip embedded in a link preview — lets LinkAttachment render its\n // native video/audio player in the hero instead of a static thumbnail.\n sourceUrl,\n layout:\n thumbnailUrl || isPlayableMedia(mimeType, sourceUrl)\n ? 'featured'\n : 'classic',\n mimeType,\n // Dominant colour of the image, resolved by the sender at stage time and\n // persisted on the attachment (`stream-custom-data.ts`), so every viewer\n // paints an identical chin without re-extracting — visitors in\n // linktr.ee-profiles cannot call the extraction query at all. Absent on\n // messages sent before MES-1349, which render the fallback chin.\n accentColor: trimToUndefined(a.accent_color),\n // A persisted attachment is by definition fully scraped.\n status: 'ready',\n } as const\n}\n\nexport function getAttachmentMediaKind(\n attachment: Attachment\n): StreamMediaKind | null {\n if (isLinkAttachment(attachment)) return null\n\n if (attachment.type === 'image') {\n const imageUrl = (attachment as { image_url?: string }).image_url\n if (imageUrl || attachment.asset_url) return 'image'\n return null\n }\n\n if (attachment.type === 'video' && attachment.asset_url) return 'video'\n if (attachment.type === 'audio' && attachment.asset_url) return 'audio'\n\n if (attachment.type === 'file' && attachment.asset_url) {\n if (attachment.mime_type === 'application/pdf') return 'pdf'\n if (attachment.mime_type?.startsWith('audio/')) return 'audio'\n return 'file'\n }\n\n return null\n}\n\nexport function isLinkAttachment(a: Attachment): boolean {\n const ogScrapeUrl = trimToUndefined(a.og_scrape_url)\n return a.type === 'link' || (!!ogScrapeUrl && !a.asset_url)\n}\n\nexport function buildOrderedAttachmentSegments(\n attachments: Attachment[] | undefined\n): AttachmentSegment[] {\n if (!attachments?.length) return []\n\n const segments: AttachmentSegment[] = []\n\n const pushOrMergeMedia = (kind: StreamMediaKind, attachment: Attachment) => {\n const last = segments[segments.length - 1]\n if (last?.type === 'media' && last.kind === kind) {\n last.attachments.push(attachment)\n return\n }\n\n segments.push({ type: 'media', kind, attachments: [attachment] })\n }\n\n const pushOrMergeLink = (attachment: Attachment) => {\n const last = segments[segments.length - 1]\n if (last?.type === 'link') {\n last.attachments.push(attachment)\n return\n }\n\n segments.push({ type: 'link', attachments: [attachment] })\n }\n\n for (const attachment of attachments) {\n if (isLinkAttachment(attachment)) {\n pushOrMergeLink(attachment)\n continue\n }\n\n const kind = getAttachmentMediaKind(attachment)\n if (!kind) continue\n\n pushOrMergeMedia(kind, attachment)\n }\n\n return segments\n}\n\nexport function countMediaSegmentBubbles(\n segments: AttachmentSegment[]\n): number {\n return segments.filter((segment) => segment.type === 'media').length\n}\n\nexport function bubblePositionInRun(\n index: number,\n total: number,\n streamPosition: BubbleGroupPosition\n): BubbleGroupPosition {\n if (total <= 1) return streamPosition\n if (index === 0) return 'first'\n if (index === total - 1) return 'end'\n return 'middle'\n}\n\nfunction imageSrcFromAttachment(attachment: Attachment): string {\n return (\n trimToUndefined((attachment as { image_url?: string }).image_url) ??\n trimToUndefined(attachment.asset_url) ??\n ''\n )\n}\n\nfunction messageAttachmentNamespaceForKind(kind: StreamMediaKind) {\n switch (kind) {\n case 'image':\n return MessageAttachment.Image\n case 'video':\n return MessageAttachment.Video\n case 'audio':\n return MessageAttachment.Audio\n case 'pdf':\n return MessageAttachment.Pdf\n default:\n return MessageAttachment.File\n }\n}\n\nfunction buildMediaClusterRenderProps(\n kind: StreamMediaKind,\n attachments: Attachment[]\n): Record<string, unknown> {\n if (attachments.length > 1) {\n switch (kind) {\n case 'image':\n return {\n items: attachments.map((attachment) => ({\n src: imageSrcFromAttachment(attachment),\n alt: trimToUndefined((attachment as { title?: string }).title),\n })),\n }\n case 'video':\n return {\n items: attachments.map((attachment) => ({\n src: trimToUndefined(attachment.asset_url) ?? '',\n poster: trimToUndefined(\n (attachment as { thumb_url?: string }).thumb_url\n ),\n mimeType: trimToUndefined(attachment.mime_type),\n })),\n }\n case 'audio':\n return {\n items: attachments.map((attachment) => ({\n src: trimToUndefined(attachment.asset_url) ?? '',\n mimeType: trimToUndefined(attachment.mime_type) ?? 'audio/mpeg',\n filename: trimToUndefined((attachment as { title?: string }).title),\n })),\n }\n case 'pdf':\n return {\n items: attachments.map((attachment) => ({\n src: trimToUndefined(attachment.asset_url) ?? '',\n filename: trimToUndefined((attachment as { title?: string }).title),\n fileSize: (attachment as { file_size?: number }).file_size,\n })),\n }\n case 'file':\n return {\n items: attachments.map((attachment) => ({\n src: trimToUndefined(attachment.asset_url) ?? '',\n filename: trimToUndefined((attachment as { title?: string }).title),\n fileSize: (attachment as { file_size?: number }).file_size,\n mimeType:\n trimToUndefined(attachment.mime_type) ??\n 'application/octet-stream',\n })),\n }\n }\n }\n\n const attachment = attachments[0]\n if (!attachment) return {}\n\n switch (kind) {\n case 'image':\n return {\n src: imageSrcFromAttachment(attachment),\n alt: trimToUndefined((attachment as { title?: string }).title),\n }\n case 'video':\n return {\n src: trimToUndefined(attachment.asset_url) ?? '',\n poster: trimToUndefined(\n (attachment as { thumb_url?: string }).thumb_url\n ),\n mimeType: trimToUndefined(attachment.mime_type),\n }\n case 'audio':\n return {\n src: trimToUndefined(attachment.asset_url) ?? '',\n mimeType: trimToUndefined(attachment.mime_type) ?? 'audio/mpeg',\n filename: trimToUndefined((attachment as { title?: string }).title),\n }\n case 'pdf':\n return {\n src: trimToUndefined(attachment.asset_url) ?? '',\n filename: trimToUndefined((attachment as { title?: string }).title),\n fileSize: (attachment as { file_size?: number }).file_size,\n }\n case 'file':\n return {\n src: trimToUndefined(attachment.asset_url) ?? '',\n filename: trimToUndefined((attachment as { title?: string }).title),\n fileSize: (attachment as { file_size?: number }).file_size,\n mimeType:\n trimToUndefined(attachment.mime_type) ?? 'application/octet-stream',\n }\n }\n}\n\nfunction MediaClusterBubble({\n groupPosition,\n isMyMessage,\n segment,\n}: {\n groupPosition: BubbleGroupPosition\n isMyMessage: boolean\n segment: Extract<AttachmentSegment, { type: 'media' }>\n}) {\n const TypeNamespace = messageAttachmentNamespaceForKind(segment.kind)\n const props = {\n ...buildMediaClusterRenderProps(segment.kind, segment.attachments),\n groupPosition,\n }\n\n if (isMyMessage) {\n return <TypeNamespace.Sent {...props} />\n }\n\n return <TypeNamespace.Received {...props} />\n}\n\nexport interface StreamAttachmentMessageProps {\n groupPosition: BubbleGroupPosition\n isMyMessage: boolean\n message: LocalMessage\n renderText?: MessageContextValue['renderText']\n}\n\nconst StreamAttachmentMessage: React.FC<StreamAttachmentMessageProps> = ({\n groupPosition,\n isMyMessage,\n message,\n renderText,\n}) => {\n const segments = buildOrderedAttachmentSegments(message.attachments)\n if (segments.length === 0) return null\n\n const totalMediaBubbles = countMediaSegmentBubbles(segments)\n const rawCaption = message.text?.trim()\n const linkSegment = segments.find((segment) => segment.type === 'link')\n const primaryLinkUrl =\n linkSegment?.type === 'link'\n ? linkCardPropsFromStreamAttachment(linkSegment.attachments[0] ?? {}).url\n : undefined\n const caption =\n rawCaption && linkCaptionDuplicatesAttachmentUrl(rawCaption, primaryLinkUrl)\n ? undefined\n : rawCaption\n\n let mediaBubbleIndex = 0\n const rows: React.ReactNode[] = []\n\n // A link card paints its own accent-coloured tail only when it is the very\n // last thing this message renders. A caption bubble follows when there is\n // one, and that bubble already owns the tail via `styles.css`; and a message\n // mid-run has its tail on a later message. Anything else is a mid-run card,\n // which must stay tail-less.\n const linkTailPosition: BubbleGroupPosition = caption\n ? 'middle'\n : groupPosition\n\n const pushLinkRow = (\n attachment: Attachment,\n key: string,\n isFinalRow: boolean\n ) => {\n const Card = isMyMessage ? LinkAttachment.Sent : LinkAttachment.Received\n\n rows.push(\n <Card\n key={key}\n {...linkCardPropsFromStreamAttachment(attachment)}\n groupPosition={isFinalRow ? linkTailPosition : 'middle'}\n />\n )\n }\n\n const pushMediaCluster = (\n segment: Extract<AttachmentSegment, { type: 'media' }>,\n key: string\n ) => {\n const position = bubblePositionInRun(\n mediaBubbleIndex,\n totalMediaBubbles,\n groupPosition\n )\n\n mediaBubbleIndex += 1\n\n rows.push(\n <MediaClusterBubble\n key={key}\n groupPosition={position}\n isMyMessage={isMyMessage}\n segment={segment}\n />\n )\n }\n\n segments.forEach((segment, segmentIndex) => {\n const isFinalSegment = segmentIndex === segments.length - 1\n\n if (segment.type === 'link') {\n segment.attachments.forEach((attachment, attachmentIndex) => {\n pushLinkRow(\n attachment,\n `link-${segmentIndex}-${attachmentIndex}`,\n isFinalSegment && attachmentIndex === segment.attachments.length - 1\n )\n })\n return\n }\n\n pushMediaCluster(segment, `media-${segmentIndex}`)\n })\n\n return (\n <div className=\"str-chat__message-bubble-wrapper\">\n <div\n className=\"str-chat__message-bubble\"\n data-attachment-bubble=\"true\"\n style={{\n background: 'transparent',\n borderRadius: 0,\n overflow: 'visible',\n padding: 0,\n }}\n >\n {rows}\n {!caption && <MessageErrorIcon />}\n </div>\n {caption ? (\n <div className=\"str-chat__message-bubble\">\n <MessageText message={message} renderText={renderText} />\n <MessageErrorIcon />\n </div>\n ) : null}\n </div>\n )\n}\n\nexport default StreamAttachmentMessage\n","import classNames from 'classnames'\nimport React, { useContext, useMemo, useState } from 'react'\nimport {\n Attachment as DefaultAttachment,\n EditMessageModal as DefaultEditMessageModal,\n MessageBounceModal,\n MessageBouncePrompt as DefaultMessageBouncePrompt,\n MessageBlocked as DefaultMessageBlocked,\n MessageDeleted as DefaultMessageDeleted,\n MessageErrorIcon,\n MessageIsThreadReplyInChannelButtonIndicator as DefaultMessageIsThreadReplyInChannelButtonIndicator,\n MessageRepliesCountButton as DefaultMessageRepliesCountButton,\n MessageText,\n Poll,\n ReminderNotification as DefaultReminderNotification,\n StreamedMessageText as DefaultStreamedMessageText,\n areMessageUIPropsEqual,\n isDateSeparatorMessage,\n isMessageBlocked,\n isMessageBounced,\n messageHasAttachments,\n messageHasReactions,\n useChannelStateContext,\n useComponentContext,\n useChatContext,\n useMessageContext,\n useMessageReminder,\n type MessageContextValue,\n type MessageUIComponentProps,\n} from 'stream-chat-react'\n\nimport { useMessageVote } from '../../hooks/useMessageVote'\nimport { getMessageDisplayText } from '../../utils/getMessageDisplayText'\nimport { Avatar } from '../Avatar'\nimport { isLinkAttachment } from '../MediaMessage'\nimport { bubbleGroupPositionFromStream as messageAttachmentGroupPositionFromStream } from '../MessageAttachment'\n\nimport { BroadcastNameContext } from './BroadcastNameContext'\nimport { useCustomMessage } from './context'\nimport LockedAttachment from './LockedAttachment'\nimport {\n MessageTag,\n isAttachmentMessage,\n isChatbotMessage,\n isMediaAttachmentMessage,\n isTextAttachmentMessage,\n isTipOnlyMessage,\n} from './MessageTag'\nimport { MessageVoteButtons } from './MessageVoteButtons'\nimport { SentMessageDeliveryStatus } from './SentMessageDeliveryStatus'\nimport StreamAttachmentMessage, {\n buildOrderedAttachmentSegments,\n} from './StreamAttachmentMessage'\n\ntype CustomMessageUIComponentProps = MessageUIComponentProps & {\n chatbotVotingEnabled?: boolean\n viewerLanguage?: string\n onBroadcastClick?: (broadcast: { id: string; name?: string }) => void\n}\n\ntype CustomMessageWithContextProps = MessageContextValue & {\n chatbotVotingEnabled?: boolean\n viewerLanguage?: string\n onBroadcastClick?: (broadcast: { id: string; name?: string }) => void\n resolvedBroadcastName?: string\n}\n\nconst CustomMessageWithContext = (props: CustomMessageWithContextProps) => {\n const {\n additionalMessageInputProps,\n chatbotVotingEnabled,\n editing,\n endOfGroup,\n firstOfGroup,\n groupedByUser,\n handleAction,\n handleOpenThread,\n handleRetry,\n highlighted,\n isMessageAIGenerated,\n isMyMessage,\n message,\n renderText,\n threadList,\n viewerLanguage,\n onBroadcastClick,\n resolvedBroadcastName,\n } = props\n\n const { client } = useChatContext('CustomMessage')\n const { channel } = useChannelStateContext('CustomMessage')\n const { isUnlocking, onUnlockClick, onFetchSource, onDownloadClick } =\n useCustomMessage('LockedAttachment')\n const [isBounceDialogOpen, setIsBounceDialogOpen] = useState(false)\n const reminder = useMessageReminder(message.id)\n const { selected: voteState, voteUp, voteDown } = useMessageVote(message)\n\n const {\n Attachment = DefaultAttachment,\n EditMessageModal = DefaultEditMessageModal,\n MessageActions,\n MessageBlocked = DefaultMessageBlocked,\n MessageBouncePrompt = DefaultMessageBouncePrompt,\n MessageDeleted = DefaultMessageDeleted,\n MessageIsThreadReplyInChannelButtonIndicator = DefaultMessageIsThreadReplyInChannelButtonIndicator,\n MessageRepliesCountButton = DefaultMessageRepliesCountButton,\n ReminderNotification = DefaultReminderNotification,\n StreamedMessageText = DefaultStreamedMessageText,\n PinIndicator,\n } = useComponentContext('CustomMessage')\n\n const hasAttachment = messageHasAttachments(message)\n const hasReactions = messageHasReactions(message)\n const isAIGenerated = useMemo(\n () => isMessageAIGenerated?.(message),\n [isMessageAIGenerated, message]\n )\n const finalAttachments = useMemo(() => {\n const attachments = message.attachments ?? []\n const raw = message.shared_location\n ? [message.shared_location, ...attachments]\n : attachments\n\n if (!isChatbotMessage(message)) return raw\n\n const filtered = raw.filter((a) => !('type' in a) || !isLinkAttachment(a))\n return filtered.length === raw.length ? raw : filtered\n }, [message])\n const attachmentSegments = useMemo(\n () => buildOrderedAttachmentSegments(finalAttachments),\n [finalAttachments]\n )\n const displayMessage = useMemo(() => {\n const displayText = getMessageDisplayText({ message, viewerLanguage })\n return displayText === message.text\n ? message\n : { ...message, text: displayText }\n }, [message, viewerLanguage])\n // Route every generic Stream-attachment message (link OG previews and\n // image/video/audio/pdf/file media) through the toolkit renderer, so\n // messaging-react owns all shared attachment rendering rather than leaving\n // media on stream-chat-react's default Attachment. App-specific types\n // (locked/paid, tips, chatbot) are handled by the branches above.\n const hasAttachmentSegments = attachmentSegments.length > 0\n // Only own the message when every attachment maps to a representable segment.\n // Otherwise a mixed message (e.g. an unsupported shared_location alongside a\n // photo) would silently drop the unrepresented attachment — those fall\n // through to the default `Attachment` renderer, which handles all of them.\n const allAttachmentsRepresented =\n attachmentSegments.reduce(\n (total, segment) => total + segment.attachments.length,\n 0\n ) === (finalAttachments?.length ?? 0)\n const streamAttachmentGroupPosition =\n messageAttachmentGroupPositionFromStream({\n endOfGroup,\n firstOfGroup,\n groupedByUser,\n })\n\n if (isDateSeparatorMessage(message)) {\n return null\n }\n\n if (message.deleted_at || message.type === 'deleted') {\n return <MessageDeleted message={message} />\n }\n\n if (isMessageBlocked(message)) {\n return <MessageBlocked />\n }\n\n const showReplyCountButton = !threadList && !!message.reply_count\n const showIsReplyInChannel =\n !threadList && message.show_in_channel && message.parent_id\n const allowRetry =\n message.status === 'failed' && message.error?.status !== 403\n const isBounced = isMessageBounced(message)\n let handleClick: (() => void) | undefined = undefined\n\n if (allowRetry) {\n handleClick = () => handleRetry(message)\n } else if (isBounced) {\n handleClick = () => setIsBounceDialogOpen(true)\n }\n\n const isMine = isMyMessage()\n const rootClassName = classNames(\n 'str-chat__message str-chat__message-simple',\n `str-chat__message--${message.type}`,\n `str-chat__message--${message.status}`,\n isMine\n ? 'str-chat__message--me str-chat__message-simple--me'\n : 'str-chat__message--other',\n message.text ? 'str-chat__message--has-text' : 'has-no-text',\n {\n 'str-chat__message--has-attachment': hasAttachment,\n 'str-chat__message--highlighted': highlighted,\n 'str-chat__message--pinned pinned-message': message.pinned,\n 'str-chat__message--with-reactions': hasReactions,\n 'str-chat__message-send-can-be-retried':\n message?.status === 'failed' && message?.error?.status !== 403,\n 'str-chat__message-with-thread-link':\n showReplyCountButton || showIsReplyInChannel,\n 'str-chat__virtual-message__wrapper--end': endOfGroup,\n 'str-chat__virtual-message__wrapper--first': firstOfGroup,\n 'str-chat__virtual-message__wrapper--group': groupedByUser,\n }\n )\n\n const poll = message.poll_id && client.polls.fromState(message.poll_id)\n const isTipOnly = isTipOnlyMessage(message)\n const isChatbot = isChatbotMessage(message)\n const isAttachment = isAttachmentMessage(message)\n const hasRenderableAttachments = !!(\n finalAttachments?.length && !message.quoted_message\n )\n const useAttachmentFooterChatbotTag =\n isChatbot && isMine && hasRenderableAttachments\n // Route generic Stream attachments through the toolkit renderer only when it\n // can faithfully own the whole message. Quoted replies (attachments are\n // suppressed there), polls, AI-streamed, and chatbot messages fall through to\n // the default branch so their Poll / StreamedMessageText / message-text and\n // chatbot attribution (MessageTag) handling is preserved — the accompanying\n // message text and attribution must never be dropped.\n const canRenderAttachmentsInToolkit =\n hasAttachmentSegments &&\n allAttachmentsRepresented &&\n !message.quoted_message &&\n !poll &&\n !isAIGenerated &&\n !isChatbot\n\n const sharedLockedTextProps = {\n contentType: 'text' as const,\n amountText: message.metadata?.amount_text,\n paymentStatus: message.metadata?.payment_status,\n renderedText: message.text && (\n <MessageText message={displayMessage} renderText={renderText} />\n ),\n }\n const sharedLockedMediaProps = {\n contentType: 'media' as const,\n title: message.metadata?.attachment_title,\n mimeType: message.metadata?.attachment_mime_type,\n thumbnailUrl: message.metadata?.attachment_thumbnail,\n amountText: message.metadata?.amount_text,\n detail: message.metadata?.attachment_detail,\n paymentStatus: message.metadata?.payment_status,\n onFetchSource: onFetchSource\n ? () => onFetchSource(message, channel)\n : undefined,\n }\n return (\n <>\n {editing && (\n <EditMessageModal\n additionalMessageInputProps={additionalMessageInputProps}\n />\n )}\n {isBounceDialogOpen && (\n <MessageBounceModal\n MessageBouncePrompt={MessageBouncePrompt}\n onClose={() => setIsBounceDialogOpen(false)}\n open={isBounceDialogOpen}\n />\n )}\n <div\n className={rootClassName}\n key={message.id}\n data-message-id={message.id}\n data-dd-privacy=\"mask\"\n >\n {PinIndicator && <PinIndicator />}\n {!!reminder && <ReminderNotification reminder={reminder} />}\n {message.user && (\n <Avatar\n className=\"str-chat__avatar str-chat__message-sender-avatar\"\n id={message.user.id}\n image={message.user.image}\n name={message.user.name || message.user.id}\n size={24}\n shape=\"circle\"\n dmAgentEnabled={isChatbot}\n />\n )}\n <div\n className={classNames('str-chat__message-inner', {\n 'str-chat__simple-message--error-failed': allowRetry || isBounced,\n })}\n data-testid=\"message-inner\"\n onClick={handleClick}\n onKeyDown={handleClick}\n role={handleClick ? 'button' : undefined}\n tabIndex={handleClick ? 0 : undefined}\n style={{\n // Force margins to 0 to prevent hover layout shift\n // Stream Chat CSS sets margin-inline-end/start to 78px, then 0 on hover\n marginInlineEnd: 0,\n marginInlineStart: 0,\n }}\n >\n {isTipOnly ? (\n <MessageTag message={message} standalone />\n ) : isTextAttachmentMessage(message) ? (\n <div className=\"str-chat__message-bubble-wrapper\">\n <div className=\"flex items-center gap-2\">\n {isMine && MessageActions && <MessageActions />}\n {isMine ? (\n <LockedAttachment\n {...sharedLockedTextProps}\n isMine={true}\n />\n ) : (\n <LockedAttachment\n {...sharedLockedTextProps}\n isMine={false}\n isUnlocking={isUnlocking(message.id)}\n onUnlockClick={() => onUnlockClick?.(message, channel)}\n />\n )}\n {!isMine && MessageActions && <MessageActions />}\n </div>\n </div>\n ) : isMediaAttachmentMessage(message) ? (\n <div className=\"str-chat__message-bubble-wrapper\">\n <div className=\"flex items-center gap-2\">\n {isMine && MessageActions && <MessageActions />}\n {isMine ? (\n <LockedAttachment\n {...sharedLockedMediaProps}\n isMine={true}\n onPreviewClick={() =>\n onUnlockClick\n ? onUnlockClick(message, channel)\n : undefined\n }\n />\n ) : (\n <LockedAttachment\n {...sharedLockedMediaProps}\n isMine={false}\n isUnlocking={isUnlocking(message.id)}\n onUnlockClick={() =>\n onUnlockClick\n ? onUnlockClick(message, channel)\n : undefined\n }\n onDownloadClick={() =>\n onDownloadClick\n ? onDownloadClick(message, channel)\n : undefined\n }\n />\n )}\n {!isMine && MessageActions && <MessageActions />}\n </div>\n {message.text && (\n <div className=\"str-chat__message-bubble\">\n <MessageText\n message={displayMessage}\n renderText={renderText}\n />\n </div>\n )}\n </div>\n ) : canRenderAttachmentsInToolkit ? (\n <StreamAttachmentMessage\n groupPosition={streamAttachmentGroupPosition}\n isMyMessage={isMine}\n message={{\n ...displayMessage,\n attachments: finalAttachments,\n // MessageText prefers message.i18n[userLanguage_text] from\n // Stream's TranslationContext over message.text. Drop i18n so\n // the caption uses displayMessage.text from viewerLanguage.\n i18n: undefined,\n }}\n renderText={renderText}\n />\n ) : (\n <div className=\"str-chat__message-bubble-wrapper\">\n <div className=\"str-chat__message-bubble\">\n {isChatbot && !useAttachmentFooterChatbotTag && (\n <MessageTag\n message={message}\n hasAttachment={hasRenderableAttachments}\n isMyMessage={isMine}\n />\n )}\n {poll && <Poll poll={poll} />}\n {finalAttachments?.length && !message.quoted_message ? (\n <Attachment\n actionHandler={handleAction}\n attachments={finalAttachments}\n />\n ) : null}\n {isAIGenerated ? (\n <StreamedMessageText\n message={displayMessage}\n renderText={renderText}\n />\n ) : (\n <MessageText\n message={displayMessage}\n renderText={renderText}\n />\n )}\n <MessageErrorIcon />\n </div>\n </div>\n )}\n </div>\n {!isAttachment && !isTipOnly && (\n <div className=\"str-chat__message-footer\">\n {(!isChatbot || useAttachmentFooterChatbotTag) && (\n <MessageTag\n message={message}\n hasAttachment={hasRenderableAttachments}\n isMyMessage={isMine}\n />\n )}\n {chatbotVotingEnabled && isChatbot && (\n <MessageVoteButtons\n selected={voteState}\n onVoteUp={voteUp}\n onVoteDown={voteDown}\n />\n )}\n </div>\n )}\n <SentMessageDeliveryStatus\n onBroadcastClick={onBroadcastClick}\n resolvedBroadcastName={resolvedBroadcastName}\n />\n {showReplyCountButton && (\n <MessageRepliesCountButton\n onClick={handleOpenThread}\n reply_count={message.reply_count}\n />\n )}\n {showIsReplyInChannel && (\n <MessageIsThreadReplyInChannelButtonIndicator />\n )}\n </div>\n </>\n )\n}\n\nconst MemoizedCustomMessage = React.memo(\n CustomMessageWithContext,\n (prev, next) => {\n if (prev.chatbotVotingEnabled !== next.chatbotVotingEnabled) return false\n if (prev.viewerLanguage !== next.viewerLanguage) return false\n if (prev.onBroadcastClick !== next.onBroadcastClick) return false\n if (prev.resolvedBroadcastName !== next.resolvedBroadcastName) return false\n return areMessageUIPropsEqual(prev, next)\n }\n) as typeof CustomMessageWithContext\n\nexport const CustomMessage = (props: CustomMessageUIComponentProps) => {\n const messageContext = useMessageContext('CustomMessage')\n const broadcastNamesById = useContext(BroadcastNameContext)\n const broadcastId = messageContext.message.metadata?.broadcast_id\n const resolvedBroadcastName =\n typeof broadcastId === 'string'\n ? broadcastNamesById?.[broadcastId]\n : undefined\n\n return (\n <MemoizedCustomMessage\n {...messageContext}\n {...props}\n resolvedBroadcastName={resolvedBroadcastName}\n />\n )\n}\n","import { MESSAGE_CUSTOM_TYPE } from '@linktr.ee/messaging-taxonomy'\nimport { FlagIcon, TrashSimpleIcon } from '@phosphor-icons/react'\nimport React from 'react'\nimport { useMessageContext } from 'stream-chat-react'\nimport {\n DefaultDropdownActionButton,\n MessageActions,\n} from 'stream-chat-react/experimental'\n\nconst DeleteAction = () => {\n const { handleDelete, message } = useMessageContext('CustomMessageActions')\n if (message.metadata?.payment_status === 'paid') return null\n return (\n <DefaultDropdownActionButton\n onClick={handleDelete}\n aria-label=\"Delete\"\n title=\"Delete\"\n className=\"bg-marble rounded-full p-2 hover:bg-sand transition-all\"\n >\n <TrashSimpleIcon size={16} weight=\"light\" aria-hidden />\n </DefaultDropdownActionButton>\n )\n}\n\nconst ReportAction = () => {\n const { handleFlag } = useMessageContext('CustomMessageActions')\n return (\n <DefaultDropdownActionButton\n onClick={handleFlag}\n aria-label=\"Report\"\n title=\"Report\"\n className=\"bg-marble rounded-full p-2 hover:bg-sand transition-all\"\n >\n <FlagIcon size={16} weight=\"light\" aria-hidden />\n </DefaultDropdownActionButton>\n )\n}\n\nexport const CustomMessageActions = () => {\n const { message } = useMessageContext('CustomMessageActions')\n if (message.metadata?.custom_type !== MESSAGE_CUSTOM_TYPE.ATTACHMENT)\n return null\n return (\n <MessageActions\n messageActionSet={[\n { Component: DeleteAction, placement: 'quick', type: 'delete' },\n { Component: ReportAction, placement: 'quick', type: 'flag' },\n ]}\n />\n )\n}\n","import React from 'react'\nimport { LinkPreviewsManager, LinkPreviewsManagerState } from 'stream-chat'\nimport { useMessageComposer, useStateStore } from 'stream-chat-react'\n\nimport LinkAttachment from '../LinkAttachment'\n\nconst linkPreviewsManagerStateSelector = (state: LinkPreviewsManagerState) => ({\n linkPreviews: Array.from(state.previews.values()).filter(\n (preview) =>\n LinkPreviewsManager.previewIsLoaded(preview) ||\n LinkPreviewsManager.previewIsLoading(preview)\n ),\n})\n\n/**\n * The composer's staged link previews, rendered as `LinkAttachment.Composer`\n * cards.\n *\n * **The cards are deliberately dismiss-only — they do not navigate.**\n * `LinkAttachment.Composer` is the one card variant whose shell is never an\n * anchor or a button, and the hand-rolled card this replaced wrapped its whole\n * body in `<a href={og_scrape_url} target=\"_blank\">` with the dismiss button\n * calling `preventDefault()` inside it. That shape is a touch hazard —\n * MES-1358 §7 Q7 raised it and deferred the call to MES-1349 — because a\n * mis-tap while composing opens a new tab mid-draft, and the dismiss button's\n * 44px hit halo (`Composer/Card.tsx`, `before:-inset-[10px]`) sits *inside*\n * that anchor, so enlarging the target for touch enlarges the navigation\n * trigger with it. A staged preview is a draft affordance rather than\n * content — its URL is still in the textarea the author just typed it into,\n * one tap away without leaving the thread.\n *\n * Nothing depended on the old behaviour: no test, story or analytics asserted\n * it here or in frontyard's parallel `ComposerLinkPreviewList`, whose own\n * tests cover text, dismiss and layout only. If a surface ever genuinely needs\n * activation, add an explicit prop to `ComposerCardProps` — do not re-wrap the\n * card in an anchor. (MES-1349)\n */\nexport const CustomLinkPreviewList = () => {\n const { linkPreviewsManager } = useMessageComposer()\n\n const { linkPreviews: stateLinkPreviews } = useStateStore(\n linkPreviewsManager.state,\n linkPreviewsManagerStateSelector\n )\n\n const handleDismiss = (url: string) => {\n linkPreviewsManager.dismissPreview(url)\n }\n\n const showLinkPreviews = stateLinkPreviews.length > 0\n\n if (!showLinkPreviews) return null\n\n return (\n // Layout contract: this list is the composer's *shrinkable* region. The\n // mobile visitor surface sizes itself to the keyboard-shrunk\n // visualViewport, so when vertical space runs out this container gives\n // way (min-h-0) and scrolls, while the textarea + send row stays visible\n // (shrink-0 in CustomMessageInput). Each card is wrapped in a shrink-0\n // block so it keeps its intrinsic height and the container scrolls — a\n // bare flex-column child would be shrunk on the column axis and its\n // fixed-height hero would spill out of the collapsed card box.\n //\n // Horizontally the card does NOT shrink, deliberately. `CardShell` bakes\n // Figma's `w-[290px]` and there is exactly one width, in the toolkit\n // (MES-1349 and MES-1358 agreed consumers add no competing cap). Do not\n // \"fix\" a narrow viewport with `max-w-full` here or on the shell: the box is\n // `flex h-[250px] flex-col` with a `flex-1` hero and a title clamped to two\n // lines against a known width, so capping deforms it on every narrow\n // surface, in-thread Sent/Received included.\n //\n // Measured against the real class chain in headless Chromium:\n //\n // chrome = 32px (`CustomMessageInput`'s outer `p-4`)\n // + 16px (this region's `px-2`) = 48px\n // card = 290px -> floor = 290 + 48 = 338px viewport\n //\n // viewport 320 360 375 393 430\n // available 272 312 327 345 382\n // delta -18 +22 +37 +55 +92\n //\n // 393px is the design frame, and its 345px reproduces the frame's measured\n // `attachment-area` width, so the chrome arithmetic is corroborated. The\n // lowest named breakpoint is `xs: 359px`\n // (`@repo/tailwind-config/transitional-tokens.js:29-36`), which is *above*\n // the 338px floor — the card fits at every width the scale names. MES-1358's\n // `max-md:p-3` trims chrome 48px -> 40px and moves the floor to 330px, still\n // above 320px, so capping `CardShell` would be the only way to reach a 320px\n // viewport. That is the whole trade: deform every narrow surface, or leave\n // one sub-floor device class awkward.\n //\n // It is awkward, not broken. Setting only `overflow-y` promotes the other\n // axis, so `overflow-x` computes to `auto` and the region scrolls sideways\n // instead of spilling; at 320px the dismiss button's right edge lands ~6px\n // past the fold, reachable by scrolling. That residue belongs to whoever\n // owns the mobile layout contract, not to this component.\n <div className=\"messaging-link-preview-list flex min-h-0 flex-col items-stretch w-full gap-2 overflow-y-auto overscroll-contain\">\n {stateLinkPreviews.map((linkPreview) => {\n // A LOADING preview has no `image_url` yet, so keying the layout off\n // the image alone rendered the skeleton as two bare text bars and then\n // snapped it open to the 250px featured box the instant the scrape\n // returned. Hold the hero's space for the duration instead — reserving\n // that space is what the skeleton is for.\n const isLoading = LinkPreviewsManager.previewIsLoading(linkPreview)\n\n return (\n <div key={linkPreview.og_scrape_url} className=\"w-full shrink-0\">\n <LinkAttachment.Composer\n title={linkPreview.title}\n url={linkPreview.og_scrape_url}\n thumbnailUrl={linkPreview.image_url}\n layout={\n isLoading || linkPreview.image_url ? 'featured' : 'classic'\n }\n status={isLoading ? 'loading' : 'ready'}\n onDismiss={() => handleDismiss(linkPreview.og_scrape_url)}\n />\n </div>\n )\n })}\n </div>\n )\n}\n","import { ArrowUpIcon } from '@phosphor-icons/react'\nimport React, { useContext } from 'react'\nimport {\n AttachmentPreviewList as DefaultAttachmentPreviewList,\n MessageInput,\n QuotedMessagePreview,\n TextareaComposer,\n useChannelStateContext,\n useComponentContext,\n useMessageComposerHasSendableData,\n useMessageInputContext,\n} from 'stream-chat-react'\n\nimport { CustomLinkPreviewList } from '../CustomLinkPreviewList'\n\n/**\n * Carries the channel's `frozen` state down to CustomMessageInputInner, which\n * renders the composer as a read-only/disabled input. Using a context — rather\n * than closing the value into the `Input` component passed to Stream's\n * <MessageInput> — keeps CustomMessageInputInner a stable reference, so the\n * value toggling re-renders the composer instead of unmounting and remounting\n * it (which would drop textarea focus and interrupt IME composition).\n */\nconst ComposerLockedContext = React.createContext(false)\n\n/**\n * Distance from the bottom (px) still treated as \"at the latest message\", used\n * to decide whether a growing composer should re-pin the thread to the bottom\n * (MES-1303). Matches stream-chat-react's own `scrolledUpThreshold` default\n * (200) so composer growth keeps the thread pinned under the same condition\n * Stream already auto-scrolls a new message — anything closer than one message\n * would let a user resting just off the bottom fall through and get covered.\n */\nconst NEAR_BOTTOM_THRESHOLD_PX = 200\n\n/**\n * Read the composer's locked (frozen-channel) state from inside a custom\n * composer supplied via `composerInput`. Returns true when the channel is\n * frozen; mirror the default composer by rendering the textarea read-only and\n * disabling the send control.\n */\nexport const useComposerLocked = (): boolean =>\n useContext(ComposerLockedContext)\n\nconst DefaultSendButton: React.FC<{\n sendMessage: () => void\n disabled?: boolean\n [key: string]: unknown\n}> = ({ sendMessage, disabled, ...rest }) => (\n <button\n {...rest}\n type=\"button\"\n aria-label=\"Send\"\n disabled={disabled}\n // Keep the soft keyboard open after tapping send (MES-1320). Pressing a\n // button moves focus to it, blurring the textarea — on mobile that\n // dismisses the on-screen keyboard, forcing the visitor to re-tap the\n // composer for every message. preventDefault on pointerdown suppresses that\n // focus shift so the textarea stays focused; the click still fires (click is\n // derived from pointerup, not pointerdown), so `sendMessage` runs as normal.\n // pointerdown covers both touch and mouse, and keyboard activation (Enter/\n // Space → click) is unaffected.\n onPointerDown={(e) => e.preventDefault()}\n onClick={sendMessage}\n >\n <ArrowUpIcon weight=\"bold\" className=\"size-4\" />\n </button>\n)\n\nconst CustomMessageInputInner: React.FC = () => {\n const disabled = useContext(ComposerLockedContext)\n const { handleSubmit } = useMessageInputContext()\n\n const hasSendableData = useMessageComposerHasSendableData()\n const isSendDisabled = disabled || !hasSendableData\n\n const {\n SendButton = DefaultSendButton,\n AttachmentPreviewList = DefaultAttachmentPreviewList,\n } = useComponentContext('CustomMessageInput')\n\n return (\n // min-h-0 lets the composer shrink under keyboard squeeze (the link\n // preview list inside is the scrollable region); the textarea + send row\n // is shrink-0 so it can never be pushed out of view. self-stretch matters\n // because the parent `.message-input` row uses items-end, which suppresses\n // the default cross-axis stretch — without it this container keeps its\n // content height and the squeeze never reaches the preview list. Stream's\n // <MessageInput> renders its Input directly (context providers only, no\n // wrapper element), so this is a direct flex item of that row.\n //\n // The container itself carries no padding of its own: it used to (p-2),\n // but that inset now lives on the textarea as padding instead, so the\n // textarea's actual (clickable) box is as large as the container — save\n // for the small margin and the send button on the right (MES-1325).\n // Visually nothing moves; the container ends up exactly the size of the\n // textarea + send button row it contains.\n //\n // Some hosts portal staged-media thumbnails (e.g. ComposerPendingMediaPortal,\n // see this component's stories) straight into `.central-container` rather\n // than through this React tree, bypassing the two wrappers below. The\n // `[&>:not(...)]:p-2` variant restores the container's old inset for any\n // such foreign direct child, without re-adding it to our own wrappers.\n <div\n className=\"central-container flex min-h-0 flex-col min-w-0 w-full self-stretch bg-white rounded-[1.5rem] shadow-[0_4px_16px_0_rgba(0,0,0,0.08),0_1px_2px_0_rgba(0,0,0,0.04),0_0_0_1px_rgba(0,0,0,0.04)] [&>:not(.messaging-composer-previews):not(.messaging-composer-row)]:p-2\"\n data-dd-privacy=\"mask\"\n >\n {/* empty:hidden collapses this row (padding, gap, and all) when none of\n the previews below have anything to render, so an idle composer has\n no leftover top inset before the textarea row. */}\n <div className=\"messaging-composer-previews empty:hidden flex min-h-0 flex-col gap-2 px-2 pt-2\">\n <QuotedMessagePreview />\n <CustomLinkPreviewList />\n <AttachmentPreviewList />\n </div>\n <div className=\"messaging-composer-row flex shrink-0 items-start\">\n <TextareaComposer\n aria-disabled={disabled || undefined}\n // TextareaComposer wraps the real <textarea> in its own div, so\n // `containerClassName` (not `className`) is what joins the row's\n // flex layout; `leading-[0]` drops the line-height space an\n // inline-level parent otherwise reserves, keeping that wrapper\n // exactly the textarea's height rather than stretched by the row\n // (items-start above is a second guard against that same stretch).\n containerClassName=\"min-w-0 flex-1 leading-[0]\"\n // bg-transparent: the container has no padding to inset it behind\n // anymore, so an opaque textarea would paint over its rounded corners.\n className=\"w-full resize-none bg-transparent py-3.5 pl-4 pr-4 outline-none leading-5 placeholder:text-black/30 text-sm\"\n // While this might usually be considered an anti-pattern, in most\n // cases, when a message thread is rendered, we want the input to\n // gain focus automatically.\n // eslint-disable-next-line jsx-a11y/no-autofocus\n autoFocus={!disabled}\n // Enter sends (Shift+Enter inserts a newline), so label the\n // on-screen keyboard's return key accordingly.\n enterKeyHint=\"send\"\n maxRows={4}\n readOnly={disabled}\n tabIndex={disabled ? -1 : undefined}\n />\n {/* The container no longer has its own p-2, so this inset — and the\n mt-auto that anchors the button to the bottom as the textarea\n grows — lives on a wrapper instead of the button's own\n className: a host-supplied SendButton can (and, per our own\n stories, does) spread its own className over the one we pass in,\n which would otherwise silently drop this spacing. */}\n <div className=\"mt-auto mb-2 mr-2 shrink-0\">\n <SendButton\n sendMessage={handleSubmit}\n aria-label=\"Send\"\n // before:-inset-2 extends the button's clickable area to 48x48\n // (MES-1325) via an invisible pseudo-element — clicks on it still\n // land on the button itself — without growing the 32x32 circle\n // `size-8`/`rounded-full`/`bg-[#121110]` visually describe.\n className=\"str-chat__send-button relative flex justify-center items-center rounded-full size-8 bg-[#121110] disabled:bg-[#F1F0EE] disabled:text-black/20 text-white focus-ring before:absolute before:-inset-2 before:content-['']\"\n data-testid=\"send-button\"\n disabled={isSendDisabled}\n type=\"button\"\n />\n </div>\n </div>\n </div>\n )\n}\n\nexport interface CustomMessageInputProps {\n renderActions?: () => React.ReactNode\n /**\n * Content rendered above the composer controls (and above the locked panel\n * when `disabled`). Used by the floating layout to keep conversation footer\n * content inside the absolutely positioned chrome so it is not covered.\n */\n renderHeader?: () => React.ReactNode\n renderFooter?: () => React.ReactNode\n /**\n * Replace the composer entirely with a non-interactive locked panel that\n * shows `disabledReason`. Used by the Linktree official channel, where the\n * linker cannot message Linktree from the inbox. Defaults to false.\n *\n * Distinct from the channel's `frozen` flag, which keeps the composer\n * rendered but read-only/dimmed.\n */\n disabled?: boolean\n /**\n * Explanatory text shown inside the locked panel. Only rendered when\n * `disabled` is true.\n */\n disabledReason?: string\n /**\n * Replace the inner composer — the textarea + send arrangement rendered\n * inside Stream's `<MessageInput>` — with a host-owned component. When\n * provided it is passed to Stream as the `Input` component, so it runs inside\n * the message-input context and can drive sending, attachments, and previews\n * via the Stream hooks (`useMessageInputContext`,\n * `useMessageComposerHasSendableData`, `TextareaComposer`, …). The outer\n * frozen/`renderActions`/`renderFooter` wrapper is unchanged; read\n * `useComposerLocked()` to honour the frozen state. Defaults to the built-in\n * composer.\n */\n composerInput?: React.ComponentType\n}\n\nexport const CustomMessageInput: React.FC<CustomMessageInputProps> = ({\n renderActions,\n renderHeader,\n renderFooter,\n disabled = false,\n disabledReason,\n composerInput,\n}) => {\n const { channel } = useChannelStateContext()\n const isFrozen = channel?.data?.frozen === true\n const isFloating = Boolean(composerInput)\n const composerRef = React.useRef<HTMLDivElement>(null)\n\n React.useEffect(() => {\n if (!isFloating) {\n return\n }\n\n const composer = composerRef.current\n const layout = composer?.parentElement\n\n if (!composer || !layout) {\n return\n }\n\n // Track the composer height across resizes so we can re-pin only when it\n // actually grows (see below).\n let previousComposerHeight = composer.offsetHeight\n\n const updateComposerHeight = () => {\n // The floating composer overlays the message list; growing it only\n // reserves space via padding-bottom, which never moves the viewport, so\n // a taller composer creeps up over the last message (MES-1303). Capture\n // whether the thread is pinned to the latest message *before* the padding\n // grows, then re-pin afterwards.\n const nextComposerHeight = composer.offsetHeight\n // Only growth can cover the latest message: shrinks free up space and\n // width-only resizes (window/layout changes) cover nothing, so re-pinning\n // then would needlessly yank a user resting just off the bottom.\n const grew = nextComposerHeight > previousComposerHeight\n previousComposerHeight = nextComposerHeight\n\n // The scroll viewport is Stream's `.str-chat__list` (overflow-y: auto);\n // its child `.str-chat__message-list-scroll` holds the padding but has\n // overflow: visible and never scrolls. The redesigned empty state also\n // renders a placeholder `.str-chat__list`, so select the one that is\n // actually scrollable rather than the first match — that is also the only\n // one where re-pinning can do anything.\n const scroller =\n Array.from(\n layout.querySelectorAll<HTMLElement>('.str-chat__list')\n ).find((el) => el.scrollHeight > el.clientHeight) ?? null\n // Guarded on `wasAtBottom` so we never yank a user reading history.\n const wasAtBottom = scroller\n ? scroller.scrollHeight - scroller.scrollTop - scroller.clientHeight <\n NEAR_BOTTOM_THRESHOLD_PX\n : false\n\n layout.style.setProperty(\n '--messaging-composer-height',\n `${nextComposerHeight}px`\n )\n\n // Reading scrollHeight forces a synchronous reflow, so it reflects the\n // padding-bottom we just set; scrolling to it pins the true bottom.\n if (grew && wasAtBottom && scroller) {\n scroller.scrollTop = scroller.scrollHeight\n }\n }\n\n updateComposerHeight()\n\n if (typeof ResizeObserver === 'undefined') {\n return\n }\n\n const resizeObserver = new ResizeObserver(updateComposerHeight)\n resizeObserver.observe(composer)\n\n return () => {\n resizeObserver.disconnect()\n layout.style.removeProperty('--messaging-composer-height')\n }\n }, [isFloating])\n\n // Linktree official channel: the composer is replaced by an info panel\n // explaining the linker cannot send messages on this thread.\n if (disabled) {\n if (!isFloating) {\n return (\n <>\n {renderHeader?.()}\n <div className=\"messaging-composer-locked-panel flex w-full flex-col items-center justify-center gap-3 px-6 py-4\">\n {disabledReason ? (\n <p className=\"max-w-[345px] text-center text-xs font-normal leading-[1.3] tracking-[0.12px] text-black/40\">\n {disabledReason}\n </p>\n ) : null}\n </div>\n {renderFooter?.()}\n </>\n )\n }\n\n return (\n <div\n ref={composerRef}\n className=\"messaging-composer-chrome messaging-composer-chrome--floating\"\n >\n <div className=\"messaging-composer-backdrop\" aria-hidden=\"true\">\n <div className=\"messaging-composer-backdrop-blur\" />\n <div className=\"messaging-composer-backdrop-blur\" />\n <div className=\"messaging-composer-backdrop-blur\" />\n <div className=\"messaging-composer-backdrop-blur\" />\n <div className=\"messaging-composer-backdrop-blur\" />\n <div className=\"messaging-composer-backdrop-gradient\" />\n </div>\n <div className=\"relative z-10 flex flex-col\">\n {renderHeader?.()}\n <div className=\"messaging-composer-locked-panel flex w-full flex-col items-center justify-center gap-3 px-6 py-4\">\n {disabledReason ? (\n <p className=\"max-w-[345px] text-center text-xs font-normal leading-[1.3] tracking-[0.12px] text-black/40\">\n {disabledReason}\n </p>\n ) : null}\n </div>\n {renderFooter?.()}\n </div>\n </div>\n )\n }\n\n if (!isFloating) {\n return (\n <div className=\"flex min-h-0 flex-col gap-4 p-4\">\n {renderHeader?.()}\n <div\n // @ts-expect-error Only React 19 onwards has `inert` in its types.\n inert={isFrozen ? '' : undefined}\n aria-disabled={isFrozen || undefined}\n className=\"message-input flex min-h-0 items-end gap-4 aria-disabled:opacity-40\"\n >\n {renderActions && (\n <div className=\"flex h-12 shrink-0 items-center justify-center\">\n {renderActions()}\n </div>\n )}\n <ComposerLockedContext.Provider value={isFrozen}>\n <MessageInput Input={CustomMessageInputInner} />\n </ComposerLockedContext.Provider>\n </div>\n {renderFooter?.()}\n </div>\n )\n }\n\n return (\n <div\n ref={composerRef}\n className=\"messaging-composer-chrome messaging-composer-chrome--floating\"\n >\n <div className=\"messaging-composer-backdrop\" aria-hidden=\"true\">\n <div className=\"messaging-composer-backdrop-blur\" />\n <div className=\"messaging-composer-backdrop-blur\" />\n <div className=\"messaging-composer-backdrop-blur\" />\n <div className=\"messaging-composer-backdrop-blur\" />\n <div className=\"messaging-composer-backdrop-blur\" />\n <div className=\"messaging-composer-backdrop-gradient\" />\n </div>\n\n <div className=\"relative z-10 flex min-h-0 flex-col\">\n {renderHeader?.()}\n <div className=\"flex min-h-0 flex-col gap-4 p-4\">\n <div\n // @ts-expect-error Only React 19 onwards has `inert` in its types.\n inert={isFrozen ? '' : undefined}\n aria-disabled={isFrozen || undefined}\n className=\"message-input flex min-h-0 items-end gap-4 aria-disabled:opacity-40\"\n >\n {renderActions && (\n <div className=\"flex h-12 shrink-0 items-center justify-center\">\n {renderActions()}\n </div>\n )}\n <ComposerLockedContext.Provider value={isFrozen}>\n <MessageInput Input={composerInput ?? CustomMessageInputInner} />\n </ComposerLockedContext.Provider>\n </div>\n {renderFooter?.()}\n </div>\n </div>\n </div>\n )\n}\n","import {\n isAgeSafetySystemType,\n isDmAgentSystemType,\n type AgeSafetySystemType,\n type DmAgentSystemType,\n} from '@linktr.ee/messaging-taxonomy'\nimport { ProhibitIcon, SparkleIcon } from '@phosphor-icons/react'\nimport { MessageTimestamp, type EventComponentProps } from 'stream-chat-react'\n\nconst DM_AGENT_SYSTEM_MESSAGE_FALLBACK_TEXT: Record<DmAgentSystemType, string> =\n {\n SYSTEM_DM_AGENT_PAUSED: 'DM Agent has left the conversation',\n SYSTEM_DM_AGENT_RESUMED: 'DM Agent has rejoined the conversation',\n }\n\n/**\n * System-message timestamps are hidden by default. A semantic type must opt in\n * here to render one, so new/unknown system types stay timestamp-less until\n * explicitly added. Keep in sync with the mobile client (cerberus\n * `CustomMessageSystem`); there is no shared package between the two surfaces.\n */\nexport const SHOW_SYSTEM_MESSAGE_TIMESTAMP_TYPES: readonly AgeSafetySystemType[] =\n ['SYSTEM_AGE_SAFETY_BLOCKED']\n\nconst AGE_SAFETY_SYSTEM_MESSAGE_FALLBACK_TEXT: Record<\n AgeSafetySystemType,\n string\n> = {\n SYSTEM_AGE_SAFETY_BLOCKED:\n 'This user isn’t able to reply because they don’t meet our age safety guidelines.',\n}\n\nconst AGE_SAFETY_SYSTEM_MESSAGE_EMPHASIS = 'age safety guidelines.'\nconst AGE_SAFETY_SYSTEM_MESSAGE_URL = 'https://linktr.ee/s/about/contact'\n\nconst isShowTimestampSystemType = (\n value: string | undefined\n): value is (typeof SHOW_SYSTEM_MESSAGE_TIMESTAMP_TYPES)[number] => {\n return SHOW_SYSTEM_MESSAGE_TIMESTAMP_TYPES.includes(\n value as (typeof SHOW_SYSTEM_MESSAGE_TIMESTAMP_TYPES)[number]\n )\n}\n\nconst shouldShowSystemMessageTimestamp = (\n message: EventComponentProps['message']\n): boolean => {\n return isShowTimestampSystemType(message.metadata?.custom_type)\n}\n\ntype CustomSystemMessageVariant =\n | {\n kind: 'dm-agent'\n type: DmAgentSystemType\n }\n | {\n kind: 'age-safety'\n type: AgeSafetySystemType\n }\n\nconst getCustomSystemMessageVariant = (\n message: EventComponentProps['message']\n): CustomSystemMessageVariant | undefined => {\n const metadataCustomType = message.metadata?.custom_type\n if (isDmAgentSystemType(metadataCustomType)) {\n return {\n kind: 'dm-agent',\n type: metadataCustomType,\n }\n }\n\n if (isAgeSafetySystemType(metadataCustomType)) {\n return {\n kind: 'age-safety',\n type: metadataCustomType,\n }\n }\n\n const fallbackType = message.dm_agent_system_type\n if (isDmAgentSystemType(fallbackType)) {\n return {\n kind: 'dm-agent',\n type: fallbackType,\n }\n }\n\n return undefined\n}\n\nconst renderAgeSafetyMessageText = (messageText: string): React.ReactNode => {\n const emphasisIndex = messageText.indexOf(AGE_SAFETY_SYSTEM_MESSAGE_EMPHASIS)\n if (emphasisIndex === -1) {\n return messageText\n }\n\n const emphasisEndIndex =\n emphasisIndex + AGE_SAFETY_SYSTEM_MESSAGE_EMPHASIS.length\n\n return (\n <>\n {messageText.slice(0, emphasisIndex)}\n <a\n href={AGE_SAFETY_SYSTEM_MESSAGE_URL}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"mes-age-safety-system-message__emphasis font-medium text-inherit underline\"\n >\n {AGE_SAFETY_SYSTEM_MESSAGE_EMPHASIS}\n </a>\n {messageText.slice(emphasisEndIndex)}\n </>\n )\n}\n\nexport const CustomSystemMessage: React.FC<EventComponentProps> = (props) => {\n const isDateHidden = !shouldShowSystemMessageTimestamp(props.message)\n const customSystemMessageVariant = getCustomSystemMessageVariant(\n props.message\n )\n\n if (customSystemMessageVariant?.kind === 'dm-agent') {\n const messageText =\n props.message.text?.trim() ||\n DM_AGENT_SYSTEM_MESSAGE_FALLBACK_TEXT[customSystemMessageVariant.type]\n\n return (\n <div className=\"str-chat__message--system\" data-testid=\"message-system\">\n <div\n className=\"mes-dm-agent-system-message mx-auto mb-2 inline-flex w-fit max-w-[min(100%,480px)] items-center justify-center gap-[10px] rounded-[12px] border border-[rgba(0,0,0,0.08)] p-3 text-[rgba(0,0,0,0.55)]\"\n data-testid=\"dm-agent-system-message\"\n data-dm-agent-system-type={customSystemMessageVariant.type}\n >\n <SparkleIcon\n size={16}\n weight=\"regular\"\n aria-hidden\n className=\"mes-dm-agent-system-message__sparkle shrink-0\"\n />\n <p className=\"mes-dm-agent-system-message__text m-0 text-center text-[14px] font-normal leading-5 tracking-[0.21px]\">\n {messageText}\n </p>\n </div>\n {!isDateHidden && <MessageTimestamp message={props.message} />}\n </div>\n )\n }\n\n if (customSystemMessageVariant?.kind === 'age-safety') {\n const messageText =\n props.message.text?.trim() ||\n AGE_SAFETY_SYSTEM_MESSAGE_FALLBACK_TEXT[customSystemMessageVariant.type]\n\n return (\n <div className=\"str-chat__message--system\" data-testid=\"message-system\">\n <div\n className=\"mes-age-safety-system-message box-border mx-auto mb-2 flex w-full max-w-[329px] items-start justify-center gap-3 rounded-[12px] border border-[var(--border-secondary,rgba(0,0,0,0.08))] bg-[var(--bg-warning-subtle,#fef3c6)] px-2 py-4 pl-5 text-[color:var(--text-warning-on-warning,#894b00)]\"\n data-testid=\"age-safety-system-message\"\n data-age-safety-system-type={customSystemMessageVariant.type}\n >\n <ProhibitIcon\n size={24}\n weight=\"duotone\"\n aria-hidden\n className=\"mes-age-safety-system-message__icon shrink-0 text-[color:var(--text-warning-on-warning,#894b00)]\"\n data-testid=\"age-safety-system-message-icon\"\n />\n <div className=\"mes-age-safety-system-message__content min-w-0 flex-[1_0_0]\">\n <p className=\"m-0 text-balance text-left text-[12px] font-normal leading-4 tracking-[0.21px] text-[color:var(--text-warning-on-warning,#894b00)]\">\n {renderAgeSafetyMessageText(messageText)}\n </p>\n </div>\n </div>\n {!isDateHidden && <MessageTimestamp message={props.message} />}\n </div>\n )\n }\n\n return (\n <div className=\"str-chat__message--system\" data-testid=\"message-system\">\n <div className=\"str-chat__message--system__text\">\n <div className=\"str-chat__message--system__line\"></div>\n <p>{props.message.text}</p>\n <div className=\"str-chat__message--system__line\"></div>\n </div>\n {!isDateHidden && <MessageTimestamp message={props.message} />}\n </div>\n )\n}\n","import { createContext } from 'react'\n\nexport const DmAgentEnabledContext = createContext<boolean>(false)\n","import React, { useContext } from 'react'\nimport type { Event, UserResponse } from 'stream-chat'\nimport {\n AIStates,\n useAIState,\n useChannelStateContext,\n useChatContext,\n useTypingContext,\n} from 'stream-chat-react'\n\nimport { Avatar } from '../Avatar'\n\nimport { DmAgentEnabledContext } from './DmAgentContext'\n\ninterface CustomTypingIndicatorProps {\n threadList?: boolean\n}\n\nconst Circle = ({ cx, index }: { cx: string; index: number }) => (\n <circle cx={cx} cy=\"6.15\" r=\"3.9\" fill=\"#A0A0A0\">\n <animateTransform\n attributeName=\"transform\"\n type=\"translate\"\n values=\"0 0; 0 -2.25; 0 0;\"\n dur=\"900ms\"\n begin={`${120 * index}ms`} // 0ms, 120ms, 240ms\n repeatCount=\"indefinite\"\n />\n </circle>\n)\n\nconst AI_ACTIVE_STATES = new Set<string>([\n AIStates.Thinking,\n AIStates.Generating,\n AIStates.ExternalSources,\n])\n\nconst CustomTypingIndicator = ({ threadList }: CustomTypingIndicatorProps) => {\n const { channel, channelConfig, thread } = useChannelStateContext()\n const { client } = useChatContext()\n const { typing = {} } = useTypingContext()\n const { aiState } = useAIState(channel)\n const dmAgentEnabled = useContext(DmAgentEnabledContext)\n\n // Show the AI indicator whenever the consumer agent is producing a reply.\n // This event stream is independent of `typing.start`/`typing.stop`, so it is\n // intentionally NOT gated by `channelConfig.typing_events`. Gate strictly on\n // `dmAgentEnabled` so stale or off-surface ai_indicator events never surface\n // the bubble on channels where the agent is not active.\n const isAiActive =\n !threadList && dmAgentEnabled && AI_ACTIVE_STATES.has(aiState)\n\n if (isAiActive) {\n const agentUser = findOtherChannelUser(channel, client.user?.id)\n return (\n <TypingBubble\n avatarId={agentUser?.id ?? 'ai-agent'}\n avatarName={agentUser?.name ?? agentUser?.id ?? 'Agent'}\n avatarImage={agentUser?.image}\n testId=\"typing-indicator-ai\"\n />\n )\n }\n\n if (channelConfig?.typing_events === false) {\n return null\n }\n\n const typingInChannel = !threadList\n ? Object.values(typing).filter(\n ({ parent_id, user }: Event) =>\n user?.id !== client.user?.id && !parent_id\n )\n : []\n\n const typingInThread = threadList\n ? Object.values(typing).filter(\n ({ parent_id, user }: Event) =>\n user?.id !== client.user?.id && parent_id === thread?.id\n )\n : []\n\n const typingUsers = threadList ? typingInThread : typingInChannel\n if (!typingUsers.length) {\n return null\n }\n\n const typingUser = typingUsers[0]?.user\n const memberUser =\n typingUser?.id && channel.state.members[typingUser.id]\n ? channel.state.members[typingUser.id].user\n : undefined\n\n return (\n <TypingBubble\n avatarId={typingUser?.id ?? memberUser?.id ?? 'typing-user'}\n avatarName={\n typingUser?.name ?? memberUser?.name ?? typingUser?.id ?? 'Typing user'\n }\n avatarImage={typingUser?.image ?? memberUser?.image}\n testId=\"typing-indicator\"\n />\n )\n}\n\nconst TypingBubble = ({\n avatarId,\n avatarName,\n avatarImage,\n testId,\n}: {\n avatarId: string\n avatarName: string\n avatarImage?: string | null\n testId: string\n}) => (\n <div\n className=\"str-chat__li str-chat__li--single str-chat__typing-indicator !static\"\n data-testid={testId}\n style={{\n marginBottom: 'var(--messaging-channel-input-spacer-height, 80px)',\n }}\n >\n <div className=\"str-chat__message str-chat__message-simple str-chat__message--regular str-chat__message--received str-chat__message--other str-chat__message--has-text\">\n <Avatar\n className=\"str-chat__avatar str-chat__message-sender-avatar\"\n id={avatarId}\n name={avatarName}\n image={avatarImage ?? undefined}\n size={24}\n shape=\"circle\"\n />\n <div className=\"str-chat__message-inner mx-0\">\n <div className=\"str-chat__message-bubble-wrapper\">\n <div className=\"str-chat__message-bubble\">\n <div className=\"str-chat__message-text min-h-11 flex items-center\">\n <div className=\"str-chat__message-text-inner str-chat__message-simple-text-inner\">\n <svg\n aria-hidden=\"true\"\n className=\"block overflow-visible\"\n viewBox=\"0 0 32 12.3\"\n width=\"32\"\n height=\"13\"\n overflow=\"visible\"\n >\n <Circle cx=\"4\" index={0} />\n <Circle cx=\"16\" index={1} />\n <Circle cx=\"28\" index={2} />\n </svg>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n)\n\ntype ChannelLike = ReturnType<typeof useChannelStateContext>['channel']\n\nfunction findOtherChannelUser(\n channel: ChannelLike,\n selfId: string | undefined\n): UserResponse | undefined {\n const members = channel?.state?.members ?? {}\n for (const member of Object.values(members)) {\n const memberUser = member?.user\n if (memberUser && memberUser.id !== selfId) {\n return memberUser\n }\n }\n return undefined\n}\n\nexport default CustomTypingIndicator\n","import React from 'react'\n\n/**\n * Empty state component shown when a channel has no messages\n * Returns null to show nothing - the LoadingIndicator handles the loading state\n */\nexport const ChannelEmptyState: React.FC = () => null\n","import classNames from 'classnames'\n\ntype LoadingProps = {\n className?: string\n message?: string\n}\n\nconst Loading = ({ className, message }: LoadingProps) => (\n <div\n className={classNames('flex items-center justify-center h-full', className)}\n >\n <svg viewBox=\"0 0 100 100\" className=\"size-8 fill-pebble\" stroke=\"none\">\n <circle cx=\"6\" cy=\"50\" r=\"6\">\n <animateTransform\n attributeName=\"transform\"\n dur=\"1s\"\n type=\"translate\"\n values=\"0 15 ; 0 -15; 0 15\"\n repeatCount=\"indefinite\"\n begin=\"0.1\"\n />\n </circle>\n <circle cx=\"30\" cy=\"50\" r=\"6\">\n <animateTransform\n attributeName=\"transform\"\n dur=\"1s\"\n type=\"translate\"\n values=\"0 10 ; 0 -10; 0 10\"\n repeatCount=\"indefinite\"\n begin=\"0.2\"\n />\n </circle>\n <circle cx=\"54\" cy=\"50\" r=\"6\">\n <animateTransform\n attributeName=\"transform\"\n dur=\"1s\"\n type=\"translate\"\n values=\"0 5 ; 0 -5; 0 5\"\n repeatCount=\"indefinite\"\n begin=\"0.3\"\n />\n </circle>\n </svg>\n {message && <span className=\"text-stone\">{message}</span>}\n </div>\n)\n\nexport default Loading\n","import React from 'react'\n\nimport Loading from '../Loading'\n\n/**\n * Loading state component\n */\nexport const LoadingState = React.memo(() => (\n <div className=\"messaging-loading-state flex items-center justify-center h-full\">\n <div className=\"flex items-center\">\n <Loading className=\"w-6 h-6\" />\n <span className=\"text-sm text-stone\">Loading messages</span>\n </div>\n </div>\n))\nLoadingState.displayName = 'LoadingState'\n","import classNames from 'classnames'\nimport React, { useCallback, useEffect, useRef } from 'react'\nimport { Channel as ChannelType } from 'stream-chat'\nimport {\n Channel,\n Window,\n MessageList,\n useMessageContext,\n useChannelStateContext,\n WithComponents,\n MessageUIComponentProps,\n} from 'stream-chat-react'\n\nimport type { ChannelViewProps } from '../types'\n\nimport { ChannelHeaderRedesign } from './ChannelHeaderRedesign'\nimport { CustomDateSeparator } from './CustomDateSeparator'\nimport { CustomMessage } from './CustomMessage'\nimport { BroadcastNameContext, useBroadcastNamesById } from './CustomMessage/BroadcastNameContext'\nimport { CustomMessageActions } from './CustomMessage/CustomMessageActions'\nimport { CustomMessageInput } from './CustomMessageInput'\nimport { CustomSystemMessage } from './CustomSystemMessage'\nimport CustomTypingIndicator from './CustomTypingIndicator'\nimport { DmAgentEnabledContext } from './CustomTypingIndicator/DmAgentContext'\nimport { ChannelEmptyState } from './MessagingShell/ChannelEmptyState'\nimport { LoadingState } from './MessagingShell/LoadingState'\n\n/**\n * Inner component that has access to channel context\n */\nconst ChannelViewInner: React.FC<{\n onBack?: () => void\n showBackButton: boolean\n renderMessageInputActions?: (channel: ChannelType) => React.ReactNode\n renderMessageInputFooter?: (channel: ChannelType) => React.ReactNode\n renderConversationFooter?: (channel: ChannelType) => React.ReactNode\n onLeaveConversation?: (channel: ChannelType) => void\n onBlockParticipant?: (participantId?: string) => void\n CustomChannelEmptyState?: React.ComponentType\n showDeleteConversation?: boolean\n onDeleteConversationClick?: () => void\n onBlockParticipantClick?: () => void\n onReportParticipantClick?: () => void\n showBlockParticipant?: boolean\n showReportParticipant?: boolean\n composerDisabled?: boolean\n composerDisabledReason?: string\n showStarButton?: boolean\n chatbotVotingEnabled?: boolean\n renderChannelBanner?: () => React.ReactNode\n customChannelActions?: React.ReactNode\n renderChannelActions?: React.ReactNode\n renderMessage?: (\n messageNode: React.ReactElement,\n message: NonNullable<MessageUIComponentProps['message']>\n ) => React.ReactNode\n viewerLanguage?: string\n showChannelInfo?: boolean\n onParticipantNameClick?: () => void\n onBroadcastClick?: ChannelViewProps['onBroadcastClick']\n resolveBroadcastName?: ChannelViewProps['resolveBroadcastName']\n composerInput?: ChannelViewProps['composerInput']\n}> = ({\n onBack,\n showBackButton,\n renderMessageInputActions,\n renderMessageInputFooter,\n renderConversationFooter,\n onLeaveConversation,\n onBlockParticipant,\n showDeleteConversation = true,\n onDeleteConversationClick,\n onBlockParticipantClick,\n onReportParticipantClick,\n showBlockParticipant = true,\n showReportParticipant = true,\n composerDisabled = false,\n composerDisabledReason,\n showStarButton = false,\n chatbotVotingEnabled = false,\n renderChannelBanner,\n customChannelActions,\n renderChannelActions,\n renderMessage,\n viewerLanguage,\n showChannelInfo = true,\n onParticipantNameClick,\n onBroadcastClick,\n resolveBroadcastName,\n composerInput,\n}) => {\n const { channel, messages } = useChannelStateContext()\n const onBroadcastClickRef = useRef(onBroadcastClick)\n useEffect(() => {\n onBroadcastClickRef.current = onBroadcastClick\n }, [onBroadcastClick])\n const stableOnBroadcastClick = useCallback<\n NonNullable<ChannelViewProps['onBroadcastClick']>\n >((broadcast) => {\n onBroadcastClickRef.current?.(broadcast)\n }, [])\n const messageBroadcastClick = onBroadcastClick\n ? stableOnBroadcastClick\n : undefined\n // Resolve outside memoized Stream rows so a stable host resolver backed by a\n // live cache still publishes new campaign names when this tree re-renders.\n const broadcastNamesById = useBroadcastNamesById(\n messages,\n resolveBroadcastName\n )\n\n const hasVisibleMessages = channel.state.messages.some(\n (message) => message.type !== 'deleted'\n )\n const channelBanner = renderChannelBanner ? (\n <React.Fragment key=\"lt-channel-banner\">\n {renderChannelBanner()}\n </React.Fragment>\n ) : null\n const channelHeader = (\n <ChannelHeaderRedesign\n className=\"-mx-[var(--str-chat\\_\\_spacing-2)] px-[var(--str-chat\\_\\_spacing-2)] md:-mx-[min(var(--str-chat\\_\\_spacing-10),4%)] md:px-[min(var(--str-chat\\_\\_spacing-10),4%)]\"\n onBack={onBack}\n showBackButton={showBackButton}\n showChannelInfo={showChannelInfo}\n showStarButton={showStarButton}\n onLeaveConversation={onLeaveConversation}\n onBlockParticipant={onBlockParticipant}\n showDeleteConversation={showDeleteConversation}\n showBlockParticipant={showBlockParticipant}\n showReportParticipant={showReportParticipant}\n onDeleteConversationClick={onDeleteConversationClick}\n onBlockParticipantClick={onBlockParticipantClick}\n onReportParticipantClick={onReportParticipantClick}\n customChannelActions={customChannelActions}\n renderChannelActions={renderChannelActions}\n onParticipantNameClick={onParticipantNameClick}\n />\n )\n\n // Prevents all message instances from unmounting when ChannelViewInner re-renders\n const MessageOverride = useCallback(\n (props: MessageUIComponentProps) => {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const { message } = useMessageContext('ChannelView')\n const messageNode = (\n <CustomMessage\n {...props}\n chatbotVotingEnabled={chatbotVotingEnabled}\n viewerLanguage={viewerLanguage}\n onBroadcastClick={messageBroadcastClick}\n />\n )\n\n if (!renderMessage || !message) {\n return messageNode\n }\n\n return renderMessage(messageNode, message)\n },\n [chatbotVotingEnabled, messageBroadcastClick, renderMessage, viewerLanguage]\n )\n\n return (\n <BroadcastNameContext.Provider value={broadcastNamesById}>\n <WithComponents\n overrides={{\n Message: MessageOverride,\n MessageActions: CustomMessageActions,\n UnreadMessagesNotification: () => null,\n UnreadMessagesSeparator: () => null,\n }}\n >\n <Window>\n {composerInput ? (\n <div className=\"messaging-channel-layout relative flex min-h-0 flex-1 flex-col\">\n {/* Message List */}\n <div\n key=\"lt-channel-message-list\"\n className=\"messaging-channel-message-list messaging-channel-message-list--floating relative min-h-0 flex-1 overflow-hidden\"\n >\n {/* Stream only renders MessageList.head when there are messages, so\n empty channels need the header and banner in normal flow. */}\n {!hasVisibleMessages && (\n <div className=\"str-chat__list\">\n <div className=\"str-chat__message-list-scroll\">\n {channelHeader}\n {channelBanner}\n </div>\n </div>\n )}\n\n <MessageList\n head={\n hasVisibleMessages ? (\n <div className=\"sticky top-0 z-10\">\n {channelHeader}\n {channelBanner}\n </div>\n ) : undefined\n }\n hideDeletedMessages\n hideNewMessageSeparator={false}\n />\n </div>\n\n {/* Message Input — conversation footer is rendered inside the\n floating chrome (via renderHeader) so it stays above the absolute\n composer and remains interactive. */}\n <CustomMessageInput\n key=\"lt-channel-message-input\"\n {...(renderMessageInputActions && {\n renderActions: () => renderMessageInputActions?.(channel),\n })}\n {...(renderConversationFooter && {\n renderHeader: () => renderConversationFooter(channel),\n })}\n renderFooter={() => renderMessageInputFooter?.(channel)}\n disabled={composerDisabled}\n disabledReason={composerDisabledReason}\n composerInput={composerInput}\n />\n </div>\n ) : (\n <>\n {/* Message List */}\n <div\n key=\"lt-channel-message-list\"\n className=\"flex-1 overflow-hidden relative\"\n >\n {/* Stream only renders MessageList.head when there are messages, so\n empty channels need the header and banner in normal flow. */}\n {!hasVisibleMessages && (\n <div className=\"str-chat__list\">\n <div className=\"str-chat__message-list-scroll\">\n {channelHeader}\n {channelBanner}\n </div>\n </div>\n )}\n\n <MessageList\n head={\n hasVisibleMessages ? (\n <div className=\"sticky top-0 z-10\">\n {channelHeader}\n {channelBanner}\n </div>\n ) : undefined\n }\n hideDeletedMessages\n hideNewMessageSeparator={false}\n />\n </div>\n\n {renderConversationFooter ? (\n <React.Fragment key=\"lt-channel-conversation-footer\">\n {renderConversationFooter(channel)}\n </React.Fragment>\n ) : null}\n\n {/* Message Input */}\n <CustomMessageInput\n key=\"lt-channel-message-input\"\n {...(renderMessageInputActions && {\n renderActions: () => renderMessageInputActions?.(channel),\n })}\n renderFooter={() => renderMessageInputFooter?.(channel)}\n disabled={composerDisabled}\n disabledReason={composerDisabledReason}\n composerInput={composerInput}\n />\n </>\n )}\n </Window>\n </WithComponents>\n </BroadcastNameContext.Provider>\n )\n}\n\n/**\n * Channel view component with message list and input\n */\nexport const ChannelView = React.memo<ChannelViewProps>(\n ({\n channel,\n onBack,\n showBackButton = false,\n renderMessageInputActions,\n renderMessageInputFooter,\n renderConversationFooter,\n onLeaveConversation,\n onBlockParticipant,\n className,\n CustomChannelEmptyState = ChannelEmptyState,\n showDeleteConversation = true,\n onDeleteConversationClick,\n onBlockParticipantClick,\n onReportParticipantClick,\n showBlockParticipant = true,\n showReportParticipant = true,\n composerDisabled = false,\n composerDisabledReason,\n dmAgentEnabled,\n messageMetadata,\n onMessageSent,\n showStarButton = false,\n chatbotVotingEnabled = false,\n renderChannelBanner,\n customChannelActions,\n renderChannelActions,\n renderMessage,\n onMessageLinkClick,\n sendButton,\n attachmentPreviewList,\n viewerLanguage,\n showChannelInfo = true,\n onParticipantNameClick,\n onBroadcastClick,\n resolveBroadcastName,\n composerInput,\n }) => {\n // Custom send message handler that:\n // 1. Applies messageMetadata if provided\n // 2. Adds skip_push and silent when DM agent is active\n // 3. Calls onMessageSent callback with full response\n // Read chatbot_paused inside callback to get current value at send time (not stale closure)\n const doSendMessageRequest = useCallback(\n async (\n _channel: ChannelType,\n message: Parameters<ChannelType['sendMessage']>[0],\n options?: Parameters<ChannelType['sendMessage']>[1]\n ) => {\n const agentPaused = channel.data?.chatbot_paused === true\n const shouldSuppressNotifications = dmAgentEnabled && !agentPaused\n\n // Build final message with nested metadata\n const finalMessage = {\n ...message,\n ...(shouldSuppressNotifications && { silent: true }),\n ...(messageMetadata && {\n metadata: {\n ...(message.metadata ?? {}),\n ...messageMetadata,\n },\n }),\n }\n\n // Build final options\n const finalOptions = {\n ...options,\n ...(shouldSuppressNotifications && { skip_push: true }),\n }\n\n const response = await channel.sendMessage(finalMessage, finalOptions)\n\n // Fire callback with full response (includes message.id)\n onMessageSent?.(response)\n\n return response\n },\n [channel, dmAgentEnabled, messageMetadata, onMessageSent]\n )\n\n const containerRef = useRef<HTMLDivElement>(null)\n useEffect(() => {\n if (!onMessageLinkClick) return\n const container = containerRef.current\n if (!container) return\n const handler = (event: MouseEvent) => {\n const target = event.target as HTMLElement | null\n const anchor = target?.closest('a[href]')\n const href = anchor?.getAttribute('href')\n if (!href) return\n const messageWrapper = anchor?.closest<HTMLElement>('[data-message-id]')\n const messageId = messageWrapper?.getAttribute('data-message-id')\n const message = messageId\n ? channel.state.messages.find((m) => m.id === messageId)\n : undefined\n onMessageLinkClick(href, message)\n }\n container.addEventListener('click', handler)\n return () => container.removeEventListener('click', handler)\n }, [onMessageLinkClick, channel])\n\n return (\n <div\n ref={containerRef}\n className={classNames(\n 'messaging-channel-view h-full flex flex-col',\n className\n )}\n >\n <DmAgentEnabledContext.Provider value={dmAgentEnabled ?? false}>\n <Channel\n channel={channel}\n MessageSystem={CustomSystemMessage}\n EmptyStateIndicator={CustomChannelEmptyState}\n LoadingIndicator={LoadingState}\n DateSeparator={CustomDateSeparator}\n TypingIndicator={CustomTypingIndicator}\n doSendMessageRequest={doSendMessageRequest}\n {...(sendButton ? { SendButton: sendButton } : {})}\n {...(attachmentPreviewList\n ? { AttachmentPreviewList: attachmentPreviewList }\n : {})}\n >\n <ChannelViewInner\n onBack={onBack}\n showBackButton={showBackButton}\n renderMessageInputActions={renderMessageInputActions}\n renderMessageInputFooter={renderMessageInputFooter}\n renderConversationFooter={renderConversationFooter}\n onLeaveConversation={onLeaveConversation}\n onBlockParticipant={onBlockParticipant}\n CustomChannelEmptyState={CustomChannelEmptyState}\n showDeleteConversation={showDeleteConversation}\n onDeleteConversationClick={onDeleteConversationClick}\n onBlockParticipantClick={onBlockParticipantClick}\n onReportParticipantClick={onReportParticipantClick}\n showBlockParticipant={showBlockParticipant}\n showReportParticipant={showReportParticipant}\n composerDisabled={composerDisabled}\n composerDisabledReason={composerDisabledReason}\n showStarButton={showStarButton}\n chatbotVotingEnabled={chatbotVotingEnabled}\n renderChannelBanner={renderChannelBanner}\n customChannelActions={customChannelActions}\n renderChannelActions={renderChannelActions}\n renderMessage={renderMessage}\n viewerLanguage={viewerLanguage}\n showChannelInfo={showChannelInfo}\n onParticipantNameClick={onParticipantNameClick}\n onBroadcastClick={onBroadcastClick}\n resolveBroadcastName={resolveBroadcastName}\n composerInput={composerInput}\n />\n </Channel>\n </DmAgentEnabledContext.Provider>\n </div>\n )\n }\n)\nChannelView.displayName = 'ChannelView'\n","import React from 'react'\n\ntype ErrorStateProps = {\n message: string\n onBack?: () => void\n}\n\n/**\n * Error state component shown when something goes wrong\n */\nexport const ErrorState = React.memo<ErrorStateProps>(({ message, onBack }) => (\n <div className=\"messaging-error-state flex items-center justify-center h-full p-8\">\n <div className=\"text-center max-w-sm\">\n <div className=\"w-24 h-24 bg-danger-alt/20 rounded-full flex items-center justify-center mx-auto mb-6\">\n <span className=\"text-4xl\">⚠️</span>\n </div>\n\n <h2 className=\"font-semibold text-charcoal mb-2\">Oops!</h2>\n\n <p className=\"text-stone text-sm mb-6\">{message}</p>\n\n {onBack && (\n <button\n type=\"button\"\n onClick={onBack}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-[#7f22fe] hover:bg-primary-alt rounded-lg transition-colors focus-ring\"\n >\n Go Back\n </button>\n )}\n </div>\n </div>\n))\nErrorState.displayName = 'ErrorState'\n","/* eslint-disable react-hooks/refs -- pre-existing pattern flagged by the React\n Compiler rules added in eslint-plugin-react-hooks v7; refactoring it is\n out of scope for the lint toolchain upgrade. */\nimport React, { useCallback, useEffect, useRef, useState } from 'react'\nimport type { Channel } from 'stream-chat'\n\nimport { useMessaging } from '../../hooks/useMessaging'\nimport type { MessagingShellProps } from '../../types'\nimport { ChannelView } from '../ChannelView'\n\nimport { ErrorState } from './ErrorState'\nimport { LoadingState } from './LoadingState'\n\n/**\n * Direct-conversation surface for one specific participant.\n *\n * Renders a single ChannelView for the channel between the connected user and\n * `initialParticipantFilter`. If no channel exists yet and\n * `initialParticipantData` is supplied, the configured StreamChatService\n * channel creator is invoked to create one.\n */\nexport const MessagingShell: React.FC<MessagingShellProps> = ({\n capabilities = {},\n renderMessageInputActions,\n renderConversationFooter,\n onChannelSelect,\n onExitConversation,\n initialParticipantFilter,\n initialParticipantData,\n CustomChannelEmptyState,\n onBlockParticipantClick,\n onReportParticipantClick,\n dmAgentEnabled,\n onMessageSent,\n chatbotVotingEnabled = false,\n viewerLanguage,\n renderChannelBanner,\n customChannelActions,\n renderChannelActions,\n onParticipantNameClick,\n onBroadcastClick,\n resolveBroadcastName,\n renderMessage,\n onMessageLinkClick,\n showChannelInfo,\n composerInput,\n}) => {\n const {\n client,\n isConnected,\n isLoading,\n error,\n refreshConnection,\n service,\n debug,\n } = useMessaging()\n\n const [selectedChannel, setSelectedChannel] = useState<Channel | null>(null)\n const [directConversationError, setDirectConversationError] = useState<\n string | null\n >(null)\n const [didExit, setDidExit] = useState(false)\n\n const { showDeleteConversation = true } = capabilities\n\n // Stash consumer props that are unstable when passed inline (object\n // literals, arrow-function callbacks) so the load effect's deps stay\n // identity-stable. Without this, the documented usage pattern in the\n // README — passing `initialParticipantData={{ ... }}` and\n // `onChannelSelect={(ch) => ...}` — re-fires the effect on every render\n // and triggers a queryChannels call each time.\n const initialParticipantDataRef = useRef(initialParticipantData)\n initialParticipantDataRef.current = initialParticipantData\n const onChannelSelectRef = useRef(onChannelSelect)\n onChannelSelectRef.current = onChannelSelect\n\n // Track the direct-conversation load to prevent repeated/concurrent loads.\n // Identity-stable deps (above) stop the common re-fire, but legitimate dep\n // changes (e.g. `service`/`client` settling during connect) can still re-run\n // this effect before the just-created channel is indexed, each firing another\n // startChannelWithParticipant call and creating duplicate welcome messages.\n const directConversationLoadRef = useRef<string | null>(null)\n\n // Mirror the currently-selected channel into a ref so the async load can read\n // the latest value rather than the (possibly stale) effect-closure value.\n const selectedChannelRef = useRef<Channel | null>(null)\n useEffect(() => {\n selectedChannelRef.current = selectedChannel\n }, [selectedChannel])\n\n useEffect(() => {\n if (!client || !isConnected) return\n\n const userId = client.userID\n if (!userId) return\n\n // Only load once per viewer ↔ participant pair. Set synchronously (before\n // the async work) so re-runs triggered by changing dependency identities\n // bail out instead of issuing another channel-create request.\n const loadKey = `${userId}::${initialParticipantFilter}`\n if (directConversationLoadRef.current === loadKey) return\n directConversationLoadRef.current = loadKey\n\n // Release the guard only if it still belongs to this load. A newer load for\n // a different pair may have taken ownership while this one was in flight, so\n // clearing unconditionally could wipe the newer guard and let a duplicate\n // load/create slip through.\n const releaseLoadGuard = () => {\n if (directConversationLoadRef.current === loadKey) {\n directConversationLoadRef.current = null\n }\n }\n\n const loadInitialChannel = async () => {\n try {\n if (debug) {\n console.log(\n '[MessagingShell] Loading initial conversation with:',\n initialParticipantFilter\n )\n }\n\n const channels = await client.queryChannels(\n {\n type: 'messaging',\n members: { $eq: [userId, initialParticipantFilter] },\n },\n {},\n { limit: 1 }\n )\n\n if (channels.length > 0) {\n setSelectedChannel(channels[0])\n setDirectConversationError(null)\n onChannelSelectRef.current?.(channels[0])\n\n if (debug) {\n console.log(\n '[MessagingShell] Initial conversation loaded:',\n channels[0].id\n )\n }\n return\n }\n\n const participantData = initialParticipantDataRef.current\n if (!participantData || !service) {\n // Allow a retry once participant data / service become available.\n releaseLoadGuard()\n setDirectConversationError('No conversation found with this account')\n if (debug) {\n console.log(\n '[MessagingShell] No conversation found for:',\n initialParticipantFilter\n )\n }\n return\n }\n\n try {\n const channel = await service.startChannelWithParticipant({\n id: participantData.id,\n name: participantData.name,\n phone: participantData.phone,\n })\n setSelectedChannel(channel)\n setDirectConversationError(null)\n onChannelSelectRef.current?.(channel)\n\n if (debug) {\n console.log(\n '[MessagingShell] Channel created and loaded:',\n channel.id\n )\n }\n } catch (createErr) {\n console.error(\n '[MessagingShell] Failed to create conversation:',\n createErr\n )\n // Allow a retry for this pair after a transient failure.\n releaseLoadGuard()\n setDirectConversationError('Failed to create conversation')\n }\n } catch (err) {\n console.error(\n '[MessagingShell] Failed to load initial conversation:',\n err\n )\n // Allow a retry for this pair after a transient failure.\n releaseLoadGuard()\n // Don't replace an already-loaded conversation with an error screen.\n // Read the latest selected channel via ref to avoid acting on a stale\n // closure value when the channel was selected mid-flight.\n if (!selectedChannelRef.current) {\n setDirectConversationError('Failed to load conversation')\n }\n }\n }\n\n void loadInitialChannel()\n }, [initialParticipantFilter, client, isConnected, service, debug])\n\n // Leave / block clears the selected channel and notifies the consumer.\n // The consumer owns what happens next — typically unmounting MessagingShell\n // or re-rendering with new participant data. When no callback is provided,\n // the shell renders an \"ended\" state rather than an indefinite spinner so\n // the surface remains honest about why no conversation is shown.\n const onExitConversationRef = useRef(onExitConversation)\n onExitConversationRef.current = onExitConversation\n const handleExitConversation = useCallback(() => {\n setSelectedChannel(null)\n setDidExit(true)\n onExitConversationRef.current?.()\n }, [])\n\n if (isLoading) {\n return <LoadingState />\n }\n\n if (error) {\n return <ErrorState message={error} onBack={refreshConnection} />\n }\n\n if (!isConnected || !client) {\n return (\n <ErrorState\n message=\"Not connected to messaging service\"\n onBack={refreshConnection}\n />\n )\n }\n\n if (directConversationError) {\n return <ErrorState message={directConversationError} />\n }\n\n if (didExit && !selectedChannel) {\n return <ErrorState message=\"Conversation ended\" />\n }\n\n if (!selectedChannel) {\n return <LoadingState />\n }\n\n return (\n <div className=\"messaging-shell h-full bg-background-primary overflow-hidden\">\n <div className=\"flex h-full min-h-0 flex-col\">\n <ChannelView\n channel={selectedChannel}\n key={selectedChannel.id}\n renderMessageInputActions={renderMessageInputActions}\n renderConversationFooter={renderConversationFooter}\n renderChannelBanner={renderChannelBanner}\n onLeaveConversation={handleExitConversation}\n onBlockParticipant={handleExitConversation}\n CustomChannelEmptyState={CustomChannelEmptyState}\n showDeleteConversation={showDeleteConversation}\n onBlockParticipantClick={onBlockParticipantClick}\n onReportParticipantClick={onReportParticipantClick}\n dmAgentEnabled={dmAgentEnabled}\n onMessageSent={onMessageSent}\n chatbotVotingEnabled={chatbotVotingEnabled}\n viewerLanguage={viewerLanguage}\n customChannelActions={customChannelActions}\n renderChannelActions={renderChannelActions}\n onParticipantNameClick={onParticipantNameClick}\n onBroadcastClick={onBroadcastClick}\n resolveBroadcastName={resolveBroadcastName}\n renderMessage={renderMessage}\n onMessageLinkClick={onMessageLinkClick}\n showChannelInfo={showChannelInfo}\n composerInput={composerInput}\n />\n </div>\n </div>\n )\n}\n","import type { Channel } from 'stream-chat'\n\n/**\n * Restores pending messages into the channel's visible message list so they\n * appear as if they were already sent.\n *\n * Stream's pending-messages feature removes messages from the channel view\n * once client state is lost (e.g. page refresh). This function works around\n * that limitation by reading `channel.state.pending_messages` and\n * re-inserting them via `channel.state.addMessageSorted`.\n */\nexport function restorePendingMessages(channel: Channel) {\n const pendingMessages = channel.state.pending_messages\n if (!pendingMessages?.length) return\n\n for (const pending of pendingMessages) {\n channel.state.addMessageSorted(pending.message)\n }\n}\n","import React from 'react'\nimport type { Channel, LocalMessage } from 'stream-chat'\n\nimport type { ChannelListProps } from '../../types'\n\ntype ChannelListContextValue = {\n selectedChannel?: Channel | null\n onChannelSelect: (channel: Channel) => void\n debug: boolean\n renderMessagePreview?: (\n message: LocalMessage | undefined,\n defaultPreview?: string\n ) => React.ReactNode\n channelPreview?: ChannelListProps['channelPreview']\n viewerLanguage?: string\n}\n\nconst ChannelListContext = React.createContext<ChannelListContextValue>({\n selectedChannel: undefined,\n onChannelSelect: () => {},\n debug: false,\n renderMessagePreview: undefined,\n channelPreview: undefined,\n viewerLanguage: undefined,\n})\n\nexport const ChannelListProvider = ChannelListContext.Provider\n\nexport const useChannelListContext = () => React.useContext(ChannelListContext)\n","/**\n * Get the number of days between two dates (calendar days in UTC, not 24-hour periods)\n * Uses UTC to ensure consistent day calculations globally since messages are stored in UTC\n */\nconst getDaysDifference = (date1: Date, date2: Date): number => {\n const d1 = new Date(\n Date.UTC(date1.getUTCFullYear(), date1.getUTCMonth(), date1.getUTCDate())\n )\n const d2 = new Date(\n Date.UTC(date2.getUTCFullYear(), date2.getUTCMonth(), date2.getUTCDate())\n )\n const diffTime = d2.getTime() - d1.getTime()\n return Math.floor(diffTime / (1000 * 60 * 60 * 24))\n}\n\n/**\n * Format a date - shows time for today, relative time for older messages\n * (e.g., \"Just now\", \"2:08 PM\" for today, \"Yesterday\" for yesterday, \"2d\" for 2 days ago)\n */\nexport const formatRelativeTime = (date: Date): string => {\n const now = new Date()\n const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000)\n\n // Less than 1 minute\n if (diffInSeconds < 60) {\n return 'Just now'\n }\n\n // Check if it's today (same calendar day)\n const daysDiff = getDaysDifference(date, now)\n\n // If today, show time in 12-hour format (e.g., \"8:40 PM\")\n if (daysDiff === 0) {\n return date.toLocaleTimeString([], {\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n })\n }\n\n // Yesterday\n if (daysDiff === 1) {\n return 'Yesterday'\n }\n\n // Less than 7 days - show days\n if (daysDiff < 7) {\n return `${daysDiff}d`\n }\n\n // Less than 4 weeks - show weeks\n if (daysDiff < 28) {\n const weeks = Math.floor(daysDiff / 7)\n return `${weeks}w`\n }\n\n // More than 4 weeks - show locale-aware date with spelled-out month\n return date.toLocaleDateString(undefined, {\n day: 'numeric',\n month: 'short',\n year: '2-digit',\n })\n}\n","import { MESSAGE_CUSTOM_TYPE } from '@linktr.ee/messaging-taxonomy'\nimport classNames from 'classnames'\nimport React from 'react'\nimport {\n ChannelPreviewUIComponentProps,\n useChatContext,\n} from 'stream-chat-react'\n\nimport { useChannelStar } from '../../hooks/useChannelStar'\nimport { formatRelativeTime } from '../../utils/formatRelativeTime'\nimport { getMessageDisplayText } from '../../utils/getMessageDisplayText'\nimport { resolveConversationParticipant } from '../../utils/resolveConversationParticipant'\nimport { resolveParticipantDisplayName } from '../../utils/resolveParticipantDisplayName'\nimport { Avatar } from '../Avatar'\nimport { isChatbotMessage } from '../CustomMessage/MessageTag'\n\nimport { useChannelListContext } from './ChannelListContext'\n\n/**\n * Custom channel preview that handles selection\n */\nconst CustomChannelPreview = React.memo<ChannelPreviewUIComponentProps>(\n (props) => {\n const { channel, unread } = props\n const {\n selectedChannel,\n onChannelSelect,\n debug,\n channelPreview,\n renderMessagePreview,\n viewerLanguage,\n } = useChannelListContext()\n const { client } = useChatContext()\n\n const isSelected = selectedChannel?.id === channel?.id\n const isChannelStarred = useChannelStar(channel)\n\n if (channelPreview) {\n const ChannelPreview = channelPreview\n\n return (\n <ChannelPreview\n {...props}\n active={isSelected}\n selectedChannel={selectedChannel}\n onChannelSelect={onChannelSelect}\n viewerLanguage={viewerLanguage}\n />\n )\n }\n\n const handleClick = () => {\n if (channel) {\n onChannelSelect(channel)\n }\n }\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n const isActivationKey = event.key === 'Enter' || event.key === ' '\n const isRepeatedKeydown = event.repeat\n\n if (!isActivationKey || isRepeatedKeydown) return\n\n event.preventDefault()\n handleClick()\n }\n\n // Get participant info\n const participant = resolveConversationParticipant(\n channel?.state?.members,\n client?.userID,\n channel?.type\n )\n const participantName = resolveParticipantDisplayName(participant?.user)\n const participantImage = participant?.user?.image\n\n // Get last non-system message for preview\n const lastMessage = (() => {\n const messages = channel?.state?.messages\n if (!messages?.length) return undefined\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].type !== 'system') return messages[i]\n }\n return undefined\n })()\n\n const getLastMessageText = () => {\n const displayText = getMessageDisplayText({\n message: lastMessage,\n viewerLanguage,\n })\n\n const { custom_type, attachment_content_type } =\n lastMessage?.metadata || {}\n\n if (custom_type === MESSAGE_CUSTOM_TYPE.TIP) {\n return displayText ? displayText : 'Sent a tip'\n }\n if (custom_type === MESSAGE_CUSTOM_TYPE.PAID) {\n return displayText ? displayText : 'Sent a message'\n }\n if (custom_type === MESSAGE_CUSTOM_TYPE.ATTACHMENT) {\n if (attachment_content_type === 'text') {\n return '🔒 Sent a locked message'\n }\n if (attachment_content_type === 'media') {\n return '🔒 Sent a locked attachment'\n }\n }\n\n if (displayText) return displayText\n\n const attachment = lastMessage?.attachments?.[0]\n if (attachment) {\n // Link previews - show the actual URL\n if (attachment.og_scrape_url) return attachment.og_scrape_url\n\n // Type-based detection\n if (attachment.type === 'image') return '📷 Sent an image'\n if (attachment.type === 'video') return '🎥 Sent a video'\n if (attachment.type === 'audio') return '🎵 Sent audio'\n if (attachment.type === 'file') return '📎 Sent a file'\n\n // Fallback\n return '📎 Sent an attachment'\n }\n\n return 'No messages yet'\n }\n\n const lastMessageText = getLastMessageText()\n const lastMessageTime = lastMessage?.created_at\n ? formatRelativeTime(new Date(lastMessage.created_at))\n : ''\n const isLastMessageFromChatbot = lastMessage\n ? isChatbotMessage(lastMessage)\n : false\n\n const messagePreview = renderMessagePreview\n ? renderMessagePreview(lastMessage, lastMessageText)\n : `${isLastMessageFromChatbot ? '✨ ' : ''}${lastMessageText}`\n\n // Use the unread prop passed by Stream Chat (reactive and updates automatically)\n const unreadCount = unread ?? 0\n\n if (debug) {\n console.log('📺 [ChannelList] 📋 CHANNEL PREVIEW RENDER', {\n channelId: channel?.id,\n isSelected,\n participantName,\n unreadCount,\n hasTimestamp: !!lastMessageTime,\n })\n }\n\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n className={classNames(\n 'group w-full px-4 py-3 transition-colors text-left max-w-full overflow-hidden focus-ring rounded-[12px] [&+&]:mt-2',\n {\n 'bg-black/[0.04]': isSelected,\n 'hover:bg-black/[0.02]': !isSelected,\n }\n )}\n data-dd-privacy=\"mask\"\n >\n <div className=\"flex items-start gap-4\">\n {/* Avatar */}\n <Avatar\n id={participant?.user?.id || channel.id || 'unknown'}\n name={participantName}\n image={participantImage}\n size={48}\n starred={isChannelStarred}\n />\n\n {/* Content column */}\n <div className=\"flex-1 min-w-0 flex flex-col gap-1\">\n {/* Name and timestamp row */}\n <div className=\"flex items-center justify-between gap-2\">\n <h3\n className={classNames(\n 'text-sm font-medium truncate text-[#191918]'\n )}\n >\n {isChannelStarred && (\n <span className=\"sr-only\">Starred conversation. </span>\n )}\n {participantName}\n </h3>\n {lastMessageTime && (\n <span className=\"text-xs text-[#717070] flex-shrink-0\">\n {lastMessageTime}\n </span>\n )}\n </div>\n\n {/* Message and unread badge row */}\n <div className=\"flex items-center justify-between gap-2 min-w-0\">\n <p className=\"text-sm text-[#717070] flex-1 line-clamp-1\">\n {messagePreview}\n </p>\n {unreadCount > 0 && (\n <span className=\"bg-[#7f22fe] text-white text-[10px] rounded-full h-4 flex items-center justify-center p-1 min-w-4 text-center flex-shrink-0\">\n {unreadCount > 99 ? '99+' : unreadCount}\n </span>\n )}\n </div>\n </div>\n </div>\n </div>\n )\n }\n)\n\nexport default CustomChannelPreview\nCustomChannelPreview.displayName = 'CustomChannelPreview'\n","import classNames from 'classnames'\nimport React from 'react'\nimport type { Channel } from 'stream-chat'\nimport {\n ChannelList as StreamChannelList,\n InfiniteScroll,\n} from 'stream-chat-react'\n\nimport { restorePendingMessages } from '../../hooks/useRestorePendingMessages'\nimport { useMessagingContext } from '../../providers/MessagingProvider'\nimport type { ChannelListProps } from '../../types'\n\nimport { ChannelListProvider } from './ChannelListContext'\nimport CustomChannelPreview from './CustomChannelPreview'\n\nconst DEFAULT_SORT = { last_message_at: -1 } as const\n\n/**\n * Channel list component with customizable header and actions\n */\nexport const ChannelList = React.memo<ChannelListProps>(\n ({\n onChannelSelect,\n selectedChannel,\n filters,\n allowNewMessagesFromUnfilteredChannels = false,\n channelRenderFilterFn,\n sort = DEFAULT_SORT,\n className,\n customEmptyStateIndicator,\n channelListPaginator: Paginator = InfiniteScroll,\n channelPreview,\n renderMessagePreview,\n viewerLanguage,\n lockChannelOrder,\n onMessageNewHandler,\n onMessageNew,\n onChannelVisible,\n onAddedToChannel,\n onChannelUpdated,\n }) => {\n // Track renders\n const renderCountRef = React.useRef(0)\n renderCountRef.current++\n\n // Get debug flag from context\n const { debug = false } = useMessagingContext()\n\n // Wrap channelRenderFilterFn to restore pending messages for all channels\n // as soon as they are loaded, without waiting for the user to click into each one.\n const wrappedChannelRenderFilterFn = React.useCallback(\n (channels: Channel[]) => {\n for (const channel of channels) {\n restorePendingMessages(channel)\n }\n return channelRenderFilterFn\n ? channelRenderFilterFn(channels)\n : channels\n },\n [channelRenderFilterFn]\n )\n\n if (debug) {\n console.log('📺 [ChannelList] 🔄 RENDER START', {\n renderCount: renderCountRef.current,\n selectedChannelId: selectedChannel?.id,\n filters,\n })\n }\n\n const contextValue = React.useMemo(\n () => ({\n selectedChannel,\n onChannelSelect,\n debug,\n channelPreview,\n renderMessagePreview,\n viewerLanguage,\n }),\n [\n selectedChannel,\n onChannelSelect,\n debug,\n channelPreview,\n renderMessagePreview,\n viewerLanguage,\n ]\n )\n\n return (\n <div\n className={classNames(\n 'messaging-channel-list h-full flex flex-col min-w-0 overflow-hidden',\n className\n )}\n >\n {/* Channel List */}\n <div className=\"flex-1 overflow-hidden min-w-0\">\n <ChannelListProvider value={contextValue}>\n <StreamChannelList\n key={`${JSON.stringify(filters)}:${JSON.stringify(sort)}`}\n filters={filters}\n sort={sort}\n options={{ limit: 30 }}\n allowNewMessagesFromUnfilteredChannels={\n allowNewMessagesFromUnfilteredChannels\n }\n channelRenderFilterFn={wrappedChannelRenderFilterFn}\n lockChannelOrder={lockChannelOrder}\n onMessageNewHandler={onMessageNewHandler}\n onMessageNew={onMessageNew}\n onChannelVisible={onChannelVisible}\n onAddedToChannel={onAddedToChannel}\n onChannelUpdated={onChannelUpdated}\n Paginator={Paginator}\n Preview={CustomChannelPreview}\n EmptyStateIndicator={customEmptyStateIndicator}\n />\n </ChannelListProvider>\n </div>\n </div>\n )\n }\n)\nChannelList.displayName = 'ChannelList'\n","import React from 'react'\n\nimport type { MessageBubbleVariant } from '../../types'\n\n/**\n * Canonical chat-bubble tail (20×23). Kept identical to the in-channel tail\n * drawn by `CustomMessage` in `styles.css` so standalone previews and real\n * messages share one silhouette — the single source of truth for the shape.\n *\n * The path points to the bottom-*right*; the `received` variant mirrors it\n * with `scaleX(-1)`, matching the in-channel convention.\n */\nconst TAIL_MASK =\n \"url(\\\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='23' fill='none'%3E%3Cpath fill='black' d='M0 0H15C15 10.1934 15.859 15.2345 19.168 21.4893C19.527 22.168 19.039 22.9917 18.274 22.9178C5.176 21.6506 0.32 6.0737 0 0Z'/%3E%3C/svg%3E\\\") no-repeat center / 100% 100%\"\n\n/**\n * Bubble surface colours, reused from the toolkit's Stream theme vars so the\n * tail is always tinted the same colour as its bubble. Those vars are declared\n * on `.str-chat`, so we supply the canonical values as `var()` fallbacks —\n * that keeps the tail correct when rendered *outside* a channel (e.g. a\n * standalone preview) while still honouring the var (or a consumer override)\n * wherever it's defined.\n */\nconst BG_VAR_BY_VARIANT: Record<MessageBubbleVariant, string> = {\n sent: 'var(--str-chat__own-message-bubble-background-color, #1e2330)',\n received: 'var(--str-chat__message-bubble-background-color, #f1f0ee)',\n}\n\n/**\n * The tail element. Absolutely positioned at the bubble's bottom corner and\n * painted behind the bubble body (`z-index: -1`), so the parent bubble must be\n * `position: relative` with `isolation: isolate` (see {@link BubbleShell}).\n */\nexport const BubbleTail = ({ variant }: { variant: MessageBubbleVariant }) => (\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute bottom-0 z-[-1] h-[1.4375rem] w-5\"\n style={{\n insetInlineEnd: variant === 'sent' ? 'calc(-1 * 0.25rem)' : undefined,\n insetInlineStart: variant === 'received' ? 'calc(-1 * 0.25rem)' : undefined,\n transform: variant === 'received' ? 'scaleX(-1)' : undefined,\n transformOrigin: 'center',\n backgroundColor: BG_VAR_BY_VARIANT[variant],\n WebkitMask: TAIL_MASK,\n mask: TAIL_MASK,\n }}\n />\n)\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport type { MessageBubbleVariant } from '../../types'\n\nimport { BubbleTail } from './bubbleTail'\n\nexport interface BubbleShellProps {\n variant: MessageBubbleVariant\n text: string\n /** Draw the bubble tail. Defaults to `true`. */\n tail?: boolean\n /** Optional header rendered above the text (e.g. sender name). */\n header?: React.ReactNode\n /**\n * Width is caller-controlled — pass a width class in `className`\n * (`w-fit` to hug the text for chat/preview bubbles, `w-full` to fill the\n * container for card-like list rows). With no width class the bubble is a\n * block element and fills its container.\n */\n className?: string\n}\n\n/**\n * Surface colours and metrics are pulled from the toolkit's Stream theme vars\n * (see `styles.css`) so a standalone bubble is pixel-identical to the\n * in-channel one and re-themes from the same single source of truth.\n */\nconst SURFACE_STYLE_BY_VARIANT: Record<\n MessageBubbleVariant,\n React.CSSProperties\n> = {\n sent: {\n backgroundColor:\n 'var(--str-chat__own-message-bubble-background-color, #1e2330)',\n color: 'var(--str-chat__own-message-bubble-color, #fff)',\n },\n received: {\n backgroundColor:\n 'var(--str-chat__message-bubble-background-color, #f1f0ee)',\n color: 'var(--str-chat__message-bubble-color, #000000)',\n },\n}\n\n/**\n * The rounded bubble box: theme-driven surface, channel-matched typography\n * (`0.875rem / 1.3125rem`, `0.14px` tracking, `0.75rem 1rem` padding), an\n * optional header slot, and an optional tail.\n *\n * `isolation: isolate` forms a stacking context so the `z-index: -1` tail\n * paints behind the bubble's own opaque, same-colour background but in front\n * of the surrounding page — matching the in-channel `::after` tail.\n *\n * `data-dd-privacy=\"mask\"` masks the message text (and header) from Datadog\n * session replay by default, matching the in-channel renderers\n * (`CustomMessage`, `MediaMessage`). Since this bubble is used for standalone\n * previews of real user content outside `ChannelView`, masking must live on\n * the component rather than relying on every consumer to wrap it.\n */\nconst BubbleShell: React.FC<BubbleShellProps> = ({\n variant,\n text,\n tail = true,\n header,\n className,\n}) => (\n <div\n data-dd-privacy=\"mask\"\n className={classNames(\n 'relative px-4 py-3',\n 'text-[0.875rem] leading-[1.3125rem] tracking-[0.14px]',\n className\n )}\n style={{\n ...SURFACE_STYLE_BY_VARIANT[variant],\n borderRadius: 'var(--str-chat__message-bubble-border-radius, 1.5rem)',\n isolation: 'isolate',\n }}\n >\n {header != null && (\n <div className=\"mb-1 font-medium\" data-testid=\"message-bubble-header\">\n {header}\n </div>\n )}\n <p className=\"m-0 whitespace-pre-wrap break-words\">{text}</p>\n {tail && <BubbleTail variant={variant} />}\n </div>\n)\n\nexport default BubbleShell\n","import React from 'react'\n\nimport type { ReceivedBubbleProps } from '../../types'\nimport BubbleShell from '../_shared/BubbleShell'\n\n/**\n * A message bubble in the recipient's treatment — light surface, left-side\n * tail, with an optional header (e.g. sender name). Use to preview how a\n * message looks *to the visitor* — including a preview of your own outgoing\n * message as the recipient will receive it (e.g. a bulk-reply confirmation).\n */\nconst ReceivedCard: React.FC<ReceivedBubbleProps> = ({\n text,\n tail,\n header,\n className,\n}) => (\n <BubbleShell\n variant=\"received\"\n text={text}\n tail={tail}\n header={header}\n className={className}\n />\n)\n\nexport default ReceivedCard\n","import React from 'react'\n\nimport type { SentBubbleProps } from '../../types'\nimport BubbleShell from '../_shared/BubbleShell'\n\n/**\n * A message bubble in the sender's own treatment — dark surface, right-side\n * tail. Use to preview how a message looks *to you in the channel*.\n *\n * Note: the variant is a visual treatment, not an authorship claim. To preview\n * an outgoing message as the *recipient* will see it, use\n * `MessageBubble.Received` instead.\n */\nconst SentCard: React.FC<SentBubbleProps> = ({ text, tail, className }) => (\n <BubbleShell variant=\"sent\" text={text} tail={tail} className={className} />\n)\n\nexport default SentCard\n","import ReceivedCard from './components/Received/Card'\nimport SentCard from './components/Sent/Card'\n\n/**\n * A dumb, context-free chat message bubble for rendering a single message row\n * *outside* a live channel — previews, digests, confirmation dialogs, the\n * Stacks \"responded\" summary, etc. Unlike `ChannelView`, it needs no Stream\n * client or provider.\n *\n * Render `MessageBubble.Sent` for the sender's own treatment (dark, right\n * tail) and `MessageBubble.Received` for the recipient's (light, left tail,\n * optional header). Surface colours, radius, typography, and the tail\n * silhouette are shared with the in-channel bubble drawn by `CustomMessage`,\n * so previews stay pixel-identical and re-theme from one source of truth.\n *\n * The variant is a **visual treatment, not an authorship claim**: to preview\n * an outgoing message as the recipient will see it, render\n * `MessageBubble.Received` with your own text.\n */\nconst MessageBubble = {\n Sent: SentCard,\n Received: ReceivedCard,\n}\n\nexport default MessageBubble\nexport type {\n MessageBubbleBaseProps,\n MessageBubbleVariant,\n SentBubbleProps,\n ReceivedBubbleProps,\n} from './types'\n","import classNames from 'classnames'\nimport React from 'react'\nexport interface FaqListItemProps {\n question: string\n onClick: () => void\n loading?: boolean\n className?: string\n}\n\nexport const FaqListItem: React.FC<FaqListItemProps> = ({\n question,\n onClick,\n loading = false,\n className,\n}) => {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n disabled={loading}\n style={{ backgroundColor: '#E6E5E3' }}\n className={classNames(\n 'w-full text-center p-4 rounded-xl text-charcoal font-medium transition-colors focus-ring',\n {\n 'hover:brightness-95 active:brightness-90': !loading,\n 'opacity-50 cursor-not-allowed': loading,\n },\n className\n )}\n >\n {question}\n </button>\n )\n}\n","import { selectEnabledFaqs } from '@linktr.ee/messaging-taxonomy'\nimport React from 'react'\n\nimport { Avatar } from '../Avatar'\n\nimport { FaqListItem } from './FaqListItem'\n\nexport interface Faq {\n id: string\n question: string\n answer: string\n enabled: boolean\n order?: number | null\n}\n\nexport interface FaqListProps {\n faqs: Faq[]\n onFaqClick: (faqId: string) => void\n loadingFaqId?: string | null\n headerText?: string\n className?: string\n avatarImage?: string\n avatarName?: string\n}\n\nexport const FaqList: React.FC<FaqListProps> = ({\n faqs,\n onFaqClick,\n loadingFaqId,\n headerText,\n className,\n avatarImage,\n avatarName,\n}) => {\n const enabledFaqs = selectEnabledFaqs(faqs)\n\n if (enabledFaqs.length === 0) {\n return null\n }\n\n return (\n <div className={className}>\n <div className=\"flex gap-3 items-end\">\n {/* Avatar at bottom-left, outside grey background */}\n {(avatarImage || avatarName) && (\n <div className=\"flex-none\">\n <Avatar\n id={avatarName || 'account'}\n name={avatarName || 'Account'}\n image={avatarImage}\n size={24}\n shape=\"circle\"\n />\n </div>\n )}\n\n {/* FAQs with grey background */}\n <div\n className=\"flex-1 flex flex-col gap-3 rounded-lg p-4\"\n style={{ backgroundColor: '#F1F0EE' }}\n >\n {headerText && (\n <p className=\"text-md text-charcoal mb-4\">{headerText}</p>\n )}\n {enabledFaqs.map((faq) => (\n <FaqListItem\n key={faq.id}\n question={faq.question}\n onClick={() => onFaqClick(faq.id)}\n loading={loadingFaqId === faq.id}\n />\n ))}\n </div>\n </div>\n </div>\n )\n}\n"],"names":["MessagingContext","createContext","useMessagingContext","useContext","MessagingProvider","children","user","serviceConfig","apiKey","capabilities","debug","injectedClient","debugLog","useCallback","message","args","service","setService","useState","client","setClient","isConnected","setIsConnected","isLoading","setIsLoading","error","setError","connectingRef","useRef","serviceRef","serviceConfigRef","debugRef","prevPropsRef","renderCountRef","clientRef","_a","StreamChat","chatClient","_b","useEffect","currentRender","currentConfig","newService","StreamChatService","connectedUserRef","streamClient","err","errorMessage","refreshConnection","contextValue","React","jsx","Chat","useMessaging","useChannelStar","channel","isChannelStarred","setIsChannelStarred","handleMemberUpdate","event","resolveConversationParticipant","members","currentUserId","channelType","memberList","isOfficialChannel","officialSender","member","OFFICIAL_SENDER_USER_ID","UUID_REGEX","isUuidLike","value","isUsableDisplayValue","userId","trimmed","resolveParticipantDisplayName","FRUITS","hashString","str","hash","i","char","getFruit","id","getAvatarEmoji","getAvatarBgColor","Avatar","image","size","className","starred","shape","dmAgentEnabled","emoji","bgColor","SMALL_EMOJI_RATIO","fontSize","aiBorderWidth","borderStyle","avatarInner","classNames","jsxs","StarIcon","REPORT_URL","useChannelModerationActions","participant","showBlockParticipant","enabled","onLeaveConversation","onBlockParticipant","onDeleteConversationClick","onBlockParticipantClick","onReportParticipantClick","onActionComplete","logLabel","participantId","willLookup","isParticipantBlocked","setIsParticipantBlocked","resolvedFor","setResolvedFor","isLeaving","setIsLeaving","isUpdatingBlockStatus","setIsUpdatingBlockStatus","isCheckingBlockedStatus","cancelled","blockedUsers","actingUserId","_c","ActionButton","variant","rest","ChannelActionsMenu","showDeleteConversation","showReportParticipant","customChannelActions","triggerClassName","isOpen","setIsOpen","containerRef","menuId","useId","close","handleLeaveConversation","handleBlockUser","handleUnblockUser","handleReportUser","handlePointerDown","handleKeyDown","open","DotsThreeIcon","SpinnerGapIcon","SignOutIcon","ProhibitInsetIcon","FlagIcon","ICON_BTN_CLASS","CUSTOMER_PAID_TAG","isCustomerPaidTag","ChannelHeaderRedesign","onBack","showBackButton","showStarButton","renderChannelActions","showChannelInfo","onParticipantNameClick","useChannelStateContext","useChatContext","participantName","participantImage","isStarred","isPaidCustomer","showStarBadge","hasNameAdornment","handleStarClick","identityContent","Fragment","_d","CurrencyDollarIcon","CaretRightIcon","ArrowLeftIcon","CustomDateSeparator","props","DateSeparator","VOTE_UP","VOTE_DOWN","getVoteFromReactions","ownReactions","r","useMessageVote","selected","useMemo","voteUp","voteDown","normalizeLanguageCode","language","getMessageDisplayText","viewerLanguage","fallbackText","normalizedLanguage","LINKTREE_CDN_HOSTS","ATTACHMENT_IMAGE_SIZE_PRESET","hostnameFromUrl","url","isLinktreeCdnHost","hostname","host","optimizeMessagingAttachmentUrl","parsedUrl","DOCUMENT_ICON_PATTERNS","getSourceType","mimeType","getDocumentIconType","match","pattern","MEDIA_TYPE_ICON","VideoCameraIcon","SpeakerHighIcon","ImageIcon","FileIcon","DOCUMENT_ICON_COMPONENT","FilePdfIcon","FileDocIcon","FileXlsIcon","FileCsvIcon","FilePptIcon","FileZipIcon","FileTextIcon","FileMdIcon","getTypeIcon","sourceType","renderTypeIcon","getClientXFromEvent","MediaPlayer","source","poster","autoPlay","playingProp","loop","controls","showProgress","muted","onContainerClick","playerRef","trackRef","rafRef","prevPlayingPropRef","playing","setPlaying","played","setPlayed","seeking","setSeeking","scrubberHovered","setScrubberHovered","manualPlayRequired","setManualPlayRequired","buffering","setBuffering","initialLoad","setInitialLoad","videoAspect","setVideoAspect","startPlaybackFromGesture","getFraction","e","track","rect","seekTo","fraction","el","handleTrackPointerDown","tick","onMove","onUp","aspectStyle","aspectClass","scrubberPercent","p","CircleNotchIcon","PlayIcon","PauseIcon","placeholderIconClass","posterShellClass","AttachmentThumbnail","sourceUrl","thumbnailUrl","title","mediaPlayerProps","containedImage","sourceReady","setSourceReady","optimizedSourceUrl","optimizedThumbnailUrl","AttachmentCard","thumbnail","placeholderTitle","detail","statusBadge","action","topLeft","topRight","rootRef","dataTestId","isDark","displayTitle","titleDimmed","formatBytes","bytes","linkCardShellClass","isMyMessage","linkThumbnailBg","linkPrimaryText","linkSecondaryText","linkTertiaryText","linkIconColor","LinkCard","attachment","text","image_url","og_scrape_url","title_link","rawUrl","body","LinkIcon","isLinkAttachment","a","resolveLinkAttachment","triggerDownload","filename","name","res","blob","objectUrl","DownloadAction","busy","setBusy","fallback","DownloadSimpleIcon","resolveMediaFromMessage","videoAttachment","imageAttachment","audioAttachment","fileAttachment","activeAttachment","resolvedUrl","resolvedType","fileSize","Creator","Visitor","MediaMessageRoot","linkAttachment","resolved","MediaMessageCreatorEntry","MediaMessageVisitorEntry","MediaMessage","BUBBLE_BG_BY_VARIANT","BUBBLE_TEXT_BY_VARIANT","BUBBLE_BORDER_BY_VARIANT","sideForVariant","CORNER_CLASSES_BY_SIDE_AND_POSITION","Bubble","bordered","groupPosition","widthClassName","paddingClassName","radiusClassName","hasText","cornerClasses","DismissButton","onClick","ariaLabel","XIcon","bubbleVariantForState","state","bubbleGroupPositionFromStream","firstOfGroup","endOfGroup","groupedByUser","resolveItems","src","items","NativeAudioPlayer","item","preload","trailingAction","AudioAttachmentRow","onDismiss","showDismiss","resolvedItems","resolvedPreload","index","AudioComposer","AudioSent","AudioReceived","AudioAttachment","formatFileSize","EXTENSION_LABEL_BY_DOCUMENT_TYPE","getFileExtensionLabel","lastDot","ext","docType","docLabel","subtype","buildCompactMetaLabel","filenameFromUrl","last","META_CLASS_BY_VARIANT","ICON_BG_BY_VARIANT","ICON_COLOR_BY_VARIANT","CompactDocumentRow","onActivate","activateLabel","resolvedTitle","metaLabel","iconTile","textBlock","FileRowButton","resolvedFilename","FileAttachmentRow","handleActivate","downloadIcon","FileComposer","FileSent","FileReceived","FileAttachment","CarouselNav","onPrev","onNext","prevLabel","nextLabel","CaretLeftIcon","label","iconOnly","tone","onTriggered","handleClick","showIconOnly","iconProps","clamp","min","max","useCarousel","length","initialIndex","safeInitial","setIndex","prev","next","onKey","active","ViewerShell","onClose","counter","actions","dialogRef","closeButtonRef","dialog","previouslyFocused","ImageViewer","TILE_SHELL","OUTER_CORNER_CLASSES","SINGLE_WIDTH_CAP_PROPERTY","SINGLE_WIDTH_CAPS","SINGLE_HEIGHT_CAP_PX","MediaStackGrid","tiles","onTileActivate","maxVisible","singleAspectRatio","total","visible","overflow","renderTile","tile","extra","sharedClass","singleTileStyle","isLastWithOverflow","useViewer","viewerOpen","setViewerOpen","viewerIndex","setViewerIndex","closeViewer","tileFromItem","totalCount","fallbackLoading","imgRef","onLoad","alt","buildViewerItems","ImageComposerInner","loading","RESERVED_SINGLE_ASPECT_RATIO","useSingleImageRatio","measured","setMeasured","measure","img","ratio","handleLoad","supplied","measuredRatio","ImageBubbleRow","isSingle","single","ImageComposer","ImageSent","ImageReceived","ImageAttachment","PdfViewer","iframeSrc","withPdfViewerParams","hashIndex","base","existing","params","PdfRowButton","PdfAttachmentRow","viewerItems","itemFilename","PdfComposer","PdfSent","PdfReceived","PdfAttachment","VideoViewer","PlayBadge","PosterTile","it","VideoComposerInner","VideoBubbleRow","VideoComposer","VideoSent","VideoReceived","VideoAttachment","MessageAttachment","BroadcastNameContext","broadcastIdFromMessage","broadcastId","buildBroadcastNamesById","messages","resolveBroadcastName","seen","names","areBroadcastNamesEqual","previous","previousIds","nextIds","useBroadcastNamesById","publishedNames","setPublishedNames","defaultLockedAttachmentContextValue","customMessageDefaults","CustomMessageContext","CustomMessageProvider","useCustomMessage","key","TextCardLazy","MediaCardLazy","LockedAttachmentFallback","LockedAttachment","Suspense","SparkleIcon","isTipMessage","MESSAGE_CUSTOM_TYPE","isPaidMessage","isChatbotMessage","isAttachmentMessage","isTextAttachmentMessage","isMediaAttachmentMessage","isTipOrPaidMessage","isTipOnlyMessage","MessageTag","standalone","hasAttachment","isTipOrPaid","isChatbot","amountText","amountLabel","GiftIcon","isSenderAttachmentVariant","chatbotLabel","chatbotClassName","icon","MessageVoteButtons","onVoteUp","onVoteDown","ThumbsUpIcon","ThumbsDownIcon","useIsLatestRealMessage","useMessageContext","lastMessageId","lastMessage","DeliveredStatus","ChecksIcon","SendingStatus","BroadcastStatus","broadcastName","resolvedBroadcastName","onBroadcastClick","campaignName","content","MegaphoneIcon","FailedStatus","WarningCircleIcon","SentMessageDeliveryStatus","threadList","isOwnMessage","isLatestRealMessage","broadcastStatus","messageStatus","MessageStatus","SCHEME_PATTERN","SAFE_SCHEMES","normalizeExternalHref","schemeMatch","scheme","BUTTON_CLASS_BY_VARIANT","CardCta","cta","normalizedHref","TITLE_CLASS_BY_VARIANT","TITLE_DIMMED_CLASS","SECONDARY_CLASS_BY_VARIANT","SKELETON_BAR_CLASS_BY_VARIANT","CardBody","chinTextColor","description","appIcon","hasTitle","hasDescription","trimmedUrl","hasUrl","hasCta","titleClass","secondaryClass","barClass","chinTextStyle","LOADING_LABEL","SHELL_CLASS","FIXED_HEIGHT_CLASS","CardShell","href","bgClassName","accentStyle","fixedHeight","isInteractive","busyProps","corner","PLACEHOLDER_BG","PLACEHOLDER_ICON","isPlayableAudio","isPlayableMedia","AUDIO_BG","AUDIO_BG_CLASS","CardThumbnail","onImageError","isPlayableVideo","parseNumber","color","len","named","parseNamed","hex","parseHex","num","per","num_per","hue","c","rgb_num_old","rgb_per_old","parseRgbLegacy","prepare","mode","parse","converter","target_mode","converters","modes","parsers","colorProfiles","identity","v","useMode","definition","k","parser","useParser","getMode","IdentStartCodePoint","IdentCodePoint","Tok","_i","is_num","chars","ch","ch1","is_ident","huenits","digits","ident","identlike","tokenize","tokens","alpha","parseColorSyntax","token","coords","consumeCoords","channels","ii","includeHue","parseModernSyntax","parsed","result","parseRgb","g","b","parseTransparent","lerp","t","get_classes","arr","classes","interpolatorPiecewise","interpolator","cls","idx","pair","interpolatorLinear","fixupAlpha","some_defined","linearize","convertA98ToXyz65","a98","gamma","convertXyz65ToA98","x","y","z","fn","abs","convertRgbToLrgb","convertRgbToXyz65","rgb","convertLrgbToRgb","convertXyz65ToRgb","normalizeHue","hues","normalized","acc","curr","fixupHueShorter","d","M","degToRad","radToDeg","DE","BE","BCAD","convertRgbToCubehelix","l","convertCubehelixToRgb","h","s","amp","cosh","sinh","differenceHueSaturation","std","smp","std_h","smp_h","dH","differenceHueNaive","differenceHueChroma","averageAngle","val","sum","rad","angle","convertLabToLch","convertLchToLab","D50","D65","convertLab65ToXyz65","fy","fx","fz","convertLab65ToRgb","lab","f","convertXyz65ToLab65","f0","f1","f2","convertRgbToLab65","kE","kCH","θ","cosθ","sinθ","factor","convertDlchToLab65","G","convertLab65ToDlch","convertDlabToLab65","convertLab65ToDlab","convertHsiToRgb","convertRgbToHsi","m","convertHslToRgb","m1","m2","convertRgbToHsl","hueToDeg","unit","hsl_old","parseHslLegacy","parseHsl","convertHsvToRgb","convertRgbToHsv","convertHwbToRgb","w","convertRgbToHwb","rgba","hsv","ParseHwb","parseHwb","YW","M1","M2","C1","C2","C3","transferPqDecode","transferPqEncode","toRel","convertItpToXyz65","toAbs","convertXyz65ToItp","absX","absY","absZ","d0","jabPqEncode","vn","n","convertXyz65ToJab","xp","yp","jabPqDecode","vp","rel","convertJabToXyz65","j","convertRgbToJab","convertJabToRgb","convertJabToJch","convertJchToJab","convertLabToXyz50","convertXyz50ToRgb","convertLabToRgb","convertRgbToXyz50","convertXyz50ToLab","convertRgbToLab","parseLab","parseLch","lch","convertLuvToLchuv","u","convertLchuvToLuv","u_fn","v_fn","un","l_fn","convertXyz50ToLuv","convertLuvToXyz50","up","convertRgbToLchuv","convertLchuvToRgb","lchuv","luv","convertLrgbToOklab","L","S","convertRgbToOklab","convertOklabToLrgb","convertOklabToRgb","toe","k_3","toe_inv","compute_max_saturation","k0","k1","k2","k3","k4","wl","wm","ws","k_l","k_m","k_s","l_","m_","s_","l_dS","m_dS","s_dS","l_dS2","m_dS2","s_dS2","find_cusp","S_cusp","L_cusp","C_cusp","find_gamut_intersection","L1","L0","cusp","dL","dC","l_dt","m_dt","s_dt","C","ldt","mdt","sdt","ldt2","mdt2","sdt2","r1","r2","u_r","t_r","g1","g2","u_g","t_g","b1","b2","u_b","t_b","get_ST_max","a_","b_","get_Cs","C_max","ST_max","S_mid","T_mid","C_a","C_b","C_mid","convertOklabToOkhsl","ret","C_0","k_0","k_1","k_2","convertOkhslToOklab","hsl","modeOkhsl","modeHsl","convertOklabToOkhsv","S_max","T","S_0","L_v","C_v","L_vt","C_vt","rgb_scale","scale_L","convertOkhsvToOklab","L_new","modeOkhsv","modeHsv","parseOklab","parseOklch","convertP3ToXyz65","convertXyz65ToP3","convertXyz50ToProphoto","convertProphotoToXyz50","prophoto","α","β","convertXyz65ToRec2020","convertRec2020ToXyz65","rec2020","bias","bias_cbrt","transfer","convertRgbToXyb","convertXybToRgb","convertXyz65ToXyz50","xyz65","convertXyz50ToXyz65","xyz50","convertRgbToYiq","convertYiqToRgb","q","fixup","serializeHex","formatHex","fixup_rgb","to_displayable_srgb","inrange_rgb","displayable","inGamut","gamut","conv","clampGamut","destMode","destConv","inDestGamut","original","converted","clamped","clampChroma","rgbGamut","inDestinationGamut","clipToGamut","start","end","range","resolution","_last_good_c","luminance","contrast","L2","modeA98","modeCubehelix","modeDlab","modeDlch","modeHsi","modeHwb","modeItp","modeJab","modeJch","modeLab","modeLab65","modeLch","modeLch65","modeLchuv","modeLrgb","modeLuv","modeOklab","modeOklch","modeP3","modeProphoto","modeRec2020","modeRgb","modeXyb","modeXyz50","modeXyz65","modeYiq","HEX_PATTERN","toCssHex","WCAG_AA_NORMAL_TEXT","INK_ON_DARK","INK_ON_LIGHT","contrastRatio","wcagContrast","inkFor","background","againstDarkInk","SURFACE_LIGHTNESS","INK_BY_VARIANT","toOklch","accentSurface","accentColor","surface","useChinPalette","status","layout","heroFailed","setHeroFailed","isAudio","painted","DISMISS_CLASS","DISMISS_TOUCH_TARGET_CLASS","ComposerCard","onEditClick","dismissLabel","isClassic","chin","dismissButton","editButton","PencilSimpleIcon","BubbleTail","side","ReceivedCard","isPlayingMedia","normalizedUrl","shellHref","shellOnClick","audioBg","wrappedCta","SentCard","LinkAttachment","trimToUndefined","normalizeLinkUrl","linkCaptionDuplicatesAttachmentUrl","caption","attachmentUrl","normalizedCaption","remainder","linkCardPropsFromStreamAttachment","getAttachmentMediaKind","ogScrapeUrl","buildOrderedAttachmentSegments","attachments","segments","pushOrMergeMedia","kind","pushOrMergeLink","countMediaSegmentBubbles","segment","bubblePositionInRun","streamPosition","imageSrcFromAttachment","messageAttachmentNamespaceForKind","buildMediaClusterRenderProps","MediaClusterBubble","TypeNamespace","StreamAttachmentMessage","renderText","totalMediaBubbles","rawCaption","linkSegment","primaryLinkUrl","mediaBubbleIndex","rows","linkTailPosition","pushLinkRow","isFinalRow","Card","pushMediaCluster","position","segmentIndex","isFinalSegment","attachmentIndex","MessageErrorIcon","MessageText","CustomMessageWithContext","additionalMessageInputProps","chatbotVotingEnabled","editing","handleAction","handleOpenThread","handleRetry","highlighted","isMessageAIGenerated","isUnlocking","onUnlockClick","onFetchSource","onDownloadClick","isBounceDialogOpen","setIsBounceDialogOpen","reminder","useMessageReminder","voteState","Attachment","DefaultAttachment","EditMessageModal","DefaultEditMessageModal","MessageActions","MessageBlocked","DefaultMessageBlocked","MessageBouncePrompt","DefaultMessageBouncePrompt","MessageDeleted","DefaultMessageDeleted","MessageIsThreadReplyInChannelButtonIndicator","DefaultMessageIsThreadReplyInChannelButtonIndicator","MessageRepliesCountButton","DefaultMessageRepliesCountButton","ReminderNotification","DefaultReminderNotification","StreamedMessageText","DefaultStreamedMessageText","PinIndicator","useComponentContext","messageHasAttachments","hasReactions","messageHasReactions","isAIGenerated","finalAttachments","raw","filtered","attachmentSegments","displayMessage","displayText","hasAttachmentSegments","allAttachmentsRepresented","streamAttachmentGroupPosition","messageAttachmentGroupPositionFromStream","isDateSeparatorMessage","isMessageBlocked","showReplyCountButton","showIsReplyInChannel","allowRetry","isBounced","isMessageBounced","isMine","rootClassName","poll","isTipOnly","isAttachment","hasRenderableAttachments","useAttachmentFooterChatbotTag","canRenderAttachmentsInToolkit","sharedLockedTextProps","sharedLockedMediaProps","_e","_f","_g","_h","_j","MessageBounceModal","Poll","MemoizedCustomMessage","areMessageUIPropsEqual","CustomMessage","messageContext","broadcastNamesById","DeleteAction","handleDelete","DefaultDropdownActionButton","TrashSimpleIcon","ReportAction","handleFlag","CustomMessageActions","linkPreviewsManagerStateSelector","preview","LinkPreviewsManager","CustomLinkPreviewList","linkPreviewsManager","useMessageComposer","stateLinkPreviews","useStateStore","handleDismiss","linkPreview","ComposerLockedContext","NEAR_BOTTOM_THRESHOLD_PX","useComposerLocked","DefaultSendButton","sendMessage","disabled","ArrowUpIcon","CustomMessageInputInner","handleSubmit","useMessageInputContext","hasSendableData","useMessageComposerHasSendableData","isSendDisabled","SendButton","AttachmentPreviewList","DefaultAttachmentPreviewList","QuotedMessagePreview","TextareaComposer","CustomMessageInput","renderActions","renderHeader","renderFooter","disabledReason","composerInput","isFrozen","isFloating","composerRef","composer","previousComposerHeight","updateComposerHeight","nextComposerHeight","grew","scroller","wasAtBottom","resizeObserver","MessageInput","DM_AGENT_SYSTEM_MESSAGE_FALLBACK_TEXT","SHOW_SYSTEM_MESSAGE_TIMESTAMP_TYPES","AGE_SAFETY_SYSTEM_MESSAGE_FALLBACK_TEXT","AGE_SAFETY_SYSTEM_MESSAGE_EMPHASIS","AGE_SAFETY_SYSTEM_MESSAGE_URL","isShowTimestampSystemType","shouldShowSystemMessageTimestamp","getCustomSystemMessageVariant","metadataCustomType","isDmAgentSystemType","isAgeSafetySystemType","fallbackType","renderAgeSafetyMessageText","messageText","emphasisIndex","emphasisEndIndex","CustomSystemMessage","isDateHidden","customSystemMessageVariant","MessageTimestamp","ProhibitIcon","DmAgentEnabledContext","Circle","cx","AI_ACTIVE_STATES","AIStates","CustomTypingIndicator","channelConfig","thread","typing","useTypingContext","aiState","useAIState","agentUser","findOtherChannelUser","TypingBubble","typingInChannel","parent_id","typingInThread","typingUsers","typingUser","memberUser","avatarId","avatarName","avatarImage","testId","selfId","ChannelEmptyState","Loading","LoadingState","ChannelViewInner","renderMessageInputActions","renderMessageInputFooter","renderConversationFooter","composerDisabled","composerDisabledReason","renderChannelBanner","renderMessage","onBroadcastClickRef","stableOnBroadcastClick","broadcast","messageBroadcastClick","hasVisibleMessages","channelBanner","channelHeader","MessageOverride","messageNode","WithComponents","Window","MessageList","ChannelView","CustomChannelEmptyState","messageMetadata","onMessageSent","onMessageLinkClick","sendButton","attachmentPreviewList","doSendMessageRequest","_channel","options","agentPaused","shouldSuppressNotifications","finalMessage","finalOptions","response","container","handler","target","anchor","messageWrapper","messageId","Channel","ErrorState","MessagingShell","onChannelSelect","onExitConversation","initialParticipantFilter","initialParticipantData","selectedChannel","setSelectedChannel","directConversationError","setDirectConversationError","didExit","setDidExit","initialParticipantDataRef","onChannelSelectRef","directConversationLoadRef","selectedChannelRef","loadKey","releaseLoadGuard","participantData","createErr","onExitConversationRef","handleExitConversation","restorePendingMessages","pendingMessages","pending","ChannelListContext","ChannelListProvider","useChannelListContext","getDaysDifference","date1","date2","d1","diffTime","formatRelativeTime","date","now","daysDiff","CustomChannelPreview","unread","channelPreview","renderMessagePreview","isSelected","isActivationKey","isRepeatedKeydown","lastMessageText","custom_type","attachment_content_type","lastMessageTime","isLastMessageFromChatbot","messagePreview","unreadCount","DEFAULT_SORT","ChannelList","filters","allowNewMessagesFromUnfilteredChannels","channelRenderFilterFn","sort","customEmptyStateIndicator","Paginator","InfiniteScroll","lockChannelOrder","onMessageNewHandler","onMessageNew","onChannelVisible","onAddedToChannel","onChannelUpdated","wrappedChannelRenderFilterFn","StreamChannelList","TAIL_MASK","BG_VAR_BY_VARIANT","SURFACE_STYLE_BY_VARIANT","BubbleShell","tail","header","MessageBubble","FaqListItem","question","FaqList","faqs","onFaqClick","loadingFaqId","headerText","enabledFaqs","selectEnabledFaqs","faq"],"mappings":"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","x_google_ignoreList":[54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186]}
|
|
1
|
+
{"version":3,"file":"index-BzRQzc30.js","sources":["../src/providers/MessagingProvider.tsx","../src/hooks/useMessaging.ts","../src/hooks/useChannelStar.ts","../src/utils/resolveConversationParticipant.ts","../src/utils/resolveParticipantDisplayName.ts","../src/components/Avatar/getAvatarEmoji.ts","../src/components/Avatar/index.tsx","../src/hooks/useChannelModerationActions.ts","../src/components/ActionButton/index.tsx","../src/components/ChannelActionsMenu/index.tsx","../src/components/ChannelHeaderRedesign.tsx","../src/components/CustomDateSeparator/index.tsx","../src/hooks/useMessageVote.ts","../src/utils/getMessageDisplayText.ts","../src/utils/cdnImageUrl.ts","../src/components/AttachmentCard/utils/mimeType.ts","../src/components/AttachmentCard/utils/icons.ts","../src/components/AttachmentCard/MediaPlayer.tsx","../src/components/AttachmentCard/Thumbnail.tsx","../src/components/AttachmentCard/index.tsx","../src/components/MediaMessage/index.tsx","../src/components/MessageAttachment/_shared/Bubble.tsx","../src/components/MessageAttachment/_shared/DismissButton.tsx","../src/components/MessageAttachment/types.ts","../src/components/MessageAttachment/Audio/index.tsx","../src/components/MessageAttachment/_shared/fileMeta.ts","../src/components/MessageAttachment/_shared/CompactDocumentRow.tsx","../src/components/MessageAttachment/_shared/triggerDownload.ts","../src/components/MessageAttachment/File/index.tsx","../src/components/MessageAttachment/_shared/CarouselNav.tsx","../src/components/MessageAttachment/_shared/DownloadAction.tsx","../src/components/MessageAttachment/_shared/useCarousel.ts","../src/components/MessageAttachment/_shared/ViewerShell.tsx","../src/components/MessageAttachment/_shared/ImageViewer.tsx","../src/components/MessageAttachment/_shared/MediaStackGrid.tsx","../src/components/MessageAttachment/_shared/useViewer.ts","../src/components/MessageAttachment/Image/index.tsx","../src/components/MessageAttachment/_shared/PdfViewer.tsx","../src/components/MessageAttachment/Pdf/index.tsx","../src/components/MessageAttachment/_shared/VideoViewer.tsx","../src/components/MessageAttachment/Video/index.tsx","../src/components/MessageAttachment/index.tsx","../src/components/CustomMessage/BroadcastNameContext.ts","../src/components/CustomMessage/LockedAttachment/types.ts","../src/components/CustomMessage/context.tsx","../src/components/CustomMessage/LockedAttachment/index.tsx","../src/components/CustomMessage/MessageTag.tsx","../src/components/CustomMessage/MessageVoteButtons.tsx","../src/components/CustomMessage/SentMessageDeliveryStatus.tsx","../src/components/LinkAttachment/components/_shared/normalizeExternalHref.ts","../src/components/LinkAttachment/components/_shared/CardCta.tsx","../src/components/LinkAttachment/components/_shared/CardBody.tsx","../src/components/LinkAttachment/components/_shared/CardShell.tsx","../src/components/LinkAttachment/components/_shared/CardThumbnail.tsx","../../../node_modules/culori/src/rgb/parseNumber.js","../../../node_modules/culori/src/colors/named.js","../../../node_modules/culori/src/rgb/parseNamed.js","../../../node_modules/culori/src/rgb/parseHex.js","../../../node_modules/culori/src/util/regex.js","../../../node_modules/culori/src/rgb/parseRgbLegacy.js","../../../node_modules/culori/src/_prepare.js","../../../node_modules/culori/src/converter.js","../../../node_modules/culori/src/modes.js","../../../node_modules/culori/src/parse.js","../../../node_modules/culori/src/rgb/parseRgb.js","../../../node_modules/culori/src/rgb/parseTransparent.js","../../../node_modules/culori/src/interpolate/lerp.js","../../../node_modules/culori/src/interpolate/piecewise.js","../../../node_modules/culori/src/interpolate/linear.js","../../../node_modules/culori/src/fixup/alpha.js","../../../node_modules/culori/src/rgb/definition.js","../../../node_modules/culori/src/a98/convertA98ToXyz65.js","../../../node_modules/culori/src/a98/convertXyz65ToA98.js","../../../node_modules/culori/src/lrgb/convertRgbToLrgb.js","../../../node_modules/culori/src/xyz65/convertRgbToXyz65.js","../../../node_modules/culori/src/lrgb/convertLrgbToRgb.js","../../../node_modules/culori/src/xyz65/convertXyz65ToRgb.js","../../../node_modules/culori/src/a98/definition.js","../../../node_modules/culori/src/util/normalizeHue.js","../../../node_modules/culori/src/fixup/hue.js","../../../node_modules/culori/src/cubehelix/constants.js","../../../node_modules/culori/src/cubehelix/convertRgbToCubehelix.js","../../../node_modules/culori/src/cubehelix/convertCubehelixToRgb.js","../../../node_modules/culori/src/difference.js","../../../node_modules/culori/src/average.js","../../../node_modules/culori/src/cubehelix/definition.js","../../../node_modules/culori/src/lch/convertLabToLch.js","../../../node_modules/culori/src/lch/convertLchToLab.js","../../../node_modules/culori/src/xyz65/constants.js","../../../node_modules/culori/src/constants.js","../../../node_modules/culori/src/lab65/convertLab65ToXyz65.js","../../../node_modules/culori/src/lab65/convertLab65ToRgb.js","../../../node_modules/culori/src/lab65/convertXyz65ToLab65.js","../../../node_modules/culori/src/lab65/convertRgbToLab65.js","../../../node_modules/culori/src/dlch/constants.js","../../../node_modules/culori/src/dlch/convertDlchToLab65.js","../../../node_modules/culori/src/dlch/convertLab65ToDlch.js","../../../node_modules/culori/src/dlab/definition.js","../../../node_modules/culori/src/dlch/definition.js","../../../node_modules/culori/src/hsi/convertHsiToRgb.js","../../../node_modules/culori/src/hsi/convertRgbToHsi.js","../../../node_modules/culori/src/hsi/definition.js","../../../node_modules/culori/src/hsl/convertHslToRgb.js","../../../node_modules/culori/src/hsl/convertRgbToHsl.js","../../../node_modules/culori/src/util/hue.js","../../../node_modules/culori/src/hsl/parseHslLegacy.js","../../../node_modules/culori/src/hsl/parseHsl.js","../../../node_modules/culori/src/hsl/definition.js","../../../node_modules/culori/src/hsv/convertHsvToRgb.js","../../../node_modules/culori/src/hsv/convertRgbToHsv.js","../../../node_modules/culori/src/hsv/definition.js","../../../node_modules/culori/src/hwb/convertHwbToRgb.js","../../../node_modules/culori/src/hwb/convertRgbToHwb.js","../../../node_modules/culori/src/hwb/parseHwb.js","../../../node_modules/culori/src/hwb/definition.js","../../../node_modules/culori/src/hdr/constants.js","../../../node_modules/culori/src/hdr/transfer.js","../../../node_modules/culori/src/itp/convertItpToXyz65.js","../../../node_modules/culori/src/itp/convertXyz65ToItp.js","../../../node_modules/culori/src/itp/definition.js","../../../node_modules/culori/src/jab/convertXyz65ToJab.js","../../../node_modules/culori/src/jab/convertJabToXyz65.js","../../../node_modules/culori/src/jab/convertRgbToJab.js","../../../node_modules/culori/src/jab/convertJabToRgb.js","../../../node_modules/culori/src/jab/definition.js","../../../node_modules/culori/src/jch/convertJabToJch.js","../../../node_modules/culori/src/jch/convertJchToJab.js","../../../node_modules/culori/src/jch/definition.js","../../../node_modules/culori/src/xyz50/constants.js","../../../node_modules/culori/src/lab/convertLabToXyz50.js","../../../node_modules/culori/src/xyz50/convertXyz50ToRgb.js","../../../node_modules/culori/src/lab/convertLabToRgb.js","../../../node_modules/culori/src/xyz50/convertRgbToXyz50.js","../../../node_modules/culori/src/lab/convertXyz50ToLab.js","../../../node_modules/culori/src/lab/convertRgbToLab.js","../../../node_modules/culori/src/lab/parseLab.js","../../../node_modules/culori/src/lab/definition.js","../../../node_modules/culori/src/lab65/definition.js","../../../node_modules/culori/src/lch/parseLch.js","../../../node_modules/culori/src/lch/definition.js","../../../node_modules/culori/src/lch65/definition.js","../../../node_modules/culori/src/lchuv/convertLuvToLchuv.js","../../../node_modules/culori/src/lchuv/convertLchuvToLuv.js","../../../node_modules/culori/src/luv/convertXyz50ToLuv.js","../../../node_modules/culori/src/luv/convertLuvToXyz50.js","../../../node_modules/culori/src/lchuv/definition.js","../../../node_modules/culori/src/lrgb/definition.js","../../../node_modules/culori/src/luv/definition.js","../../../node_modules/culori/src/oklab/convertLrgbToOklab.js","../../../node_modules/culori/src/oklab/convertRgbToOklab.js","../../../node_modules/culori/src/oklab/convertOklabToLrgb.js","../../../node_modules/culori/src/oklab/convertOklabToRgb.js","../../../node_modules/culori/src/okhsl/helpers.js","../../../node_modules/culori/src/okhsl/convertOklabToOkhsl.js","../../../node_modules/culori/src/okhsl/convertOkhslToOklab.js","../../../node_modules/culori/src/okhsl/modeOkhsl.js","../../../node_modules/culori/src/okhsv/convertOklabToOkhsv.js","../../../node_modules/culori/src/okhsv/convertOkhsvToOklab.js","../../../node_modules/culori/src/okhsv/modeOkhsv.js","../../../node_modules/culori/src/oklab/parseOklab.js","../../../node_modules/culori/src/oklab/definition.js","../../../node_modules/culori/src/oklch/parseOklch.js","../../../node_modules/culori/src/oklch/definition.js","../../../node_modules/culori/src/p3/convertP3ToXyz65.js","../../../node_modules/culori/src/p3/convertXyz65ToP3.js","../../../node_modules/culori/src/p3/definition.js","../../../node_modules/culori/src/prophoto/convertXyz50ToProphoto.js","../../../node_modules/culori/src/prophoto/convertProphotoToXyz50.js","../../../node_modules/culori/src/prophoto/definition.js","../../../node_modules/culori/src/rec2020/convertXyz65ToRec2020.js","../../../node_modules/culori/src/rec2020/convertRec2020ToXyz65.js","../../../node_modules/culori/src/rec2020/definition.js","../../../node_modules/culori/src/xyb/constants.js","../../../node_modules/culori/src/xyb/convertRgbToXyb.js","../../../node_modules/culori/src/xyb/convertXybToRgb.js","../../../node_modules/culori/src/xyb/definition.js","../../../node_modules/culori/src/xyz50/definition.js","../../../node_modules/culori/src/xyz65/convertXyz65ToXyz50.js","../../../node_modules/culori/src/xyz65/convertXyz50ToXyz65.js","../../../node_modules/culori/src/xyz65/definition.js","../../../node_modules/culori/src/yiq/convertRgbToYiq.js","../../../node_modules/culori/src/yiq/convertYiqToRgb.js","../../../node_modules/culori/src/yiq/definition.js","../../../node_modules/culori/src/formatter.js","../../../node_modules/culori/src/clamp.js","../../../node_modules/culori/src/wcag.js","../../../node_modules/culori/src/index.js","../src/components/LinkAttachment/components/_shared/hex.ts","../src/components/LinkAttachment/components/_shared/chinContrast.ts","../src/components/LinkAttachment/components/_shared/accentSurface.ts","../src/components/LinkAttachment/components/_shared/useChinPalette.ts","../src/components/LinkAttachment/components/Composer/Card.tsx","../src/components/LinkAttachment/components/_shared/BubbleTail.tsx","../src/components/LinkAttachment/components/Received/Card.tsx","../src/components/LinkAttachment/components/Sent/Card.tsx","../src/components/LinkAttachment/index.tsx","../src/components/CustomMessage/StreamAttachmentMessage.tsx","../src/components/CustomMessage/index.tsx","../src/components/CustomMessage/CustomMessageActions.tsx","../src/components/CustomLinkPreviewList/index.tsx","../src/components/CustomMessageInput/index.tsx","../src/components/CustomSystemMessage/index.tsx","../src/components/CustomTypingIndicator/DmAgentContext.ts","../src/components/CustomTypingIndicator/index.tsx","../src/components/MessagingShell/ChannelEmptyState.tsx","../src/components/Loading/index.tsx","../src/components/MessagingShell/LoadingState.tsx","../src/components/ChannelView.tsx","../src/components/MessagingShell/ErrorState.tsx","../src/components/MessagingShell/index.tsx","../src/hooks/useRestorePendingMessages.ts","../src/components/ChannelList/ChannelListContext.tsx","../src/utils/formatRelativeTime.ts","../src/components/ChannelList/CustomChannelPreview.tsx","../src/components/ChannelList/index.tsx","../src/components/MessageBubble/components/_shared/bubbleTail.tsx","../src/components/MessageBubble/components/_shared/BubbleShell.tsx","../src/components/MessageBubble/components/Received/Card.tsx","../src/components/MessageBubble/components/Sent/Card.tsx","../src/components/MessageBubble/index.tsx","../src/components/FaqList/FaqListItem.tsx","../src/components/FaqList/index.tsx"],"sourcesContent":["/* eslint-disable react-hooks/refs, react-hooks/set-state-in-effect -- pre-existing pattern flagged by the React\n Compiler rules added in eslint-plugin-react-hooks v7; refactoring it is\n out of scope for the lint toolchain upgrade. */\nimport { StreamChatService } from '@linktr.ee/messaging-core'\nimport React, {\n createContext,\n useContext,\n useEffect,\n useState,\n useRef,\n useCallback,\n} from 'react'\nimport { StreamChat } from 'stream-chat'\nimport { Chat } from 'stream-chat-react'\n\nimport type { MessagingProviderProps, MessagingCapabilities } from '../types'\n\n/**\n * Context value for messaging state and service\n */\nexport interface MessagingContextValue {\n service: StreamChatService | null\n client: StreamChat | null // Stream Chat client\n isConnected: boolean\n isLoading: boolean\n error: string | null\n capabilities: MessagingCapabilities\n refreshConnection: () => Promise<void>\n debug: boolean\n}\n\nconst MessagingContext = createContext<MessagingContextValue>({\n service: null,\n client: null,\n isConnected: false,\n isLoading: false,\n error: null,\n capabilities: {},\n refreshConnection: async () => {},\n debug: false,\n})\n\n/**\n * Hook to access messaging context\n */\nexport const useMessagingContext = () => useContext(MessagingContext)\n\n/**\n * Provider component that wraps messaging-core with React state management\n */\nexport const MessagingProvider: React.FC<MessagingProviderProps> = ({\n children,\n user,\n serviceConfig,\n apiKey,\n capabilities = {},\n debug = false,\n client: injectedClient,\n}) => {\n // Create debug logger that respects the debug prop\n const debugLog = useCallback(\n (message: string, ...args: unknown[]) => {\n if (debug) {\n console.log(`🔥 [MessagingProvider] ${message}`, ...args)\n }\n },\n [debug]\n )\n\n debugLog('🔄 RENDER START', {\n userId: user?.id,\n apiKey: apiKey?.substring(0, 8) + '...',\n serviceConfig: !!serviceConfig,\n capabilities: Object.keys(capabilities),\n })\n\n const [service, setService] = useState<StreamChatService | null>(null)\n const [client, setClient] = useState<StreamChat | null>(null)\n const [isConnected, setIsConnected] = useState(false)\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n // Prevent multiple concurrent connection attempts\n const connectingRef = useRef(false)\n\n // The single service instance, for teardown in the client-cleanup effect.\n const serviceRef = useRef<StreamChatService | null>(null)\n\n // serviceConfig / debug are read at service-creation time via refs so that\n // changing them does not recreate the service (and re-adopt the live client).\n // The service is created once per client lifetime (apiKey); the connection is\n // driven by `user`. Real consumers pass a stable, memoized serviceConfig.\n const serviceConfigRef = useRef(serviceConfig)\n serviceConfigRef.current = serviceConfig\n const debugRef = useRef(debug)\n debugRef.current = debug\n\n // Track renders and prop changes\n const prevPropsRef = useRef({\n userId: user?.id,\n apiKey,\n serviceConfig,\n capabilities,\n })\n const renderCountRef = useRef(0)\n renderCountRef.current++\n\n debugLog('📊 RENDER INFO', {\n renderCount: renderCountRef.current,\n currentProps: { userId: user?.id, apiKey: apiKey?.substring(0, 8) + '...' },\n propChanges: {\n userChanged: prevPropsRef.current.userId !== user?.id,\n apiKeyChanged: prevPropsRef.current.apiKey !== apiKey,\n serviceConfigChanged:\n prevPropsRef.current.serviceConfig !== serviceConfig,\n capabilitiesChanged: prevPropsRef.current.capabilities !== capabilities,\n },\n })\n\n prevPropsRef.current = {\n userId: user?.id,\n apiKey,\n serviceConfig,\n capabilities,\n }\n\n // Construct the Stream client synchronously so <Chat> can render against a\n // stable instance on the very first render. Without this the subtree mounted\n // as a bare `children` while connecting, then remounted inside <Chat> once\n // connectUser resolved (~0.8s later) because the children's parent element\n // changed — re-running every mount effect (refetches, Stream listeners,\n // page-view events) and resetting transient state. This client is injected\n // into the service below, so connectUser connects this exact instance.\n //\n // Stored in a ref (not useMemo) so its identity is *guaranteed* stable for the\n // apiKey's lifetime. useMemo is unsafe here: React may discard a memo and\n // recompute it, which would mint a new client, re-run the service-init effect,\n // and tear down + rebuild the live connection — the very remount this fix\n // exists to prevent. Both effects below key on `chatClient`, so it must not\n // depend on memo retention. One client per provider mount (keyed on apiKey) —\n // not the process-wide StreamChat.getInstance, which is shared across keys and\n // provider instances.\n const clientRef = useRef<{ apiKey: string; client: StreamChat } | null>(null)\n if (!injectedClient && apiKey && clientRef.current?.apiKey !== apiKey) {\n clientRef.current = { apiKey, client: new StreamChat(apiKey) }\n }\n // An injected client takes precedence and short-circuits the apiKey-derived\n // client, the service, and the connect/disconnect lifecycle below — the\n // caller owns that instance (offline/dev via `createMockMessagingClient`, or\n // a test). Otherwise fall back to the apiKey-derived client as before.\n const chatClient = injectedClient\n ? injectedClient\n : apiKey\n ? (clientRef.current?.client ?? null)\n : null\n\n // Create the service once per client lifetime (apiKey). Keyed on `chatClient`\n // — NOT on serviceConfig/debug — so those changing does not spin up a second\n // service that would re-adopt the live client and race the in-flight connect.\n // serviceConfig/debug are read from refs at creation. There is therefore a\n // single service per client, which owns the connection lifecycle and tracks\n // the active user; `user` changes reconnect through it.\n useEffect(() => {\n const currentRender = renderCountRef.current\n const currentConfig = serviceConfigRef.current\n\n // An injected client owns its own connection — never create a service or\n // connect for it. Reset all apiKey-path connection state (service, client,\n // isConnected, error, isLoading): while injected these are masked by the\n // context, but on a later return to apiKey mode they would leak back —\n // before the fresh service reconnects — feeding the user-connection effect\n // a stale service and MessagingShell (which gates its load on\n // `client && isConnected`) a disconnected client to queryChannels on.\n if (injectedClient) {\n serviceRef.current = null\n setService(null)\n setClient(null)\n setIsConnected(false)\n setError(null)\n setIsLoading(false)\n return\n }\n\n if (!apiKey || !chatClient || !currentConfig) {\n debugLog('⚠️ SERVICE INIT SKIPPED', {\n renderCount: currentRender,\n reason: 'Missing apiKey, client, or serviceConfig',\n })\n return\n }\n\n debugLog('🚀 CREATING SERVICE', {\n renderCount: currentRender,\n apiKey: apiKey?.substring(0, 8) + '...',\n })\n\n const newService = new StreamChatService({\n ...currentConfig,\n apiKey,\n debug: debugRef.current,\n client: chatClient,\n })\n\n serviceRef.current = newService\n setService(newService)\n debugLog('✅ SERVICE SET', {\n renderCount: currentRender,\n serviceInstance: !!newService,\n })\n\n // No disconnect on cleanup here — disconnection is owned by the\n // client-cleanup effect below, keyed on `chatClient` (apiKey) and unmount.\n // eslint-disable-next-line react-hooks/exhaustive-deps -- serviceConfig/debug/debugLog are read via refs by design (see above); recreating on them would re-adopt the live client\n }, [apiKey, chatClient, injectedClient])\n\n // Track if we've already connected this user with this service to prevent duplicate connections\n const connectedUserRef = useRef<{\n serviceId: StreamChatService\n userId: string\n } | null>(null)\n\n // Connect user when service and user are available\n useEffect(() => {\n debugLog('🔗 USER CONNECTION EFFECT TRIGGERED', {\n hasService: !!service,\n hasUser: !!user,\n userId: user?.id,\n isConnecting: connectingRef.current,\n isConnected: isConnected,\n dependencies: { service: !!service, userId: user?.id },\n })\n\n // The injected client owns its own connection — never connect a service for\n // it. Without this guard a `user` change in injected-client mode would run\n // service.connectUser on a stale apiKey-path service (the toggle case).\n if (injectedClient) {\n return\n }\n\n if (!service || !user) {\n debugLog('⚠️ USER CONNECTION SKIPPED', 'Missing service or user')\n return\n }\n\n if (connectingRef.current) {\n debugLog('⚠️ USER CONNECTION SKIPPED', 'Already connecting')\n return\n }\n\n // Check if we've already connected this exact user with this exact service instance\n if (\n connectedUserRef.current?.serviceId === service &&\n connectedUserRef.current?.userId === user.id\n ) {\n debugLog(\n '⚠️ USER CONNECTION SKIPPED',\n 'Already connected this user with this service'\n )\n return\n }\n\n const connectUser = async () => {\n debugLog('🚀 STARTING USER CONNECTION', { userId: user.id })\n connectingRef.current = true\n setIsLoading(true)\n setError(null)\n\n try {\n debugLog('📞 CALLING SERVICE.CONNECTUSER', { userId: user.id })\n const streamClient = await service.connectUser(user)\n setClient(streamClient)\n setIsConnected(true)\n connectedUserRef.current = { serviceId: service, userId: user.id } // Mark as connected\n debugLog('✅ USER CONNECTION SUCCESS', {\n userId: user.id,\n clientId: streamClient.userID,\n })\n } catch (err) {\n const errorMessage =\n err instanceof Error ? err.message : 'Connection failed'\n setError(errorMessage)\n debugLog('❌ USER CONNECTION ERROR', {\n userId: user.id,\n error: errorMessage,\n })\n } finally {\n setIsLoading(false)\n connectingRef.current = false\n debugLog('🔄 USER CONNECTION FINISHED', {\n userId: user.id,\n isConnected,\n })\n }\n }\n\n connectUser()\n }, [service, user, debugLog, isConnected, injectedClient])\n\n // Disconnect tied to the client's lifetime: only when `chatClient` changes\n // (i.e. `apiKey` changes) or the provider unmounts — never on a mere\n // serviceConfig/debug change, which reuses the same client. Uses `serviceRef`\n // so the disconnect goes through the latest service instance. Deliberately\n // keyed on `chatClient` only: depending on `debugLog` (which changes identity\n // when the `debug` prop toggles) would tear down the live client just for a\n // logging change.\n useEffect(() => {\n const client = chatClient\n return () => {\n if (!client) return\n connectedUserRef.current = null // Reset connection tracking\n serviceRef.current?.disconnectUser().catch(console.error)\n }\n }, [chatClient])\n\n const refreshConnection = useCallback(async () => {\n debugLog('🔄 REFRESH CONNECTION CALLED', {\n hasService: !!service,\n hasUser: !!user,\n })\n\n // The injected client owns its own connection lifecycle — refresh is a\n // no-op. Guarding here (not just the context fields) stops a stale\n // apiKey-path `service` from being disconnected/reconnected if the same\n // provider previously connected via apiKey and then received a client.\n if (injectedClient) {\n return\n }\n\n if (!service || !user) {\n debugLog('⚠️ REFRESH CONNECTION SKIPPED', 'Missing service or user')\n return\n }\n\n debugLog('🚀 STARTING CONNECTION REFRESH', { userId: user.id })\n setIsLoading(true)\n try {\n debugLog('🔌 DISCONNECTING FOR REFRESH')\n await service.disconnectUser()\n debugLog('📞 RECONNECTING FOR REFRESH')\n const streamClient = await service.connectUser(user)\n setClient(streamClient)\n setIsConnected(true)\n setError(null)\n debugLog('✅ CONNECTION REFRESH SUCCESS', { userId: user.id })\n } catch (err) {\n const errorMessage = err instanceof Error ? err.message : 'Refresh failed'\n setError(errorMessage)\n debugLog('❌ CONNECTION REFRESH ERROR', {\n userId: user.id,\n error: errorMessage,\n })\n } finally {\n setIsLoading(false)\n debugLog('🔄 CONNECTION REFRESH FINISHED', { userId: user.id })\n }\n }, [service, user, debugLog, injectedClient])\n\n // Memoize context value to prevent unnecessary re-renders\n const contextValue: MessagingContextValue = React.useMemo(() => {\n debugLog('💫 CONTEXT VALUE MEMOIZATION', {\n hasService: !!service,\n hasClient: !!client,\n isConnected,\n isLoading,\n hasError: !!error,\n capabilitiesKeys: Object.keys(capabilities),\n })\n\n return {\n // With an injected client, expose no service — the injected client owns\n // its lifecycle and there is no backend to reach. Suppressing it stops\n // service-dependent paths (channel creation, block/unblock) from calling\n // a stale apiKey-path service if the same provider previously connected.\n service: injectedClient ? null : service,\n // An injected client is already connected and owns its lifecycle, so\n // surface it directly and report a clean connected state — the apiKey\n // path's `client`/`isLoading`/`error` (from connectUser) must not leak\n // through if the same provider previously attempted an apiKey connect.\n client: injectedClient ?? client,\n isConnected: injectedClient ? true : isConnected,\n isLoading: injectedClient ? false : isLoading,\n error: injectedClient ? null : error,\n capabilities,\n refreshConnection,\n debug,\n }\n }, [\n service,\n client,\n injectedClient,\n isConnected,\n isLoading,\n error,\n capabilities,\n refreshConnection,\n debug,\n debugLog,\n ])\n\n debugLog('🔄 RENDER END', {\n renderCount: renderCountRef.current,\n willRenderChat: !!chatClient,\n contextValueReady: !!contextValue,\n })\n\n return (\n <MessagingContext.Provider value={contextValue}>\n {chatClient ? (\n <Chat\n client={chatClient}\n customClasses={{\n channelList:\n 'str-chat__channel-list str-chat__channel-list-react bg-transparent lg:border-r-2 border-r-0 border-[#0000000A]',\n }}\n >\n {children}\n </Chat>\n ) : (\n children\n )}\n </MessagingContext.Provider>\n )\n}\n","import { useMessagingContext } from '../providers/MessagingProvider';\nimport type { MessagingContextValue } from '../providers/MessagingProvider';\n\n/**\n * Hook to access messaging service and state\n */\nexport const useMessaging = (): MessagingContextValue => {\n return useMessagingContext();\n};\n","/* eslint-disable react-hooks/set-state-in-effect -- pre-existing pattern flagged by the React\n Compiler rules added in eslint-plugin-react-hooks v7; refactoring it is\n out of scope for the lint toolchain upgrade. */\nimport { useEffect, useState } from 'react'\nimport { Channel, Event } from 'stream-chat'\n\nexport const useChannelStar = (channel?: Channel) => {\n const [isChannelStarred, setIsChannelStarred] = useState(\n !!channel?.state?.membership?.pinned_at\n )\n\n useEffect(() => {\n if (!channel) {\n setIsChannelStarred(false)\n return\n }\n\n setIsChannelStarred(!!channel.state.membership?.pinned_at)\n\n const handleMemberUpdate = (event: Event) => {\n setIsChannelStarred(\n event?.member ? !!event.member.pinned_at : !!channel.state.membership?.pinned_at\n )\n }\n\n channel.on('member.updated', handleMemberUpdate)\n\n return () => {\n channel.off('member.updated', handleMemberUpdate)\n }\n }, [channel])\n\n return isChannelStarred\n}\n","import {\n isOfficialChannel,\n OFFICIAL_SENDER_USER_ID,\n} from '@linktr.ee/messaging-taxonomy'\nimport type { Channel } from 'stream-chat'\n\ntype ChannelMembers = NonNullable<Channel['state']>['members']\ntype ChannelMember = ChannelMembers[string]\n\n/**\n * Resolves the member to display as the conversation's \"other party\".\n *\n * For a normal 1:1 channel this is the member that isn't the current user. The\n * official channel is special: its display identity is always the official\n * sender (\"Linktree\"), regardless of who is viewing. That matters because an\n * unverified sensitive linker reads the official channel as a guest whose\n * random Stream id isn't a member, so the \"not me\" heuristic would otherwise\n * fall back to the linker's own member and show their name instead of Linktree.\n */\nexport function resolveConversationParticipant(\n members: ChannelMembers | undefined,\n currentUserId: string | undefined,\n channelType: string | undefined\n): ChannelMember | undefined {\n const memberList = Object.values(members || {})\n\n if (isOfficialChannel(channelType)) {\n const officialSender = memberList.find(\n (member) => member.user?.id === OFFICIAL_SENDER_USER_ID\n )\n if (officialSender) return officialSender\n }\n\n return memberList.find(\n (member) => member.user?.id && member.user.id !== currentUserId\n )\n}\n","const UUID_REGEX =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i\n\nexport type ParticipantDisplayUser = {\n id?: string\n name?: string | null\n username?: string | null\n}\n\nexport function isUuidLike(value: string): boolean {\n return UUID_REGEX.test(value.trim())\n}\n\nfunction isUsableDisplayValue(\n value: string | null | undefined,\n userId?: string\n): value is string {\n const trimmed = value?.trim()\n if (!trimmed) return false\n if (userId && trimmed === userId) return false\n // Followers with no real name were historically provisioned in Stream Chat with a\n // placeholder name of the form `Follower <id>` (the string \"Follower \" + the user id).\n // Treat it as missing so surfaces fall back to their own label instead of leaking the\n // internal placeholder as a display name (MES-1077).\n if (userId && trimmed === `Follower ${userId}`) return false\n return !isUuidLike(trimmed)\n}\n\n/**\n * Resolves a human-readable participant label from Stream user fields.\n * Never falls back to user.id. UUID-like names are treated as missing.\n */\nexport function resolveParticipantDisplayName(\n user?: ParticipantDisplayUser | null\n): string {\n if (isUsableDisplayValue(user?.name, user?.id)) {\n return user.name.trim()\n }\n\n if (isUsableDisplayValue(user?.username, user?.id)) {\n return user.username.trim()\n }\n\n return 'Unknown member'\n}\n","/**\n * Fruit emojis paired with their avatar background color.\n * Single source of truth for both `getAvatarEmoji` and `getAvatarBgColor`.\n */\nconst FRUITS = [\n { emoji: '🍎', bgColor: '#FFD1DD' }, // Apple\n { emoji: '🍌', bgColor: '#FFF1C9' }, // Banana\n { emoji: '🍇', bgColor: '#E6D9FF' }, // Grape\n { emoji: '🍊', bgColor: '#D6F4FF' }, // Orange\n { emoji: '🍓', bgColor: '#FFE0AE' }, // Strawberry\n { emoji: '🥥', bgColor: '#F7E7D8' }, // Coconut\n { emoji: '🍒', bgColor: '#DFF4D8' }, // Cherry\n { emoji: '🥭', bgColor: '#FFD8C2' }, // Mango\n { emoji: '🍉', bgColor: '#D6EBFF' }, // Watermelon\n { emoji: '🍋', bgColor: '#CAEEB5' }, // Lemon\n { emoji: '🥝', bgColor: '#FFE7C7' }, // Kiwi\n { emoji: '🫒', bgColor: '#F6E3B4' }, // Olive\n { emoji: '🍈', bgColor: '#D9F7E1' }, // Melon\n]\n\n/**\n * Simple hash function to convert string to number\n */\nfunction hashString(str: string): number {\n let hash = 0\n for (let i = 0; i < str.length; i++) {\n const char = str.charCodeAt(i)\n hash = (hash << 5) - hash + char\n hash = hash & hash // Convert to 32-bit integer\n }\n return Math.abs(hash)\n}\n\n/**\n * Pick a consistent fruit for an id string\n */\nfunction getFruit(id: string) {\n return FRUITS[hashString(id) % FRUITS.length]\n}\n\n/**\n * Get a fruit emoji based on an id string\n * @param id - The string id to generate emoji from\n * @returns A fruit emoji string\n */\nexport function getAvatarEmoji(id: string): string {\n return getFruit(id).emoji\n}\n\n/**\n * Get the background color paired with an id's fruit emoji\n * @param id - The string id to generate the color from\n * @returns A hex color string\n */\nexport function getAvatarBgColor(id: string): string {\n return getFruit(id).bgColor\n}\n","import { StarIcon } from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React from 'react'\n\nimport { getAvatarBgColor, getAvatarEmoji } from './getAvatarEmoji'\n\nexport interface AvatarProps {\n id: string\n name: string\n image?: string\n size?: number\n className?: string\n starred?: boolean\n shape?: 'squircle' | 'circle'\n dmAgentEnabled?: boolean\n}\n\n/**\n * Avatar component that displays a user image or colored initial fallback\n */\nexport const Avatar = ({\n id,\n image,\n size = 40,\n className,\n starred = false,\n shape = 'squircle',\n dmAgentEnabled = false,\n}: AvatarProps) => {\n const emoji = getAvatarEmoji(id)\n const bgColor = getAvatarBgColor(id)\n\n // Small avatars scale the emoji with the avatar so it doesn't overpower a\n // tiny circle — a fixed floor read ~60% of a 17px avatar vs ~35% at 40px.\n // Larger avatars keep fixed sizes. 0.45 is continuous with the 14px step at\n // 32px; lower it to shrink small emoji further.\n const SMALL_EMOJI_RATIO = 0.45\n const getFontSize = () => {\n if (size < 32) return Math.round(size * SMALL_EMOJI_RATIO)\n if (size < 56) return 14\n if (size < 120) return 18\n return 36\n }\n\n const fontSize = getFontSize()\n // Match design treatment: 2px AI border at 40px avatar size.\n const aiBorderWidth = size >= 40 ? 2 : 1\n\n const borderStyle =\n shape === 'circle'\n ? { borderRadius: '50%' }\n : { borderRadius: '1rem' }\n\n const avatarInner = (\n <div className=\"h-full w-full overflow-hidden\" style={borderStyle}>\n {image ? (\n <img\n src={image}\n alt=\"\"\n className=\"h-full w-full object-cover\"\n />\n ) : (\n <div\n aria-hidden=\"true\"\n className={classNames(\n 'avatar-fallback flex h-full w-full items-center justify-center font-semibold select-none transition-colors'\n )}\n style={{ fontSize, lineHeight: 1 }}\n >\n {emoji}\n </div>\n )}\n </div>\n )\n\n return (\n <div\n className={classNames(\n 'relative flex-shrink-0',\n className\n )}\n style={{\n '--str-chat__avatar-size': `${size}px`,\n width: `${size}px`,\n height: `${size}px`,\n backgroundColor: image ? undefined : bgColor,\n ...borderStyle,\n } as React.CSSProperties}\n >\n {starred && (\n <div\n aria-hidden=\"true\"\n className=\"absolute -left-1.5 -top-1.5 z-10 flex size-5 items-center justify-center rounded-full bg-white shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_4px_8px_rgba(0,0,0,0.06)]\"\n >\n <StarIcon className=\"size-3 text-yellow-600\" weight=\"duotone\" />\n </div>\n )}\n <div\n data-testid=\"avatar-ring\"\n className={classNames(\n 'h-full w-full',\n 'bg-transparent'\n )}\n style={{\n ...borderStyle,\n ...(dmAgentEnabled && {\n borderWidth: `${aiBorderWidth}px`,\n borderStyle: 'solid',\n borderColor: 'var(--AI-Gradient, #7F22FE)',\n boxShadow: 'inset 0 1px 2px 0 rgba(255, 255, 255, 0.5)',\n }),\n }}\n >\n {avatarInner}\n </div>\n </div>\n )\n}\n","/* eslint-disable react-hooks/set-state-in-effect -- pre-existing pattern flagged by the React\n Compiler rules added in eslint-plugin-react-hooks v7; refactoring it is\n out of scope for the lint toolchain upgrade. */\nimport { useEffect, useState } from 'react'\nimport type { Channel as ChannelType, ChannelMemberResponse } from 'stream-chat'\n\nimport { useMessagingContext } from '../providers/MessagingProvider'\n\n// Blocked user from Stream Chat API\ntype BlockedUser = {\n blocked_user_id: string\n}\n\nconst REPORT_URL = 'https://linktr.ee/s/about/trust-center/report'\n\nexport interface UseChannelModerationActionsParams {\n channel: ChannelType\n participant: ChannelMemberResponse | undefined\n /**\n * When false, the blocked-status lookup is skipped (the result would be\n * unused, e.g. the Linktree official channel does not offer blocking).\n * Defaults to true.\n */\n showBlockParticipant?: boolean\n /**\n * When false, the blocked-status lookup is deferred. Useful for surfaces\n * that mount the actions ahead of time (e.g. a closed popover) and only\n * need block state once visible. Defaults to true.\n */\n enabled?: boolean\n onLeaveConversation?: (channel: ChannelType) => void\n onBlockParticipant?: (participantId?: string) => void\n onDeleteConversationClick?: () => void\n onBlockParticipantClick?: () => void\n onReportParticipantClick?: () => void\n /**\n * Called after an action completes successfully (e.g. to close the\n * surrounding dialog or popover).\n */\n onActionComplete?: () => void\n /** Prefix used for debug logging. */\n logLabel?: string\n}\n\nexport interface ChannelModerationActions {\n isParticipantBlocked: boolean\n /**\n * True while the initial blocked-status lookup is in flight. Until this is\n * false, `isParticipantBlocked` has not yet been resolved and the\n * block/unblock action should not be acted on.\n */\n isCheckingBlockedStatus: boolean\n isLeaving: boolean\n isUpdatingBlockStatus: boolean\n handleLeaveConversation: () => Promise<void>\n handleBlockUser: () => Promise<void>\n handleUnblockUser: () => Promise<void>\n handleReportUser: () => void\n}\n\n/**\n * Encapsulates the conversation moderation actions (leave/delete, block,\n * unblock, report) shared by the channel info dialog and the channel actions\n * popover menu. Keeping the logic in one place ensures both surfaces stay in\n * sync.\n */\nexport const useChannelModerationActions = ({\n channel,\n participant,\n showBlockParticipant = true,\n enabled = true,\n onLeaveConversation,\n onBlockParticipant,\n onDeleteConversationClick,\n onBlockParticipantClick,\n onReportParticipantClick,\n onActionComplete,\n logLabel = 'useChannelModerationActions',\n}: UseChannelModerationActionsParams): ChannelModerationActions => {\n const { service, debug } = useMessagingContext()\n const participantId = participant?.user?.id\n const willLookup = Boolean(\n enabled && showBlockParticipant && service && participantId\n )\n\n const [isParticipantBlocked, setIsParticipantBlocked] = useState(false)\n // Tracks the participant + service the most recent lookup has completed\n // for. Keying on both so a service swap (e.g. MessagingProvider rebuilding\n // its StreamChatService when config/apiKey/debug changes) re-triggers the\n // loading state for the same participant — otherwise the menu would\n // briefly show actionable Block/Unblock against the new service with the\n // old service's blocked result. Computing the flag at render time — rather\n // than from a useState updated inside useEffect — also closes the brief\n // window where the menu would render the regular (enabled) Block button\n // before the effect flipped the disabled placeholder on.\n const [resolvedFor, setResolvedFor] = useState<{\n participantId: string\n service: unknown\n } | null>(null)\n const [isLeaving, setIsLeaving] = useState(false)\n const [isUpdatingBlockStatus, setIsUpdatingBlockStatus] = useState(false)\n\n const isCheckingBlockedStatus =\n willLookup &&\n (resolvedFor?.participantId !== participantId ||\n resolvedFor?.service !== service)\n\n // Resolve whether the participant is blocked whenever the participant or\n // surface visibility changes.\n useEffect(() => {\n // When the lookup is skipped (Block action hidden, surface disabled, or no\n // participant), clear any stale blocked state so a previous participant's\n // value can't leak into the next conversation.\n if (!willLookup || !service || !participantId) {\n setIsParticipantBlocked(false)\n setResolvedFor(null)\n return\n }\n\n let cancelled = false\n\n void (async () => {\n try {\n const blockedUsers = await service.getBlockedUsers()\n if (cancelled) return\n setIsParticipantBlocked(\n blockedUsers.some(\n (user: BlockedUser) => user.blocked_user_id === participantId\n )\n )\n } catch (error) {\n if (!cancelled) {\n console.error(`[${logLabel}] Failed to check blocked status:`, error)\n }\n } finally {\n // Mark the lookup as resolved regardless of success/failure so a\n // rejected `getBlockedUsers()` doesn't leave the menu stuck in the\n // disabled-spinner state. On failure the blocked flag stays at its\n // default (false), matching the prior behavior — the user can attempt\n // to block/unblock and the server rejects if the state is wrong.\n if (!cancelled) setResolvedFor({ participantId, service })\n }\n })()\n\n // Ignore an in-flight result if the participant/surface changes first.\n return () => {\n cancelled = true\n }\n }, [willLookup, service, participantId, logLabel])\n\n const handleLeaveConversation = async () => {\n if (isLeaving) return\n\n // Fire analytics callback before action\n onDeleteConversationClick?.()\n\n if (debug) {\n console.log(`[${logLabel}] Leave conversation`, channel.cid)\n }\n setIsLeaving(true)\n\n try {\n const actingUserId = channel._client?.userID ?? null\n await channel.hide(actingUserId, false)\n\n if (onLeaveConversation) {\n await onLeaveConversation(channel)\n }\n\n onActionComplete?.()\n } catch (error) {\n console.error(`[${logLabel}] Failed to leave conversation`, error)\n } finally {\n setIsLeaving(false)\n }\n }\n\n const handleBlockUser = async () => {\n if (isUpdatingBlockStatus || !service) return\n\n // Fire analytics callback before action\n onBlockParticipantClick?.()\n\n if (debug) {\n console.log(`[${logLabel}] Block member`, participant?.user?.id)\n }\n setIsUpdatingBlockStatus(true)\n\n try {\n await service.blockUser(participant?.user?.id)\n\n if (onBlockParticipant) {\n await onBlockParticipant(participant?.user?.id)\n }\n\n onActionComplete?.()\n } catch (error) {\n console.error(`[${logLabel}] Failed to block member`, error)\n } finally {\n setIsUpdatingBlockStatus(false)\n }\n }\n\n const handleUnblockUser = async () => {\n if (isUpdatingBlockStatus || !service) return\n\n // Fire analytics callback before action\n onBlockParticipantClick?.()\n\n if (debug) {\n console.log(`[${logLabel}] Unblock member`, participant?.user?.id)\n }\n setIsUpdatingBlockStatus(true)\n\n try {\n await service.unBlockUser(participant?.user?.id)\n\n if (onBlockParticipant) {\n await onBlockParticipant(participant?.user?.id)\n }\n\n onActionComplete?.()\n } catch (error) {\n console.error(`[${logLabel}] Failed to unblock member`, error)\n } finally {\n setIsUpdatingBlockStatus(false)\n }\n }\n\n const handleReportUser = () => {\n // Fire analytics callback before action\n onReportParticipantClick?.()\n\n onActionComplete?.()\n window.open(REPORT_URL, '_blank', 'noopener,noreferrer')\n }\n\n return {\n isParticipantBlocked,\n isCheckingBlockedStatus,\n isLeaving,\n isUpdatingBlockStatus,\n handleLeaveConversation,\n handleBlockUser,\n handleUnblockUser,\n handleReportUser,\n }\n}\n","import classNames from \"classnames\";\nimport React from \"react\";\n\nexport interface ActionButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n variant?: \"default\" | \"danger\";\n}\n\nconst ActionButton = ({\n variant = \"default\",\n className,\n children,\n ...rest\n}: ActionButtonProps) => {\n const isDanger = variant === \"danger\";\n return (\n <button\n type=\"button\"\n className={classNames(\n \"flex w-full items-center gap-3 rounded-lg px-4 py-3 text-left text-sm transition-colors focus-ring disabled:cursor-not-allowed disabled:opacity-60\",\n isDanger\n ? \"text-danger hover:bg-danger/50\"\n : \"text-charcoal hover:bg-sand\",\n className,\n )}\n {...rest}\n >\n {children}\n </button>\n );\n};\n\nexport default ActionButton;\n","import {\n DotsThreeIcon,\n FlagIcon,\n ProhibitInsetIcon,\n SignOutIcon,\n SpinnerGapIcon,\n} from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React, { useCallback, useEffect, useId, useRef, useState } from 'react'\nimport type { Channel as ChannelType, ChannelMemberResponse } from 'stream-chat'\n\nimport { useChannelModerationActions } from '../../hooks/useChannelModerationActions'\nimport ActionButton from '../ActionButton'\n\nexport interface ChannelActionsMenuProps {\n channel: ChannelType\n participant: ChannelMemberResponse | undefined\n showDeleteConversation?: boolean\n /**\n * Show the Block/Unblock action. Defaults to true.\n * Set false to hide it (e.g. the Linktree official channel).\n */\n showBlockParticipant?: boolean\n /**\n * Show the Report action. Defaults to true.\n * Set false to hide it (e.g. the Linktree official channel).\n */\n showReportParticipant?: boolean\n onLeaveConversation?: (channel: ChannelType) => void\n onBlockParticipant?: (participantId?: string) => void\n onDeleteConversationClick?: () => void\n onBlockParticipantClick?: () => void\n onReportParticipantClick?: () => void\n customChannelActions?: React.ReactNode\n /** Classes applied to the trigger (\"...\") button so it matches the header. */\n triggerClassName?: string\n}\n\n/**\n * Conversation overflow (\"...\") menu rendered as an anchored popover.\n *\n * Replaces the slide-in sidebar dialog for moderation actions: the trigger\n * opens a small popover that lists the available options (delete, block,\n * report) inline with their icons.\n */\nexport const ChannelActionsMenu: React.FC<ChannelActionsMenuProps> = ({\n channel,\n participant,\n showDeleteConversation = true,\n showBlockParticipant = true,\n showReportParticipant = true,\n onLeaveConversation,\n onBlockParticipant,\n onDeleteConversationClick,\n onBlockParticipantClick,\n onReportParticipantClick,\n customChannelActions,\n triggerClassName,\n}) => {\n const [isOpen, setIsOpen] = useState(false)\n const containerRef = useRef<HTMLDivElement>(null)\n const menuId = useId()\n\n const close = useCallback(() => setIsOpen(false), [])\n\n const {\n isParticipantBlocked,\n isCheckingBlockedStatus,\n isLeaving,\n isUpdatingBlockStatus,\n handleLeaveConversation,\n handleBlockUser,\n handleUnblockUser,\n handleReportUser,\n } = useChannelModerationActions({\n channel,\n participant,\n showBlockParticipant,\n enabled: isOpen,\n onLeaveConversation,\n onBlockParticipant,\n onDeleteConversationClick,\n onBlockParticipantClick,\n onReportParticipantClick,\n onActionComplete: close,\n logLabel: 'ChannelActionsMenu',\n })\n\n // Close the popover on outside click or Escape.\n useEffect(() => {\n if (!isOpen) return\n\n const handlePointerDown = (event: MouseEvent) => {\n if (\n containerRef.current &&\n !containerRef.current.contains(event.target as Node)\n ) {\n setIsOpen(false)\n }\n }\n\n const handleKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n setIsOpen(false)\n }\n }\n\n document.addEventListener('mousedown', handlePointerDown)\n document.addEventListener('keydown', handleKeyDown)\n\n return () => {\n document.removeEventListener('mousedown', handlePointerDown)\n document.removeEventListener('keydown', handleKeyDown)\n }\n }, [isOpen])\n\n if (!participant) return null\n\n const hasActions =\n showDeleteConversation ||\n showBlockParticipant ||\n showReportParticipant ||\n Boolean(customChannelActions)\n\n if (!hasActions) return null\n\n return (\n <div ref={containerRef} className=\"relative\">\n <button\n className={triggerClassName}\n type=\"button\"\n aria-haspopup=\"true\"\n aria-expanded={isOpen}\n aria-controls={isOpen ? menuId : undefined}\n onClick={() => setIsOpen((open) => !open)}\n >\n <DotsThreeIcon className=\"size-5 text-black/90\" />\n <span className=\"sr-only\">More options</span>\n </button>\n\n {isOpen && (\n <div\n id={menuId}\n aria-label=\"Conversation options\"\n className={classNames(\n 'absolute right-0 top-full z-50 mt-2 w-56 overflow-hidden',\n 'rounded-lg border border-sand bg-white p-1 shadow-max-elevation-light'\n )}\n >\n <ul className=\"flex flex-col gap-1\">\n {showDeleteConversation && (\n <li>\n <ActionButton\n onClick={handleLeaveConversation}\n disabled={isLeaving}\n aria-busy={isLeaving}\n >\n {isLeaving ? (\n <SpinnerGapIcon className=\"h-5 w-5 animate-spin\" />\n ) : (\n <SignOutIcon className=\"h-5 w-5\" />\n )}\n <span>Delete Conversation</span>\n </ActionButton>\n </li>\n )}\n {showBlockParticipant && (\n <li>\n {isCheckingBlockedStatus ? (\n // Block status not yet resolved — show a disabled placeholder\n // so a premature click can't act on a stale block state.\n <ActionButton disabled aria-busy>\n <SpinnerGapIcon className=\"h-5 w-5 animate-spin\" />\n <span>Block</span>\n </ActionButton>\n ) : isParticipantBlocked ? (\n <ActionButton\n onClick={handleUnblockUser}\n disabled={isUpdatingBlockStatus}\n aria-busy={isUpdatingBlockStatus}\n >\n {isUpdatingBlockStatus ? (\n <SpinnerGapIcon className=\"h-5 w-5 animate-spin\" />\n ) : (\n <ProhibitInsetIcon className=\"h-5 w-5\" />\n )}\n <span>Unblock</span>\n </ActionButton>\n ) : (\n <ActionButton\n onClick={handleBlockUser}\n disabled={isUpdatingBlockStatus}\n aria-busy={isUpdatingBlockStatus}\n >\n {isUpdatingBlockStatus ? (\n <SpinnerGapIcon className=\"h-5 w-5 animate-spin\" />\n ) : (\n <ProhibitInsetIcon className=\"h-5 w-5\" />\n )}\n <span>Block</span>\n </ActionButton>\n )}\n </li>\n )}\n {showReportParticipant && (\n <li>\n <ActionButton variant=\"danger\" onClick={handleReportUser}>\n <FlagIcon className=\"h-5 w-5\" />\n <span>Report</span>\n </ActionButton>\n </li>\n )}\n {customChannelActions}\n </ul>\n </div>\n )}\n </div>\n )\n}\n\nexport default ChannelActionsMenu\n","import {\n ArrowLeftIcon,\n CaretRightIcon,\n CurrencyDollarIcon,\n StarIcon,\n} from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React from 'react'\nimport type { Channel as ChannelType } from 'stream-chat'\nimport { useChannelStateContext, useChatContext } from 'stream-chat-react'\n\nimport { useChannelStar } from '../hooks/useChannelStar'\nimport { resolveConversationParticipant } from '../utils/resolveConversationParticipant'\nimport { resolveParticipantDisplayName } from '../utils/resolveParticipantDisplayName'\n\nimport { Avatar } from './Avatar'\nimport { ChannelActionsMenu } from './ChannelActionsMenu'\n\nconst ICON_BTN_CLASS =\n 'flex size-10 flex-shrink-0 items-center justify-center rounded-full bg-white/65 shadow-[0px_4px_8px_0px_rgba(0,0,0,0.06),0px_0px_0px_1px_rgba(0,0,0,0.04)] backdrop-blur-[40px] transition-filter duration-150 hover:brightness-95 aria-expanded:brightness-95 focus-ring'\n\nconst CUSTOMER_PAID_TAG = 'CUSTOMER_PAID'\n\nconst isCustomerPaidTag = (value: unknown) =>\n typeof value === 'string' &&\n value\n .trim()\n .replace(/[\\s-]+/g, '_')\n .toUpperCase() === CUSTOMER_PAID_TAG\n\ninterface ChannelHeaderRedesignProps {\n className?: string\n onBack?: () => void\n showBackButton: boolean\n showStarButton?: boolean\n onLeaveConversation?: (channel: ChannelType) => void\n onBlockParticipant?: (participantId?: string) => void\n showDeleteConversation?: boolean\n showBlockParticipant?: boolean\n showReportParticipant?: boolean\n onDeleteConversationClick?: () => void\n onBlockParticipantClick?: () => void\n onReportParticipantClick?: () => void\n customChannelActions?: React.ReactNode\n renderChannelActions?: React.ReactNode\n showChannelInfo?: boolean\n onParticipantNameClick?: () => void\n}\n\nexport const ChannelHeaderRedesign: React.FC<ChannelHeaderRedesignProps> = ({\n className,\n onBack,\n showBackButton,\n showStarButton = false,\n onLeaveConversation,\n onBlockParticipant,\n showDeleteConversation = true,\n showBlockParticipant = true,\n showReportParticipant = true,\n onDeleteConversationClick,\n onBlockParticipantClick,\n onReportParticipantClick,\n customChannelActions,\n renderChannelActions,\n showChannelInfo = true,\n onParticipantNameClick,\n}) => {\n const { channel } = useChannelStateContext()\n const { client } = useChatContext()\n\n const participant = React.useMemo(\n () =>\n resolveConversationParticipant(\n channel.state?.members,\n client?.userID,\n channel.type\n ),\n [channel.state?.members, client?.userID, channel.type]\n )\n\n const participantName = resolveParticipantDisplayName(participant?.user)\n const participantImage = participant?.user?.image\n const isStarred = useChannelStar(channel)\n const isPaidCustomer =\n isCustomerPaidTag(channel.data?.customer_tag) &&\n participant?.is_follower === true\n\n const showStarBadge = showStarButton && isStarred\n const hasNameAdornment =\n isPaidCustomer || showStarBadge || Boolean(onParticipantNameClick)\n\n const handleStarClick = async () => {\n try {\n if (isStarred) {\n await (channel as ChannelType).unpin()\n } else {\n await (channel as ChannelType).pin()\n }\n } catch (error) {\n console.error(\n '[ChannelHeaderRedesign] Failed to update pinned status:',\n error\n )\n }\n }\n\n const identityContent = (\n <>\n <Avatar\n id={participant?.user?.id || channel.id || 'unknown'}\n name={participantName}\n image={participantImage}\n shape=\"circle\"\n size={48}\n className=\"-mb-2\"\n />\n <span\n className={classNames(\n 'relative z-10 flex max-w-full flex-col items-center justify-center rounded-full border border-white/10 bg-white/65 py-1.5 shadow-[0px_0px_0px_0px_rgba(0,0,0,0.04),0px_1px_2px_0px_rgba(0,0,0,0.04),0px_8px_32px_0px_rgba(0,0,0,0.1)] backdrop-blur-[2px] transition-filter duration-150 group-hover:brightness-95',\n hasNameAdornment ? 'pl-3 pr-2' : 'px-3'\n )}\n >\n <span className=\"flex max-w-full items-center justify-center\">\n <span className=\"min-w-0 truncate text-sm font-bold leading-[1.43] tracking-[0.28px] text-black/90\">\n {participantName}\n </span>\n {hasNameAdornment && (\n <span className=\"ml-2 flex gap-1\">\n {isPaidCustomer && (\n <span\n aria-label=\"Paid customer\"\n className=\"flex size-4 shrink-0 items-center justify-center rounded-full bg-[#34C759] text-white\"\n >\n <CurrencyDollarIcon className=\"size-2.5\" weight=\"bold\" />\n </span>\n )}\n {showStarBadge && (\n <span\n aria-label=\"Starred conversation\"\n className=\"flex size-4 shrink-0 items-center justify-center rounded-full bg-[#FFD60A] text-white\"\n >\n <StarIcon className=\"size-2.5\" weight=\"fill\" />\n </span>\n )}\n {onParticipantNameClick && (\n <CaretRightIcon\n aria-hidden=\"true\"\n className=\"size-4 shrink-0 text-black/65\"\n weight=\"bold\"\n />\n )}\n </span>\n )}\n </span>\n </span>\n </>\n )\n\n return (\n <div\n className={classNames(\n '@container bg-[linear-gradient(180deg,#FBFAF9_0%,rgba(251,250,249,0.92)_58%,rgba(251,250,249,0)_100%)]',\n className\n )}\n >\n <div className=\"grid min-h-[100px] grid-cols-[minmax(40px,1fr)_auto_minmax(40px,1fr)] items-start pb-2 pt-5 @lg:min-h-[104px] @lg:pt-6\">\n <div className=\"flex items-start\">\n {showBackButton && (\n <button\n className={classNames(\n ICON_BTN_CLASS,\n 'messaging-channel-view-back-button-mobile messaging-channel-view-back-button-desktop'\n )}\n onClick={onBack || (() => {})}\n type=\"button\"\n aria-label=\"Back to conversations\"\n >\n <ArrowLeftIcon className=\"size-5 text-black/90\" />\n </button>\n )}\n </div>\n\n <div className=\"flex min-w-0 justify-center\" data-dd-privacy=\"mask\">\n {onParticipantNameClick ? (\n <button\n type=\"button\"\n onClick={onParticipantNameClick}\n aria-label={`View details for ${participantName}`}\n className=\"group flex min-w-0 max-w-full appearance-none flex-col items-center border-0 bg-transparent px-2 focus-ring focus-visible:outline-none\"\n >\n {identityContent}\n </button>\n ) : (\n <div className=\"flex min-w-0 max-w-full flex-col items-center px-2\">\n {identityContent}\n </div>\n )}\n </div>\n\n <div className=\"flex items-start justify-end gap-2\">\n {showStarButton && (\n <button\n className={ICON_BTN_CLASS}\n onClick={handleStarClick}\n type=\"button\"\n aria-pressed={isStarred}\n aria-label={\n isStarred ? 'Unstar conversation' : 'Star conversation'\n }\n >\n <StarIcon\n className={classNames('size-5', {\n 'text-[#FFD60A]': isStarred,\n 'text-black/90': !isStarred,\n })}\n weight={isStarred ? 'fill' : 'regular'}\n />\n </button>\n )}\n {showChannelInfo &&\n (renderChannelActions !== undefined ? (\n renderChannelActions\n ) : (\n <ChannelActionsMenu\n channel={channel as ChannelType}\n participant={participant}\n showDeleteConversation={showDeleteConversation}\n showBlockParticipant={showBlockParticipant}\n showReportParticipant={showReportParticipant}\n onLeaveConversation={onLeaveConversation}\n onBlockParticipant={onBlockParticipant}\n onDeleteConversationClick={onDeleteConversationClick}\n onBlockParticipantClick={onBlockParticipantClick}\n onReportParticipantClick={onReportParticipantClick}\n customChannelActions={customChannelActions}\n triggerClassName={ICON_BTN_CLASS}\n />\n ))}\n </div>\n </div>\n </div>\n )\n}\n","import { DateSeparator, type DateSeparatorProps } from 'stream-chat-react'\n\nexport const CustomDateSeparator = (props: DateSeparatorProps) => (\n <DateSeparator {...props} position=\"center\" />\n)\n","import { useCallback, useMemo } from 'react'\nimport type { LocalMessage } from 'stream-chat'\nimport { useChannelStateContext, useChatContext } from 'stream-chat-react'\n\nexport type VoteSelection = 'up' | 'down' | null\n\nconst VOTE_UP = 'vote_up'\nconst VOTE_DOWN = 'vote_down'\n\nfunction getVoteFromReactions(\n ownReactions: LocalMessage['own_reactions']\n): VoteSelection {\n if (!ownReactions?.length) return null\n if (ownReactions.some((r) => r.type === VOTE_DOWN)) return 'down'\n if (ownReactions.some((r) => r.type === VOTE_UP)) return 'up'\n return null\n}\n\ninterface UseMessageVoteResult {\n selected: VoteSelection\n voteUp: () => void\n voteDown: () => void\n}\n\n/**\n * Hook that wraps Stream Chat reactions to provide toggle-style\n * upvote/downvote behavior on a message.\n *\n * Uses enforce_unique so sending a new reaction type automatically\n * removes the previous one. Uses skip_push to avoid notifying the\n * Linker on every vote.\n */\nexport function useMessageVote(message: LocalMessage): UseMessageVoteResult {\n const { channel } = useChannelStateContext()\n const { client } = useChatContext('useMessageVote')\n\n const selected = useMemo(\n () => getVoteFromReactions(message.own_reactions),\n [message.own_reactions]\n )\n\n const voteUp = useCallback(async () => {\n if (!client?.userID) return\n try {\n if (selected === 'up') {\n await channel.deleteReaction(message.id, VOTE_UP)\n } else {\n await channel.sendReaction(\n message.id,\n { type: VOTE_UP },\n { enforce_unique: true, skip_push: true }\n )\n }\n } catch {\n // Silently fail — voting is non-critical\n }\n }, [channel, client?.userID, message.id, selected])\n\n const voteDown = useCallback(async () => {\n if (!client?.userID) return\n try {\n if (selected === 'down') {\n await channel.deleteReaction(message.id, VOTE_DOWN)\n } else {\n await channel.sendReaction(\n message.id,\n { type: VOTE_DOWN },\n { enforce_unique: true, skip_push: true }\n )\n }\n } catch {\n // Silently fail — voting is non-critical\n }\n }, [channel, client?.userID, message.id, selected])\n\n return { selected, voteUp, voteDown }\n}\n","import type { LocalMessage } from 'stream-chat'\n\ntype MessageWithI18n = Pick<LocalMessage, 'text'> & {\n i18n?: Record<string, string> | null\n}\n\nexport function normalizeLanguageCode(language?: string): string | undefined {\n const normalized = language?.trim().toLowerCase().split(/[-_]/)[0]\n return normalized || undefined\n}\n\nexport function getMessageDisplayText({\n message,\n viewerLanguage,\n}: {\n message?: MessageWithI18n | null\n viewerLanguage?: string\n}): string | undefined {\n const fallbackText = message?.text\n const normalizedLanguage = normalizeLanguageCode(viewerLanguage)\n\n if (!normalizedLanguage) {\n return fallbackText\n }\n\n return message?.i18n?.[`${normalizedLanguage}_text`] ?? fallbackText\n}\n","const LINKTREE_CDN_HOSTS = ['linktr.ee']\n\nconst ATTACHMENT_IMAGE_SIZE_PRESET = 'messaging-attachment-v1_0'\n\nfunction hostnameFromUrl(url: string): string | null {\n try {\n return new URL(url).hostname.toLowerCase()\n } catch {\n return null\n }\n}\n\nfunction isLinktreeCdnHost(hostname: string): boolean {\n return LINKTREE_CDN_HOSTS.some(\n (host) => hostname === host || hostname.endsWith(`.${host}`)\n )\n}\n\nexport function optimizeMessagingAttachmentUrl(\n url: string | undefined | null\n): string | undefined {\n const trimmed = url?.trim()\n if (!trimmed) return undefined\n\n const hostname = hostnameFromUrl(trimmed)\n if (!hostname || !isLinktreeCdnHost(hostname)) return trimmed\n\n const parsedUrl = new URL(trimmed)\n const isAlreadyMessagingOptimized =\n parsedUrl.searchParams.get('io') === 'true' &&\n parsedUrl.searchParams.get('size') === ATTACHMENT_IMAGE_SIZE_PRESET\n\n if (isAlreadyMessagingOptimized) {\n return trimmed\n }\n\n parsedUrl.searchParams.set('io', 'true')\n parsedUrl.searchParams.set('size', ATTACHMENT_IMAGE_SIZE_PRESET)\n\n return parsedUrl.toString()\n}\n","export type AttachmentSourceType = 'image' | 'audio' | 'video' | 'document'\n\nexport type DocumentIconType =\n | 'pdf'\n | 'doc'\n | 'xls'\n | 'csv'\n | 'ppt'\n | 'zip'\n | 'text'\n | 'markdown'\n | 'generic'\n\nconst DOCUMENT_ICON_PATTERNS: Array<[RegExp, DocumentIconType]> = [\n [/pdf/, 'pdf'],\n [/wordprocessingml|msword|\\.doc/, 'doc'],\n [/spreadsheetml|ms-excel|\\.xls/, 'xls'],\n [/csv/, 'csv'],\n [/presentationml|ms-powerpoint|\\.ppt/, 'ppt'],\n [/zip|x-rar|x-7z|x-tar|x-gzip/, 'zip'],\n [/plain|rtf/, 'text'],\n [/markdown/, 'markdown'],\n]\n\nexport function getSourceType(mimeType: string): AttachmentSourceType {\n if (mimeType.startsWith('video/')) return 'video'\n if (mimeType.startsWith('audio/')) return 'audio'\n if (mimeType.startsWith('image/')) return 'image'\n return 'document'\n}\n\nexport function getDocumentIconType(mimeType: string): DocumentIconType {\n const match = DOCUMENT_ICON_PATTERNS.find(([pattern]) =>\n pattern.test(mimeType)\n )\n return match ? match[1] : 'generic'\n}\n","import {\n FileIcon,\n FileCsvIcon,\n FileDocIcon,\n FileMdIcon,\n FilePdfIcon,\n FilePptIcon,\n FileTextIcon,\n FileXlsIcon,\n FileZipIcon,\n ImageIcon,\n SpeakerHighIcon,\n VideoCameraIcon,\n IconProps,\n} from '@phosphor-icons/react'\nimport React from 'react'\n\nimport { getDocumentIconType, getSourceType } from './mimeType'\nimport type { AttachmentSourceType } from './mimeType'\n\nexport const MEDIA_TYPE_ICON: Record<AttachmentSourceType, React.ElementType> =\n {\n video: VideoCameraIcon,\n audio: SpeakerHighIcon,\n image: ImageIcon,\n document: FileIcon,\n }\n\nconst DOCUMENT_ICON_COMPONENT = {\n pdf: FilePdfIcon,\n doc: FileDocIcon,\n xls: FileXlsIcon,\n csv: FileCsvIcon,\n ppt: FilePptIcon,\n zip: FileZipIcon,\n text: FileTextIcon,\n markdown: FileMdIcon,\n generic: FileIcon,\n} as const\n\nexport function getTypeIcon(mimeType: string): React.ElementType {\n const sourceType = getSourceType(mimeType)\n if (sourceType !== 'document') return MEDIA_TYPE_ICON[sourceType]\n return DOCUMENT_ICON_COMPONENT[getDocumentIconType(mimeType)]\n}\n\n/** Use instead of `<TypeIcon />` where TypeIcon = getTypeIcon(mime) to satisfy react-hooks/static-components. */\nexport function renderTypeIcon(\n mimeType: string,\n props: IconProps\n): React.ReactElement {\n return React.createElement(getTypeIcon(mimeType), props)\n}\n","import { CircleNotchIcon, PauseIcon, PlayIcon } from '@phosphor-icons/react'\nimport React, { useCallback, useEffect, useRef, useState } from 'react'\n\nimport { isDevBuild } from '../../utils/isDevBuild'\n\nimport { renderTypeIcon } from './utils/icons'\nimport { getSourceType } from './utils/mimeType'\n\ntype TouchEventUnion =\n | MouseEvent\n | TouchEvent\n | React.MouseEvent\n | React.TouchEvent\n\n\nconst getClientXFromEvent = (e: TouchEventUnion): number => {\n if ('touches' in e) {\n return e.touches[0]?.clientX ?? e.changedTouches[0]?.clientX ?? 0\n }\n return e.clientX\n}\n\nexport interface MediaPlayerProps {\n source: string\n mimeType: string\n poster?: string\n autoPlay?: boolean\n /** Controlled playing state. When provided, syncs to internal play/pause. */\n playing?: boolean\n loop?: boolean\n controls?: boolean\n showProgress?: boolean\n /** When true, requests muted playback (helps autoplay policies on video). */\n muted?: boolean\n /**\n * When provided, overrides the default click-to-play-toggle behaviour on the\n * player container. The play/pause button (which calls stopPropagation) is\n * unaffected, so inline playback still works.\n */\n onContainerClick?: (e: React.MouseEvent) => void\n}\n\nconst MediaPlayer: React.FC<MediaPlayerProps> = ({\n source,\n mimeType,\n poster,\n autoPlay = false,\n playing: playingProp,\n loop = false,\n controls = true,\n showProgress = false,\n muted = false,\n onContainerClick,\n}) => {\n // --- Derived ---\n const sourceType = getSourceType(mimeType)\n\n // --- Refs ---\n const playerRef = useRef<HTMLMediaElement>(null)\n const trackRef = useRef<HTMLDivElement>(null)\n const rafRef = useRef<number | null>(null)\n const prevPlayingPropRef = useRef(playingProp)\n\n // --- State: playback ---\n const [playing, setPlaying] = useState(autoPlay)\n const [played, setPlayed] = useState(0)\n const [seeking, setSeeking] = useState(false)\n\n // --- State: UI ---\n const [scrubberHovered, setScrubberHovered] = useState(false)\n /** Set when autoplay/play() was rejected so user can start via gesture (no controls UI). */\n const [manualPlayRequired, setManualPlayRequired] = useState(false)\n\n // --- State: loading ---\n const [buffering, setBuffering] = useState(false)\n /** True until the first canPlay fires for the current source — hides controls/spinner behind poster. */\n const [initialLoad, setInitialLoad] = useState(true)\n const [videoAspect, setVideoAspect] = useState<number | null>(null)\n\n // --- Callbacks ---\n const startPlaybackFromGesture = useCallback(() => {\n setManualPlayRequired(false)\n setPlaying(true)\n }, [])\n\n const getFraction = useCallback((e: TouchEventUnion) => {\n const track = trackRef.current\n if (!track) return 0\n const rect = track.getBoundingClientRect()\n return Math.max(\n 0,\n Math.min(1, (getClientXFromEvent(e) - rect.left) / rect.width)\n )\n }, [])\n\n const seekTo = useCallback((fraction: number) => {\n const el = playerRef.current\n if (el && el.duration) el.currentTime = fraction * el.duration\n }, [])\n\n const handleTrackPointerDown = (\n e: React.MouseEvent<HTMLDivElement> | React.TouchEvent<HTMLDivElement>\n ) => {\n e.stopPropagation()\n setSeeking(true)\n const fraction = getFraction(e)\n setPlayed(fraction)\n seekTo(fraction)\n }\n\n // --- Effects ---\n\n // Sync controlled playing prop to internal state\n useEffect(() => {\n if (\n playingProp !== undefined &&\n playingProp !== prevPlayingPropRef.current\n ) {\n prevPlayingPropRef.current = playingProp\n setPlaying(playingProp)\n }\n }, [playingProp])\n\n // RAF-driven progress updates\n useEffect(() => {\n if (!playing) {\n if (rafRef.current !== null) {\n cancelAnimationFrame(rafRef.current)\n rafRef.current = null\n }\n return\n }\n const tick = () => {\n const el = playerRef.current\n if (el && el.duration && !seeking) setPlayed(el.currentTime / el.duration)\n rafRef.current = requestAnimationFrame(tick)\n }\n rafRef.current = requestAnimationFrame(tick)\n return () => {\n if (rafRef.current !== null) cancelAnimationFrame(rafRef.current)\n }\n }, [playing, seeking])\n\n // ReactPlayer v3 uses native HTML media elements and does not support a\n // declarative `playing` prop — playback must be driven imperatively.\n useEffect(() => {\n const el = playerRef.current\n if (!el) return\n if (playing) {\n void el.play().catch((err) => {\n setPlaying(false)\n setManualPlayRequired(true)\n if (isDevBuild()) {\n console.debug('[MediaPlayer] play() failed', err)\n }\n })\n } else {\n el.pause()\n }\n }, [playing])\n\n // Global seeking listeners\n useEffect(() => {\n if (!seeking) return\n const onMove = (e: MouseEvent | TouchEvent) => setPlayed(getFraction(e))\n const onUp = (e: MouseEvent | TouchEvent) => {\n setSeeking(false)\n seekTo(getFraction(e))\n }\n window.addEventListener('mousemove', onMove)\n window.addEventListener('mouseup', onUp)\n window.addEventListener('touchmove', onMove, { passive: true })\n window.addEventListener('touchend', onUp)\n return () => {\n window.removeEventListener('mousemove', onMove)\n window.removeEventListener('mouseup', onUp)\n window.removeEventListener('touchmove', onMove)\n window.removeEventListener('touchend', onUp)\n }\n }, [seeking, getFraction, seekTo])\n\n // --- Derived render values ---\n // Use natural aspect ratio once metadata loads, fall back to 16:9 before then.\n const aspectStyle = videoAspect\n ? { aspectRatio: String(videoAspect) }\n : undefined\n const aspectClass = !videoAspect ? ' aspect-video' : ''\n const scrubberPercent = Math.round(played * 100)\n\n return (\n <div\n role=\"button\"\n tabIndex={0}\n className={`relative cursor-pointer overflow-hidden bg-black ${aspectClass}`}\n style={aspectStyle}\n onClick={(e) => {\n if (onContainerClick) { onContainerClick(e); return }\n if (manualPlayRequired) return\n if (controls) setPlaying((p) => !p)\n }}\n onKeyDown={(e) => {\n if (e.key !== 'Enter' && e.key !== ' ') return\n e.preventDefault()\n if (onContainerClick) { onContainerClick(e as unknown as React.MouseEvent); return }\n if (manualPlayRequired) return\n if (controls) setPlaying((p) => !p)\n }}\n >\n {/* For audio, poster persists as a visual background. For video, hide once loaded. */}\n {poster && (sourceType === 'audio' || initialLoad) && (\n <img\n src={poster}\n alt=\"\"\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n )}\n {!poster && (sourceType === 'audio' || initialLoad) && (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n {renderTypeIcon(mimeType, {\n className: 'size-12 text-black/20',\n weight: 'regular',\n })}\n </div>\n )}\n <div className=\"absolute inset-0\">\n {sourceType === 'audio' ? (\n <audio\n ref={playerRef as React.RefObject<HTMLAudioElement>}\n src={source}\n loop={loop}\n muted={muted}\n style={{ width: '100%', height: '100%' }}\n onLoadStart={() => setBuffering(true)}\n onCanPlay={() => {\n setBuffering(false)\n setInitialLoad(false)\n }}\n onWaiting={() => setBuffering(true)}\n onPlay={() => setManualPlayRequired(false)}\n onEnded={() => {\n if (!loop) {\n setPlaying(false)\n setPlayed(0)\n }\n }}\n >\n <track kind=\"captions\" />\n </audio>\n ) : (\n <video\n ref={playerRef as React.RefObject<HTMLVideoElement>}\n src={source}\n loop={loop}\n muted={muted}\n playsInline\n style={{ width: '100%', height: '100%' }}\n onLoadStart={() => setBuffering(true)}\n onCanPlay={() => {\n setBuffering(false)\n setInitialLoad(false)\n }}\n onWaiting={() => setBuffering(true)}\n onPlay={() => setManualPlayRequired(false)}\n onLoadedMetadata={() => {\n const el = playerRef.current\n if (\n el instanceof HTMLVideoElement &&\n el.videoWidth &&\n el.videoHeight\n ) {\n setVideoAspect(el.videoWidth / el.videoHeight)\n }\n }}\n onEnded={() => {\n if (!loop) {\n setPlaying(false)\n setPlayed(0)\n }\n }}\n >\n <track kind=\"captions\" />\n </video>\n )}\n </div>\n\n {buffering && !manualPlayRequired && (\n <div className=\"absolute inset-0 z-10 flex items-center justify-center\">\n <CircleNotchIcon\n className=\"size-8 animate-spin text-white/80\"\n weight=\"bold\"\n />\n </div>\n )}\n\n {manualPlayRequired && !controls && (\n <div\n className=\"absolute inset-0 z-30 flex cursor-pointer items-center justify-center bg-black/35\"\n role=\"button\"\n tabIndex={0}\n aria-label=\"Play preview\"\n onClick={(e) => {\n e.stopPropagation()\n startPlaybackFromGesture()\n }}\n onKeyDown={(e) => {\n if (e.key !== 'Enter' && e.key !== ' ') return\n e.preventDefault()\n e.stopPropagation()\n startPlaybackFromGesture()\n }}\n >\n <span className=\"flex size-16 items-center justify-center rounded-full bg-white/20 text-white backdrop-blur-sm\">\n <PlayIcon className=\"size-9 translate-x-0.5\" weight=\"fill\" />\n </span>\n </div>\n )}\n\n {showProgress && !controls && (\n <div className=\"absolute inset-x-0 bottom-0 px-3 pb-2.5 pt-6 bg-gradient-to-t from-black/40 to-transparent\">\n <div\n role=\"slider\"\n aria-label=\"Playback position\"\n aria-valuenow={scrubberPercent}\n aria-valuemin={0}\n aria-valuemax={100}\n tabIndex={0}\n ref={trackRef}\n className=\"relative flex h-4 w-full cursor-pointer items-center\"\n onMouseDown={handleTrackPointerDown}\n onTouchStart={handleTrackPointerDown}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => {\n if (e.key === 'ArrowRight') seekTo(Math.min(1, played + 0.05))\n if (e.key === 'ArrowLeft') seekTo(Math.max(0, played - 0.05))\n }}\n >\n <div className=\"w-full overflow-hidden rounded-full bg-white/30 h-1\">\n <div\n className=\"h-full rounded-full bg-white\"\n style={{ width: `${scrubberPercent}%` }}\n />\n </div>\n </div>\n </div>\n )}\n\n {controls && (\n <div className=\"absolute inset-x-0 bottom-0 flex items-center gap-2 bg-gradient-to-t from-black/60 to-transparent px-3 pb-2.5 pt-6 transition-all duration-200\">\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n setPlaying((p) => !p)\n }}\n className=\"shrink-0 text-white\"\n aria-label={playing ? 'Pause' : 'Play'}\n >\n {playing ? (\n <PauseIcon className=\"size-5\" weight=\"fill\" />\n ) : (\n <PlayIcon className=\"size-5 translate-x-px\" weight=\"fill\" />\n )}\n </button>\n\n <div\n role=\"slider\"\n aria-label=\"Playback position\"\n aria-valuenow={scrubberPercent}\n aria-valuemin={0}\n aria-valuemax={100}\n tabIndex={0}\n ref={trackRef}\n className=\"relative flex h-4 w-full cursor-pointer items-center\"\n onMouseDown={handleTrackPointerDown}\n onTouchStart={handleTrackPointerDown}\n onClick={(e) => e.stopPropagation()}\n onMouseEnter={() => setScrubberHovered(true)}\n onMouseLeave={() => setScrubberHovered(false)}\n onKeyDown={(e) => {\n if (e.key === 'ArrowRight') seekTo(Math.min(1, played + 0.05))\n if (e.key === 'ArrowLeft') seekTo(Math.max(0, played - 0.05))\n }}\n >\n <div\n className={`w-full overflow-hidden rounded-full bg-white/30 transition-all duration-200 ${scrubberHovered || seeking ? 'h-1.5' : 'h-1'}`}\n >\n <div\n className=\"h-full rounded-full bg-white\"\n style={{ width: `${scrubberPercent}%` }}\n />\n </div>\n <div\n className={`absolute size-3 -translate-x-1/2 rounded-full bg-white shadow transition-[opacity,transform] duration-200 ${scrubberHovered || seeking ? 'scale-100 opacity-100' : 'scale-0 opacity-0'}`}\n style={{ left: `${scrubberPercent}%` }}\n />\n </div>\n </div>\n )}\n </div>\n )\n}\n\nexport default MediaPlayer\n","import React, { useState } from 'react'\n\nimport { optimizeMessagingAttachmentUrl } from '../../utils/cdnImageUrl'\n\nimport MediaPlayer, { type MediaPlayerProps } from './MediaPlayer'\nimport { renderTypeIcon } from './utils/icons'\nimport { getSourceType } from './utils/mimeType'\n\nexport type AttachmentThumbnailVariant = 'light' | 'dark'\n\nexport interface AttachmentThumbnailProps {\n mimeType: string\n sourceUrl?: string\n thumbnailUrl?: string\n title?: string\n variant: AttachmentThumbnailVariant\n /** Extra props passed to MediaPlayer when source is video or audio. */\n mediaPlayerProps?: Partial<\n Pick<\n MediaPlayerProps,\n 'autoPlay' | 'loop' | 'muted' | 'controls' | 'onContainerClick'\n >\n >\n /**\n * When true (Visitor unlocked image/document), use aspect-video + object-contain fade-in.\n */\n containedImage?: boolean\n}\n\nconst placeholderIconClass = (variant: AttachmentThumbnailVariant) =>\n variant === 'dark' ? 'size-12 text-white/20' : 'size-12 text-black/20'\n\nconst posterShellClass = (variant: AttachmentThumbnailVariant) =>\n variant === 'dark'\n ? 'aspect-video overflow-hidden bg-white/10'\n : 'aspect-video overflow-hidden bg-black/5'\n\n/**\n * Renders the media preview area for attachment cards (LockedAttachment, MediaMessage).\n * Overlays (dim, lock, eye toggle) are composed by the parent.\n */\nconst AttachmentThumbnail: React.FC<AttachmentThumbnailProps> = ({\n mimeType,\n sourceUrl,\n thumbnailUrl,\n title,\n variant,\n mediaPlayerProps,\n containedImage = false,\n}) => {\n const sourceType = getSourceType(mimeType)\n const [sourceReady, setSourceReady] = useState(false)\n const optimizedSourceUrl = optimizeMessagingAttachmentUrl(sourceUrl)\n const optimizedThumbnailUrl = optimizeMessagingAttachmentUrl(thumbnailUrl)\n\n if (sourceUrl && (sourceType === 'video' || sourceType === 'audio')) {\n return (\n <MediaPlayer\n source={sourceUrl}\n mimeType={mimeType}\n poster={optimizedThumbnailUrl}\n controls\n {...mediaPlayerProps}\n />\n )\n }\n\n if (sourceUrl && sourceType === 'image') {\n if (containedImage) {\n return (\n <div className=\"relative aspect-video overflow-hidden bg-black/5\">\n <img\n src={optimizedSourceUrl ?? sourceUrl}\n alt={title ?? ''}\n className={`absolute inset-0 h-full w-full object-contain transition-opacity duration-300 ${sourceReady ? 'opacity-100' : 'opacity-0'}`}\n draggable={false}\n onLoad={() => setSourceReady(true)}\n />\n </div>\n )\n }\n return (\n <img\n src={optimizedSourceUrl ?? sourceUrl}\n alt={title ?? ''}\n className=\"block w-full\"\n draggable={false}\n />\n )\n }\n\n if (sourceUrl && sourceType === 'document') {\n if (thumbnailUrl) {\n if (containedImage) {\n return (\n <div className=\"relative aspect-video overflow-hidden bg-black/5\">\n <img\n src={optimizedThumbnailUrl ?? thumbnailUrl}\n alt={title ?? ''}\n className={`absolute inset-0 h-full w-full object-contain transition-opacity duration-300 ${sourceReady ? 'opacity-100' : 'opacity-0'}`}\n draggable={false}\n onLoad={() => setSourceReady(true)}\n />\n </div>\n )\n }\n return (\n <img\n src={optimizedThumbnailUrl ?? thumbnailUrl}\n alt=\"\"\n className=\"block w-full\"\n draggable={false}\n />\n )\n }\n return (\n <div\n className={`flex aspect-video w-full items-center justify-center ${variant === 'dark' ? 'bg-white/10' : 'bg-black/5'}`}\n >\n {renderTypeIcon(mimeType, {\n className: placeholderIconClass(variant),\n weight: 'regular',\n })}\n </div>\n )\n }\n\n // Poster-only or empty (no sourceUrl)\n if (thumbnailUrl) {\n return (\n <div className={`relative ${posterShellClass(variant)}`}>\n <img\n src={optimizedThumbnailUrl ?? thumbnailUrl}\n alt={title ?? ''}\n draggable={false}\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n </div>\n )\n }\n\n return (\n <div\n className={`flex aspect-video w-full items-center justify-center ${variant === 'dark' ? 'bg-white/10' : 'bg-black/5'}`}\n >\n {renderTypeIcon(mimeType, {\n className: placeholderIconClass(variant),\n weight: 'regular',\n })}\n </div>\n )\n}\n\nexport default AttachmentThumbnail\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport { renderTypeIcon } from './utils/icons'\n\nexport { default as AttachmentThumbnail } from './Thumbnail'\nexport type {\n AttachmentThumbnailProps,\n AttachmentThumbnailVariant,\n} from './Thumbnail'\nexport { default as MediaPlayer } from './MediaPlayer'\nexport type { MediaPlayerProps } from './MediaPlayer'\nexport { renderTypeIcon, getTypeIcon, MEDIA_TYPE_ICON } from './utils/icons'\nexport {\n getSourceType,\n getDocumentIconType,\n type AttachmentSourceType,\n type DocumentIconType,\n} from './utils/mimeType'\n\nexport interface AttachmentCardProps {\n variant: 'light' | 'dark'\n thumbnail: React.ReactNode\n title?: string\n placeholderTitle?: string\n mimeType: string\n detail?: string\n statusBadge?: React.ReactNode\n action?: React.ReactNode\n topLeft?: React.ReactNode\n topRight?: React.ReactNode\n rootRef?: React.Ref<HTMLDivElement>\n 'data-testid'?: string\n}\n\nconst AttachmentCard: React.FC<AttachmentCardProps> = ({\n variant,\n thumbnail,\n title,\n placeholderTitle = 'Attachment title',\n mimeType,\n detail,\n statusBadge,\n action,\n topLeft,\n topRight,\n rootRef,\n 'data-testid': dataTestId,\n}) => {\n const isDark = variant === 'dark'\n const displayTitle = isDark ? (title ?? placeholderTitle) : (title ?? '')\n const titleDimmed = isDark && !title\n\n return (\n <div\n ref={rootRef}\n data-testid={dataTestId}\n className={classNames(\n 'relative w-[280px] select-none overflow-hidden rounded-[24px] shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_4px_8px_rgba(0,0,0,0.06)]',\n isDark ? 'bg-[#1e2330]' : 'bg-white'\n )}\n >\n {topLeft ? (\n <div className=\"pointer-events-auto absolute left-3 top-3 z-50\">{topLeft}</div>\n ) : null}\n {topRight ? (\n <div className=\"pointer-events-auto absolute right-3 top-3 z-50\">{topRight}</div>\n ) : null}\n\n {thumbnail}\n\n <div className=\"px-4 pb-3 pt-3\">\n {displayTitle.trim() !== '' && (\n <p\n className={classNames('mb-0.5 truncate text-base font-medium', {\n 'text-black': !isDark,\n 'text-white/30': isDark && titleDimmed,\n 'text-white': isDark && !titleDimmed,\n })}\n >\n {displayTitle}\n </p>\n )}\n\n <div className=\"flex flex-wrap items-center gap-1\">\n {renderTypeIcon(mimeType, {\n className: classNames(\n 'size-5 shrink-0',\n isDark ? 'text-white/55' : 'text-black/55'\n ),\n weight: 'regular',\n })}\n\n {detail != null && detail !== '' && (\n <span\n className={classNames(\n 'text-xs font-medium',\n isDark ? 'text-white/55' : 'text-black/55'\n )}\n >\n {detail}\n </span>\n )}\n\n {statusBadge}\n </div>\n\n {action}\n </div>\n </div>\n )\n}\n\nexport default AttachmentCard\n","import { CircleNotchIcon, DownloadSimpleIcon, LinkIcon } from '@phosphor-icons/react'\nimport React, { useState } from 'react'\nimport type { Attachment, LocalMessage } from 'stream-chat'\n\nimport { optimizeMessagingAttachmentUrl } from '../../utils/cdnImageUrl'\nimport AttachmentCard, {\n AttachmentThumbnail,\n getSourceType,\n} from '../AttachmentCard'\nimport { Avatar } from '../Avatar'\n\nfunction formatBytes(bytes: number): string {\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n return `${(bytes / (1024 * 1024)).toFixed(1)} MB`\n}\n\nfunction linkCardShellClass(isMyMessage: boolean) {\n const bg = isMyMessage ? 'bg-[#1e2330]' : 'bg-[#F3F3F1]'\n return `w-[280px] select-none overflow-hidden rounded-[24px] ${bg} shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_4px_8px_rgba(0,0,0,0.06)]`\n}\n\nfunction linkThumbnailBg(isMyMessage: boolean) {\n return isMyMessage ? 'bg-white/10' : 'bg-black/5'\n}\n\nfunction linkPrimaryText(isMyMessage: boolean) {\n return isMyMessage ? 'text-white' : 'text-black'\n}\n\nfunction linkSecondaryText(isMyMessage: boolean) {\n return isMyMessage ? 'text-white/55' : 'text-black/55'\n}\n\nfunction linkTertiaryText(isMyMessage: boolean) {\n return isMyMessage ? 'text-white/40' : 'text-black/40'\n}\n\nfunction linkIconColor(isMyMessage: boolean) {\n return isMyMessage ? 'text-white/20' : 'text-black/20'\n}\n\n/** Link preview (OG) — no download; opens in a new tab. */\nconst LinkCard: React.FC<{\n attachment: Attachment\n isMyMessage: boolean\n}> = ({ attachment, isMyMessage }) => {\n const { title, text, image_url, og_scrape_url, title_link } = attachment\n const rawUrl = og_scrape_url ?? title_link\n const url =\n typeof rawUrl === 'string' && rawUrl.trim() !== '' ? rawUrl : undefined\n\n const body = (\n <React.Fragment>\n <div className=\"p-2\">\n {image_url ? (\n <img\n src={optimizeMessagingAttachmentUrl(image_url) ?? image_url}\n alt={title ?? ''}\n className=\"aspect-video w-full rounded-[20px] object-cover\"\n />\n ) : (\n <div\n className={`aspect-video w-full rounded-[20px] ${linkThumbnailBg(isMyMessage)} flex items-center justify-center`}\n >\n <LinkIcon className={`size-12 ${linkIconColor(isMyMessage)}`} />\n </div>\n )}\n </div>\n <div className=\"px-3 pb-3\">\n {title && (\n <p className={`truncate text-[14px] font-medium leading-5 ${linkPrimaryText(isMyMessage)}`}>\n {title}\n </p>\n )}\n {text && (\n <p className={`truncate text-[12px] leading-4 ${linkSecondaryText(isMyMessage)}`}>{text}</p>\n )}\n {url && (\n <p className={`mt-1 truncate text-[12px] leading-4 ${linkTertiaryText(isMyMessage)}`}>\n {url}\n </p>\n )}\n </div>\n </React.Fragment>\n )\n\n if (url) {\n return (\n <a href={url} target=\"_blank\" rel=\"noopener noreferrer\" className=\"block no-underline\">\n {body}\n </a>\n )\n }\n\n return <div className=\"block\">{body}</div>\n}\n\nexport function isLinkAttachment(a: Attachment): boolean {\n return a.type === 'link' || (!!a.og_scrape_url && !a.asset_url)\n}\n\nexport function resolveLinkAttachment(\n message: LocalMessage\n): Attachment | undefined {\n return message.attachments?.find(isLinkAttachment)\n}\n\nasync function triggerDownload(url: string, filename?: string): Promise<void> {\n let name: string\n try { name = filename ?? new URL(url).pathname.split('/').pop() ?? 'download' }\n catch { name = filename ?? 'download' }\n const res = await fetch(url, { mode: 'cors' })\n if (!res.ok) throw new Error(`HTTP ${res.status}`)\n const blob = await res.blob()\n const objectUrl = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = objectUrl\n a.download = name\n a.style.display = 'none'\n document.body.appendChild(a)\n a.click()\n document.body.removeChild(a)\n URL.revokeObjectURL(objectUrl)\n}\n\nconst DownloadAction: React.FC<{ url: string; filename?: string }> = ({\n url,\n filename,\n}) => {\n const [busy, setBusy] = useState(false)\n\n const handleClick = (e: React.MouseEvent) => {\n e.stopPropagation()\n const fallback = window.open('', '_blank', 'noopener,noreferrer')\n setBusy(true)\n triggerDownload(url, filename)\n .then(() => { fallback?.close() })\n .catch(() => { if (fallback) fallback.location.href = url })\n .finally(() => setBusy(false))\n }\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={busy}\n className=\"mt-3 inline-flex h-10 w-full items-center justify-center gap-2 rounded-full bg-[#121110] px-4 text-sm font-medium leading-none text-white hover:bg-[#2a2928] disabled:opacity-70\"\n >\n {busy ? (\n <CircleNotchIcon className=\"size-4 animate-spin text-white\" weight=\"bold\" />\n ) : (\n <React.Fragment>\n <DownloadSimpleIcon className=\"size-4 text-white\" weight=\"bold\" />\n Download\n </React.Fragment>\n )}\n </button>\n )\n}\n\nexport interface MediaMessageResolved {\n resolvedUrl: string\n resolvedType: string\n title?: string\n fileSize?: number\n thumbnailUrl?: string\n}\n\nexport function resolveMediaFromMessage(\n message: LocalMessage\n): MediaMessageResolved | null {\n const videoAttachment = message.attachments?.find(\n (a) => a.type === 'video' && a.asset_url\n )\n const imageAttachment = message.attachments?.find(\n (a) => a.type === 'image' && (a as { image_url?: string }).image_url\n )\n const audioAttachment = message.attachments?.find(\n (a) => a.type === 'audio' && a.asset_url\n )\n const fileAttachment = message.attachments?.find(\n (a) => a.type === 'file' && a.asset_url\n )\n\n const activeAttachment =\n videoAttachment ?? imageAttachment ?? audioAttachment ?? fileAttachment\n\n const resolvedUrl =\n videoAttachment?.asset_url ??\n (imageAttachment as { image_url?: string } | undefined)?.image_url ??\n audioAttachment?.asset_url ??\n fileAttachment?.asset_url\n\n if (!resolvedUrl) return null\n\n const resolvedType =\n activeAttachment?.mime_type ??\n (activeAttachment?.type === 'image'\n ? 'image/jpeg'\n : activeAttachment?.type === 'video'\n ? 'video/mp4'\n : activeAttachment?.type === 'audio'\n ? 'audio/mpeg'\n : 'application/octet-stream')\n\n const title = (activeAttachment as { title?: string } | undefined)?.title\n const fileSize = (activeAttachment as { file_size?: number } | undefined)?.file_size\n const thumbnailUrl = (videoAttachment as { thumb_url?: string } | undefined)?.thumb_url\n\n return {\n resolvedUrl,\n resolvedType,\n title,\n fileSize,\n thumbnailUrl,\n }\n}\n\n/** Dark card (sent / own message) — matches LockedAttachment.Sent preview without toggle. */\nconst Creator: React.FC<MediaMessageResolved> = ({\n resolvedUrl,\n resolvedType,\n title,\n fileSize,\n thumbnailUrl,\n}) => {\n const detail = fileSize !== undefined ? formatBytes(fileSize) : undefined\n\n return (\n <AttachmentCard\n variant=\"dark\"\n title={title}\n placeholderTitle=\"\"\n mimeType={resolvedType}\n detail={detail}\n thumbnail={\n <AttachmentThumbnail\n mimeType={resolvedType}\n sourceUrl={resolvedUrl}\n thumbnailUrl={thumbnailUrl}\n title={title}\n variant=\"dark\"\n />\n }\n />\n )\n}\n\n/** Light card (received) — matches LockedAttachment.Received unlocked without Purchased copy. */\nconst Visitor: React.FC<MediaMessageResolved> = ({\n resolvedUrl,\n resolvedType,\n title,\n fileSize,\n thumbnailUrl,\n}) => {\n const sourceType = getSourceType(resolvedType)\n const detail = fileSize !== undefined ? formatBytes(fileSize) : undefined\n\n return (\n <AttachmentCard\n variant=\"light\"\n title={title}\n mimeType={resolvedType}\n detail={detail}\n thumbnail={\n <AttachmentThumbnail\n mimeType={resolvedType}\n sourceUrl={resolvedUrl}\n thumbnailUrl={thumbnailUrl}\n title={title}\n variant=\"light\"\n containedImage={sourceType === 'image' || sourceType === 'document'}\n />\n }\n action={<DownloadAction url={resolvedUrl} filename={title} />}\n />\n )\n}\n\nexport interface MediaMessageProps {\n message: LocalMessage\n isMyMessage?: boolean\n}\n\n/**\n * @deprecated Slated for removal once the profile repo is migrated to\n * `LinkAttachment` (and its forthcoming media-only Attachment variants).\n * New consumers should reach for `LinkAttachment.Composer`,\n * `LinkAttachment.Sent`, or `LinkAttachment.Received` instead.\n */\nconst MediaMessageRoot: React.FC<MediaMessageProps> = ({\n message,\n isMyMessage = false,\n}) => {\n const linkAttachment = resolveLinkAttachment(message)\n const resolved = resolveMediaFromMessage(message)\n if (!linkAttachment && !resolved) return null\n\n const messageClass = isMyMessage\n ? 'str-chat__message str-chat__message-simple str-chat__message--me str-chat__message-simple--me'\n : 'str-chat__message str-chat__message-simple str-chat__message--other'\n\n return (\n <div className={messageClass} data-dd-privacy=\"mask\">\n {!isMyMessage && message.user && (\n <Avatar\n className=\"str-chat__avatar str-chat__message-sender-avatar\"\n id={message.user.id}\n image={message.user.image}\n name={message.user.name ?? message.user.id}\n />\n )}\n <div\n className=\"str-chat__message-inner\"\n style={{ marginInlineEnd: 0, marginInlineStart: 0 }}\n >\n <div className=\"str-chat__message-bubble-wrapper\">\n <div\n className=\"str-chat__message-bubble\"\n // The visible child is a self-contained AttachmentCard (white /\n // #1e2330 card with its own shadow + radius), not a speech\n // bubble, and this wrapper is transparent. Mark it so the\n // received/sent tail in `styles.css` skips it — otherwise a\n // tail tinted from the text-bubble surface (#f2f1ef) hangs off\n // a white card and reads as a detached grey nub.\n data-attachment-bubble=\"true\"\n style={{ padding: 0, borderRadius: 0, overflow: 'visible', background: 'transparent' }}\n >\n {linkAttachment ? (\n <div className={linkCardShellClass(isMyMessage)}>\n <LinkCard attachment={linkAttachment} isMyMessage={isMyMessage} />\n </div>\n ) : isMyMessage ? (\n <Creator {...resolved!} />\n ) : (\n <Visitor {...resolved!} />\n )}\n </div>\n </div>\n </div>\n </div>\n )\n}\n\nconst MediaMessageCreatorEntry: React.FC<{ message: LocalMessage }> = ({\n message,\n}) => {\n const linkAttachment = resolveLinkAttachment(message)\n if (linkAttachment) {\n return (\n <div className={linkCardShellClass(true)} data-dd-privacy=\"mask\">\n <LinkCard attachment={linkAttachment} isMyMessage={true} />\n </div>\n )\n }\n const resolved = resolveMediaFromMessage(message)\n if (!resolved) return null\n return (\n <div style={{ display: 'contents' }} data-dd-privacy=\"mask\">\n <Creator {...resolved} />\n </div>\n )\n}\n\nconst MediaMessageVisitorEntry: React.FC<{ message: LocalMessage }> = ({\n message,\n}) => {\n const linkAttachment = resolveLinkAttachment(message)\n if (linkAttachment) {\n return (\n <div className={linkCardShellClass(false)} data-dd-privacy=\"mask\">\n <LinkCard attachment={linkAttachment} isMyMessage={false} />\n </div>\n )\n }\n const resolved = resolveMediaFromMessage(message)\n if (!resolved) return null\n return (\n <div style={{ display: 'contents' }} data-dd-privacy=\"mask\">\n <Visitor {...resolved} />\n </div>\n )\n}\n\nexport const MediaMessage = Object.assign(MediaMessageRoot, {\n Creator: MediaMessageCreatorEntry,\n Visitor: MediaMessageVisitorEntry,\n})\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport type { BubbleGroupPosition, BubbleVariant } from '../types'\n\nexport interface BubbleProps {\n variant: BubbleVariant\n /** Optional message text rendered below the attachment slot. */\n text?: React.ReactNode\n /**\n * Renders a hairline border around the bubble. Defaults to `true` —\n * matches the design system's \"small border around link / message\n * attachments\" treatment from the mobile spec.\n */\n bordered?: boolean\n /**\n * Position of this bubble inside a same-author message run. Drives\n * the corner-flattening that visually merges consecutive bubbles\n * (matches the grouping stream-chat-react applies to text bubbles).\n * Defaults to `'single'` so standalone usage keeps every corner\n * fully rounded.\n */\n groupPosition?: BubbleGroupPosition\n /**\n * Width utility that REPLACES the default `'w-[280px]'`. Supply the\n * whole declaration (`'w-fit'`, `'w-[383px] max-w-full'`) — nothing\n * is merged with the default.\n */\n widthClassName?: string\n /**\n * Padding utility that REPLACES the default `'px-2 py-2'`. Supply\n * the full inset (`'p-0.5'`, `'py-5 pl-5 pr-3'`).\n */\n paddingClassName?: string\n /**\n * Corner utility that REPLACES the `groupPosition`-derived corner\n * table entirely. Opting in means opting OUT of same-author corner\n * flattening — the bubble renders the supplied radius on all four\n * corners. That is what the attachment redesign wants: Figma draws\n * media cards at a uniform r20 even when a caption bubble sits 4px\n * below (nodes `1973:12776`, `1973:20239`).\n *\n * It replaces rather than appends because appending cannot be made\n * reliable — an appended `rounded-[20px]` and the corner table have\n * identical CSS specificity, so Tailwind's emitted source order,\n * not argument order, would pick the winner.\n */\n radiusClassName?: string\n className?: string\n children: React.ReactNode\n 'data-testid'?: string\n}\n\n// Colors and metrics tracked from `stream-chat-react`'s default\n// `.str-chat__message-bubble` token set so attachments visually drop\n// into a normal `CustomMessage` thread without any seams:\n// - light → `--str-chat__message-bubble-background-color` in `styles.css` (#f2f1ef)\n// - dark → `.str-chat__message--me` override in `styles.css` (#1e2330)\n// - text padding → `--str-chat__spacing-2 --str-chat__spacing-4` = 8px 16px\n// - border-radius → `--str-chat__border-radius-md` = 18px\n//\n// TODO: migrate to Tailwind theme tokens once they exist for the\n// `linktree.dark` / `linktree.surface.secondary` palette — these hex\n// literals are repeated across LinkAttachment / LockedAttachment /\n// MediaMessage / CustomMessageInput / DownloadAction etc., so a\n// rebrand would need to touch every site. A central token would\n// collapse the migration to one definition.\nconst BUBBLE_BG_BY_VARIANT: Record<BubbleVariant, string> = {\n dark: 'bg-[#1e2330]',\n light: 'bg-[#f2f1ef]',\n}\n\nconst BUBBLE_TEXT_BY_VARIANT: Record<BubbleVariant, string> = {\n dark: 'text-white',\n light: 'text-[#000000]',\n}\n\nconst BUBBLE_BORDER_BY_VARIANT: Record<BubbleVariant, string> = {\n dark: 'border-white/[0.08]',\n light: 'border-black/[0.08]',\n}\n\n/**\n * Per-corner rounding tables that mirror stream-chat-react's default\n * bubble grouping. Sender bubbles cluster against the right edge so\n * the right corners get flattened in a run; receiver bubbles cluster\n * against the left edge so the left corners get flattened.\n *\n * Rounded corners use `--str-chat__border-radius-md` (18px) and\n * flattened corners use `--str-chat__border-radius-sm` (4px) — same\n * tokens stream's stylesheet uses for `.str-chat__message-bubble`\n * inside a `--first` / `--group` / `--end` wrapper.\n */\ntype BubbleSide = 'sender' | 'receiver'\n\nconst sideForVariant = (variant: BubbleVariant): BubbleSide =>\n variant === 'dark' ? 'sender' : 'receiver'\n\nconst CORNER_CLASSES_BY_SIDE_AND_POSITION: Record<\n BubbleSide,\n Record<BubbleGroupPosition, string>\n> = {\n sender: {\n single:\n 'rounded-tl-[18px] rounded-tr-[18px] rounded-bl-[18px] rounded-br-[18px]',\n first:\n 'rounded-tl-[18px] rounded-tr-[18px] rounded-bl-[18px] rounded-br-[4px]',\n middle:\n 'rounded-tl-[18px] rounded-tr-[4px] rounded-bl-[18px] rounded-br-[4px]',\n end: 'rounded-tl-[18px] rounded-tr-[4px] rounded-bl-[18px] rounded-br-[18px]',\n },\n receiver: {\n single:\n 'rounded-tl-[18px] rounded-tr-[18px] rounded-bl-[18px] rounded-br-[18px]',\n first:\n 'rounded-tl-[18px] rounded-tr-[18px] rounded-bl-[4px] rounded-br-[18px]',\n middle:\n 'rounded-tl-[4px] rounded-tr-[18px] rounded-bl-[4px] rounded-br-[18px]',\n end: 'rounded-tl-[4px] rounded-tr-[18px] rounded-bl-[18px] rounded-br-[18px]',\n },\n}\n\n/**\n * Chat-bubble container shared by every `MessageAttachment.*` card.\n *\n * Holds the attachment slot (image / video / row) and an optional\n * `text` caption rendered below it — mirrors the mobile chat layout\n * where a sender can attach a caption alongside an attachment ('Here\n * is the file', 'Here is the image').\n *\n * Two visual variants:\n * - `dark` — sender-side (Composer / Sent), white text on `#1e2330`.\n * - `light` — recipient-side (Received), dark text on `#f2f1ef`.\n *\n * Background colors, padding, border-radius, and inherited font come\n * from the stream-chat-react `.str-chat__message-bubble` token set so\n * attachments line up with the `CustomMessage` text bubbles in a real\n * conversation. Padding is uniform across every variant — text rows,\n * audio rows, document rows, and media bubbles all get the same\n * 8px / 16px inset, with media inside getting its own rounded corners.\n */\nconst Bubble: React.FC<BubbleProps> = ({\n variant,\n text,\n bordered = true,\n groupPosition = 'single',\n widthClassName = 'w-[280px]',\n paddingClassName = 'px-2 py-2',\n radiusClassName,\n className,\n children,\n 'data-testid': dataTestId,\n}) => {\n const hasText = text != null && text !== ''\n const cornerClasses =\n radiusClassName ??\n CORNER_CLASSES_BY_SIDE_AND_POSITION[sideForVariant(variant)][groupPosition]\n\n return (\n <div\n data-testid={dataTestId}\n data-group-position={groupPosition}\n className={classNames(\n // Defaults describe a 280px-wide document / audio / link\n // bubble: that width matches the mobile chat attachment and\n // the 8px / 16px inset matches `--str-chat__spacing-2\n // --str-chat__spacing-4`, so attachments share the same hit /\n // negative-space rhythm as the surrounding `CustomMessage`\n // text bubbles. Media cards override both — Figma sizes them\n // to the media (330 / 383px) with a 2px frame instead.\n 'relative',\n widthClassName,\n 'overflow-hidden',\n paddingClassName,\n // The caption below owns the bubble's whole bottom inset when\n // it is present, so the container hands it over. Without this\n // the inset is whatever `paddingClassName` happens to supply,\n // which is 2px for the media cards' `p-0.5` frame and leaves\n // caption text sitting on the card edge. Safe to append: this\n // is shorthand-then-longhand (`p-*`/`py-*` then `pb-*`), which\n // Tailwind always emits in that order inside its `padding`\n // plugin — unlike the same-utility `rounded-*` clash above,\n // there is no ambiguity to resolve.\n hasText && 'pb-0',\n cornerClasses,\n BUBBLE_BG_BY_VARIANT[variant],\n BUBBLE_TEXT_BY_VARIANT[variant],\n bordered && 'border',\n bordered && BUBBLE_BORDER_BY_VARIANT[variant],\n className\n )}\n >\n {children}\n\n {hasText ? (\n <p\n className={classNames(\n // No `text-*` / `font-*` overrides here — caption inherits\n // the same font family + size as `.str-chat__message-text`\n // so it matches the surrounding `CustomMessage` bubbles.\n 'whitespace-pre-wrap break-words leading-snug',\n // Owns the full vertical inset: an 8px gutter above (the\n // children render flush against their own bottom edge)\n // and the bubble's 8px bottom inset below, which the\n // container gave up via `pb-0`. Horizontally this stacks\n // on the container's inset so a default bubble's caption\n // lands at the 16px `--str-chat__spacing-4` text inset.\n 'pb-2 pt-2',\n 'px-2'\n )}\n >\n {text}\n </p>\n ) : null}\n </div>\n )\n}\n\nexport default Bubble\n","import { XIcon } from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React from 'react'\n\nexport interface DismissButtonProps {\n onClick: () => void\n /**\n * `'overlay'` — translucent button sitting on top of media (image /\n * video corner). `'inline'` — opaque button placed in the row of a\n * compact attachment alongside other content.\n */\n variant?: 'overlay' | 'inline'\n ariaLabel?: string\n}\n\nconst DismissButton: React.FC<DismissButtonProps> = ({\n onClick,\n variant = 'overlay',\n ariaLabel = 'Dismiss attachment',\n}) => (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n onClick()\n }}\n aria-label={ariaLabel}\n className={classNames(\n 'flex size-6 items-center justify-center rounded-full text-white',\n variant === 'overlay'\n ? 'bg-[#121110]/85 backdrop-blur'\n : 'bg-white/15 hover:bg-white/25'\n )}\n >\n <XIcon className=\"size-3\" weight=\"bold\" />\n </button>\n)\n\nexport default DismissButton\n","import type React from 'react'\n\n/**\n * Three messaging states a `MessageAttachment.*` card can render in,\n * mirroring the LinkAttachment / LockedAttachment families.\n */\nexport type MessageAttachmentState = 'composer' | 'sent' | 'received'\n\n/**\n * Visual variant of the surrounding `Bubble` chrome. Sender-side bubbles\n * (`composer`, `sent`) get the dark treatment; recipient-side bubbles\n * (`received`) get the light treatment.\n */\nexport type BubbleVariant = 'dark' | 'light'\n\n/** Maps a state to the bubble chrome it should render with. */\nexport const bubbleVariantForState = (\n state: MessageAttachmentState\n): BubbleVariant => (state === 'received' ? 'light' : 'dark')\n\n/**\n * Position of a bubble inside a same-author run, mirroring the grouping\n * stream-chat-react applies to consecutive messages from the same user:\n *\n * - `'single'` — standalone message, every corner fully rounded.\n * - `'first'` — first in a 2+ message run; the corner facing the\n * next bubble in the run is flattened.\n * - `'middle'` — both the corner facing the previous bubble and the\n * corner facing the next bubble are flattened.\n * - `'end'` — last in a 2+ message run; the corner facing the\n * previous bubble is flattened (this is also the\n * bubble the avatar attaches to on the receiver side).\n *\n * \"Facing\" is determined by the bubble's side: sender-aligned bubbles\n * cluster against their right edge, receiver-aligned bubbles against\n * their left edge.\n */\nexport type BubbleGroupPosition = 'single' | 'first' | 'middle' | 'end'\n\n/**\n * Convenience adapter that derives the `BubbleGroupPosition` from the\n * three booleans `stream-chat-react` forwards into the `Message` HOC.\n * Drop-in for `useMessageContext()` consumers:\n *\n * ```tsx\n * const { firstOfGroup, endOfGroup, groupedByUser } = useMessageContext()\n * <MessageAttachment.Image.Sent\n * {...props}\n * groupPosition={bubbleGroupPositionFromStream({\n * firstOfGroup, endOfGroup, groupedByUser,\n * })}\n * />\n * ```\n */\nexport const bubbleGroupPositionFromStream = ({\n firstOfGroup,\n endOfGroup,\n groupedByUser,\n}: {\n firstOfGroup?: boolean\n endOfGroup?: boolean\n groupedByUser?: boolean\n}): BubbleGroupPosition => {\n if (!groupedByUser) return 'single'\n if (firstOfGroup && endOfGroup) return 'single'\n if (firstOfGroup) return 'first'\n if (endOfGroup) return 'end'\n return 'middle'\n}\n\n/** Loading hint forwarded to the underlying `<img>` element. */\nexport type ImageLoadingMode = 'lazy' | 'eager'\n\n/** Preload hint forwarded to the underlying `<video>` / `<audio>` element. */\nexport type MediaPreloadMode = 'none' | 'metadata' | 'auto'\n\n/** A single image inside an Image attachment (single or stacked). */\nexport interface ImageItem {\n src: string\n alt?: string\n /** Optional width/height hint — preserved aspect on cover-fit. */\n width?: number\n height?: number\n /**\n * Per-tile native lazy-load override. Defaults to the parent\n * attachment's `loading` value (which itself defaults to `'lazy'`).\n * Pass `'eager'` for above-the-fold hero tiles.\n */\n loading?: ImageLoadingMode\n}\n\n/** A single video inside a Video attachment (single or stacked). */\nexport interface VideoItem {\n src: string\n /** Poster / thumbnail rendered before playback starts. */\n poster?: string\n /** Optional MIME type (e.g. `video/mp4`). */\n mimeType?: string\n /**\n * Per-item override for the `<video preload>` hint. Defaults to the\n * parent attachment's `preload` value (which itself defaults to\n * `'none'` so the poster carries the visual weight and no video\n * bytes are fetched until playback).\n */\n preload?: MediaPreloadMode\n}\n\n/** A single PDF inside a Pdf attachment (single or stacked). */\nexport interface PdfItem {\n src: string\n /** Filename — drives the row title + the meta line + the viewer dialog's accessible name. */\n filename?: string\n /** File size in bytes — formatted into the `EXT · SIZE` meta line. */\n fileSize?: number\n /** Override displayed title. Defaults to `filename`. */\n title?: string\n}\n\n/** A single audio file inside an Audio attachment (single or stacked). */\nexport interface AudioItem {\n src: string\n /** MIME type hint — typed onto the inline `<source>` element. */\n mimeType?: string\n /**\n * Filename — used as the download default name (consumed by the\n * native player's kebab menu).\n */\n filename?: string\n /**\n * Per-track override for the `<audio preload>` hint. Defaults to\n * the parent attachment's `preload` value, which itself defaults\n * to `'metadata'` for a single audio (so the native player can\n * surface duration immediately) and `'none'` for a stacked thread\n * (so a fan-out of metadata requests doesn't happen on first paint).\n */\n preload?: MediaPreloadMode\n}\n\n/** A single generic file inside a File attachment (single or stacked). */\nexport interface FileItem {\n src: string\n /** Filename — drives the title + the meta line + the download default name. */\n filename?: string\n /** File size in bytes — formatted into the `EXT · SIZE` meta line. */\n fileSize?: number\n /** MIME type — drives the type icon. Defaults to `application/octet-stream`. */\n mimeType?: string\n /** Override displayed title. Defaults to `filename`. */\n title?: string\n}\n\n/** Shared props every `MessageAttachment.*.{Composer|Sent|Received}` accepts. */\nexport interface MessageAttachmentBaseProps {\n /**\n * Optional text rendered below the attachment inside the same bubble.\n * Mirrors the chat behavior in the mobile screenshots — `'Here is the\n * file'`, `'Here is the image'`, etc.\n */\n text?: React.ReactNode\n /**\n * Position of this attachment inside a same-author message run —\n * mirrors the corner-flattening stream-chat-react applies to text\n * bubbles in a clustered conversation. Defaults to `'single'`, so\n * standalone usage keeps every corner rounded. Pass the value\n * derived from `bubbleGroupPositionFromStream({ firstOfGroup,\n * endOfGroup, groupedByUser })` when rendering inside a real\n * `CustomMessage` thread to make the attachment visually merge\n * with adjacent bubbles. Image / Video Composer ignore this — the\n * draft preview renders bare without the surrounding bubble.\n */\n groupPosition?: BubbleGroupPosition\n}\n\n/** Shared props for the `Composer` state of every attachment type. */\nexport interface ComposerExtras {\n /** Renders a dismiss `×` button overlaid on the attachment. */\n onDismiss?: () => void\n}\n","import React from 'react'\n\nimport Bubble from '../_shared/Bubble'\nimport DismissButton from '../_shared/DismissButton'\nimport {\n bubbleVariantForState,\n type AudioItem,\n type ComposerExtras,\n type MediaPreloadMode,\n type MessageAttachmentBaseProps,\n type MessageAttachmentState,\n} from '../types'\n\nexport interface AudioAttachmentSharedProps extends MessageAttachmentBaseProps {\n /** Audio source URL (`mp3`, `aac`, `wav`, …). */\n src?: string\n /** MIME type hint — typed onto the inline `<source>` element. */\n mimeType?: string\n /**\n * Filename — used as the download default name (consumed by the\n * native player's kebab menu). The HTML `<audio>` element doesn't\n * expose a built-in title slot, so we don't render the filename\n * inside the bubble itself.\n */\n filename?: string\n /**\n * Stacked audio. Takes precedence over `src` when set. Each item\n * renders its own native `<audio controls>` player, vertically\n * stacked inside the same bubble with an 8px gap between players.\n * Sent + Received only — the composer surface accepts a single\n * attachment at a time.\n */\n items?: AudioItem[]\n /**\n * `<audio preload>` hint applied to every player on the bubble.\n * When omitted, the default depends on the rendered shape:\n *\n * - Single audio (no `items`, or `items.length === 1`) →\n * `'metadata'` so the native player surfaces duration\n * immediately.\n * - Stacked audio (`items.length > 1`) → `'none'` so a thread\n * of voice memos doesn't fan out N parallel metadata requests\n * on first paint.\n *\n * Per-track overrides live on `AudioItem.preload`.\n */\n preload?: MediaPreloadMode\n}\n\nconst resolveItems = ({\n src,\n mimeType,\n filename,\n items,\n}: {\n src?: string\n mimeType?: string\n filename?: string\n items?: AudioItem[]\n}): AudioItem[] => {\n if (items && items.length > 0) return items\n if (src) return [{ src, mimeType, filename }]\n return []\n}\n\nconst NativeAudioPlayer: React.FC<{\n item: AudioItem\n preload: MediaPreloadMode\n trailingAction?: React.ReactNode\n}> = ({ item, preload, trailingAction }) => (\n <div className=\"flex items-center gap-2\">\n {/* No `<track>` is rendered — we don't author caption sidecars\n for chat attachments, and an empty `<track kind=\"captions\" />`\n emits a runtime warning. Re-add a real track (with `src`,\n `srcLang`, and `default`) once caption support actually ships.\n The `jsx-a11y/media-has-caption` rule is suppressed for the\n same reason. */}\n {/* eslint-disable-next-line jsx-a11y/media-has-caption */}\n <audio\n src={item.src}\n controls\n preload={item.preload ?? preload}\n className=\"block min-w-0 flex-1\"\n >\n {item.mimeType ? <source src={item.src} type={item.mimeType} /> : null}\n </audio>\n {trailingAction ?? null}\n </div>\n)\n\ninterface InternalAudioRowProps extends AudioAttachmentSharedProps {\n state: MessageAttachmentState\n onDismiss?: () => void\n}\n\nconst AudioAttachmentRow: React.FC<InternalAudioRowProps> = ({\n state,\n src,\n mimeType,\n filename,\n items,\n text,\n groupPosition,\n preload,\n onDismiss,\n}) => {\n const variant = bubbleVariantForState(state)\n const showDismiss = state === 'composer' && !!onDismiss\n const resolvedItems = resolveItems({ src, mimeType, filename, items })\n\n if (resolvedItems.length === 0) {\n return null\n }\n\n // Default rule: surface duration immediately for a single player,\n // but avoid fanning out N metadata requests when the bubble is a\n // thread of voice memos. An explicit `preload` prop overrides;\n // per-track overrides live on `AudioItem.preload`.\n const resolvedPreload: MediaPreloadMode =\n preload ?? (resolvedItems.length > 1 ? 'none' : 'metadata')\n\n return (\n <Bubble\n variant={variant}\n text={text}\n groupPosition={groupPosition}\n data-testid=\"audio-attachment\"\n >\n {/* Native `<audio controls>` already exposes a download in its\n kebab menu, so we don't render a separate Download button.\n The element also has no built-in title slot — the dismiss\n button (Composer only) sits inline next to the player.\n Stacked players get an 8px vertical gap so each track reads\n as a discrete attachment. */}\n <div className=\"flex flex-col gap-2\">\n {resolvedItems.map((item, index) => (\n <NativeAudioPlayer\n key={`${item.src}-${index}`}\n item={item}\n preload={resolvedPreload}\n trailingAction={\n // Composer only supports a single attachment, so the\n // dismiss control sits on the only player.\n showDismiss && index === 0 ? (\n <DismissButton onClick={onDismiss!} variant=\"inline\" />\n ) : undefined\n }\n />\n ))}\n </div>\n </Bubble>\n )\n}\n\n/**\n * Composer-only props. Single audio (`src`) only — the composer\n * surface accepts a single attachment at a time, so `items` is not\n * supported. Captions (`text`) and `groupPosition` are also dropped:\n * the composer renders a standalone draft, not part of a same-author\n * run, and captions live in the message-input textarea, not inside\n * the draft attachment preview.\n */\nexport interface AudioComposerProps extends ComposerExtras {\n src?: string\n mimeType?: string\n filename?: string\n /** See `AudioAttachmentSharedProps.preload`. */\n preload?: MediaPreloadMode\n}\nexport type AudioSentProps = AudioAttachmentSharedProps\nexport type AudioReceivedProps = AudioAttachmentSharedProps\n\nconst AudioComposer: React.FC<AudioComposerProps> = (props) => (\n <AudioAttachmentRow {...props} state=\"composer\" />\n)\nconst AudioSent: React.FC<AudioSentProps> = (props) => (\n <AudioAttachmentRow {...props} state=\"sent\" />\n)\nconst AudioReceived: React.FC<AudioReceivedProps> = (props) => (\n <AudioAttachmentRow {...props} state=\"received\" />\n)\n\nconst AudioAttachment = {\n Composer: AudioComposer,\n Sent: AudioSent,\n Received: AudioReceived,\n}\n\nexport default AudioAttachment\n","import {\n getDocumentIconType,\n getSourceType,\n} from '../../AttachmentCard/utils/mimeType'\n\n/**\n * Format a byte count as a short human-readable string (`'379.5 KB'`).\n * Mirrors the meta line shown next to file attachments in the mobile chat\n * design — `EXT · SIZE`, e.g. `PDF · 379.5 KB`.\n */\nexport function formatFileSize(bytes: number): string {\n if (!Number.isFinite(bytes) || bytes < 0) return ''\n if (bytes < 1024) return `${bytes} B`\n if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`\n if (bytes < 1024 * 1024 * 1024)\n return `${(bytes / (1024 * 1024)).toFixed(2)} MB`\n return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`\n}\n\nconst EXTENSION_LABEL_BY_DOCUMENT_TYPE: Record<string, string> = {\n pdf: 'PDF',\n doc: 'DOC',\n xls: 'XLS',\n csv: 'CSV',\n ppt: 'PPT',\n zip: 'ZIP',\n text: 'TXT',\n markdown: 'MD',\n}\n\n/**\n * Returns the short uppercase extension label shown in the meta line of\n * compact document / file attachments. Prefers the filename extension\n * when present (matches the mobile design which trusts the filename),\n * and falls back to a label derived from the MIME type.\n */\nexport function getFileExtensionLabel(\n mimeType?: string,\n filename?: string\n): string | undefined {\n if (filename) {\n const lastDot = filename.lastIndexOf('.')\n if (lastDot > 0 && lastDot < filename.length - 1) {\n const ext = filename.slice(lastDot + 1)\n if (ext && ext.length <= 5) return ext.toUpperCase()\n }\n }\n\n if (!mimeType) return undefined\n\n const sourceType = getSourceType(mimeType)\n if (sourceType === 'document') {\n const docType = getDocumentIconType(mimeType)\n const docLabel = EXTENSION_LABEL_BY_DOCUMENT_TYPE[docType]\n if (docLabel) return docLabel\n if (mimeType === 'application/octet-stream') return undefined\n }\n\n const subtype = mimeType.split('/')[1]\n if (!subtype || subtype === '*') return undefined\n return subtype.toUpperCase()\n}\n\n/**\n * Build the meta line shown under the title in compact document / file\n * attachments — `EXT · SIZE` (`PDF · 379.5 KB`). Either part is dropped\n * when not available so audio / generic files still get a useful label.\n */\nexport function buildCompactMetaLabel(\n mimeType?: string,\n filename?: string,\n fileSize?: number\n): string | undefined {\n const ext = getFileExtensionLabel(mimeType, filename)\n const size =\n typeof fileSize === 'number' && fileSize > 0\n ? formatFileSize(fileSize)\n : undefined\n return [ext, size].filter(Boolean).join(' · ') || undefined\n}\n\n/**\n * Derive a sensible filename from a URL — used as the fallback save name\n * when the attachment has no `filename` set. Returns `'download'` for\n * URLs we can't parse.\n */\nexport function filenameFromUrl(url: string): string {\n try {\n const parsed = new URL(url)\n const last = parsed.pathname.split('/').pop()\n return last && last.length > 0 ? decodeURIComponent(last) : 'download'\n } catch {\n return 'download'\n }\n}\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport { renderTypeIcon } from '../../AttachmentCard'\nimport type { BubbleVariant } from '../types'\n\nimport { buildCompactMetaLabel } from './fileMeta'\n\nexport interface CompactDocumentRowProps {\n variant: BubbleVariant\n /** Filename — drives the title (when no `title` set) and the `EXT` label. */\n filename?: string\n /** Override displayed title. Defaults to `filename`. */\n title?: string\n mimeType?: string\n fileSize?: number\n /**\n * When set, the icon + filename area becomes a `<button>` that fires\n * this handler. Lets the row's primary activation (e.g. opening the\n * PDF viewer) live separately from the trailing slot's own button\n * (e.g. a download icon) without nesting `<button>` inside `<button>`.\n * When omitted, the row renders as a plain presentational `<div>`\n * and the caller is responsible for any outer activation wrapper.\n */\n onActivate?: () => void\n /**\n * Required when `onActivate` is set. Visible to assistive tech as\n * the inner button's label (e.g. `'Open ESOP-summary.pdf'`).\n */\n activateLabel?: string\n /**\n * Optional trailing slot — sits outside the activation button so it\n * can host its own interactive controls (e.g. a download `<button>`,\n * the Composer's `DismissButton`) without nesting one button inside\n * another.\n */\n trailingAction?: React.ReactNode\n}\n\n// Meta line + icon tile are tinted relative to the bubble background,\n// so they stay variant-aware. The title inherits the bubble's text\n// color (set on the parent `Bubble`).\n//\n// `text-black/55` on the `#f2f1ef` light bubble lands right at the\n// WCAG AA 4.5:1 small-text threshold (≈4.5:1) — bump to `/65` so\n// the meta line has a comfortable margin on the light bubble. The\n// dark variant (`text-white/55` on `#1e2330`) already passes AA,\n// so we leave it alone.\nconst META_CLASS_BY_VARIANT: Record<BubbleVariant, string> = {\n dark: 'text-white/55',\n light: 'text-black/65',\n}\n\nconst ICON_BG_BY_VARIANT: Record<BubbleVariant, string> = {\n dark: 'bg-white/10',\n light: 'bg-black/5',\n}\n\nconst ICON_COLOR_BY_VARIANT: Record<BubbleVariant, string> = {\n dark: 'text-white/85',\n light: 'text-black/85',\n}\n\n/**\n * Compact icon-row used by `Pdf` / `File` `MessageAttachment` variants.\n * Mirrors the mobile chat document attachment from\n * `EARN-8448/pr-2-chat-bubbles-and-file-icons` — a 40x40 typed icon\n * tile on the left, filename + `EXT · SIZE` meta on the right.\n *\n * The row is always wrapped by `Bubble`, which contributes the bubble\n * background, padding, border, and (when the parent wires it up) the\n * click target.\n */\nconst CompactDocumentRow: React.FC<CompactDocumentRowProps> = ({\n variant,\n filename,\n title,\n mimeType = 'application/octet-stream',\n fileSize,\n onActivate,\n activateLabel,\n trailingAction,\n}) => {\n const resolvedTitle = title ?? filename ?? 'File'\n const metaLabel = buildCompactMetaLabel(mimeType, filename, fileSize)\n\n const iconTile = (\n <div\n className={classNames(\n 'flex size-10 shrink-0 items-center justify-center rounded-sm',\n ICON_BG_BY_VARIANT[variant]\n )}\n aria-hidden\n >\n {renderTypeIcon(mimeType, {\n className: classNames('size-6', ICON_COLOR_BY_VARIANT[variant]),\n weight: 'regular',\n })}\n </div>\n )\n\n const textBlock = (\n <div className=\"flex min-w-0 flex-1 flex-col text-left\">\n <p className=\"truncate font-medium leading-snug\">{resolvedTitle}</p>\n {metaLabel ? (\n <p\n className={classNames(\n 'truncate text-xs leading-4',\n META_CLASS_BY_VARIANT[variant]\n )}\n >\n {metaLabel}\n </p>\n ) : null}\n </div>\n )\n\n // When the row is activatable, its body (icon + text) becomes the\n // click target — wrapping it in a `<button>` rather than wrapping\n // the entire row preserves the trailing slot for its own buttons\n // (download / dismiss) instead of nesting them inside one.\n const body = onActivate ? (\n <button\n type=\"button\"\n onClick={onActivate}\n aria-label={activateLabel}\n className={classNames(\n 'flex min-w-0 flex-1 items-center gap-3 rounded-sm text-left transition-colors',\n variant === 'dark'\n ? 'hover:bg-white/[0.04]'\n : 'hover:bg-black/[0.04]'\n )}\n >\n {iconTile}\n {textBlock}\n </button>\n ) : (\n <>\n {iconTile}\n {textBlock}\n </>\n )\n\n return (\n <div className=\"flex items-center gap-3 px-3 py-2\">\n {body}\n {trailingAction ? <div className=\"shrink-0\">{trailingAction}</div> : null}\n </div>\n )\n}\n\nexport default CompactDocumentRow\n","import { filenameFromUrl } from './fileMeta'\n\n/**\n * Download a remote asset with the desired filename.\n *\n * Tries the same-origin `fetch` → `Blob` → invisible-`<a>.download`\n * route first so the file lands on disk under `filename` instead of\n * navigating the tab to it. When CORS / network errors trip us up we\n * fall back to `window.open` and then to a no-window anchor — the\n * popup-blocker fallback ensures the download still fires even when\n * a browser blocks the `_blank` window.\n *\n * Shared by `DownloadAction` (rendered as an explicit Download button\n * in PDF / image / video viewers) and `MessageAttachment.File` rows\n * (where the entire row is the download trigger). Centralizing here\n * keeps one source of truth for the fallback chain.\n */\nexport async function triggerDownload(\n url: string,\n filename?: string\n): Promise<void> {\n const name = filename ?? filenameFromUrl(url)\n\n try {\n const res = await fetch(url, { mode: 'cors' })\n if (!res.ok) throw new Error(`HTTP ${res.status}`)\n const blob = await res.blob()\n const objectUrl = URL.createObjectURL(blob)\n const a = document.createElement('a')\n a.href = objectUrl\n a.download = name\n a.style.display = 'none'\n document.body.appendChild(a)\n a.click()\n document.body.removeChild(a)\n URL.revokeObjectURL(objectUrl)\n } catch {\n const fallback = window.open(url, '_blank', 'noopener,noreferrer')\n if (!fallback) {\n // popup blocked — fall back to a non-windowed anchor\n const a = document.createElement('a')\n a.href = url\n a.download = name\n a.target = '_blank'\n a.rel = 'noopener noreferrer'\n a.style.display = 'none'\n document.body.appendChild(a)\n a.click()\n document.body.removeChild(a)\n }\n }\n}\n\nexport default triggerDownload\n","import { DownloadSimpleIcon } from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React from 'react'\n\nimport Bubble from '../_shared/Bubble'\nimport CompactDocumentRow from '../_shared/CompactDocumentRow'\nimport DismissButton from '../_shared/DismissButton'\nimport { filenameFromUrl } from '../_shared/fileMeta'\nimport { triggerDownload } from '../_shared/triggerDownload'\nimport {\n bubbleVariantForState,\n type BubbleVariant,\n type ComposerExtras,\n type FileItem,\n type MessageAttachmentBaseProps,\n type MessageAttachmentState,\n} from '../types'\n\nexport interface FileAttachmentSharedProps extends MessageAttachmentBaseProps {\n /** Source URL of the file (used as the download target). */\n src?: string\n /** Filename — drives the title + the meta line + the download default name. */\n filename?: string\n fileSize?: number\n /** MIME type — drives the type icon. Defaults to `application/octet-stream`. */\n mimeType?: string\n /**\n * Override displayed title (defaults to `filename`). Useful when a\n * sender renames the attachment before sending.\n */\n title?: string\n /**\n * Stacked files. Takes precedence over `src` when set. Each item\n * renders as its own row inside the bubble; clicking a row downloads\n * that file. Sent + Received only — the composer surface accepts a\n * single attachment at a time.\n */\n items?: FileItem[]\n /**\n * Forwarded to the row trigger. When omitted the click still\n * downloads the file. Supply this for analytics, or return `false`\n * to fully intercept the download (e.g. show a confirmation modal,\n * route to a custom preview, throttle large files). Any other\n * return value — including `void`/`undefined` — lets the built-in\n * download proceed. For stacked attachments the `index` argument\n * identifies the row.\n */\n onClick?: (index: number) => boolean | void\n}\n\nconst resolveItems = ({\n src,\n filename,\n fileSize,\n mimeType,\n title,\n items,\n}: {\n src?: string\n filename?: string\n fileSize?: number\n mimeType?: string\n title?: string\n items?: FileItem[]\n}): FileItem[] => {\n if (items && items.length > 0) return items\n if (src) return [{ src, filename, fileSize, mimeType, title }]\n return []\n}\n\ninterface FileRowButtonProps {\n variant: BubbleVariant\n item: FileItem\n index: number\n onActivate: (index: number) => void\n trailingAction: React.ReactNode\n}\n\n/**\n * Single tappable file row — used both for the lone file case and\n * for each child of a stacked attachment. The icon + filename area\n * is the click target (downloads the asset); the trailing slot is\n * decorative on Sent / Received and hosts the dismiss control on\n * Composer.\n */\nconst FileRowButton: React.FC<FileRowButtonProps> = ({\n variant,\n item,\n index,\n onActivate,\n trailingAction,\n}) => {\n const resolvedFilename = item.filename ?? filenameFromUrl(item.src)\n return (\n <CompactDocumentRow\n variant={variant}\n filename={resolvedFilename}\n title={item.title}\n mimeType={item.mimeType ?? 'application/octet-stream'}\n fileSize={item.fileSize}\n onActivate={() => onActivate(index)}\n activateLabel={`Download ${resolvedFilename}`}\n trailingAction={trailingAction}\n />\n )\n}\n\ninterface InternalFileRowProps extends FileAttachmentSharedProps {\n state: MessageAttachmentState\n onDismiss?: () => void\n}\n\nconst FileAttachmentRow: React.FC<InternalFileRowProps> = ({\n state,\n src,\n filename,\n fileSize,\n mimeType,\n title,\n items,\n text,\n groupPosition,\n onClick,\n onDismiss,\n}) => {\n const variant = bubbleVariantForState(state)\n const showDismiss = state === 'composer' && !!onDismiss\n const resolvedItems = resolveItems({\n src,\n filename,\n fileSize,\n mimeType,\n title,\n items,\n })\n\n // `useCallback` would be pointless here — `resolvedItems` is rebuilt\n // every render, so memoizing on it produces a fresh function every\n // render anyway. Keep this as a plain function.\n const handleActivate = (index: number) => {\n // `onClick` returning `false` cancels the built-in download so\n // consumers can route the click to a confirmation modal, custom\n // preview, etc. Any other return value (including void) lets the\n // default download proceed.\n if (onClick?.(index) === false) return\n const item = resolvedItems[index]\n if (!item) return\n const resolvedFilename = item.filename ?? filenameFromUrl(item.src)\n void triggerDownload(item.src, resolvedFilename)\n }\n\n if (resolvedItems.length === 0) {\n return null\n }\n\n const downloadIcon = (\n <span\n className={classNames(\n 'flex size-8 items-center justify-center rounded-full',\n variant === 'dark' ? 'text-white/70' : 'text-black/70'\n )}\n aria-hidden\n >\n <DownloadSimpleIcon className=\"size-5\" weight=\"bold\" />\n </span>\n )\n\n return (\n <Bubble\n variant={variant}\n text={text}\n groupPosition={groupPosition}\n data-testid=\"file-attachment\"\n >\n {/* Stacked rows get a small vertical gap so each file reads as\n a discrete attachment rather than one merged blob. Single\n row falls through to a no-op `gap-0`. */}\n <div className=\"flex flex-col gap-2\">\n {resolvedItems.map((item, index) => {\n // Composer only supports a single attachment so the dismiss\n // control sits on the only row; otherwise every row gets\n // the trailing download icon hint.\n const trailingAction =\n showDismiss && index === 0 ? (\n <DismissButton onClick={onDismiss!} variant=\"inline\" />\n ) : (\n downloadIcon\n )\n return (\n <FileRowButton\n key={`${item.src}-${index}`}\n variant={variant}\n item={item}\n index={index}\n onActivate={handleActivate}\n trailingAction={trailingAction}\n />\n )\n })}\n </div>\n </Bubble>\n )\n}\n\n/**\n * Composer-only props. Single file (`src`) only — the composer surface\n * accepts a single attachment at a time, so `items` is not supported.\n * Captions (`text`) and `groupPosition` are also dropped: the composer\n * renders a standalone draft, not part of a same-author run, and\n * captions live in the message-input textarea, not inside the draft\n * attachment preview.\n */\nexport interface FileComposerProps extends ComposerExtras {\n src?: string\n filename?: string\n fileSize?: number\n mimeType?: string\n title?: string\n onClick?: (index: number) => boolean | void\n}\nexport type FileSentProps = FileAttachmentSharedProps\nexport type FileReceivedProps = FileAttachmentSharedProps\n\nconst FileComposer: React.FC<FileComposerProps> = (props) => (\n <FileAttachmentRow {...props} state=\"composer\" />\n)\nconst FileSent: React.FC<FileSentProps> = (props) => (\n <FileAttachmentRow {...props} state=\"sent\" />\n)\nconst FileReceived: React.FC<FileReceivedProps> = (props) => (\n <FileAttachmentRow {...props} state=\"received\" />\n)\n\nconst FileAttachment = {\n Composer: FileComposer,\n Sent: FileSent,\n Received: FileReceived,\n}\n\nexport default FileAttachment\n","import { CaretLeftIcon, CaretRightIcon } from '@phosphor-icons/react'\nimport React from 'react'\n\nexport interface CarouselNavProps {\n onPrev: () => void\n onNext: () => void\n /** Accessible label for the previous-item button. */\n prevLabel?: string\n /** Accessible label for the next-item button. */\n nextLabel?: string\n}\n\n/**\n * Prev / next chrome shared by every carousel-aware viewer. Rendered\n * inside the dialog body so the buttons sit absolutely positioned\n * against the viewer (`.mes-media-viewer__nav--{prev,next}`).\n *\n * Styling lives as plain CSS in `styles.css` so the buttons render\n * correctly regardless of whether the consumer has Tailwind wired up.\n */\nconst CarouselNav: React.FC<CarouselNavProps> = ({\n onPrev,\n onNext,\n prevLabel = 'Previous',\n nextLabel = 'Next',\n}) => (\n <>\n <button\n type=\"button\"\n onClick={onPrev}\n aria-label={prevLabel}\n className=\"mes-media-viewer__nav mes-media-viewer__nav--prev\"\n >\n <CaretLeftIcon size={20} weight=\"bold\" aria-hidden />\n </button>\n <button\n type=\"button\"\n onClick={onNext}\n aria-label={nextLabel}\n className=\"mes-media-viewer__nav mes-media-viewer__nav--next\"\n >\n <CaretRightIcon size={20} weight=\"bold\" aria-hidden />\n </button>\n </>\n)\n\nexport default CarouselNav\n","import {\n CircleNotchIcon,\n DownloadSimpleIcon,\n IconProps,\n} from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React, { useCallback, useState } from 'react'\n\nimport { triggerDownload } from './triggerDownload'\n\nexport type DownloadActionVariant =\n /** Solid pill button used inside compact / file rows. */\n | 'pill'\n /**\n * Compact round icon button sized for the trailing slot of a\n * `CompactDocumentRow` (PDF / File rows). Adopts the row's tone so\n * it sits inline next to the filename without competing with it.\n */\n | 'inline'\n /**\n * Round icon button sized to match the close action in the\n * `ViewerShell` chrome — used by `ImageViewer` for in-viewer\n * downloads. Styled with plain CSS (`.mes-media-viewer__action`) so\n * it renders correctly without a Tailwind dependency in the\n * consumer's app.\n */\n | 'viewer'\n\nexport interface DownloadActionProps {\n url: string\n filename?: string\n variant?: DownloadActionVariant\n /**\n * Override the visible label on `pill` variants. Defaults to\n * `'Download'`. On `inline` / `viewer` variants the label is\n * hidden visually and surfaced as the button's `aria-label`.\n */\n label?: string\n /** Hide the label, keeping just the icon. Defaults to `true` for non-pill variants. */\n iconOnly?: boolean\n /** Tone of the surface. Used by the `pill` variant. */\n tone?: 'dark' | 'light'\n /**\n * Triggered after the download starts so consumers can fire analytics\n * or close a viewer. Errors during download don't suppress the call.\n */\n onTriggered?: () => void\n}\n\nconst DownloadAction: React.FC<DownloadActionProps> = ({\n url,\n filename,\n variant = 'pill',\n label = 'Download',\n iconOnly,\n tone = 'dark',\n onTriggered,\n}) => {\n const [busy, setBusy] = useState(false)\n\n const handleClick = useCallback(\n (e: React.MouseEvent) => {\n e.stopPropagation()\n if (busy) return\n setBusy(true)\n triggerDownload(url, filename)\n .catch(() => {\n /* swallowed — fallback path inside `triggerDownload` */\n })\n .finally(() => {\n setBusy(false)\n onTriggered?.()\n })\n },\n [busy, url, filename, onTriggered]\n )\n\n const showIconOnly = iconOnly ?? variant !== 'pill'\n\n const iconClass = classNames(\n variant === 'pill' ? 'size-4' : 'size-5',\n 'shrink-0'\n )\n const iconProps: IconProps = { className: iconClass, weight: 'bold' }\n\n if (variant === 'inline') {\n // Sized to match the existing trailing slot used by `DismissButton`\n // and the decorative download span in `FileAttachment`. Tone keys\n // off the surrounding `Bubble` variant so a sender (dark) bubble\n // gets a lighter icon and a receiver (light) bubble gets a darker\n // one — same approach `CompactDocumentRow` already uses for the\n // type icon.\n const inlineToneClasses: Record<'dark' | 'light', string> = {\n dark: 'text-white/70 hover:bg-white/[0.08] hover:text-white',\n light: 'text-black/70 hover:bg-black/[0.08] hover:text-black',\n }\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={busy}\n aria-label={label}\n className={classNames(\n 'flex size-8 shrink-0 items-center justify-center rounded-full transition-colors disabled:opacity-70',\n inlineToneClasses[tone]\n )}\n >\n {busy ? (\n <CircleNotchIcon\n className=\"size-4 animate-spin\"\n weight=\"bold\"\n aria-hidden\n />\n ) : (\n <DownloadSimpleIcon\n className=\"size-5 shrink-0\"\n weight=\"bold\"\n aria-hidden\n />\n )}\n </button>\n )\n }\n\n if (variant === 'viewer') {\n // Styled entirely through `.mes-media-viewer__action` (plain CSS\n // in `styles.css`) so the button renders correctly when consumed\n // outside this repo without a Tailwind setup. Sits next to the\n // close action inside `ViewerShell`'s top-right chrome.\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={busy}\n aria-label={label}\n className=\"mes-media-viewer__action\"\n >\n {busy ? (\n <CircleNotchIcon size={20} weight=\"bold\" aria-hidden />\n ) : (\n <DownloadSimpleIcon size={20} weight=\"bold\" aria-hidden />\n )}\n </button>\n )\n }\n\n // pill — only remaining variant\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={busy}\n aria-label={showIconOnly ? label : undefined}\n className={classNames(\n 'mt-3 inline-flex h-10 w-full items-center justify-center gap-2 rounded-full px-4 text-sm font-medium leading-none transition-colors disabled:opacity-70',\n tone === 'dark'\n ? 'bg-[#121110] text-white hover:bg-[#2a2928]'\n : 'bg-white text-[#121110] hover:bg-white/90'\n )}\n >\n {busy ? (\n <CircleNotchIcon\n className=\"size-4 animate-spin\"\n weight=\"bold\"\n aria-hidden\n />\n ) : (\n <DownloadSimpleIcon {...iconProps} aria-hidden />\n )}\n {showIconOnly ? null : label}\n </button>\n )\n}\n\nexport default DownloadAction\n","/* eslint-disable react-hooks/set-state-in-effect -- pre-existing pattern flagged by the React\n Compiler rules added in eslint-plugin-react-hooks v7; refactoring it is\n out of scope for the lint toolchain upgrade. */\nimport { useCallback, useEffect, useState } from 'react'\n\nconst clamp = (value: number, min: number, max: number) =>\n Math.min(Math.max(value, min), max)\n\nexport interface UseCarouselOptions {\n /** Total number of items in the carousel. */\n length: number\n /** Index to display when the carousel first opens / re-opens. */\n initialIndex: number\n /** When `false`, the keyboard listener is detached. */\n open: boolean\n}\n\nexport interface UseCarouselResult {\n /** Currently displayed index (clamped to `[0, length - 1]`). */\n index: number\n /** Step one item back, wrapping at the start. */\n prev: () => void\n /** Step one item forward, wrapping at the end. */\n next: () => void\n}\n\n/**\n * Tiny carousel state used by `ImageViewer`, `VideoViewer`, and\n * `PdfViewer` when their items array has more than one entry.\n *\n * - Resets to `initialIndex` whenever the viewer (re-)opens, so\n * clicking a different tile on the bubble surface lands on that\n * item rather than restoring the last-viewed position.\n * - Clamps defensively when `length` shrinks below the active index\n * (server push / optimistic update / stack edit) so the viewer\n * gracefully falls back instead of dereferencing `undefined`.\n * - Listens for `ArrowLeft` / `ArrowRight` while the viewer is open,\n * but yields when the focused element is a `<video>` / `<audio>`\n * element so the native media controls can use the same keys for\n * seek / volume.\n */\nexport const useCarousel = ({\n length,\n initialIndex,\n open,\n}: UseCarouselOptions): UseCarouselResult => {\n const safeInitial = clamp(initialIndex, 0, Math.max(length - 1, 0))\n const [index, setIndex] = useState(safeInitial)\n\n // Snap the active index back to whatever the caller asked for every\n // time the viewer (re)opens or its initial target / length changes.\n // Without this the viewer would remember the last index across\n // open/close cycles, which is wrong for a chat lightbox where each\n // tile click should land on that tile.\n useEffect(() => {\n if (!open) return\n setIndex(clamp(initialIndex, 0, Math.max(length - 1, 0)))\n }, [open, initialIndex, length])\n\n // Re-clamp on length change so a stale index doesn't dereference\n // past the new array bounds (e.g. items shrank while the viewer is\n // open). The `Math.max(..., 0)` keeps the index at `0` when the\n // array empties out so callers can render an empty-state instead of\n // a runtime crash.\n useEffect(() => {\n setIndex((i) => clamp(i, 0, Math.max(length - 1, 0)))\n }, [length])\n\n const prev = useCallback(() => {\n if (length <= 1) return\n setIndex((i) => (i <= 0 ? length - 1 : i - 1))\n }, [length])\n\n const next = useCallback(() => {\n if (length <= 1) return\n setIndex((i) => (i >= length - 1 ? 0 : i + 1))\n }, [length])\n\n useEffect(() => {\n if (!open || length <= 1) return undefined\n\n const onKey = (e: KeyboardEvent) => {\n if (e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') return\n // Don't hijack arrow keys when a native media element is\n // focused — the browser's own controls already use them for\n // seek / volume, and stealing them would feel broken.\n const active = document.activeElement\n if (\n active &&\n (active.tagName === 'VIDEO' || active.tagName === 'AUDIO')\n ) {\n return\n }\n e.preventDefault()\n if (e.key === 'ArrowLeft') prev()\n else next()\n }\n\n window.addEventListener('keydown', onKey)\n return () => window.removeEventListener('keydown', onKey)\n }, [open, length, prev, next])\n\n return { index, prev, next }\n}\n\nexport default useCarousel\n","import { XIcon } from '@phosphor-icons/react'\nimport React, { useEffect, useRef } from 'react'\n\nexport interface ViewerShellProps {\n open: boolean\n onClose: () => void\n /**\n * Accessible label for the dialog — usually the media's filename. We\n * intentionally don't render a visible title bar (the chrome is a\n * single close button + optional actions so the media stays the\n * focus), so this is the only way assistive tech gets a name for\n * the modal.\n */\n ariaLabel?: string\n /**\n * Optional counter rendered in the top-left chrome (e.g. `2 / 6`).\n * Carousel-aware viewers set this when their items array has more\n * than one entry; omit it for single-item viewers.\n */\n counter?: React.ReactNode\n /**\n * Extra buttons rendered alongside the close button in the top-right\n * chrome (e.g. a download action). They share `.mes-media-viewer__action`\n * styling so the row reads as one consistent button group.\n */\n actions?: React.ReactNode\n children: React.ReactNode\n 'data-testid'?: string\n}\n\n/**\n * Full-viewport lightbox shell shared by `ImageViewer`, `VideoViewer`,\n * and `PdfViewer`. Built on a native `<dialog>` so the package ships\n * without a Tailwind dependency for the load-bearing chrome:\n *\n * - Top-layer + body-scroll lock come for free from `showModal()`.\n * - `Escape` to close is wired by the platform.\n * - Focus management (move-in on open, restore on close) is handled\n * by the browser; we explicitly focus the close button as a\n * fallback for environments where `showModal` is unavailable\n * (jsdom under tests).\n *\n * The structural styling lives as plain CSS under `.mes-media-viewer*`\n * in `styles.css` so a consumer who imports\n * `@linktr.ee/messaging-react/styles.css` gets a working lightbox even\n * if their Tailwind pipeline isn't scanning our `dist`.\n */\nconst ViewerShell: React.FC<ViewerShellProps> = ({\n open,\n onClose,\n ariaLabel,\n counter,\n actions,\n children,\n 'data-testid': dataTestId,\n}) => {\n const dialogRef = useRef<HTMLDialogElement | null>(null)\n const closeButtonRef = useRef<HTMLButtonElement | null>(null)\n\n // Drive `<dialog>` open/close imperatively from the React `open` prop.\n // We guard `showModal` / `close` because jsdom 23 ships the element\n // without those methods — falling back to the `[open]` attribute\n // keeps tests (and any other non-DOM environment) functional even if\n // the true top-layer modal behavior isn't available there.\n useEffect(() => {\n const dialog = dialogRef.current\n if (!dialog) return undefined\n\n if (open) {\n if (!dialog.open) {\n if (typeof dialog.showModal === 'function') {\n try {\n dialog.showModal()\n } catch {\n dialog.setAttribute('open', '')\n }\n } else {\n dialog.setAttribute('open', '')\n }\n }\n\n const previouslyFocused =\n typeof document !== 'undefined'\n ? (document.activeElement as HTMLElement | null)\n : null\n\n // Explicitly focus the close button. In a real browser\n // `showModal()` would already focus the first sequentially\n // focusable child (which is the close button), but doing it\n // ourselves guarantees the same behavior in jsdom and in any\n // browser where focus heuristics differ.\n closeButtonRef.current?.focus()\n\n return () => {\n if (dialog.open) {\n if (typeof dialog.close === 'function') {\n try {\n dialog.close()\n } catch {\n dialog.removeAttribute('open')\n }\n } else {\n dialog.removeAttribute('open')\n }\n }\n if (previouslyFocused && document.body.contains(previouslyFocused)) {\n previouslyFocused.focus()\n }\n }\n }\n\n if (dialog.open) {\n if (typeof dialog.close === 'function') {\n try {\n dialog.close()\n } catch {\n dialog.removeAttribute('open')\n }\n } else {\n dialog.removeAttribute('open')\n }\n }\n return undefined\n }, [open])\n\n // The platform fires `close` when the user dismisses via Escape or\n // any other native path. Mirror that into React state so the parent's\n // `open` flag stays in sync — otherwise the dialog would close\n // visually but our effect would re-open it on the next render.\n const handleDialogClose = () => {\n onClose()\n }\n\n // Backdrop click closes the viewer. The click lands on the `<dialog>`\n // itself (not its children) because the body sits inside an inner\n // wrapper — the easiest reliable check.\n const handleDialogClick = (e: React.MouseEvent<HTMLDialogElement>) => {\n if (e.target === dialogRef.current) onClose()\n }\n\n return (\n // The native `<dialog>` element ships its own keyboard dismissal\n // (Escape, handled by the platform and surfaced through `onClose`),\n // so the `onClick` on the backdrop doesn't need a paired keyboard\n // listener — that's the whole point of using `<dialog>`. The\n // `jsx-a11y` rules below don't model `<dialog>` as interactive, so\n // we silence them locally with the rationale captured here.\n // eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-noninteractive-element-interactions\n <dialog\n ref={dialogRef}\n className=\"mes-media-viewer\"\n aria-label={ariaLabel ?? 'Attachment viewer'}\n data-testid={dataTestId}\n onClose={handleDialogClose}\n onClick={handleDialogClick}\n >\n <div className=\"mes-media-viewer__chrome\">\n {counter ? (\n <span className=\"mes-media-viewer__counter\">{counter}</span>\n ) : null}\n <div className=\"mes-media-viewer__actions\">\n {actions}\n <button\n ref={closeButtonRef}\n type=\"button\"\n onClick={onClose}\n aria-label=\"Close viewer\"\n className=\"mes-media-viewer__action\"\n >\n <XIcon size={20} weight=\"bold\" aria-hidden />\n </button>\n </div>\n </div>\n <div className=\"mes-media-viewer__body\">{children}</div>\n </dialog>\n )\n}\n\nexport default ViewerShell\n","import React, { useMemo } from 'react'\n\nimport CarouselNav from './CarouselNav'\nimport DownloadAction from './DownloadAction'\nimport { filenameFromUrl } from './fileMeta'\nimport { useCarousel } from './useCarousel'\nimport ViewerShell from './ViewerShell'\n\nexport interface ImageViewerItem {\n src: string\n alt?: string\n /**\n * Filename used by the download action and as the dialog's\n * accessible name. Falls back to the last pathname segment of\n * `src` when omitted.\n */\n filename?: string\n}\n\nexport interface ImageViewerProps {\n open: boolean\n items: ImageViewerItem[]\n /** Index to display when the viewer first opens. Defaults to `0`. */\n initialIndex?: number\n onClose: () => void\n}\n\n/**\n * Native lightbox-style image viewer — full-viewport `<dialog>` with\n * the image centered at reasonable max dimensions, a single close\n * button, and a download action in the chrome.\n *\n * When `items.length > 1` the viewer becomes a carousel:\n *\n * - Prev / next on-screen controls hug the viewport sides.\n * - `ArrowLeft` / `ArrowRight` step between siblings (the keyboard\n * listener is parked while a `<video>` / `<audio>` element is\n * focused so native media seek still works in mixed contexts).\n * - A `current / total` counter sits in the top-left chrome.\n *\n * Used by every `MessageAttachment.Image.*` variant\n * (Composer / Sent / Received) so admins can preview attachments\n * before sending and recipients can preview after receipt.\n */\nconst ImageViewer: React.FC<ImageViewerProps> = ({\n open,\n items,\n initialIndex = 0,\n onClose,\n}) => {\n const { index, prev, next } = useCarousel({\n length: items.length,\n initialIndex,\n open,\n })\n\n const item = items[index]\n const filename = useMemo(\n () => item?.filename ?? (item ? filenameFromUrl(item.src) : 'image'),\n [item]\n )\n\n if (!item) return null\n\n return (\n <ViewerShell\n open={open}\n onClose={onClose}\n ariaLabel={filename}\n counter={\n items.length > 1 ? `${index + 1} / ${items.length}` : undefined\n }\n actions={\n <DownloadAction\n url={item.src}\n filename={filename}\n variant=\"viewer\"\n label={`Download ${filename}`}\n />\n }\n data-testid=\"image-viewer\"\n >\n {open ? (\n <img\n // Forcing a key swap on item change ensures React replaces\n // the `<img>` cleanly between siblings — otherwise the\n // previous image stays painted for a frame while the new\n // `src` decodes, which reads as a stutter at carousel pace.\n key={`${index}:${item.src}`}\n src={item.src}\n alt={item.alt ?? filename}\n draggable={false}\n // The user has explicitly opened the viewer, so we want the\n // active image to appear immediately rather than fall to the\n // browser's lazy-load heuristics. Which is exactly why the\n // element is gated on `open`: `ViewerShell` keeps its\n // `<dialog>` mounted across open/close so the platform\n // transition can play, and an eager `<img>` inside a closed\n // dialog made every image bubble in a thread download its\n // full-resolution original — note the viewer intentionally\n // uses the raw `item.src`, not the CDN-optimised URL the\n // bubble tile renders.\n loading=\"eager\"\n decoding=\"async\"\n className=\"mes-media-viewer__image\"\n />\n ) : null}\n\n {items.length > 1 ? (\n <CarouselNav\n onPrev={prev}\n onNext={next}\n prevLabel=\"Previous image\"\n nextLabel=\"Next image\"\n />\n ) : null}\n </ViewerShell>\n )\n}\n\nexport default ImageViewer\n","import classNames from 'classnames'\nimport React from 'react'\n\nexport interface MediaStackTile {\n /** Renderable tile content (image / video / poster). */\n content: React.ReactNode\n /** Pure-tile aria label (e.g. `'Photo 1'`). Used by `Pressable` mode. */\n ariaLabel?: string\n}\n\nexport interface MediaStackGridProps {\n tiles: MediaStackTile[]\n /**\n * When set, every tile is wrapped in a `<button>` and forwards the\n * tile index to `onTileActivate`. Used by Image / Video so any tile\n * opens the lightbox / video viewer at the right index.\n */\n onTileActivate?: (index: number) => void\n /**\n * Maximum tiles to render before the last one collapses into an\n * \"+N more\" overflow indicator. Defaults to `4`.\n */\n maxVisible?: number\n /**\n * Aspect ratio (width / height) for the SINGLE-tile layout. Applies\n * to every media kind, not just images. When omitted the 1-tile\n * branch keeps today's `aspect-square`. Ignored for 2+ tiles, whose\n * grid aspect is fixed.\n */\n singleAspectRatio?: number\n className?: string\n}\n\n// The tile is the focusable element, and its focus ring has to be drawn\n// INSIDE it. Figma leaves only a 2px frame around the media and `Bubble`\n// clips its own overflow, so an outset ring is swallowed by the frame;\n// an inset ring or a negative-offset `outline` on the tile is covered by\n// the media, which is `absolute inset-0`. A positioned `::after` is the\n// last child in tree order, so it paints above the media, inherits the\n// tile's outer-corner radius, and ignores every ancestor clip. Same\n// two-tone treatment as before — a dark band over a white ring — so it\n// stays legible on light and dark photos alike. Verified in Chromium.\nconst TILE_SHELL =\n 'relative block size-full overflow-hidden bg-black/5 outline-none after:pointer-events-none after:absolute after:inset-0 after:rounded-[inherit] focus-visible:after:ring-2 focus-visible:after:ring-inset focus-visible:after:ring-white/80 focus-visible:after:ring-offset-2 focus-visible:after:ring-offset-black'\n\n// Figma rounds only the four OUTER corners of a media cluster and leaves\n// every inner edge square: on `attachment-single-image` 1973:13863 the\n// `left` column carries `rectangleCornerRadii [18,0,0,18]` and `right`\n// `[0,18,18,0]`, while the tiles themselves carry none.\n//\n// So the radius lives on the tiles, keyed by layout and DOM position.\n// A single `overflow-hidden rounded-[18px]` container would be shorter,\n// but it also clips the tiles' `focus-visible` ring — an outset\n// `box-shadow` — and in the 1-tile layout the tile fills the container\n// exactly, so keyboard users would get no focus indicator at all.\n// Neither `ring-inset` nor a negative `outline-offset` rescues that:\n// the tile's `<img>` is `absolute inset-0` and paints over both.\n// Measured in Chromium, not assumed.\nconst OUTER_CORNER_CLASSES: Record<number, readonly string[]> = {\n 1: ['rounded-[18px]'],\n 2: ['rounded-l-[18px]', 'rounded-r-[18px]'],\n 3: ['rounded-l-[18px]', 'rounded-tr-[18px]', 'rounded-br-[18px]'],\n 4: [\n 'rounded-tl-[18px]',\n 'rounded-tr-[18px]',\n 'rounded-bl-[18px]',\n 'rounded-br-[18px]',\n ],\n}\n\n// Figma fits a single media item inside a max 326x436 content box on\n// web and 309x436 on mobile, preserving its aspect ratio, and the card\n// then adopts the resulting box — so `object-fit: cover` performs no\n// crop and nothing is letterboxed.\n//\n// The fit is `width = min(widthCap, heightCap * ratio)`, with\n// `aspect-ratio` supplying the other axis. Only the width cap is\n// breakpoint-dependent, so it travels as a custom property while the\n// ratio-derived term resolves to a concrete pixel value. Together they\n// reproduce all eight measured frames (`2032:22651` / `23000` /\n// `23353` / `23707` plus their mobile counterparts) to within Figma's\n// float rounding — including the 9:16 portrait, which renders 246x436\n// on web *and* mobile precisely because the height cap is NOT\n// breakpoint-dependent: a width-only rule would give mobile 309x547.6.\n//\n// The property name is spelled out again inside `SINGLE_WIDTH_CAPS` on\n// purpose. Tailwind extracts classes by scanning source text, so an\n// interpolated `` `[${SINGLE_WIDTH_CAP_PROPERTY}:309px]` `` would emit\n// no CSS at all and silently drop the width cap. Keep it literal.\nconst SINGLE_WIDTH_CAP_PROPERTY = '--mes-single-width-cap'\nconst SINGLE_WIDTH_CAPS =\n '[--mes-single-width-cap:309px] sm:[--mes-single-width-cap:326px]'\nconst SINGLE_HEIGHT_CAP_PX = 436\n\n/**\n * Adaptive grid used by stacked image / video attachments. Layouts:\n *\n * - 1 tile — full-bleed\n * - 2 tiles — equal-width side-by-side row\n * - 3 tiles — one large left tile + two stacked right tiles\n * - 4 tiles — 2×2 grid\n * - 5+ — 2×2 grid with the bottom-right tile showing \"+N more\"\n *\n * A single tile adopts `singleAspectRatio` when supplied and otherwise\n * stays square; 2 tiles sit in a 16:9 row, 3 in a 4:3 box, and 4 in\n * the 379x286 content box Figma draws for a stacked media card. Only\n * the cluster's four outer corners round — see `OUTER_CORNER_CLASSES`.\n */\nconst MediaStackGrid: React.FC<MediaStackGridProps> = ({\n tiles,\n onTileActivate,\n maxVisible = 4,\n singleAspectRatio,\n className,\n}) => {\n const total = tiles.length\n if (total === 0) return null\n\n const visible = tiles.slice(0, Math.min(total, maxVisible))\n const overflow = total - visible.length\n\n const renderTile = (tile: MediaStackTile, index: number, extra?: React.ReactNode) => {\n const sharedClass = classNames(\n TILE_SHELL,\n 'h-full w-full',\n OUTER_CORNER_CLASSES[visible.length]?.[index]\n )\n if (onTileActivate) {\n return (\n <button\n type=\"button\"\n key={index}\n onClick={() => onTileActivate(index)}\n aria-label={tile.ariaLabel ?? `Open media ${index + 1}`}\n className={classNames(sharedClass, 'cursor-zoom-in')}\n >\n {tile.content}\n {extra}\n </button>\n )\n }\n return (\n <div key={index} className={sharedClass}>\n {tile.content}\n {extra}\n </div>\n )\n }\n\n let singleTileStyle: React.CSSProperties | undefined\n if (singleAspectRatio) {\n singleTileStyle = {\n aspectRatio: singleAspectRatio,\n // Hundredths keep the emitted declaration readable in devtools;\n // the rounding error is well under a device pixel.\n width: `min(var(${SINGLE_WIDTH_CAP_PROPERTY}), ${\n Math.round(SINGLE_HEIGHT_CAP_PX * singleAspectRatio * 100) / 100\n }px)`,\n // Only bites in a container narrower than the width cap.\n maxWidth: '100%',\n }\n }\n\n if (visible.length === 1) {\n return (\n <div\n className={classNames(\n singleAspectRatio ? SINGLE_WIDTH_CAPS : 'aspect-square w-full',\n className\n )}\n style={singleTileStyle}\n >\n {renderTile(visible[0], 0)}\n </div>\n )\n }\n\n if (visible.length === 2) {\n return (\n <div\n className={classNames(\n 'grid aspect-[16/9] w-full grid-cols-2 gap-0.5',\n className\n )}\n >\n {visible.map((tile, index) => renderTile(tile, index))}\n </div>\n )\n }\n\n if (visible.length === 3) {\n return (\n <div\n className={classNames(\n 'grid aspect-[4/3] w-full grid-cols-2 grid-rows-2 gap-0.5',\n className\n )}\n >\n <div className=\"row-span-2\">{renderTile(visible[0], 0)}</div>\n {renderTile(visible[1], 1)}\n {renderTile(visible[2], 2)}\n </div>\n )\n }\n\n // 4 tiles (or 4 visible with overflow on the last)\n return (\n <div\n className={classNames(\n // 379x286 is the content box of Figma's 383x290 stacked-media\n // card (`attachment-single-image` 1973:13863) once its 2px\n // frame is removed. Pinning the aspect on the container — as\n // this branch has always done — makes the card resolve to\n // exactly 383x290, and the 2px gutters then split it into\n // 188.5x142 tiles (Figma draws 188x142; its own 383 does not\n // divide evenly, so half a pixel goes to the columns).\n 'grid aspect-[379/286] w-full grid-cols-2 grid-rows-2 gap-0.5',\n className\n )}\n >\n {visible.map((tile, index) => {\n const isLastWithOverflow = overflow > 0 && index === visible.length - 1\n return renderTile(\n tile,\n index,\n isLastWithOverflow ? (\n <div className=\"absolute inset-0 flex items-center justify-center bg-black/55 text-2xl font-semibold text-white\">\n +{overflow}\n </div>\n ) : null\n )\n })}\n </div>\n )\n}\n\nexport default MediaStackGrid\n","import { useCallback, useState } from 'react'\n\n/**\n * Optional click handler used by every viewer-backed attachment.\n *\n * Return `false` to cancel the default open behavior — useful for\n * route-based viewers or confirmation modals. Any other return value\n * (including `void`/`undefined`) lets the built-in viewer open as\n * normal. The `index` argument identifies the row in stacked\n * attachments and is `0` for the single-attachment shape.\n */\nexport type ViewerClickHandler = (index: number) => boolean | void\n\nexport interface UseViewerResult {\n viewerOpen: boolean\n viewerIndex: number\n /**\n * Open the viewer at the given index. Forwards to the caller's\n * `onClick` first so analytics + intercept logic can fire before\n * the viewer mounts; if `onClick` returns `false` the open is\n * skipped entirely.\n */\n handleActivate: (index: number) => void\n closeViewer: () => void\n}\n\n/**\n * Tiny piece of state shared by every `MessageAttachment` that opens\n * a fullscreen viewer (`Image`, `Video`, `Pdf`). Tracks the open flag\n * + the active index, and threads the caller's `onClick` callback\n * through `handleActivate` so consumers can intercept the open\n * (e.g. analytics) or cancel it (return `false` to swap in a\n * route-based viewer / confirmation modal).\n */\nexport const useViewer = (onClick?: ViewerClickHandler): UseViewerResult => {\n const [viewerOpen, setViewerOpen] = useState(false)\n const [viewerIndex, setViewerIndex] = useState(0)\n\n const handleActivate = useCallback(\n (index: number) => {\n if (onClick?.(index) === false) return\n setViewerIndex(index)\n setViewerOpen(true)\n },\n [onClick]\n )\n\n const closeViewer = useCallback(() => setViewerOpen(false), [])\n\n return { viewerOpen, viewerIndex, handleActivate, closeViewer }\n}\n\nexport default useViewer\n","import React from 'react'\n\nimport { optimizeMessagingAttachmentUrl } from '../../../utils/cdnImageUrl'\nimport Bubble from '../_shared/Bubble'\nimport DismissButton from '../_shared/DismissButton'\nimport ImageViewer, {\n type ImageViewerItem,\n} from '../_shared/ImageViewer'\nimport MediaStackGrid, {\n type MediaStackTile,\n} from '../_shared/MediaStackGrid'\nimport { useViewer } from '../_shared/useViewer'\nimport {\n bubbleVariantForState,\n type ImageItem,\n type ImageLoadingMode,\n type MessageAttachmentBaseProps,\n type MessageAttachmentState,\n} from '../types'\n\nexport interface ImageAttachmentSharedProps extends MessageAttachmentBaseProps {\n /** Single image — convenience for the most common case. */\n src?: string\n alt?: string\n /** Filename used as the viewer dialog's accessible name. */\n filename?: string\n /**\n * Stacked images. Takes precedence over `src` when set. Renders a\n * 1 / 2 / 3 / 4-tile grid (5+ collapse into a `+N` overflow tile).\n * Sent + Received only — the composer surface intentionally accepts\n * a single attachment at a time.\n */\n items?: ImageItem[]\n /**\n * Native lazy-load hint forwarded to every `<img>` rendered on the\n * bubble surface (Composer thumbnail, single + stacked tiles, and\n * the `+N` overflow tile). Defaults to `'lazy'` — chat surfaces\n * usually scroll a long history, and lazy loading prevents every\n * historical image from being fetched on mount. Set `'eager'` for\n * above-the-fold hero attachments. Per-tile overrides live on\n * `ImageItem.loading`. The opened `ImageViewer` always eager-loads\n * the active image regardless of this value.\n */\n loading?: ImageLoadingMode\n /**\n * Forwarded to the Image viewer trigger. When omitted the click\n * still opens the built-in viewer — supply this for analytics, or\n * return `false` to intercept the open (e.g. switch to a route-\n * based gallery / confirmation modal). Any other return value\n * (including `void`/`undefined`) lets the built-in viewer open.\n * For stacked attachments the `index` argument identifies the tile.\n */\n onClick?: (index: number) => boolean | void\n}\n\nconst tileFromItem = ({\n item,\n index,\n totalCount,\n fallbackLoading,\n imgRef,\n onLoad,\n}: {\n item: ImageItem\n index: number\n totalCount: number\n fallbackLoading: ImageLoadingMode\n /** Set on the single-image tile only — see `useSingleImageRatio`. */\n imgRef?: React.Ref<HTMLImageElement>\n onLoad?: React.ReactEventHandler<HTMLImageElement>\n}): MediaStackTile => ({\n ariaLabel: `Open image ${index + 1} of ${totalCount}`,\n content: (\n // No corner radius here: `MediaStackGrid` clips the four outer\n // corners of the whole cluster and keeps every inner edge square.\n <img\n ref={imgRef}\n src={optimizeMessagingAttachmentUrl(item.src) ?? item.src}\n alt={item.alt ?? ''}\n width={item.width}\n height={item.height}\n draggable={false}\n loading={item.loading ?? fallbackLoading}\n decoding=\"async\"\n onLoad={onLoad}\n className=\"absolute inset-0 size-full object-cover\"\n />\n ),\n})\n\nconst resolveItems = ({\n src,\n alt,\n items,\n}: {\n src?: string\n alt?: string\n items?: ImageItem[]\n}): ImageItem[] => {\n if (items && items.length > 0) return items\n if (src) return [{ src, alt }]\n return []\n}\n\ninterface InternalImageRowProps extends ImageAttachmentSharedProps {\n state: MessageAttachmentState\n /**\n * Renders a dismiss button on each tile (Composer only). When the\n * stack has multiple tiles, the dismiss applies to the whole stack\n * — that mirrors the mobile composer where attachments are removed\n * as a single unit.\n */\n onDismiss?: () => void\n}\n\n/**\n * Project the bubble's `ImageItem`s onto the carousel-aware viewer's\n * `ImageViewerItem` shape. When a shared outer `filename` is supplied\n * for a stacked bubble, suffix `(N)` per sibling so each carousel page\n * still gets a distinct accessible name + download default.\n */\nconst buildViewerItems = (\n resolvedItems: ImageItem[],\n filename?: string\n): ImageViewerItem[] =>\n resolvedItems.map((item, index) => ({\n src: item.src,\n alt: item.alt,\n filename:\n filename && resolvedItems.length === 1\n ? filename\n : filename\n ? `${filename} (${index + 1})`\n : undefined,\n }))\n\n/**\n * Composer rendering — bare 280px-square image with a dismiss `×`\n * overlay and `rounded-md` corners. Intentionally renders without the\n * shared `Bubble` chrome (no border / no background / no padding) so\n * the in-progress attachment looks like a draft preview, not a sent\n * message. The composer surface only supports a single attachment at\n * a time — `items` and `text` are ignored here.\n */\nconst ImageComposerInner: React.FC<{\n src: string\n alt?: string\n filename?: string\n loading?: ImageLoadingMode\n onClick?: (index: number) => boolean | void\n onDismiss?: () => void\n}> = ({ src, alt, filename, loading = 'lazy', onClick, onDismiss }) => {\n const { viewerOpen, viewerIndex, handleActivate, closeViewer } = useViewer(\n onClick\n )\n\n return (\n <div className=\"relative w-fit\">\n <button\n type=\"button\"\n onClick={() => handleActivate(0)}\n aria-label=\"Open image\"\n className=\"block size-[280px] cursor-zoom-in overflow-hidden rounded-md outline-none focus-visible:ring-2 focus-visible:ring-black/40\"\n >\n <img\n src={optimizeMessagingAttachmentUrl(src) ?? src}\n alt={alt ?? ''}\n draggable={false}\n loading={loading}\n decoding=\"async\"\n className=\"size-full object-cover\"\n />\n </button>\n {onDismiss ? (\n <div className=\"absolute right-2 top-2 z-10\">\n <DismissButton onClick={onDismiss} />\n </div>\n ) : null}\n\n <ImageViewer\n open={viewerOpen}\n items={buildViewerItems([{ src, alt }], filename)}\n initialIndex={viewerIndex}\n onClose={closeViewer}\n />\n </div>\n )\n}\n\n/**\n * Box reserved for a single image whose ratio is not known yet — the\n * 4:3 landscape card Figma draws for the most common case (330×250\n * card, 326×246 content, `attachment-single-media` 1972:13149). A\n * bounded reserve keeps a scrolling thread from jumping by an\n * arbitrary amount between mount and decode.\n */\nconst RESERVED_SINGLE_ASPECT_RATIO = 326 / 246\n\n/**\n * Resolves the aspect ratio of a single-image bubble, in order:\n *\n * 1. caller-supplied `ImageItem.width` / `height` — ratio known at\n * first paint, so the card never resizes;\n * 2. the decoded `<img>`'s `naturalWidth` / `naturalHeight`;\n * 3. `RESERVED_SINGLE_ASPECT_RATIO`.\n *\n * Nothing propagates dimensions through the Stream path today, so (2)\n * is the branch that runs in production. It reads both on `load` and\n * from the ref, because an image already in the browser cache can be\n * `complete` before React attaches a `load` listener.\n */\nconst useSingleImageRatio = (item: ImageItem | undefined) => {\n const src = item?.src\n const [measured, setMeasured] = React.useState<{\n src: string\n ratio: number\n }>()\n\n const measure = React.useCallback(\n (img: HTMLImageElement | null) => {\n if (!img || img.naturalWidth <= 0 || img.naturalHeight <= 0) return\n if (src === undefined) return\n const ratio = img.naturalWidth / img.naturalHeight\n // Returning `prev` unchanged matters: the ref callback runs on\n // every commit, and a fresh object each time would schedule an\n // endless render loop.\n setMeasured((prev) =>\n prev && prev.src === src && prev.ratio === ratio ? prev : { src, ratio }\n )\n },\n [src]\n )\n\n const handleLoad = React.useCallback(\n (event: React.SyntheticEvent<HTMLImageElement>) =>\n measure(event.currentTarget),\n [measure]\n )\n\n const supplied =\n item?.width && item?.height ? item.width / item.height : undefined\n // Discard a measurement left over from a previous `src`.\n const measuredRatio =\n measured && measured.src === src ? measured.ratio : undefined\n\n return {\n ratio: supplied ?? measuredRatio ?? RESERVED_SINGLE_ASPECT_RATIO,\n imgRef: measure,\n onLoad: handleLoad,\n }\n}\n\n/**\n * Sent / Received rendering — wrapped in the shared `Bubble` chrome,\n * supports single or stacked items, and renders an optional caption\n * below the media.\n */\nconst ImageBubbleRow: React.FC<InternalImageRowProps> = ({\n state,\n src,\n alt,\n filename,\n items,\n text,\n groupPosition,\n loading = 'lazy',\n onClick,\n}) => {\n const resolvedItems = resolveItems({ src, alt, items })\n const variant = bubbleVariantForState(state)\n const { viewerOpen, viewerIndex, handleActivate, closeViewer } = useViewer(\n onClick\n )\n const isSingle = resolvedItems.length === 1\n const single = useSingleImageRatio(isSingle ? resolvedItems[0] : undefined)\n\n if (resolvedItems.length === 0) {\n return null\n }\n\n const tiles: MediaStackTile[] = resolvedItems.map((item, index) =>\n tileFromItem({\n item,\n index,\n totalCount: resolvedItems.length,\n fallbackLoading: loading,\n imgRef: isSingle ? single.imgRef : undefined,\n onLoad: isSingle ? single.onLoad : undefined,\n })\n )\n\n return (\n <Bubble\n variant={variant}\n text={text}\n groupPosition={groupPosition}\n // Media cards drop the 280px document width and the 8px inset\n // for a 2px frame around the media, at a uniform r20 that never\n // flattens against a caption bubble — `attachment-single-media`\n // 330×250 and `attachment-single-image` 383×290, both `pad2`\n // `cornerRadius: 20` with no stroke. The single card sizes to\n // the fitted media box (capped so a long in-bubble caption can\n // not stretch it past the 330px design maximum); the stacked\n // card is a fixed 383px, capped so it cannot overflow a narrow\n // viewport. `bordered={false}` because a hairline on top of the\n // 2px frame would read as a third edge and push the card 2px\n // over its measured width.\n bordered={false}\n widthClassName={\n isSingle\n ? 'w-fit max-w-[313px] sm:max-w-[330px]'\n : 'w-[383px] max-w-full'\n }\n paddingClassName=\"p-0.5\"\n radiusClassName=\"rounded-[20px]\"\n data-testid=\"image-attachment\"\n >\n <div className=\"relative\">\n <MediaStackGrid\n tiles={tiles}\n onTileActivate={handleActivate}\n singleAspectRatio={isSingle ? single.ratio : undefined}\n />\n </div>\n\n <ImageViewer\n open={viewerOpen}\n items={buildViewerItems(resolvedItems, filename)}\n initialIndex={viewerIndex}\n onClose={closeViewer}\n />\n </Bubble>\n )\n}\n\n/**\n * Composer-only props. Single image (`src`) is required; stacked\n * `items` and `text` captions are not supported in the composer state.\n */\nexport interface ImageComposerProps {\n src: string\n alt?: string\n filename?: string\n /**\n * Native lazy-load hint forwarded to the composer thumbnail `<img>`.\n * Defaults to `'lazy'`. See `ImageAttachmentSharedProps.loading` for\n * the rationale.\n */\n loading?: ImageLoadingMode\n onClick?: (index: number) => boolean | void\n onDismiss?: () => void\n}\n\nexport type ImageSentProps = ImageAttachmentSharedProps\nexport type ImageReceivedProps = ImageAttachmentSharedProps\n\nconst ImageComposer: React.FC<ImageComposerProps> = (props) => (\n <ImageComposerInner {...props} />\n)\nconst ImageSent: React.FC<ImageSentProps> = (props) => (\n <ImageBubbleRow {...props} state=\"sent\" />\n)\nconst ImageReceived: React.FC<ImageReceivedProps> = (props) => (\n <ImageBubbleRow {...props} state=\"received\" />\n)\n\nconst ImageAttachment = {\n Composer: ImageComposer,\n Sent: ImageSent,\n Received: ImageReceived,\n}\n\nexport default ImageAttachment\n","import React, { useMemo } from 'react'\n\nimport CarouselNav from './CarouselNav'\nimport { filenameFromUrl } from './fileMeta'\nimport { useCarousel } from './useCarousel'\nimport ViewerShell from './ViewerShell'\n\nexport interface PdfViewerItem {\n /** Source URL of the PDF document. */\n src: string\n /** Filename used as the dialog's accessible name. */\n filename?: string\n}\n\nexport interface PdfViewerProps {\n open: boolean\n items: PdfViewerItem[]\n /** Index to display when the viewer first opens. Defaults to `0`. */\n initialIndex?: number\n onClose: () => void\n}\n\n/**\n * Modal PDF viewer that hosts the active document inside a sandboxed\n * `<iframe>`, leaving native rendering, scroll, search, and the\n * browser's built-in download controls to the browser. The lightbox\n * chrome is intentionally just a close button plus, for stacked\n * attachments, carousel prev/next + counter.\n */\nconst PdfViewer: React.FC<PdfViewerProps> = ({\n open,\n items,\n initialIndex = 0,\n onClose,\n}) => {\n const { index, prev, next } = useCarousel({\n length: items.length,\n initialIndex,\n open,\n })\n\n const item = items[index]\n const filename = useMemo(\n () => item?.filename ?? (item ? filenameFromUrl(item.src) : 'document'),\n [item]\n )\n\n // `#toolbar=0` is honored by Chromium-family browsers and hides the\n // built-in PDF toolbar's redundant controls. Firefox / Safari ignore\n // it and keep their native toolbars, which is fine — the user gets a\n // familiar experience either way.\n //\n // Preserve any existing fragment the caller supplied (e.g.\n // `#page=3`) by merging our params into it rather than naively\n // appending a second `#…` segment.\n const iframeSrc = useMemo(\n () => (item ? withPdfViewerParams(item.src) : undefined),\n [item]\n )\n\n if (!item || !iframeSrc) return null\n\n return (\n <ViewerShell\n open={open}\n onClose={onClose}\n ariaLabel={filename}\n counter={\n items.length > 1 ? `${index + 1} / ${items.length}` : undefined\n }\n data-testid=\"pdf-viewer\"\n >\n <iframe\n // Force a key swap on item change so the iframe remounts a\n // fresh document rather than re-using the previous scroll\n // position / search state when the user navigates between\n // siblings.\n key={`${index}:${item.src}`}\n src={iframeSrc}\n title={filename}\n className=\"mes-media-viewer__iframe\"\n // Sandbox the iframe to stop the embedded document from\n // reaching parent context. We intentionally omit\n // `allow-same-origin`: even when the PDF host happens to share\n // our origin, granting it defeats the rest of the sandbox.\n // `allow-scripts` keeps the native PDF viewer's interactive\n // affordances (search, page nav, form filling) working,\n // `allow-downloads` lets the user save via the built-in\n // toolbar where it's still visible (Firefox / Safari), and\n // `allow-popups` lets external links inside the PDF open in a\n // new tab.\n sandbox=\"allow-scripts allow-forms allow-popups allow-downloads\"\n />\n\n {items.length > 1 ? (\n <CarouselNav\n onPrev={prev}\n onNext={next}\n prevLabel=\"Previous document\"\n nextLabel=\"Next document\"\n />\n ) : null}\n </ViewerShell>\n )\n}\n\n/**\n * Merge our PDF-viewer params (`toolbar=0`, `navpanes=0`) into the\n * URL's existing fragment so callers can still pass things like\n * `#page=3` without us clobbering them — naively appending\n * `#toolbar=0` to a URL that already has a fragment produces\n * `…#page=3#toolbar=0` which most readers ignore.\n */\nconst withPdfViewerParams = (src: string): string => {\n const hashIndex = src.indexOf('#')\n const base = hashIndex === -1 ? src : src.slice(0, hashIndex)\n const existing = hashIndex === -1 ? '' : src.slice(hashIndex + 1)\n\n const params = new URLSearchParams(existing)\n if (!params.has('toolbar')) params.set('toolbar', '0')\n if (!params.has('navpanes')) params.set('navpanes', '0')\n\n return `${base}#${params.toString()}`\n}\n\nexport default PdfViewer\n","import React from 'react'\n\nimport Bubble from '../_shared/Bubble'\nimport CompactDocumentRow from '../_shared/CompactDocumentRow'\nimport DismissButton from '../_shared/DismissButton'\nimport DownloadAction from '../_shared/DownloadAction'\nimport { filenameFromUrl } from '../_shared/fileMeta'\nimport PdfViewer, { type PdfViewerItem } from '../_shared/PdfViewer'\nimport { useViewer } from '../_shared/useViewer'\nimport {\n bubbleVariantForState,\n type BubbleVariant,\n type ComposerExtras,\n type MessageAttachmentBaseProps,\n type MessageAttachmentState,\n type PdfItem,\n} from '../types'\n\nexport interface PdfAttachmentSharedProps extends MessageAttachmentBaseProps {\n /** Single PDF — convenience for the most common case. */\n src?: string\n /** Filename — drives the row title + the meta line + the viewer dialog's accessible name. */\n filename?: string\n /** File size in bytes — formatted into the `EXT · SIZE` meta line. */\n fileSize?: number\n /**\n * Override displayed title (defaults to `filename`). Useful when a\n * sender re-titles a generated PDF before sending.\n */\n title?: string\n /**\n * Stacked PDFs. Takes precedence over `src` when set. Each item\n * renders as its own row inside the bubble; clicking a row opens\n * that PDF in the viewer. Sent + Received only — the composer\n * surface accepts a single attachment at a time.\n */\n items?: PdfItem[]\n /**\n * Forwarded to the viewer trigger. When omitted the click still\n * opens the built-in `PdfViewer`. Supply this to fire analytics, or\n * return `false` to intercept the open (e.g. swap to a route-based\n * viewer / confirmation modal). Any other return value (including\n * `void`/`undefined`) lets the built-in viewer open. For stacked\n * attachments the `index` argument identifies the row.\n */\n onClick?: (index: number) => boolean | void\n}\n\nconst resolveItems = ({\n src,\n filename,\n fileSize,\n title,\n items,\n}: {\n src?: string\n filename?: string\n fileSize?: number\n title?: string\n items?: PdfItem[]\n}): PdfItem[] => {\n if (items && items.length > 0) return items\n if (src) return [{ src, filename, fileSize, title }]\n return []\n}\n\ninterface PdfRowButtonProps {\n variant: BubbleVariant\n item: PdfItem\n index: number\n onActivate: (index: number) => void\n trailingAction?: React.ReactNode\n}\n\n/**\n * Single tappable PDF row — used both for the lone PDF case and for\n * each child of a stacked attachment. The icon + filename area opens\n * the viewer; the trailing slot hosts a separate, sibling button\n * (download or dismiss) so each affordance owns its own click target.\n */\nconst PdfRowButton: React.FC<PdfRowButtonProps> = ({\n variant,\n item,\n index,\n onActivate,\n trailingAction,\n}) => {\n const resolvedFilename = item.filename ?? filenameFromUrl(item.src)\n return (\n <CompactDocumentRow\n variant={variant}\n filename={resolvedFilename}\n title={item.title}\n mimeType=\"application/pdf\"\n fileSize={item.fileSize}\n onActivate={() => onActivate(index)}\n activateLabel={`Open ${resolvedFilename}`}\n trailingAction={trailingAction}\n />\n )\n}\n\ninterface InternalPdfRowProps extends PdfAttachmentSharedProps {\n state: MessageAttachmentState\n onDismiss?: () => void\n}\n\nconst PdfAttachmentRow: React.FC<InternalPdfRowProps> = ({\n state,\n src,\n filename,\n fileSize,\n title,\n items,\n text,\n groupPosition,\n onClick,\n onDismiss,\n}) => {\n const variant = bubbleVariantForState(state)\n const resolvedItems = resolveItems({ src, filename, fileSize, title, items })\n const { viewerOpen, viewerIndex, handleActivate, closeViewer } = useViewer(\n onClick\n )\n const showDismiss = state === 'composer' && !!onDismiss\n\n if (resolvedItems.length === 0) {\n return null\n }\n\n // Project the bubble's `PdfItem`s onto the viewer's carousel-aware\n // shape. The viewer clamps its own active index defensively, so we\n // don't need to second-guess `viewerIndex` here.\n const viewerItems: PdfViewerItem[] = resolvedItems.map((item) => ({\n src: item.src,\n filename: item.filename ?? filenameFromUrl(item.src),\n }))\n\n return (\n <Bubble\n variant={variant}\n text={text}\n groupPosition={groupPosition}\n data-testid=\"pdf-attachment\"\n >\n {/* Stacked rows get a small vertical gap so each PDF reads as\n a discrete attachment rather than one merged blob. Single\n row falls through to a no-op `gap-0`. */}\n <div className=\"flex flex-col gap-2\">\n {resolvedItems.map((item, index) => {\n const itemFilename = item.filename ?? filenameFromUrl(item.src)\n // Composer only supports a single attachment so the dismiss\n // control sits on the only row. Sent / Received rows expose\n // a download icon button so the user can grab the PDF\n // without opening the viewer first — the viewer dialog is\n // intentionally just the document + a close button, so this\n // sibling action is the only one-click download surface.\n const trailingAction =\n showDismiss && index === 0 ? (\n <DismissButton onClick={onDismiss!} variant=\"inline\" />\n ) : state === 'composer' ? undefined : (\n <DownloadAction\n url={item.src}\n filename={itemFilename}\n variant=\"inline\"\n label={`Download ${itemFilename}`}\n tone={variant}\n />\n )\n return (\n <PdfRowButton\n key={`${item.src}-${index}`}\n variant={variant}\n item={item}\n index={index}\n onActivate={handleActivate}\n trailingAction={trailingAction}\n />\n )\n })}\n </div>\n\n <PdfViewer\n open={viewerOpen}\n items={viewerItems}\n initialIndex={viewerIndex}\n onClose={closeViewer}\n />\n </Bubble>\n )\n}\n\n/**\n * Composer-only props. Single PDF (`src`) only — the composer surface\n * accepts a single attachment at a time, so `items` is not supported.\n * Captions (`text`) and `groupPosition` are also dropped: the composer\n * renders a standalone draft, not part of a same-author run, and\n * captions live in the message-input textarea, not inside the draft\n * attachment preview.\n */\nexport interface PdfComposerProps extends ComposerExtras {\n src?: string\n filename?: string\n fileSize?: number\n title?: string\n onClick?: (index: number) => boolean | void\n}\nexport type PdfSentProps = PdfAttachmentSharedProps\nexport type PdfReceivedProps = PdfAttachmentSharedProps\n\nconst PdfComposer: React.FC<PdfComposerProps> = (props) => (\n <PdfAttachmentRow {...props} state=\"composer\" />\n)\nconst PdfSent: React.FC<PdfSentProps> = (props) => (\n <PdfAttachmentRow {...props} state=\"sent\" />\n)\nconst PdfReceived: React.FC<PdfReceivedProps> = (props) => (\n <PdfAttachmentRow {...props} state=\"received\" />\n)\n\nconst PdfAttachment = {\n Composer: PdfComposer,\n Sent: PdfSent,\n Received: PdfReceived,\n}\n\nexport default PdfAttachment\n","import React, { useMemo } from 'react'\n\nimport type { MediaPreloadMode } from '../types'\n\nimport CarouselNav from './CarouselNav'\nimport { filenameFromUrl } from './fileMeta'\nimport { useCarousel } from './useCarousel'\nimport ViewerShell from './ViewerShell'\n\nexport interface VideoViewerItem {\n src: string\n poster?: string\n mimeType?: string\n filename?: string\n /**\n * Per-item `<video preload>` override. Defaults to `'metadata'`\n * for the active item so duration / first-frame are available\n * immediately. Non-active siblings aren't mounted here (we render\n * only `items[index]` at a time via a `key` swap), so they\n * naturally stay unloaded.\n */\n preload?: MediaPreloadMode\n}\n\nexport interface VideoViewerProps {\n open: boolean\n items: VideoViewerItem[]\n /** Index to display when the viewer first opens. Defaults to `0`. */\n initialIndex?: number\n onClose: () => void\n}\n\n/**\n * Full-viewport video viewer used by every `MessageAttachment.Video.*`\n * variant. Renders a single `<video controls>` element with the\n * browser's native chrome (play / pause / seek / fullscreen / volume /\n * download).\n *\n * When `items.length > 1` the viewer becomes a carousel — see\n * `ImageViewer` for the same behavior; arrow-key navigation yields to\n * the focused `<video>` so the native seek shortcuts still work.\n */\nconst VideoViewer: React.FC<VideoViewerProps> = ({\n open,\n items,\n initialIndex = 0,\n onClose,\n}) => {\n const { index, prev, next } = useCarousel({\n length: items.length,\n initialIndex,\n open,\n })\n\n const item = items[index]\n const filename = useMemo(\n () => item?.filename ?? (item ? filenameFromUrl(item.src) : 'video'),\n [item]\n )\n\n if (!item) return null\n\n return (\n <ViewerShell\n open={open}\n onClose={onClose}\n ariaLabel={filename}\n counter={\n items.length > 1 ? `${index + 1} / ${items.length}` : undefined\n }\n data-testid=\"video-viewer\"\n >\n {/* No `<track>` is rendered — we don't author caption sidecars\n for chat attachments, and an empty `<track kind=\"captions\" />`\n emits a runtime warning. Re-add a real track (with `src`,\n `srcLang`, and `default`) once caption support ships. */}\n <video\n // Forcing a key swap on item change ensures the new source\n // mounts a fresh element instead of reusing the previous\n // playback state — keeps the video paused-at-start when\n // navigating between stacked items.\n key={`${index}:${item.src}`}\n src={item.src}\n poster={item.poster}\n controls\n // `autoPlay` without `muted` is blocked by Chrome / Safari /\n // Firefox autoplay policies — the click that opens the viewer\n // doesn't count as a user-gesture for the freshly-mounted\n // `<video>` element. Defaulting to muted means playback\n // actually starts (matches how IG / Slack handle their video\n // lightboxes); the user can unmute via the native controls if\n // they want sound.\n autoPlay\n muted\n playsInline\n preload={item.preload ?? 'metadata'}\n className=\"mes-media-viewer__video\"\n >\n {item.mimeType ? <source src={item.src} type={item.mimeType} /> : null}\n </video>\n\n {items.length > 1 ? (\n <CarouselNav\n onPrev={prev}\n onNext={next}\n prevLabel=\"Previous video\"\n nextLabel=\"Next video\"\n />\n ) : null}\n </ViewerShell>\n )\n}\n\nexport default VideoViewer\n","import { PlayIcon, VideoCameraIcon } from '@phosphor-icons/react'\nimport React from 'react'\n\nimport Bubble from '../_shared/Bubble'\nimport DismissButton from '../_shared/DismissButton'\nimport MediaStackGrid, {\n type MediaStackTile,\n} from '../_shared/MediaStackGrid'\nimport { useViewer } from '../_shared/useViewer'\nimport VideoViewer, { type VideoViewerItem } from '../_shared/VideoViewer'\nimport {\n bubbleVariantForState,\n type MediaPreloadMode,\n type MessageAttachmentBaseProps,\n type MessageAttachmentState,\n type VideoItem,\n} from '../types'\n\nexport interface VideoAttachmentSharedProps extends MessageAttachmentBaseProps {\n /** Single video — convenience for the most common case. */\n src?: string\n /** Poster image — preview shown before playback starts. */\n poster?: string\n /** MIME type hint — typed onto the inline `<source>` element. */\n mimeType?: string\n /** Filename used as the viewer dialog's accessible name. */\n filename?: string\n /**\n * Stacked videos. Takes precedence over `src` when set. Renders a\n * 1 / 2 / 3 / 4-tile grid (5+ collapse into a `+N` overflow tile).\n * Sent + Received only — the composer surface intentionally accepts\n * a single attachment at a time.\n */\n items?: VideoItem[]\n /**\n * `<video preload>` hint forwarded into the viewer. Defaults to\n * `'none'` — the poster `<img>` carries the visual weight on the\n * bubble surface, and we shouldn't fetch any video bytes until the\n * user actually opens the viewer. Per-item overrides live on\n * `VideoItem.preload`. The opened `VideoViewer` always preloads\n * metadata for the active item (so duration / first-frame appear\n * immediately) regardless of this value.\n */\n preload?: MediaPreloadMode\n /**\n * Forwarded to the viewer trigger. When omitted the click still\n * opens the built-in `VideoViewer` — supply this for analytics, or\n * return `false` to intercept the open (e.g. switch to a route-\n * based player / confirmation modal). Any other return value\n * (including `void`/`undefined`) lets the built-in viewer open.\n * For stacked attachments the `index` argument identifies the tile.\n */\n onClick?: (index: number) => boolean | void\n}\n\nconst PlayBadge: React.FC = () => (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center\">\n <span className=\"flex size-12 items-center justify-center rounded-full bg-black/55 text-white backdrop-blur\">\n <PlayIcon className=\"size-6\" weight=\"fill\" aria-hidden />\n </span>\n </div>\n)\n\n// The tile shell owns the cluster's geometry: `MediaStackGrid` gives\n// each tile the 18px radius on the cluster's OUTER corners only and\n// clips with `overflow-hidden`, so a poster must carry no radius of\n// its own. A `rounded-md` here would round all four corners of every\n// tile at 6px, cutting dark wedges out of the `bg-[#0d0d0d]` backing\n// at each interior grid junction.\nconst PosterTile: React.FC<{ item: VideoItem; index: number }> = ({\n item,\n index,\n}) => (\n <div className=\"absolute inset-0 size-full bg-[#0d0d0d]\">\n {item.poster ? (\n <img\n src={item.poster}\n alt={`Video ${index + 1} thumbnail`}\n draggable={false}\n loading=\"lazy\"\n decoding=\"async\"\n className=\"absolute inset-0 size-full object-cover\"\n />\n ) : (\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <VideoCameraIcon\n className=\"size-16 text-white/30\"\n weight=\"regular\"\n aria-hidden\n />\n </div>\n )}\n <PlayBadge />\n </div>\n)\n\nconst tileFromItem = (\n item: VideoItem,\n index: number,\n totalCount: number\n): MediaStackTile => ({\n ariaLabel: `Play video ${index + 1} of ${totalCount}`,\n content: <PosterTile item={item} index={index} />,\n})\n\nconst resolveItems = ({\n src,\n poster,\n mimeType,\n preload,\n items,\n}: {\n src?: string\n poster?: string\n mimeType?: string\n preload?: MediaPreloadMode\n items?: VideoItem[]\n}): VideoItem[] => {\n if (items && items.length > 0) {\n return preload ? items.map((it) => ({ ...it, preload: it.preload ?? preload })) : items\n }\n if (src) return [{ src, poster, mimeType, preload }]\n return []\n}\n\ninterface InternalVideoRowProps extends VideoAttachmentSharedProps {\n state: MessageAttachmentState\n}\n\n/**\n * Project the bubble's `VideoItem`s onto the carousel-aware viewer's\n * `VideoViewerItem` shape. When a shared outer `filename` is supplied\n * for a stacked bubble, suffix `(N)` per sibling so each carousel page\n * still gets a distinct accessible name.\n */\nconst buildViewerItems = (\n resolvedItems: VideoItem[],\n filename?: string\n): VideoViewerItem[] =>\n resolvedItems.map((item, index) => ({\n src: item.src,\n poster: item.poster,\n mimeType: item.mimeType,\n preload: item.preload,\n filename:\n filename && resolvedItems.length === 1\n ? filename\n : filename\n ? `${filename} (${index + 1})`\n : undefined,\n }))\n\n/**\n * Composer rendering — bare 280px-square poster with a play badge,\n * a dismiss `×` overlay, and `rounded-md` corners. Renders without the\n * shared `Bubble` chrome (no border / no background / no padding) so\n * the in-progress attachment looks like a draft preview rather than a\n * sent message. Single attachment only — `items` and `text` are not\n * supported on the composer surface.\n */\nconst VideoComposerInner: React.FC<{\n src: string\n poster?: string\n mimeType?: string\n filename?: string\n preload?: MediaPreloadMode\n onClick?: (index: number) => boolean | void\n onDismiss?: () => void\n}> = ({ src, poster, mimeType, filename, preload, onClick, onDismiss }) => {\n const { viewerOpen, viewerIndex, handleActivate, closeViewer } = useViewer(\n onClick\n )\n\n return (\n <div className=\"relative w-fit\">\n <button\n type=\"button\"\n onClick={() => handleActivate(0)}\n aria-label=\"Play video\"\n className=\"relative block size-[280px] cursor-pointer overflow-hidden rounded-md outline-none focus-visible:ring-2 focus-visible:ring-black/40\"\n >\n <PosterTile item={{ src, poster, mimeType }} index={0} />\n </button>\n {onDismiss ? (\n <div className=\"absolute right-2 top-2 z-10\">\n <DismissButton onClick={onDismiss} />\n </div>\n ) : null}\n\n <VideoViewer\n open={viewerOpen}\n items={buildViewerItems(\n [{ src, poster, mimeType, preload }],\n filename\n )}\n initialIndex={viewerIndex}\n onClose={closeViewer}\n />\n </div>\n )\n}\n\n/**\n * Sent / Received rendering — wrapped in the shared `Bubble` chrome,\n * supports single or stacked items, and renders an optional caption\n * below the media.\n */\nconst VideoBubbleRow: React.FC<InternalVideoRowProps> = ({\n state,\n src,\n poster,\n mimeType,\n filename,\n items,\n text,\n groupPosition,\n preload,\n onClick,\n}) => {\n const resolvedItems = resolveItems({ src, poster, mimeType, preload, items })\n const variant = bubbleVariantForState(state)\n const { viewerOpen, viewerIndex, handleActivate, closeViewer } = useViewer(\n onClick\n )\n\n if (resolvedItems.length === 0) {\n return null\n }\n\n const tiles: MediaStackTile[] = resolvedItems.map((item, index) =>\n tileFromItem(item, index, resolvedItems.length)\n )\n\n return (\n <Bubble\n variant={variant}\n text={text}\n groupPosition={groupPosition}\n data-testid=\"video-attachment\"\n >\n <div className=\"relative\">\n <MediaStackGrid tiles={tiles} onTileActivate={handleActivate} />\n </div>\n\n <VideoViewer\n open={viewerOpen}\n items={buildViewerItems(resolvedItems, filename)}\n initialIndex={viewerIndex}\n onClose={closeViewer}\n />\n </Bubble>\n )\n}\n\n/**\n * Composer-only props. Single video (`src`) is required; stacked\n * `items` and `text` captions are not supported in the composer state.\n */\nexport interface VideoComposerProps {\n src: string\n poster?: string\n mimeType?: string\n filename?: string\n /**\n * `<video preload>` hint forwarded into the viewer. Defaults to\n * `'none'`. See `VideoAttachmentSharedProps.preload`.\n */\n preload?: MediaPreloadMode\n onClick?: (index: number) => boolean | void\n onDismiss?: () => void\n}\n\nexport type VideoSentProps = VideoAttachmentSharedProps\nexport type VideoReceivedProps = VideoAttachmentSharedProps\n\nconst VideoComposer: React.FC<VideoComposerProps> = (props) => (\n <VideoComposerInner {...props} />\n)\nconst VideoSent: React.FC<VideoSentProps> = (props) => (\n <VideoBubbleRow {...props} state=\"sent\" />\n)\nconst VideoReceived: React.FC<VideoReceivedProps> = (props) => (\n <VideoBubbleRow {...props} state=\"received\" />\n)\n\nconst VideoAttachment = {\n Composer: VideoComposer,\n Sent: VideoSent,\n Received: VideoReceived,\n}\n\nexport default VideoAttachment\n","import AudioAttachment, {\n type AudioComposerProps,\n type AudioReceivedProps,\n type AudioSentProps,\n} from './Audio'\nimport FileAttachment, {\n type FileComposerProps,\n type FileReceivedProps,\n type FileSentProps,\n} from './File'\nimport ImageAttachment, {\n type ImageComposerProps,\n type ImageReceivedProps,\n type ImageSentProps,\n} from './Image'\nimport PdfAttachment, {\n type PdfComposerProps,\n type PdfReceivedProps,\n type PdfSentProps,\n} from './Pdf'\nimport VideoAttachment, {\n type VideoComposerProps,\n type VideoReceivedProps,\n type VideoSentProps,\n} from './Video'\n\n/**\n * Per-MIME chat attachment cards used inside the messaging stream.\n *\n * Each subnamespace (`Image`, `Video`, `Audio`, `Pdf`, `File`) exposes\n * three states (`Composer`, `Sent`, `Received`) that map to the\n * sender / recipient sides of a chat:\n *\n * - `Composer` — sender draft state with a dismiss `×` affordance.\n * - `Sent` — sender-side state shown after posting.\n * - `Received` — recipient-side state.\n *\n * Sent / Received variants accept an optional `text` prop that renders\n * inside the same bubble as the attachment — mirroring the mobile chat\n * where a sender can pair a caption with an attachment ('Here is the\n * file', 'Here is the image'). Composer prop types intentionally omit\n * `text` (and `items` / `groupPosition`) so the type system enforces\n * the same contract: captions live in the message-input textarea, not\n * inside the draft attachment preview.\n *\n * Stacked attachments — every type except `Composer` accepts an\n * `items={[…]}` prop on Sent / Received that takes precedence over\n * the singular `src`/`filename`/etc. inputs:\n *\n * - Image / Video render a 1 / 2 / 3 / 4-tile grid (5+ collapse\n * into a `+N` overflow tile). Activating any tile opens the\n * built-in `ImageViewer` / `VideoViewer` at that index; when\n * `items.length > 1` the lightbox becomes a carousel (prev / next\n * chrome, ArrowLeft / ArrowRight, current / total counter) so the\n * user can browse siblings without closing the modal.\n * - Pdf / Audio / File render their compact rows / players in a\n * vertical stack with an 8px gap between rows. Each row keeps\n * its own activation target — Pdf opens the carousel-aware\n * `PdfViewer` at that index, Audio gets its own native player,\n * and File downloads the asset for that row.\n *\n * The Composer surface accepts only a single attachment at a time,\n * so its props omit `items` / `text`.\n *\n * Image / Video Composer renders bare — just the media with rounded\n * corners and a dismiss overlay, no surrounding bubble — so the draft\n * preview reads as an in-progress attachment instead of a sent\n * message. Sent / Received wrap the media in the shared bubble chrome.\n *\n * Image / Video / Pdf are interactive in every state (Composer, Sent,\n * Received) — clicks open the corresponding native lightbox `<dialog>`,\n * which centers the media at reasonable max dimensions (Escape and\n * backdrop click also dismiss). The Image viewer adds an explicit\n * download button to the chrome; the Video viewer relies on the\n * native `<video controls>` download menu, and the Pdf viewer\n * inherits the browser's built-in PDF download. Sibling-row Download\n * buttons on Pdf / File and the native `<audio>` controls expose\n * downloads outside the viewer too. The lightbox chrome is styled\n * with plain CSS (`.mes-media-viewer*`) so the package's shipped\n * stylesheet is enough to render the viewer correctly without a\n * Tailwind dependency in the consumer.\n *\n * # Lazy-loading defaults\n *\n * Media attachments bake in network-friendly defaults for long chat\n * histories and expose explicit escape hatches when a caller knows\n * better (e.g. a hero attachment that's already on-screen):\n *\n * - **Image** — every `<img>` rendered on the bubble surface\n * (Composer thumbnail, single + stacked tiles, `+N` overflow)\n * ships with `loading=\"lazy\" decoding=\"async\"`. Override via the\n * attachment's `loading` prop (or `ImageItem.loading` for per-tile\n * control). The opened `ImageViewer` always eager-loads the\n * active image so it appears immediately.\n * - **Video** — the `<video>` rendered inside the `VideoViewer`\n * defaults to `preload=\"none\"`, so no video bytes are fetched\n * until the user opens the viewer. Poster `<img>` thumbnails on\n * the bubble surface are `loading=\"lazy\" decoding=\"async\"`.\n * Override via the attachment's `preload` prop (or\n * `VideoItem.preload` per item). Once the viewer is open the\n * active item bumps to `preload=\"metadata\"` so duration / the\n * first frame appear immediately.\n * - **Audio** — a single audio bubble defaults to\n * `preload=\"metadata\"` so the native player surfaces duration\n * immediately. A stacked audio bubble (`items.length > 1`)\n * defaults to `preload=\"none\"` for every player so a thread of\n * voice memos doesn't fan out N parallel metadata requests on\n * first paint. Override via the attachment's `preload` prop\n * (or `AudioItem.preload` per track).\n * - **Pdf** / **File** — no inline media element to throttle; the\n * bubble renders compact rows that download / open lazily on\n * activation. No `loading` / `preload` props on these surfaces.\n */\nconst MessageAttachment = {\n Image: ImageAttachment,\n Video: VideoAttachment,\n Audio: AudioAttachment,\n Pdf: PdfAttachment,\n File: FileAttachment,\n}\n\nexport default MessageAttachment\n\nexport type {\n ImageComposerProps,\n ImageSentProps,\n ImageReceivedProps,\n VideoComposerProps,\n VideoSentProps,\n VideoReceivedProps,\n AudioComposerProps,\n AudioSentProps,\n AudioReceivedProps,\n PdfComposerProps,\n PdfSentProps,\n PdfReceivedProps,\n FileComposerProps,\n FileSentProps,\n FileReceivedProps,\n}\nexport type {\n ImageItem,\n ImageLoadingMode,\n VideoItem,\n PdfItem,\n AudioItem,\n FileItem,\n BubbleGroupPosition,\n MediaPreloadMode,\n MessageAttachmentBaseProps,\n MessageAttachmentState,\n} from './types'\nexport { bubbleGroupPositionFromStream } from './types'\nexport {\n formatFileSize,\n getFileExtensionLabel,\n buildCompactMetaLabel,\n} from './_shared/fileMeta'\n","import { createContext, useState } from 'react'\n\nimport type { BroadcastNameResolver } from '../../types'\n\n/** Live campaign names keyed by broadcast id — not the resolver function. */\nexport type BroadcastNamesById = Readonly<Record<string, string>>\n\nexport const BroadcastNameContext = createContext<\n BroadcastNamesById | undefined\n>(undefined)\n\nconst broadcastIdFromMessage = (message: {\n metadata?: { broadcast_id?: unknown }\n}): string | undefined => {\n const broadcastId = message.metadata?.broadcast_id\n return typeof broadcastId === 'string' ? broadcastId : undefined\n}\n\n/**\n * Resolve campaign names for the messages currently in view.\n *\n * Built outside memoized Stream rows so a new resolver reference can publish\n * new campaign names without remounting the Stream message rows.\n */\nexport const buildBroadcastNamesById = (\n messages: readonly { metadata?: { broadcast_id?: unknown } }[] | undefined,\n resolveBroadcastName: BroadcastNameResolver | undefined\n): BroadcastNamesById | undefined => {\n if (!resolveBroadcastName || !messages?.length) {\n return undefined\n }\n\n const seen = new Set<string>()\n let names: Record<string, string> | undefined\n\n for (const message of messages) {\n const broadcastId = broadcastIdFromMessage(message)\n if (!broadcastId || seen.has(broadcastId)) {\n continue\n }\n seen.add(broadcastId)\n\n const resolved = resolveBroadcastName(broadcastId)\n if (!resolved) {\n continue\n }\n\n names ??= {}\n names[broadcastId] = resolved\n }\n\n return names\n}\n\nconst areBroadcastNamesEqual = (\n previous: BroadcastNamesById | undefined,\n next: BroadcastNamesById | undefined\n): boolean => {\n if (previous === next) {\n return true\n }\n if (!previous || !next) {\n return false\n }\n\n const previousIds = Object.keys(previous)\n const nextIds = Object.keys(next)\n if (previousIds.length !== nextIds.length) {\n return false\n }\n\n return previousIds.every((id) => previous[id] === next[id])\n}\n\n/**\n * Re-invokes the resolver on every render, but only returns a new object when\n * the resolved strings actually change — so context consumers update for\n * late-arriving campaign names without thrashing on unrelated renders.\n */\nexport const useBroadcastNamesById = (\n messages: readonly { metadata?: { broadcast_id?: unknown } }[] | undefined,\n resolveBroadcastName: BroadcastNameResolver | undefined\n): BroadcastNamesById | undefined => {\n const names = buildBroadcastNamesById(messages, resolveBroadcastName)\n const [publishedNames, setPublishedNames] = useState<\n BroadcastNamesById | undefined\n >(names)\n\n if (!areBroadcastNamesEqual(publishedNames, names)) {\n setPublishedNames(names)\n return names\n }\n\n return publishedNames\n}\n","import type { Channel, LocalMessage } from 'stream-chat'\n\nimport type { PaymentStatus } from '../../../stream-custom-data'\n\nexport interface LockedAttachmentGalleryItem {\n /** Drives the per-item play/lock affordance. */\n mimeType: string\n /** Poster image, locked or unlocked. */\n thumbnailUrl?: string\n /** Media source, shown only when unlocked. */\n sourceUrl?: string\n}\n\nexport interface LockedAttachmentSource {\n /** Proxied URL for in-app playback. */\n sourceUrl: string\n /** Opened when the visitor clicks Download. */\n redeemUrl?: string\n /** Overrides the metadata thumbnail when present. */\n thumbnailUrl?: string\n}\n\nexport type { PaymentStatus }\n\n/** Fetches the underlying source; `void` return means none available. */\nexport type FetchSourceHandler = () => Promise<LockedAttachmentSource | void>\n\nexport interface LockedAttachmentContextValue {\n /** Whether the given message is mid-checkout. */\n isUnlocking: (id: string) => boolean\n /** Opens the checkout flow for a message. */\n onUnlockClick?: (message: LocalMessage, channel: Channel) => void\n /** Handles a Download click for a message. */\n onDownloadClick?: (message: LocalMessage, channel: Channel) => void\n /** Reveals the locked media's source. Unused for text — payment writes `message.text` directly. */\n onFetchSource?: (\n message: LocalMessage,\n channel: Channel\n ) => Promise<LockedAttachmentSource | void>\n}\n\nexport const defaultLockedAttachmentContextValue: LockedAttachmentContextValue = {\n isUnlocking: () => false,\n}\n","import { createContext, useContext } from 'react'\n\nimport { defaultLockedAttachmentContextValue, type LockedAttachmentContextValue } from './LockedAttachment/types'\n\nexport interface CustomMessageRegistry {\n LockedAttachment: LockedAttachmentContextValue\n}\n\nconst customMessageDefaults: CustomMessageRegistry = {\n LockedAttachment: defaultLockedAttachmentContextValue,\n}\n\nconst CustomMessageContext = createContext<Partial<CustomMessageRegistry>>({})\n\nexport const CustomMessageProvider = CustomMessageContext.Provider\n\nexport function useCustomMessage<K extends keyof CustomMessageRegistry>(key: K): CustomMessageRegistry[K] {\n const ctx = useContext(CustomMessageContext)\n return (ctx[key] ?? customMessageDefaults[key]) as CustomMessageRegistry[K]\n}\n","import React, { Suspense } from 'react'\n\nimport type {\n MediaCardDraftProps,\n MediaCardOtherProps,\n MediaCardOwnProps,\n MediaCardPreviewProps,\n} from './components/Media/types'\nimport type {\n TextCardOtherProps,\n TextCardOwnProps,\n} from './components/Text/types'\n\nconst TextCardLazy = React.lazy(() => import('./components/Text/Card'))\nconst MediaCardLazy = React.lazy(() => import('./components/Media/Card'))\n\nconst LockedAttachmentFallback = () => (\n <div\n className=\"w-[280px] min-h-[200px] animate-pulse rounded-md bg-black/[0.06] shadow-[0_0_0_1px_rgba(0,0,0,0.04),0_1px_2px_rgba(0,0,0,0.04),0_8px_32px_rgba(0,0,0,0.1)]\"\n aria-hidden\n />\n)\n\nexport type DraftProps = MediaCardDraftProps & {\n /** Drafting is always the sender — doesn't apply here. */\n isMine?: never\n /**\n * \"text\" renders as a chat bubble showing the real draft `text` instead of\n * a media thumbnail card. Media-only fields below are ignored in text mode.\n * Defaults to `\"media\"`.\n */\n contentType?: 'text' | 'media'\n /** The message's own text, shown as-is (not redacted yet). Only used when `contentType` is `\"text\"`. */\n renderedText?: React.ReactNode\n}\n\nexport type PreviewProps = MediaCardPreviewProps & {\n /** Drafting is always the sender — doesn't apply here. */\n isMine?: never\n /**\n * \"text\" renders as a chat bubble instead of a media thumbnail card.\n * Media-only fields below are ignored in text mode. Defaults to `\"media\"`.\n */\n contentType?: 'text' | 'media'\n}\n\nexport type SentTextOwnProps = TextCardOwnProps & {\n contentType: 'text'\n /** Sender's view has no unlock flow — doesn't apply here. */\n onUnlockClick?: never\n isUnlocking?: never\n}\n\nexport type SentTextOtherProps = TextCardOtherProps & {\n contentType: 'text'\n}\n\nexport type SentMediaOwnProps = MediaCardOwnProps & {\n contentType?: 'media'\n /** Sender's view has no unlock/download flow — doesn't apply here. */\n onUnlockClick?: never\n isUnlocking?: never\n onDownloadClick?: never\n}\n\nexport type SentMediaOtherProps = MediaCardOtherProps & {\n contentType?: 'media'\n}\n\n/**\n * The card for a paid attachment — a still-drafting `isDraft` card, a static\n * receiver-facing `isPreview` mockup, or a sent text/media card discriminated\n * by `isMine` + `contentType`. Internally lazy-loads only the one underlying\n * implementation the resolved branch needs.\n */\nexport type LockedAttachmentProps =\n | DraftProps\n | PreviewProps\n | SentTextOwnProps\n | SentTextOtherProps\n | SentMediaOwnProps\n | SentMediaOtherProps\n\nconst LockedAttachment: React.FC<LockedAttachmentProps> = (props) => {\n return (\n <Suspense fallback={<LockedAttachmentFallback />}>\n {props.contentType === 'text' ? (\n <TextCardLazy {...props} />\n ) : (\n <MediaCardLazy {...props} />\n )}\n </Suspense>\n )\n}\n\nexport default LockedAttachment\nexport { default as PurchaseStatusBadge } from './components/_shared/PurchaseStatusBadge'\nexport type { PurchaseStatusBadgeProps } from './components/_shared/PurchaseStatusBadge'\nexport type {\n PaymentStatus,\n FetchSourceHandler,\n LockedAttachmentSource,\n LockedAttachmentGalleryItem,\n LockedAttachmentContextValue,\n} from './types'\n","import { MESSAGE_CUSTOM_TYPE } from '@linktr.ee/messaging-taxonomy'\nimport { GiftIcon } from '@phosphor-icons/react'\nimport { LocalMessage } from 'stream-chat'\n\ninterface MessageTagProps {\n message: LocalMessage\n /** When true, renders as a standalone bubble instead of a small tag */\n standalone?: boolean\n /** When true, renders sender-side chatbot variants */\n isMyMessage?: boolean\n /** Whether the message includes an attachment */\n hasAttachment?: boolean\n}\n\nconst SparkleIcon = ({ size = 15 }: { size?: number }) => (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 15 15\"\n fill=\"none\"\n aria-hidden=\"true\"\n >\n <path\n d=\"M12.003 9a.985.985 0 0 1-.652.934l-3.223 1.191-1.188 3.226a.995.995 0 0 1-1.867 0l-1.195-3.226L.65 9.937a.995.995 0 0 1 0-1.867l3.227-1.195 1.187-3.226a.995.995 0 0 1 1.868 0l1.195 3.226 3.226 1.187a.99.99 0 0 1 .649.938m3-5.83a.52.52 0 0 1-.344.492l-1.702.63-.627 1.703a.525.525 0 0 1-.986 0l-.63-1.704-1.704-.627a.525.525 0 0 1 0-.986l1.703-.63.627-1.704a.526.526 0 0 1 .986 0l.631 1.703 1.704.627a.52.52 0 0 1 .342.495\"\n fill=\"currentColor\"\n fillOpacity={0.55}\n />\n </svg>\n)\n\n/** Check if a message is a tip based on metadata */\nexport const isTipMessage = (message: LocalMessage): boolean => {\n return message.metadata?.custom_type === MESSAGE_CUSTOM_TYPE.TIP\n}\n\n/** Check if a message is a paid message based on metadata */\nexport const isPaidMessage = (message: LocalMessage): boolean => {\n return message.metadata?.custom_type === MESSAGE_CUSTOM_TYPE.PAID\n}\n\n/** Check if a message is a chatbot message based on metadata */\nexport const isChatbotMessage = (message: LocalMessage): boolean => {\n return message.metadata?.custom_type === MESSAGE_CUSTOM_TYPE.CHATBOT\n}\n\n/** Check if a message is a locked attachment */\nexport const isAttachmentMessage = (message: LocalMessage): boolean => {\n return message.metadata?.custom_type === MESSAGE_CUSTOM_TYPE.ATTACHMENT\n}\n\nexport const isTextAttachmentMessage = (message: LocalMessage): boolean => {\n return (\n isAttachmentMessage(message) &&\n message.metadata?.attachment_content_type === 'text'\n )\n}\n\nexport const isMediaAttachmentMessage = (message: LocalMessage): boolean => {\n return (\n isAttachmentMessage(message) &&\n message.metadata?.attachment_content_type !== 'text'\n )\n}\n\n/** Check if a message has a tip or paid tag (shared layout, distinct copy) */\nexport const isTipOrPaidMessage = (message: LocalMessage): boolean => {\n return isTipMessage(message) || isPaidMessage(message)\n}\n\n/** Check if a message is a tip/paid-only message (no text) */\nexport const isTipOnlyMessage = (message: LocalMessage): boolean => {\n return isTipOrPaidMessage(message) && !message.text?.trim()\n}\n\nexport const MessageTag = ({\n message,\n standalone = false,\n isMyMessage = false,\n hasAttachment = false,\n}: MessageTagProps) => {\n const isTipOrPaid = isTipOrPaidMessage(message)\n const isChatbot = isChatbotMessage(message)\n\n if (!isTipOrPaid && !isChatbot) {\n return null\n }\n\n if (isTipOrPaid) {\n const amountText = message.metadata?.amount_text\n if (!amountText) return null\n\n const className = standalone\n ? 'message-tip-standalone'\n : 'message-tag message-tag--tip'\n\n const amountLabel = isPaidMessage(message) ? 'message' : 'tip'\n const label = standalone\n ? `${amountText} ${amountLabel}`\n : `Delivered with ${amountText} ${amountLabel}`\n\n return (\n <div className={className}>\n <GiftIcon size={standalone ? 14 : 12} />\n <span>{label}</span>\n </div>\n )\n }\n\n const isSenderAttachmentVariant = isMyMessage && hasAttachment\n const chatbotLabel = isSenderAttachmentVariant\n ? 'Sent with AI'\n : 'Sent by AI Assistant'\n\n const chatbotClassName = [\n 'message-chatbot-indicator',\n isMyMessage\n ? 'message-chatbot-indicator--sender'\n : 'message-chatbot-indicator--receiver',\n isSenderAttachmentVariant\n ? 'message-chatbot-indicator--attachment'\n : 'message-chatbot-indicator--text',\n ].join(' ')\n\n const label = (\n <span className=\"message-chatbot-indicator__label\">{chatbotLabel}</span>\n )\n const icon = (\n <span className=\"message-chatbot-indicator__icon\">\n <SparkleIcon size={isSenderAttachmentVariant ? 12 : 15} />\n </span>\n )\n\n // Chatbot indicator variant\n return (\n <div className={chatbotClassName} data-testid=\"message-chatbot-indicator\">\n {isMyMessage && !isSenderAttachmentVariant ? (\n <>\n {label}\n {icon}\n </>\n ) : (\n <>\n {icon}\n {label}\n </>\n )}\n </div>\n )\n}\n","import { ThumbsUpIcon, ThumbsDownIcon } from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React from 'react'\n\nimport type { VoteSelection } from '../../hooks/useMessageVote'\n\ninterface MessageVoteButtonsProps {\n selected: VoteSelection\n onVoteUp: () => void\n onVoteDown: () => void\n}\n\nexport const MessageVoteButtons: React.FC<MessageVoteButtonsProps> = ({\n selected,\n onVoteUp,\n onVoteDown,\n}) => (\n <div className=\"message-vote-buttons\">\n <button\n type=\"button\"\n className={classNames('message-vote-button focus-ring', {\n 'message-vote-button--selected': selected === 'up',\n })}\n onClick={onVoteUp}\n aria-label=\"Good response\"\n aria-pressed={selected === 'up'}\n data-tooltip=\"Good response\"\n >\n <ThumbsUpIcon size={16} weight={selected === 'up' ? 'fill' : 'regular'} />\n </button>\n <button\n type=\"button\"\n className={classNames('message-vote-button focus-ring', {\n 'message-vote-button--selected': selected === 'down',\n })}\n onClick={onVoteDown}\n aria-label=\"Bad response\"\n aria-pressed={selected === 'down'}\n data-tooltip=\"Bad response\"\n >\n <ThumbsDownIcon size={16} weight={selected === 'down' ? 'fill' : 'regular'} />\n </button>\n </div>\n)\n","import {\n ChecksIcon,\n CircleNotchIcon,\n MegaphoneIcon,\n WarningCircleIcon,\n} from '@phosphor-icons/react'\nimport {\n MessageStatus,\n useChannelStateContext,\n useMessageContext,\n} from 'stream-chat-react'\n\n/**\n * Message status stamps for sending and terminal `MessageStatus` states\n * (sent / delivered / read), plus failed messages.\n *\n * Two reasons this is more than a static label:\n *\n * 1. `MessageStatus` picks its `delivered`/`read` branches ahead of `sent`\n * whenever Stream has `deliveredTo`/`readBy`, and — unlike `sent` — those\n * branches aren't gated to the last message. So we override all three\n * terminal slots with this same label (never Stream's default delivered\n * icon / read avatars — Read is out of scope) and re-apply the \"latest\n * message in the thread\" gate ourselves.\n *\n * 2. We derive \"latest message\" from **live channel state**, not the message\n * context's `lastOwnMessage`/`lastReceivedId`. Stream's `Message` is\n * memoised by `areMessagePropsEqual`, which does not compare those props;\n * a previous own row whose message/grouping props are unchanged (e.g.\n * after an intervening incoming message) never re-renders, so the old\n * bubble would keep showing \"Delivered\" beside the new one.\n * `useChannelStateContext` gets a fresh `messages` array on every new\n * message and, being a context, re-renders this leaf straight through the\n * stale `Message`/`MessageStatus` memos — so the label reliably clears\n * once a reply lands. We still skip non-participant rows (`system`,\n * `ephemeral`, `deleted`) when finding the last real message so a trailing\n * system event does not clear the label.\n *\n * Rendered inside stream's `.str-chat__message-status` span, which supplies\n * the flex layout; icon and copy are styled via that span in `styles.css`.\n */\nconst useIsLatestRealMessage = () => {\n const { message } = useMessageContext('SentMessageDeliveryStatus')\n const { messages } = useChannelStateContext('SentMessageDeliveryStatus')\n\n const lastMessageId = (() => {\n if (!messages) {\n return undefined\n }\n\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n const lastMessage = messages[index]\n\n if (\n lastMessage.type === 'system' ||\n lastMessage.type === 'ephemeral' ||\n lastMessage.type === 'deleted'\n ) {\n continue\n }\n\n return lastMessage.id\n }\n\n return undefined\n })()\n\n return message.id === lastMessageId\n}\n\nconst DeliveredStatus = () => {\n if (!useIsLatestRealMessage()) return null\n\n return (\n <>\n <ChecksIcon weight=\"bold\" aria-hidden=\"true\" />\n <span data-testid=\"sent-message-delivery-status\">Delivered</span>\n </>\n )\n}\n\nconst SendingStatus = () => {\n if (!useIsLatestRealMessage()) return null\n\n return (\n <>\n <CircleNotchIcon\n className=\"sent-message-status__spinner animate-spin\"\n weight=\"bold\"\n aria-hidden=\"true\"\n />\n <span data-testid=\"sent-message-sending-status\">Sending</span>\n </>\n )\n}\n\nconst BroadcastStatus = ({\n broadcastId,\n broadcastName,\n resolvedBroadcastName,\n onBroadcastClick,\n}: {\n broadcastId: string\n broadcastName?: string\n resolvedBroadcastName?: string\n onBroadcastClick?: (broadcast: { id: string; name?: string }) => void\n}) => {\n const campaignName = resolvedBroadcastName || broadcastName\n const name = campaignName || 'Broadcast'\n const content = (\n <>\n <span className=\"sent-message-broadcast-badge\" aria-hidden=\"true\">\n <MegaphoneIcon weight=\"fill\" />\n </span>\n <span\n className=\"sent-message-broadcast-name\"\n data-testid=\"sent-message-broadcast-status\"\n >\n {name}\n </span>\n </>\n )\n\n return onBroadcastClick ? (\n <button\n type=\"button\"\n className=\"sent-message-broadcast-link\"\n aria-label={`View broadcast ${name}`}\n onClick={() =>\n onBroadcastClick({\n id: broadcastId,\n ...(campaignName ? { name: campaignName } : {}),\n })\n }\n >\n {content}\n </button>\n ) : (\n content\n )\n}\n\nconst FailedStatus = () => (\n <span className=\"str-chat__message-status sent-message-status--failed\">\n <WarningCircleIcon weight=\"bold\" aria-hidden=\"true\" />\n <span data-testid=\"sent-message-failed-status\">Failed to send</span>\n </span>\n)\n\n/**\n * Delivery status beneath the viewer's most recent sent message (MES-1036):\n * a right-aligned \"✓✓ Delivered\" that appears once Stream confirms the\n * message is stored and updates live.\n *\n * Built on stream-chat-react's `MessageStatus`, which owns the own-message /\n * not-error gating and only surfaces a terminal (sending/sent/delivered/read)\n * state once the message is stored. Stream's `threadList` guard covers\n * sent/delivered/read only — not `sending` — so we suppress the whole stamp\n * (including failed) in thread lists ourselves. Sending uses the same\n * latest-message-in-thread gate; failed messages bypass `MessageStatus`\n * because it has no failed slot and are shown on every own, non-thread\n * failed message.\n */\nexport const SentMessageDeliveryStatus = ({\n onBroadcastClick,\n resolvedBroadcastName,\n}: {\n onBroadcastClick?: (broadcast: { id: string; name?: string }) => void\n resolvedBroadcastName?: string\n}) => {\n const { isMyMessage, message, threadList } = useMessageContext(\n 'SentMessageDeliveryStatus'\n )\n const isOwnMessage = isMyMessage()\n const isLatestRealMessage = useIsLatestRealMessage()\n\n // Stream's MessageStatus still mounts MessageSendingStatus when\n // threadList is true; keep all of our stamps out of thread replies.\n if (threadList) {\n return null\n }\n\n if (message.status === 'failed' && isOwnMessage && message.type !== 'error') {\n return <FailedStatus />\n }\n\n if (!isOwnMessage) {\n return null\n }\n\n const broadcastId = message.metadata?.broadcast_id\n const broadcastName = message.metadata?.broadcast_name\n const broadcastStatus =\n message.status !== 'sending' &&\n message.status !== 'failed' &&\n broadcastId ? (\n <BroadcastStatus\n broadcastId={broadcastId}\n broadcastName={broadcastName}\n resolvedBroadcastName={resolvedBroadcastName}\n onBroadcastClick={onBroadcastClick}\n />\n ) : null\n\n const messageStatus = (\n <MessageStatus\n MessageSentStatus={DeliveredStatus}\n MessageDeliveredStatus={DeliveredStatus}\n MessageReadStatus={DeliveredStatus}\n MessageSendingStatus={SendingStatus}\n />\n )\n\n if (!broadcastStatus) {\n return messageStatus\n }\n\n return (\n <span className=\"sent-message-status-row\">\n {messageStatus}\n {isLatestRealMessage && (\n <span\n className=\"sent-message-broadcast-separator\"\n aria-hidden=\"true\"\n >\n •\n </span>\n )}\n {broadcastStatus}\n </span>\n )\n}\n","/**\n * Scheme detector: `protocol:` per RFC 3986 — a letter followed by any\n * combination of letters, digits, `+`, `.`, or `-` then `:`.\n */\nconst SCHEME_PATTERN = /^([a-z][a-z0-9+.-]*):/i\n\n/**\n * Allowlist of schemes that are safe to forward into `<a href>` for\n * external navigation. `javascript:` / `data:` / `vbscript:` etc. are\n * intentionally **not** on this list — link-attachment data is\n * effectively user-controlled, so passing them through would let a\n * recipient click execute attacker-supplied code or markup.\n */\nconst SAFE_SCHEMES = new Set(['http', 'https', 'mailto', 'tel', 'sms'])\n\n/**\n * Normalize a user-supplied URL into something safe to assign to\n * `<a href>` for external navigation.\n *\n * Link attachments / link apps always point at external destinations\n * (Spotify, TikTok, FAQ links, bare-hostname Linktree URLs like\n * `tr.ee/briemix`, etc.). Without normalization, a bare hostname is\n * treated as a relative path by the browser and clicks navigate within\n * the host site (e.g. `https://linktr.ee/admin/tr.ee/briemix`) instead\n * of opening the intended destination.\n *\n * Rules:\n * - Empty / whitespace-only → returns `undefined` (no href).\n * - Explicit scheme in the safe allowlist (`http`, `https`, `mailto`,\n * `tel`, `sms`) → returned trimmed.\n * - Explicit scheme **not** on the allowlist (`javascript:`, `data:`,\n * `vbscript:`, custom protocols, …) → returns `undefined` so the\n * shell falls back to a non-navigational chrome instead of letting\n * an attacker-controlled URL execute on click.\n * - Protocol-relative (`//example.com/…`) → returned as-is; browsers\n * resolve these against the current page's scheme.\n * - Site-relative path (`/admin/…`) → returned as-is so consumers can\n * still opt into in-app navigation if they really want to.\n * - Bare hostname or anything else → `https://` is prepended so the\n * browser treats it as an external URL.\n */\nexport function normalizeExternalHref(value?: string): string | undefined {\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n if (trimmed === '') return undefined\n\n const schemeMatch = SCHEME_PATTERN.exec(trimmed)\n if (schemeMatch) {\n const scheme = schemeMatch[1].toLowerCase()\n return SAFE_SCHEMES.has(scheme) ? trimmed : undefined\n }\n\n if (trimmed.startsWith('//')) return trimmed\n if (trimmed.startsWith('/')) return trimmed\n return `https://${trimmed}`\n}\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport type { LinkAttachmentCta } from '../../types'\n\nimport type { LinkAttachmentVariant } from './CardShell'\nimport { normalizeExternalHref } from './normalizeExternalHref'\n\nexport interface CardCtaProps {\n variant: LinkAttachmentVariant\n cta: LinkAttachmentCta\n}\n\nconst BUTTON_CLASS_BY_VARIANT: Record<LinkAttachmentVariant, string> = {\n dark: 'bg-white text-[#121110] hover:bg-white/90',\n light: 'bg-[#121110] text-white hover:bg-[#2a2928]',\n}\n\n/**\n * Pill-shaped CTA rendered below the description on Link App cards that\n * surface an action instead of a URL (e.g. FAQ \"View FAQs\", Form \"Complete form\").\n * Renders as `<a target=\"_blank\">` when `cta.href` is set, otherwise as a\n * plain `<button>`.\n */\nconst CardCta: React.FC<CardCtaProps> = ({ variant, cta }) => {\n const className = classNames(\n 'mt-2 inline-flex h-10 w-full items-center justify-center rounded-full px-4 text-sm font-medium leading-none transition-colors',\n BUTTON_CLASS_BY_VARIANT[variant]\n )\n\n // Mirror the URL normalization used by the shell anchor so bare\n // hostnames (e.g. `tr.ee/foo`) open as external links rather than\n // resolving against the current host.\n const normalizedHref = normalizeExternalHref(cta.href)\n\n if (normalizedHref) {\n return (\n <a\n href={normalizedHref}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n onClick={(e) => {\n // Stop the click from bubbling up to the card's anchor wrapper\n // (Received variant) so we don't navigate twice.\n e.stopPropagation()\n cta.onClick?.()\n }}\n className={`${className} no-underline`}\n >\n {cta.label}\n </a>\n )\n }\n\n return (\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation()\n cta.onClick?.()\n }}\n className={className}\n >\n {cta.label}\n </button>\n )\n}\n\nexport default CardCta\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport type { LinkAttachmentCta } from '../../types'\n\nimport CardCta from './CardCta'\nimport type { LinkAttachmentVariant } from './CardShell'\n\nexport interface CardBodyProps {\n variant: LinkAttachmentVariant\n title?: string\n /** Placeholder shown in the title slot when no title is set (dark variants only). */\n placeholderTitle?: string\n description?: string\n /** Footer URL shown below the description. Ignored when `cta` is set. */\n url?: string\n /**\n * Ink for both chin lines, from `chinContrast.inkFor` — measured against the\n * surface this card actually paints, which may be a derived accent, the audio\n * strip, or the variant fallback. Replaces the variant's own `text-*` classes\n * (including their opacity) on both lines, so a card whose surface is not the\n * variant default still reads (MES-1388).\n */\n chinTextColor?: string\n /**\n * Optional 16x16 brand badge rendered before the title (used by Link Apps:\n * Spotify, TikTok, FAQ, Form, etc.).\n */\n appIcon?: React.ReactNode\n /** Optional CTA rendered in place of the URL footer. */\n cta?: LinkAttachmentCta\n /** Trailing action rendered on the right of the title/description block. */\n trailingAction?: React.ReactNode\n /** Renders two neutral pulsing bars in place of the text. */\n isLoading?: boolean\n}\n\nconst TITLE_CLASS_BY_VARIANT: Record<LinkAttachmentVariant, string> = {\n dark: 'text-white',\n light: 'text-black/90',\n}\n\nconst TITLE_DIMMED_CLASS = 'text-white/30'\n\nconst SECONDARY_CLASS_BY_VARIANT: Record<LinkAttachmentVariant, string> = {\n dark: 'text-white/55',\n light: 'text-black/55',\n}\n\n// Skeleton bars, variant-aware for the same reason the placeholder hero is: a\n// fixed dark tint is invisible on the dark card's own dark fill. Values\n// match `SkeletonTextLines`, the toolkit's existing skeleton bars, which also\n// documents why these are explicit black/white rather than `bg-current/N`\n// (Tailwind emits nothing for an opacity modifier on `current`).\nconst SKELETON_BAR_CLASS_BY_VARIANT: Record<LinkAttachmentVariant, string> = {\n dark: 'bg-white/25',\n light: 'bg-black/15',\n}\n\n/**\n * Body of a `LinkAttachment.*` card — the \"chin\". Matches the Figma\n * `content > Labels` group: 16px horizontal padding, 12px vertical padding,\n * 2px gap between the title and the URL. `shrink-0` so it keeps its natural\n * height inside the shell's fixed-height column and the hero absorbs the\n * remainder.\n *\n * Returns `null` when there's nothing to render so plain image / file\n * attachments collapse to a thumbnail-only card — unless the card is still\n * loading, when the skeleton *is* the content.\n */\nconst CardBody: React.FC<CardBodyProps> = ({\n variant,\n chinTextColor,\n title,\n placeholderTitle,\n description,\n url,\n appIcon,\n cta,\n trailingAction,\n isLoading = false,\n}) => {\n const isDark = variant === 'dark'\n const displayTitle = title ?? (isDark ? placeholderTitle : undefined) ?? ''\n const hasTitle = displayTitle.trim() !== ''\n const hasDescription = description != null && description.trim() !== ''\n // Mirror the trimming applied by `ReceivedCard` so a whitespace-only\n // `url` collapses the body footer (and the whole body, for media-only\n // cards) instead of rendering an empty line.\n const trimmedUrl = typeof url === 'string' ? url.trim() : ''\n const hasUrl = trimmedUrl !== ''\n const hasCta = cta != null\n\n if (!isLoading && !hasTitle && !hasDescription && !hasUrl && !hasCta) {\n return null\n }\n\n const titleDimmed = isDark && !title\n\n const titleClass = classNames(\n 'line-clamp-2 text-[14px] font-medium leading-5 tracking-[0.28px]',\n chinTextColor == null &&\n (titleDimmed ? TITLE_DIMMED_CLASS : TITLE_CLASS_BY_VARIANT[variant])\n )\n\n const secondaryClass = classNames(\n 'truncate text-[12px] leading-4 tracking-[0.24px]',\n chinTextColor == null && SECONDARY_CLASS_BY_VARIANT[variant]\n )\n\n if (isLoading) {\n const barClass = classNames(\n 'animate-pulse rounded',\n SKELETON_BAR_CLASS_BY_VARIANT[variant]\n )\n\n return (\n <div className=\"shrink-0 px-4 py-3\">\n <div className=\"flex min-w-0 flex-col gap-[2px]\">\n {/* Sized to the lines they stand in for: 14/20 title, 12/16 URL. */}\n <div className={classNames('h-5 w-3/4', barClass)} aria-hidden />\n <div className={classNames('h-4 w-1/2', barClass)} aria-hidden />\n </div>\n </div>\n )\n }\n\n const chinTextStyle = chinTextColor ? { color: chinTextColor } : undefined\n\n return (\n <div className=\"shrink-0 px-4 py-3\">\n <div className=\"flex items-end gap-3\">\n <div className=\"flex min-w-0 flex-1 flex-col gap-[2px]\">\n {hasTitle && (\n <div className=\"flex min-w-0 items-center gap-2\">\n {appIcon ? <span className=\"shrink-0\">{appIcon}</span> : null}\n <p\n className={classNames('min-w-0', titleClass)}\n style={chinTextStyle}\n >\n {displayTitle}\n </p>\n </div>\n )}\n\n {hasDescription && (\n <p className={secondaryClass} style={chinTextStyle}>\n {description}\n </p>\n )}\n\n {!hasCta && hasUrl && (\n <p className={secondaryClass} style={chinTextStyle}>\n {trimmedUrl}\n </p>\n )}\n </div>\n\n {trailingAction && <div className=\"shrink-0\">{trailingAction}</div>}\n </div>\n\n {cta && <CardCta variant={variant} cta={cta} />}\n </div>\n )\n}\n\nexport default CardBody\n","import classNames from 'classnames'\nimport React from 'react'\n\nexport type LinkAttachmentVariant = 'dark' | 'light'\n\nexport interface CardShellProps {\n variant: LinkAttachmentVariant\n children: React.ReactNode\n /**\n * When provided, the entire card chrome is rendered as an anchor (used\n * by Sent / Received cards to open the link target on click). Falls\n * back to a `<div>` when omitted so Composer cards stay\n * non-navigational while drafting.\n */\n href?: string\n /**\n * Click handler for the card chrome. When `href` is set the shell is an\n * anchor and `onClick` is invoked in addition to navigation. When `href`\n * is omitted but `onClick` is set, the shell renders as a clickable\n * button (used by media-only Received cards to open an image preview).\n */\n onClick?: () => void\n /** Accessible label for the clickable variant (when `onClick` is set without `href`). */\n ariaLabel?: string\n rootRef?: React.Ref<HTMLElement>\n /**\n * Absolutely-positioned slot rendered in the top-right corner of the\n * shell. Used by the Composer card to surface its dismiss affordance\n * when there's no hero thumbnail to anchor it to.\n */\n topRight?: React.ReactNode\n /**\n * Overrides the variant-derived background colour (e.g. audio cards\n * use `bg-[#F2F3F4]` regardless of the dark/light variant).\n */\n bgClassName?: string\n /**\n * Inline background for the dynamic accent colour extracted from the\n * attachment image. Wins over `bgClassName` / the variant default when\n * set — Tailwind cannot express a runtime hex.\n */\n accentStyle?: React.CSSProperties\n /**\n * Locks the card to Figma's 250px box and makes it a flex column, so the\n * hero absorbs whatever height the chin leaves. Only the `featured` layout\n * is drawn at a fixed height — `classic` cards and the audio-player card\n * size to their content.\n */\n fixedHeight?: boolean\n /**\n * Renders the shell as a labelled busy region while the link preview is\n * still being fetched. `role=\"status\"` is what makes `aria-label` legal\n * (and announced) on an otherwise generic container.\n */\n busy?: boolean\n 'data-testid'?: string\n}\n\n/**\n * Accessible name for the loading skeleton. Hardcoded English, matching the\n * toolkit's existing convention (`aria-label=\"Dismiss attachment\"`) — there\n * is no i18n layer here.\n */\nexport const LOADING_LABEL = 'Loading link preview'\n\nconst SHELL_CLASS = classNames(\n 'relative w-[290px] select-none overflow-hidden',\n // 20px corners — no token exists for it in the component-library preset,\n // whose radius scale is sm .5rem / md 1rem / lg 1.5rem / xl 4rem.\n 'rounded-[20px]'\n)\n\n// The 290x250 lock: the chin takes the height its 1-2 line title needs\n// (82px at two lines, 62px at one) and the hero absorbs the remainder.\nconst FIXED_HEIGHT_CLASS = 'flex h-[250px] flex-col'\n\n/**\n * Outer chrome for every `LinkAttachment.*` card. Matches the 290px x 250px\n * box, 20px corner radius, and borderless / shadowless treatment of the\n * composer and sent instances in Figma.\n */\nconst CardShell: React.FC<CardShellProps> = ({\n variant,\n children,\n href,\n onClick,\n ariaLabel,\n rootRef,\n topRight,\n bgClassName,\n accentStyle,\n fixedHeight = false,\n busy = false,\n 'data-testid': dataTestId,\n}) => {\n const isInteractive = href != null || onClick != null\n const className = classNames(\n SHELL_CLASS,\n fixedHeight ? FIXED_HEIGHT_CLASS : 'block',\n // Kept underneath `accentStyle` rather than swapped out: the inline\n // background wins on specificity, and leaving the class in place means\n // an accent that somehow doesn't paint still lands on a sane surface.\n //\n // MUST be an arbitrary value, not a theme token. This package ships no\n // Tailwind utilities — `dist/assets/index.css` is only the hand-written\n // `.str-chat`/`.mes-*` CSS — so consumers generate our classes by scanning\n // `messaging-react/dist` against *their own* theme. `shade` comes from the\n // component-library preset that this package builds with; frontyard builds\n // on the Arbor preset and has no such colour, so `bg-shade` was silently\n // dropped, the chin rendered transparent, and the own-message `color: white`\n // left the title and URL invisible (MES-1388). An arbitrary value is\n // generated from the class name alone and cannot depend on consumer theme.\n //\n // Both values are the plain message bubble's own fill, so a card with no\n // usable accent matches the text bubbles around it: `#1e2330` is\n // `--str-chat__own-message-bubble-background-color` and `#f1f0ee` is\n // `--str-chat__message-bubble-background-color`. Mirrored in\n // `chinContrast.BUBBLE_BG_BY_VARIANT`, which the bubble tail reads.\n bgClassName ?? (variant === 'dark' ? 'bg-[#1e2330]' : 'bg-[#f1f0ee]'),\n // `focus-ring` is a design-system utility from the component-library\n // tailwind preset — outline-none + a black 2px focus-visible ring\n // with offset, so keyboard users can see the focused card.\n isInteractive ? 'cursor-pointer no-underline focus-ring' : null\n )\n\n const busyProps = busy\n ? { role: 'status', 'aria-busy': true, 'aria-label': LOADING_LABEL }\n : undefined\n\n const corner = topRight ? (\n <div className=\"pointer-events-auto absolute right-3 top-3 z-10\">\n {topRight}\n </div>\n ) : null\n\n if (href) {\n return (\n <a\n ref={rootRef as React.Ref<HTMLAnchorElement>}\n href={href}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n onClick={onClick}\n data-testid={dataTestId}\n className={className}\n style={accentStyle}\n {...busyProps}\n >\n {children}\n {corner}\n </a>\n )\n }\n\n if (onClick) {\n return (\n <button\n ref={rootRef as React.Ref<HTMLButtonElement>}\n type=\"button\"\n onClick={onClick}\n aria-label={ariaLabel}\n data-testid={dataTestId}\n className={classNames(className, 'text-left')}\n style={accentStyle}\n {...busyProps}\n >\n {children}\n {corner}\n </button>\n )\n }\n\n return (\n <div\n ref={rootRef as React.Ref<HTMLDivElement>}\n data-testid={dataTestId}\n className={className}\n style={accentStyle}\n {...busyProps}\n >\n {children}\n {corner}\n </div>\n )\n}\n\nexport default CardShell\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport { optimizeMessagingAttachmentUrl } from '../../../../utils/cdnImageUrl'\nimport { renderTypeIcon } from '../../../AttachmentCard'\nimport { getSourceType } from '../../../AttachmentCard/utils/mimeType'\n\nimport type { LinkAttachmentVariant } from './CardShell'\n\nexport interface CardThumbnailProps {\n variant: LinkAttachmentVariant\n /** Source URL of the hero image (or poster for video). */\n thumbnailUrl?: string\n /**\n * Playable media URL. When provided alongside a video / audio `mimeType`,\n * the hero region renders a native HTML5 player with controls instead of\n * the static thumbnail / placeholder.\n */\n sourceUrl?: string\n /** Alt text — typically the card's title. */\n title?: string\n /**\n * Drives the placeholder type icon when no `thumbnailUrl` is provided,\n * and selects between image / video / audio rendering when `sourceUrl`\n * is set. Defaults to a generic image icon when unset.\n */\n mimeType?: string\n /** Optional decorations layered into the top corners of the thumbnail. */\n topLeft?: React.ReactNode\n topRight?: React.ReactNode\n /**\n * Renders a neutral pulsing block instead of the image while the link\n * preview is still being fetched.\n */\n isLoading?: boolean\n /**\n * Fired when the hero image fails to load. The owning card clears\n * `thumbnailUrl` (so the type-icon placeholder takes over) and drops the\n * accent colour, which was derived from an image the viewer cannot see.\n */\n onImageError?: () => void\n}\n\nconst PLACEHOLDER_BG: Record<LinkAttachmentVariant, string> = {\n dark: 'bg-white/10',\n light: 'bg-black/5',\n}\n\nconst PLACEHOLDER_ICON: Record<LinkAttachmentVariant, string> = {\n dark: 'size-16 text-white/25',\n light: 'size-16 text-black/25',\n}\n\n/** Mime + sourceUrl gives us a playable audio attachment. */\nexport const isPlayableAudio = (mimeType?: string, sourceUrl?: string) =>\n !!sourceUrl && !!mimeType && getSourceType(mimeType) === 'audio'\n\n/**\n * Mime + sourceUrl gives us a playable video or audio attachment. Used by\n * Received to skip wrapping the shell in an interactive `<button>` so the\n * native media controls remain operable.\n */\nexport const isPlayableMedia = (mimeType?: string, sourceUrl?: string) => {\n if (!sourceUrl || !mimeType) return false\n const source = getSourceType(mimeType)\n return source === 'video' || source === 'audio'\n}\n\n/**\n * Background colour the LinkAttachment cards switch to when the source is\n * audio — flat neutral around the native `<audio>` chrome regardless of\n * the dark / light variant.\n *\n * The hex is exported alongside the class because the card's ink is chosen by\n * measuring contrast against whatever surface it lands on, and contrast needs\n * channels rather than a class name. They are written out twice on purpose:\n * Tailwind only generates utilities it can find as complete literals when it\n * scans `dist`, so building the class from the constant\n * (`` `bg-[${AUDIO_BG}]` ``) would emit nothing at all. `chinContrast.test.ts`\n * asserts the two stay in step.\n */\nexport const AUDIO_BG = '#F2F3F4'\nexport const AUDIO_BG_CLASS = 'bg-[#F2F3F4]'\n\n/**\n * Hero region shown above the card body. Inside the `featured` card's fixed\n * 250px box it takes `flex-1`, absorbing whatever height the chin leaves.\n * Renders, in priority order: a loading placeholder, a native\n * `<video controls>` / `<audio controls>` when `sourceUrl` + mime say so, the\n * thumbnail image, then a type-icon placeholder.\n */\nconst CardThumbnail: React.FC<CardThumbnailProps> = ({\n variant,\n thumbnailUrl,\n sourceUrl,\n title,\n mimeType = 'image/*',\n topLeft,\n topRight,\n isLoading = false,\n onImageError,\n}) => {\n const sourceType = getSourceType(mimeType)\n const isPlayableVideo = !!sourceUrl && sourceType === 'video'\n const optimizedThumbnailUrl = optimizeMessagingAttachmentUrl(thumbnailUrl)\n\n // `!isLoading` first, deliberately: while the scrape is in flight we do not\n // yet know what the asset is, so honouring a `mimeType` the caller happens to\n // have set already would mount a live player next to `CardBody`'s skeleton\n // bars. The loading branch below owns every hero shape (MES-1349).\n if (!isLoading && isPlayableAudio(mimeType, sourceUrl)) {\n // Audio collapses the hero entirely — the native player sits inside\n // the card chrome with a bit of padding so the card background\n // (typically `bg-[#F2F3F4]`) is visible around it.\n return (\n <div className=\"p-3\">\n <audio\n src={sourceUrl}\n controls\n preload=\"metadata\"\n className=\"block w-full\"\n >\n <track kind=\"captions\" />\n </audio>\n </div>\n )\n }\n\n return (\n <div\n className={classNames(\n // `flex-1 min-h-0` inside the shell's 250px column: the hero takes\n // every pixel the chin doesn't, which is 168px at a two-line title\n // and 188px at one.\n 'relative min-h-0 w-full flex-1 overflow-hidden',\n isPlayableVideo && 'bg-black'\n )}\n >\n {isLoading ? (\n // Reuses the placeholder fill: a fixed `bg-black/[0.06]` would be\n // invisible on the dark card's dark surface. Stock Tailwind only\n // — `animate-shimmer` exists in this package's own tailwind config but\n // not in either consumer's, so it would compile to nothing in\n // frontyard and profiles while looking right in this Storybook.\n <div\n className={classNames(\n 'h-full w-full animate-pulse',\n PLACEHOLDER_BG[variant]\n )}\n aria-hidden\n />\n ) : isPlayableVideo ? (\n <>\n <video\n src={sourceUrl}\n poster={optimizedThumbnailUrl}\n controls\n playsInline\n preload=\"metadata\"\n className=\"absolute inset-0 h-full w-full object-contain\"\n >\n <track kind=\"captions\" />\n </video>\n {/*\n The poster *is* the hero on this branch, and `<video>` raises no\n event when one fails to load — its own `error` is about the media\n resource, not the poster — so the `<img>` below verifies it. A\n `display:none` image is still fetched and still fires `onError`\n (checked in a browser, not assumed), and it dedupes with the\n poster's own request for the same URL, so this costs a DOM node\n rather than a round trip. No `loading=\"lazy\"`: that would defer the\n probe while off screen. Without it a 404 poster left the card and\n its tail accent-painted over a bare `bg-black` box, which is the\n one thing `useChinPalette`'s rule exists to prevent (MES-1349).\n */}\n {optimizedThumbnailUrl && onImageError ? (\n <img\n src={optimizedThumbnailUrl}\n alt=\"\"\n aria-hidden\n onError={onImageError}\n className=\"hidden\"\n />\n ) : null}\n </>\n ) : thumbnailUrl ? (\n <img\n src={optimizedThumbnailUrl ?? thumbnailUrl}\n alt={title ?? ''}\n draggable={false}\n loading=\"lazy\"\n decoding=\"async\"\n onError={onImageError}\n className=\"absolute inset-0 h-full w-full object-cover\"\n />\n ) : (\n <div\n className={classNames(\n 'flex h-full w-full items-center justify-center',\n PLACEHOLDER_BG[variant]\n )}\n >\n {renderTypeIcon(mimeType, {\n className: PLACEHOLDER_ICON[variant],\n weight: 'regular',\n })}\n </div>\n )}\n\n {topLeft ? (\n <div className=\"pointer-events-auto absolute left-3 top-3 z-10\">\n {topLeft}\n </div>\n ) : null}\n {topRight ? (\n <div className=\"pointer-events-auto absolute right-3 top-3 z-10\">\n {topRight}\n </div>\n ) : null}\n </div>\n )\n}\n\nexport default CardThumbnail\n","const parseNumber = (color, len) => {\n\tif (typeof color !== 'number') return;\n\n\t// hex3: #c93 -> #cc9933\n\tif (len === 3) {\n\t\treturn {\n\t\t\tmode: 'rgb',\n\t\t\tr: (((color >> 8) & 0xf) | ((color >> 4) & 0xf0)) / 255,\n\t\t\tg: (((color >> 4) & 0xf) | (color & 0xf0)) / 255,\n\t\t\tb: ((color & 0xf) | ((color << 4) & 0xf0)) / 255\n\t\t};\n\t}\n\n\t// hex4: #c931 -> #cc993311\n\tif (len === 4) {\n\t\treturn {\n\t\t\tmode: 'rgb',\n\t\t\tr: (((color >> 12) & 0xf) | ((color >> 8) & 0xf0)) / 255,\n\t\t\tg: (((color >> 8) & 0xf) | ((color >> 4) & 0xf0)) / 255,\n\t\t\tb: (((color >> 4) & 0xf) | (color & 0xf0)) / 255,\n\t\t\talpha: ((color & 0xf) | ((color << 4) & 0xf0)) / 255\n\t\t};\n\t}\n\n\t// hex6: #f0f1f2\n\tif (len === 6) {\n\t\treturn {\n\t\t\tmode: 'rgb',\n\t\t\tr: ((color >> 16) & 0xff) / 255,\n\t\t\tg: ((color >> 8) & 0xff) / 255,\n\t\t\tb: (color & 0xff) / 255\n\t\t};\n\t}\n\n\t// hex8: #f0f1f2ff\n\tif (len === 8) {\n\t\treturn {\n\t\t\tmode: 'rgb',\n\t\t\tr: ((color >> 24) & 0xff) / 255,\n\t\t\tg: ((color >> 16) & 0xff) / 255,\n\t\t\tb: ((color >> 8) & 0xff) / 255,\n\t\t\talpha: (color & 0xff) / 255\n\t\t};\n\t}\n};\n\nexport default parseNumber;\n","const named = {\n\taliceblue: 0xf0f8ff,\n\tantiquewhite: 0xfaebd7,\n\taqua: 0x00ffff,\n\taquamarine: 0x7fffd4,\n\tazure: 0xf0ffff,\n\tbeige: 0xf5f5dc,\n\tbisque: 0xffe4c4,\n\tblack: 0x000000,\n\tblanchedalmond: 0xffebcd,\n\tblue: 0x0000ff,\n\tblueviolet: 0x8a2be2,\n\tbrown: 0xa52a2a,\n\tburlywood: 0xdeb887,\n\tcadetblue: 0x5f9ea0,\n\tchartreuse: 0x7fff00,\n\tchocolate: 0xd2691e,\n\tcoral: 0xff7f50,\n\tcornflowerblue: 0x6495ed,\n\tcornsilk: 0xfff8dc,\n\tcrimson: 0xdc143c,\n\tcyan: 0x00ffff,\n\tdarkblue: 0x00008b,\n\tdarkcyan: 0x008b8b,\n\tdarkgoldenrod: 0xb8860b,\n\tdarkgray: 0xa9a9a9,\n\tdarkgreen: 0x006400,\n\tdarkgrey: 0xa9a9a9,\n\tdarkkhaki: 0xbdb76b,\n\tdarkmagenta: 0x8b008b,\n\tdarkolivegreen: 0x556b2f,\n\tdarkorange: 0xff8c00,\n\tdarkorchid: 0x9932cc,\n\tdarkred: 0x8b0000,\n\tdarksalmon: 0xe9967a,\n\tdarkseagreen: 0x8fbc8f,\n\tdarkslateblue: 0x483d8b,\n\tdarkslategray: 0x2f4f4f,\n\tdarkslategrey: 0x2f4f4f,\n\tdarkturquoise: 0x00ced1,\n\tdarkviolet: 0x9400d3,\n\tdeeppink: 0xff1493,\n\tdeepskyblue: 0x00bfff,\n\tdimgray: 0x696969,\n\tdimgrey: 0x696969,\n\tdodgerblue: 0x1e90ff,\n\tfirebrick: 0xb22222,\n\tfloralwhite: 0xfffaf0,\n\tforestgreen: 0x228b22,\n\tfuchsia: 0xff00ff,\n\tgainsboro: 0xdcdcdc,\n\tghostwhite: 0xf8f8ff,\n\tgold: 0xffd700,\n\tgoldenrod: 0xdaa520,\n\tgray: 0x808080,\n\tgreen: 0x008000,\n\tgreenyellow: 0xadff2f,\n\tgrey: 0x808080,\n\thoneydew: 0xf0fff0,\n\thotpink: 0xff69b4,\n\tindianred: 0xcd5c5c,\n\tindigo: 0x4b0082,\n\tivory: 0xfffff0,\n\tkhaki: 0xf0e68c,\n\tlavender: 0xe6e6fa,\n\tlavenderblush: 0xfff0f5,\n\tlawngreen: 0x7cfc00,\n\tlemonchiffon: 0xfffacd,\n\tlightblue: 0xadd8e6,\n\tlightcoral: 0xf08080,\n\tlightcyan: 0xe0ffff,\n\tlightgoldenrodyellow: 0xfafad2,\n\tlightgray: 0xd3d3d3,\n\tlightgreen: 0x90ee90,\n\tlightgrey: 0xd3d3d3,\n\tlightpink: 0xffb6c1,\n\tlightsalmon: 0xffa07a,\n\tlightseagreen: 0x20b2aa,\n\tlightskyblue: 0x87cefa,\n\tlightslategray: 0x778899,\n\tlightslategrey: 0x778899,\n\tlightsteelblue: 0xb0c4de,\n\tlightyellow: 0xffffe0,\n\tlime: 0x00ff00,\n\tlimegreen: 0x32cd32,\n\tlinen: 0xfaf0e6,\n\tmagenta: 0xff00ff,\n\tmaroon: 0x800000,\n\tmediumaquamarine: 0x66cdaa,\n\tmediumblue: 0x0000cd,\n\tmediumorchid: 0xba55d3,\n\tmediumpurple: 0x9370db,\n\tmediumseagreen: 0x3cb371,\n\tmediumslateblue: 0x7b68ee,\n\tmediumspringgreen: 0x00fa9a,\n\tmediumturquoise: 0x48d1cc,\n\tmediumvioletred: 0xc71585,\n\tmidnightblue: 0x191970,\n\tmintcream: 0xf5fffa,\n\tmistyrose: 0xffe4e1,\n\tmoccasin: 0xffe4b5,\n\tnavajowhite: 0xffdead,\n\tnavy: 0x000080,\n\toldlace: 0xfdf5e6,\n\tolive: 0x808000,\n\tolivedrab: 0x6b8e23,\n\torange: 0xffa500,\n\torangered: 0xff4500,\n\torchid: 0xda70d6,\n\tpalegoldenrod: 0xeee8aa,\n\tpalegreen: 0x98fb98,\n\tpaleturquoise: 0xafeeee,\n\tpalevioletred: 0xdb7093,\n\tpapayawhip: 0xffefd5,\n\tpeachpuff: 0xffdab9,\n\tperu: 0xcd853f,\n\tpink: 0xffc0cb,\n\tplum: 0xdda0dd,\n\tpowderblue: 0xb0e0e6,\n\tpurple: 0x800080,\n\n\t// Added in CSS Colors Level 4:\n\t// https://drafts.csswg.org/css-color/#changes-from-3\n\trebeccapurple: 0x663399,\n\n\tred: 0xff0000,\n\trosybrown: 0xbc8f8f,\n\troyalblue: 0x4169e1,\n\tsaddlebrown: 0x8b4513,\n\tsalmon: 0xfa8072,\n\tsandybrown: 0xf4a460,\n\tseagreen: 0x2e8b57,\n\tseashell: 0xfff5ee,\n\tsienna: 0xa0522d,\n\tsilver: 0xc0c0c0,\n\tskyblue: 0x87ceeb,\n\tslateblue: 0x6a5acd,\n\tslategray: 0x708090,\n\tslategrey: 0x708090,\n\tsnow: 0xfffafa,\n\tspringgreen: 0x00ff7f,\n\tsteelblue: 0x4682b4,\n\ttan: 0xd2b48c,\n\tteal: 0x008080,\n\tthistle: 0xd8bfd8,\n\ttomato: 0xff6347,\n\tturquoise: 0x40e0d0,\n\tviolet: 0xee82ee,\n\twheat: 0xf5deb3,\n\twhite: 0xffffff,\n\twhitesmoke: 0xf5f5f5,\n\tyellow: 0xffff00,\n\tyellowgreen: 0x9acd32\n};\n\nexport default named;\n","import parseNumber from './parseNumber.js';\nimport named from '../colors/named.js';\n\n// Also supports the `transparent` color as defined in:\n// https://drafts.csswg.org/css-color/#transparent-black\nconst parseNamed = color => {\n\treturn parseNumber(named[color.toLowerCase()], 6);\n};\n\nexport default parseNamed;\n","import parseNumber from './parseNumber.js';\n\nconst hex = /^#?([0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{4}|[0-9a-f]{3})$/i;\n\nconst parseHex = color => {\n\tlet match;\n\t// eslint-disable-next-line no-cond-assign\n\treturn (match = color.match(hex))\n\t\t? parseNumber(parseInt(match[1], 16), match[1].length)\n\t\t: undefined;\n};\n\nexport default parseHex;\n","/*\n\tBasic building blocks for color regexes\n\t---------------------------------------\n\n\tThese regexes are expressed as strings\n\tto be interpolated in the color regexes.\n */\n\n// <number>\nexport const num = '([+-]?\\\\d*\\\\.?\\\\d+(?:[eE][+-]?\\\\d+)?)';\n\n// <number> or 'none'\nexport const num_none = `(?:${num}|none)`;\n\n// <percentage>\nexport const per = `${num}%`;\n\n// <percent> or 'none'\nexport const per_none = `(?:${num}%|none)`;\n\n// <number-percentage> (<alpha-value>)\nexport const num_per = `(?:${num}%|${num})`;\n\n// <number-percentage> (<alpha-value>) or 'none'\nexport const num_per_none = `(?:${num}%|${num}|none)`;\n\n// <hue>\nexport const hue = `(?:${num}(deg|grad|rad|turn)|${num})`;\n\n// <hue> or 'none'\nexport const hue_none = `(?:${num}(deg|grad|rad|turn)|${num}|none)`;\n\nexport const c = `\\\\s*,\\\\s*`; // comma\nexport const so = '\\\\s*'; // space, optional\nexport const s = `\\\\s+`; // space\n\nexport const rx_num_per_none = new RegExp('^' + num_per_none + '$');\n","import { num, per, num_per, c } from '../util/regex.js';\n\n/*\n\trgb() regular expressions for legacy format\n\tReference: https://drafts.csswg.org/css-color/#rgb-functions\n */\nconst rgb_num_old = new RegExp(\n\t`^rgba?\\\\(\\\\s*${num}${c}${num}${c}${num}\\\\s*(?:,\\\\s*${num_per}\\\\s*)?\\\\)$`\n);\n\nconst rgb_per_old = new RegExp(\n\t`^rgba?\\\\(\\\\s*${per}${c}${per}${c}${per}\\\\s*(?:,\\\\s*${num_per}\\\\s*)?\\\\)$`\n);\n\nconst parseRgbLegacy = color => {\n\tlet res = { mode: 'rgb' };\n\tlet match;\n\tif ((match = color.match(rgb_num_old))) {\n\t\tif (match[1] !== undefined) {\n\t\t\tres.r = match[1] / 255;\n\t\t}\n\t\tif (match[2] !== undefined) {\n\t\t\tres.g = match[2] / 255;\n\t\t}\n\t\tif (match[3] !== undefined) {\n\t\t\tres.b = match[3] / 255;\n\t\t}\n\t} else if ((match = color.match(rgb_per_old))) {\n\t\tif (match[1] !== undefined) {\n\t\t\tres.r = match[1] / 100;\n\t\t}\n\t\tif (match[2] !== undefined) {\n\t\t\tres.g = match[2] / 100;\n\t\t}\n\t\tif (match[3] !== undefined) {\n\t\t\tres.b = match[3] / 100;\n\t\t}\n\t} else {\n\t\treturn undefined;\n\t}\n\n\tif (match[4] !== undefined) {\n\t\tres.alpha = Math.max(0, Math.min(1, match[4] / 100));\n\t} else if (match[5] !== undefined) {\n\t\tres.alpha = Math.max(0, Math.min(1, +match[5]));\n\t}\n\n\treturn res;\n};\n\nexport default parseRgbLegacy;\n","import parse from './parse.js';\n\nconst prepare = (color, mode) =>\n\tcolor === undefined\n\t\t? undefined\n\t\t: typeof color !== 'object'\n\t\t? parse(color)\n\t\t: color.mode !== undefined\n\t\t? color\n\t\t: mode\n\t\t? { ...color, mode }\n\t\t: undefined;\n\nexport default prepare;\n","import { converters } from './modes.js';\nimport prepare from './_prepare.js';\n\nconst converter =\n\t(target_mode = 'rgb') =>\n\tcolor =>\n\t\t(color = prepare(color, target_mode)) !== undefined\n\t\t\t? // if the color's mode corresponds to our target mode\n\t\t\t color.mode === target_mode\n\t\t\t\t? // then just return the color\n\t\t\t\t color\n\t\t\t\t: // otherwise check to see if we have a dedicated\n\t\t\t\t// converter for the target mode\n\t\t\t\tconverters[color.mode][target_mode]\n\t\t\t\t? // and return its result...\n\t\t\t\t converters[color.mode][target_mode](color)\n\t\t\t\t: // ...otherwise pass through RGB as an intermediary step.\n\t\t\t\t// if the target mode is RGB...\n\t\t\t\ttarget_mode === 'rgb'\n\t\t\t\t? // just return the RGB\n\t\t\t\t converters[color.mode].rgb(color)\n\t\t\t\t: // otherwise convert color.mode -> RGB -> target_mode\n\t\t\t\t converters.rgb[target_mode](converters[color.mode].rgb(color))\n\t\t\t: undefined;\n\nexport default converter;\n","import converter from './converter.js';\n\nconst converters = {};\nconst modes = {};\n\nconst parsers = [];\nconst colorProfiles = {};\n\nconst identity = v => v;\n\nconst useMode = definition => {\n\tconverters[definition.mode] = {\n\t\t...converters[definition.mode],\n\t\t...definition.toMode\n\t};\n\n\tObject.keys(definition.fromMode || {}).forEach(k => {\n\t\tif (!converters[k]) {\n\t\t\tconverters[k] = {};\n\t\t}\n\t\tconverters[k][definition.mode] = definition.fromMode[k];\n\t});\n\n\t// Color space channel ranges\n\tif (!definition.ranges) {\n\t\tdefinition.ranges = {};\n\t}\n\n\tif (!definition.difference) {\n\t\tdefinition.difference = {};\n\t}\n\n\tdefinition.channels.forEach(channel => {\n\t\t// undefined channel ranges default to the [0, 1] interval\n\t\tif (definition.ranges[channel] === undefined) {\n\t\t\tdefinition.ranges[channel] = [0, 1];\n\t\t}\n\n\t\tif (!definition.interpolate[channel]) {\n\t\t\tthrow new Error(`Missing interpolator for: ${channel}`);\n\t\t}\n\n\t\tif (typeof definition.interpolate[channel] === 'function') {\n\t\t\tdefinition.interpolate[channel] = {\n\t\t\t\tuse: definition.interpolate[channel]\n\t\t\t};\n\t\t}\n\n\t\tif (!definition.interpolate[channel].fixup) {\n\t\t\tdefinition.interpolate[channel].fixup = identity;\n\t\t}\n\t});\n\n\tmodes[definition.mode] = definition;\n\t(definition.parse || []).forEach(parser => {\n\t\tuseParser(parser, definition.mode);\n\t});\n\n\treturn converter(definition.mode);\n};\n\nconst getMode = mode => modes[mode];\n\nconst useParser = (parser, mode) => {\n\tif (typeof parser === 'string') {\n\t\tif (!mode) {\n\t\t\tthrow new Error(`'mode' required when 'parser' is a string`);\n\t\t}\n\t\tcolorProfiles[parser] = mode;\n\t} else if (typeof parser === 'function') {\n\t\tif (parsers.indexOf(parser) < 0) {\n\t\t\tparsers.push(parser);\n\t\t}\n\t}\n};\n\nconst removeParser = parser => {\n\tif (typeof parser === 'string') {\n\t\tdelete colorProfiles[parser];\n\t} else if (typeof parser === 'function') {\n\t\tconst idx = parsers.indexOf(parser);\n\t\tif (idx > 0) {\n\t\t\tparsers.splice(idx, 1);\n\t\t}\n\t}\n};\n\nexport {\n\tuseMode,\n\tgetMode,\n\tuseParser,\n\tremoveParser,\n\tconverters,\n\tparsers,\n\tcolorProfiles\n};\n","import { parsers, colorProfiles, getMode } from './modes.js';\n\n/* eslint-disable-next-line no-control-regex */\nconst IdentStartCodePoint = /[^\\x00-\\x7F]|[a-zA-Z_]/;\n\n/* eslint-disable-next-line no-control-regex */\nconst IdentCodePoint = /[^\\x00-\\x7F]|[-\\w]/;\n\nexport const Tok = {\n\tFunction: 'function',\n\tIdent: 'ident',\n\tNumber: 'number',\n\tPercentage: 'percentage',\n\tParenClose: ')',\n\tNone: 'none',\n\tHue: 'hue',\n\tAlpha: 'alpha'\n};\n\nlet _i = 0;\n\n/*\n\t4.3.10. Check if three code points would start a number\n\thttps://drafts.csswg.org/css-syntax/#starts-with-a-number\n */\nfunction is_num(chars) {\n\tlet ch = chars[_i];\n\tlet ch1 = chars[_i + 1];\n\tif (ch === '-' || ch === '+') {\n\t\treturn /\\d/.test(ch1) || (ch1 === '.' && /\\d/.test(chars[_i + 2]));\n\t}\n\tif (ch === '.') {\n\t\treturn /\\d/.test(ch1);\n\t}\n\treturn /\\d/.test(ch);\n}\n\n/*\n\tCheck if the stream starts with an identifier.\n */\n\nfunction is_ident(chars) {\n\tif (_i >= chars.length) {\n\t\treturn false;\n\t}\n\tlet ch = chars[_i];\n\tif (IdentStartCodePoint.test(ch)) {\n\t\treturn true;\n\t}\n\tif (ch === '-') {\n\t\tif (chars.length - _i < 2) {\n\t\t\treturn false;\n\t\t}\n\t\tlet ch1 = chars[_i + 1];\n\t\tif (ch1 === '-' || IdentStartCodePoint.test(ch1)) {\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\treturn false;\n}\n\n/*\n\t4.3.3. Consume a numeric token\n\thttps://drafts.csswg.org/css-syntax/#consume-numeric-token\n */\n\nconst huenits = {\n\tdeg: 1,\n\trad: 180 / Math.PI,\n\tgrad: 9 / 10,\n\tturn: 360\n};\n\nfunction num(chars) {\n\tlet value = '';\n\tif (chars[_i] === '-' || chars[_i] === '+') {\n\t\tvalue += chars[_i++];\n\t}\n\tvalue += digits(chars);\n\tif (chars[_i] === '.' && /\\d/.test(chars[_i + 1])) {\n\t\tvalue += chars[_i++] + digits(chars);\n\t}\n\tif (chars[_i] === 'e' || chars[_i] === 'E') {\n\t\tif (\n\t\t\t(chars[_i + 1] === '-' || chars[_i + 1] === '+') &&\n\t\t\t/\\d/.test(chars[_i + 2])\n\t\t) {\n\t\t\tvalue += chars[_i++] + chars[_i++] + digits(chars);\n\t\t} else if (/\\d/.test(chars[_i + 1])) {\n\t\t\tvalue += chars[_i++] + digits(chars);\n\t\t}\n\t}\n\tif (is_ident(chars)) {\n\t\tlet id = ident(chars);\n\t\tif (id === 'deg' || id === 'rad' || id === 'turn' || id === 'grad') {\n\t\t\treturn { type: Tok.Hue, value: value * huenits[id] };\n\t\t}\n\t\treturn undefined;\n\t}\n\tif (chars[_i] === '%') {\n\t\t_i++;\n\t\treturn { type: Tok.Percentage, value: +value };\n\t}\n\treturn { type: Tok.Number, value: +value };\n}\n\n/*\n\tConsume digits.\n */\nfunction digits(chars) {\n\tlet v = '';\n\twhile (/\\d/.test(chars[_i])) {\n\t\tv += chars[_i++];\n\t}\n\treturn v;\n}\n\n/*\n\tConsume an identifier.\n */\nfunction ident(chars) {\n\tlet v = '';\n\twhile (_i < chars.length && IdentCodePoint.test(chars[_i])) {\n\t\tv += chars[_i++];\n\t}\n\treturn v;\n}\n\n/*\n\tConsume an ident-like token.\n */\nfunction identlike(chars) {\n\tlet v = ident(chars);\n\tif (chars[_i] === '(') {\n\t\t_i++;\n\t\treturn { type: Tok.Function, value: v };\n\t}\n\tif (v === 'none') {\n\t\treturn { type: Tok.None, value: undefined };\n\t}\n\treturn { type: Tok.Ident, value: v };\n}\n\nexport function tokenize(str = '') {\n\tlet chars = str.trim();\n\tlet tokens = [];\n\tlet ch;\n\n\t/* reset counter */\n\t_i = 0;\n\n\twhile (_i < chars.length) {\n\t\tch = chars[_i++];\n\n\t\t/*\n\t\t\tConsume whitespace without emitting it\n\t\t */\n\t\tif (ch === '\\n' || ch === '\\t' || ch === ' ') {\n\t\t\twhile (\n\t\t\t\t_i < chars.length &&\n\t\t\t\t(chars[_i] === '\\n' || chars[_i] === '\\t' || chars[_i] === ' ')\n\t\t\t) {\n\t\t\t\t_i++;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (ch === ',') {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (ch === ')') {\n\t\t\ttokens.push({ type: Tok.ParenClose });\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (ch === '+') {\n\t\t\t_i--;\n\t\t\tif (is_num(chars)) {\n\t\t\t\ttokens.push(num(chars));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (ch === '-') {\n\t\t\t_i--;\n\t\t\tif (is_num(chars)) {\n\t\t\t\ttokens.push(num(chars));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (is_ident(chars)) {\n\t\t\t\ttokens.push({ type: Tok.Ident, value: ident(chars) });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (ch === '.') {\n\t\t\t_i--;\n\t\t\tif (is_num(chars)) {\n\t\t\t\ttokens.push(num(chars));\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (ch === '/') {\n\t\t\twhile (\n\t\t\t\t_i < chars.length &&\n\t\t\t\t(chars[_i] === '\\n' || chars[_i] === '\\t' || chars[_i] === ' ')\n\t\t\t) {\n\t\t\t\t_i++;\n\t\t\t}\n\t\t\tlet alpha;\n\t\t\tif (is_num(chars)) {\n\t\t\t\talpha = num(chars);\n\t\t\t\tif (alpha.type !== Tok.Hue) {\n\t\t\t\t\ttokens.push({ type: Tok.Alpha, value: alpha });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (is_ident(chars)) {\n\t\t\t\tif (ident(chars) === 'none') {\n\t\t\t\t\ttokens.push({\n\t\t\t\t\t\ttype: Tok.Alpha,\n\t\t\t\t\t\tvalue: { type: Tok.None, value: undefined }\n\t\t\t\t\t});\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (/\\d/.test(ch)) {\n\t\t\t_i--;\n\t\t\ttokens.push(num(chars));\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (IdentStartCodePoint.test(ch)) {\n\t\t\t_i--;\n\t\t\ttokens.push(identlike(chars));\n\t\t\tcontinue;\n\t\t}\n\n\t\t/*\n\t\t\tTreat everything not already handled as an error.\n\t\t */\n\t\treturn undefined;\n\t}\n\n\treturn tokens;\n}\n\nexport function parseColorSyntax(tokens) {\n\ttokens._i = 0;\n\tlet token = tokens[tokens._i++];\n\tif (!token || token.type !== Tok.Function || token.value !== 'color') {\n\t\treturn undefined;\n\t}\n\ttoken = tokens[tokens._i++];\n\tif (token.type !== Tok.Ident) {\n\t\treturn undefined;\n\t}\n\tconst mode = colorProfiles[token.value];\n\tif (!mode) {\n\t\treturn undefined;\n\t}\n\tconst res = { mode };\n\tconst coords = consumeCoords(tokens, false);\n\tif (!coords) {\n\t\treturn undefined;\n\t}\n\tconst channels = getMode(mode).channels;\n\tfor (let ii = 0, c, ch; ii < channels.length; ii++) {\n\t\tc = coords[ii];\n\t\tch = channels[ii];\n\t\tif (c.type !== Tok.None) {\n\t\t\tres[ch] = c.type === Tok.Number ? c.value : c.value / 100;\n\t\t\tif (ch === 'alpha') {\n\t\t\t\tres[ch] = Math.max(0, Math.min(1, res[ch]));\n\t\t\t}\n\t\t}\n\t}\n\treturn res;\n}\n\nfunction consumeCoords(tokens, includeHue) {\n\tconst coords = [];\n\tlet token;\n\twhile (tokens._i < tokens.length) {\n\t\ttoken = tokens[tokens._i++];\n\t\tif (\n\t\t\ttoken.type === Tok.None ||\n\t\t\ttoken.type === Tok.Number ||\n\t\t\ttoken.type === Tok.Alpha ||\n\t\t\ttoken.type === Tok.Percentage ||\n\t\t\t(includeHue && token.type === Tok.Hue)\n\t\t) {\n\t\t\tcoords.push(token);\n\t\t\tcontinue;\n\t\t}\n\t\tif (token.type === Tok.ParenClose) {\n\t\t\tif (tokens._i < tokens.length) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\treturn undefined;\n\t}\n\n\tif (coords.length < 3 || coords.length > 4) {\n\t\treturn undefined;\n\t}\n\n\tif (coords.length === 4) {\n\t\tif (coords[3].type !== Tok.Alpha) {\n\t\t\treturn undefined;\n\t\t}\n\t\tcoords[3] = coords[3].value;\n\t}\n\tif (coords.length === 3) {\n\t\tcoords.push({ type: Tok.None, value: undefined });\n\t}\n\n\treturn coords.every(c => c.type !== Tok.Alpha) ? coords : undefined;\n}\n\nexport function parseModernSyntax(tokens, includeHue) {\n\ttokens._i = 0;\n\tlet token = tokens[tokens._i++];\n\tif (!token || token.type !== Tok.Function) {\n\t\treturn undefined;\n\t}\n\tlet coords = consumeCoords(tokens, includeHue);\n\tif (!coords) {\n\t\treturn undefined;\n\t}\n\tcoords.unshift(token.value);\n\treturn coords;\n}\n\nconst parse = color => {\n\tif (typeof color !== 'string') {\n\t\treturn undefined;\n\t}\n\tconst tokens = tokenize(color);\n\tconst parsed = tokens ? parseModernSyntax(tokens, true) : undefined;\n\tlet result = undefined;\n\tlet i = 0;\n\tlet len = parsers.length;\n\twhile (i < len) {\n\t\tif ((result = parsers[i++](color, parsed)) !== undefined) {\n\t\t\treturn result;\n\t\t}\n\t}\n\treturn tokens ? parseColorSyntax(tokens) : undefined;\n};\n\nexport default parse;\n","import { Tok } from '../parse.js';\n\nfunction parseRgb(color, parsed) {\n\tif (!parsed || (parsed[0] !== 'rgb' && parsed[0] !== 'rgba')) {\n\t\treturn undefined;\n\t}\n\tconst res = { mode: 'rgb' };\n\tconst [, r, g, b, alpha] = parsed;\n\tif (r.type === Tok.Hue || g.type === Tok.Hue || b.type === Tok.Hue) {\n\t\treturn undefined;\n\t}\n\tif (r.type !== Tok.None) {\n\t\tres.r = r.type === Tok.Number ? r.value / 255 : r.value / 100;\n\t}\n\tif (g.type !== Tok.None) {\n\t\tres.g = g.type === Tok.Number ? g.value / 255 : g.value / 100;\n\t}\n\tif (b.type !== Tok.None) {\n\t\tres.b = b.type === Tok.Number ? b.value / 255 : b.value / 100;\n\t}\n\tif (alpha.type !== Tok.None) {\n\t\tres.alpha = Math.min(\n\t\t\t1,\n\t\t\tMath.max(\n\t\t\t\t0,\n\t\t\t\talpha.type === Tok.Number ? alpha.value : alpha.value / 100\n\t\t\t)\n\t\t);\n\t}\n\n\treturn res;\n}\n\nexport default parseRgb;\n","const parseTransparent = c =>\n\tc === 'transparent'\n\t\t? { mode: 'rgb', r: 0, g: 0, b: 0, alpha: 0 }\n\t\t: undefined;\n\nexport default parseTransparent;\n","const lerp = (a, b, t) => a + t * (b - a);\nconst unlerp = (a, b, v) => (v - a) / (b - a);\n\nconst blerp = (a00, a01, a10, a11, tx, ty) => {\n\treturn lerp(lerp(a00, a01, tx), lerp(a10, a11, tx), ty);\n};\n\nconst trilerp = (\n\ta000,\n\ta010,\n\ta100,\n\ta110,\n\ta001,\n\ta011,\n\ta101,\n\ta111,\n\ttx,\n\tty,\n\ttz\n) => {\n\treturn lerp(\n\t\tblerp(a000, a010, a100, a110, tx, ty),\n\t\tblerp(a001, a011, a101, a111, tx, ty),\n\t\ttz\n\t);\n};\n\nexport { lerp, blerp, trilerp, unlerp };\n","const get_classes = arr => {\n\tlet classes = [];\n\tfor (let i = 0; i < arr.length - 1; i++) {\n\t\tlet a = arr[i];\n\t\tlet b = arr[i + 1];\n\t\tif (a === undefined && b === undefined) {\n\t\t\tclasses.push(undefined);\n\t\t} else if (a !== undefined && b !== undefined) {\n\t\t\tclasses.push([a, b]);\n\t\t} else {\n\t\t\tclasses.push(a !== undefined ? [a, a] : [b, b]);\n\t\t}\n\t}\n\treturn classes;\n};\n\nconst interpolatorPiecewise = interpolator => arr => {\n\tlet classes = get_classes(arr);\n\treturn t => {\n\t\tlet cls = t * classes.length;\n\t\tlet idx = t >= 1 ? classes.length - 1 : Math.max(Math.floor(cls), 0);\n\t\tlet pair = classes[idx];\n\t\treturn pair === undefined\n\t\t\t? undefined\n\t\t\t: interpolator(pair[0], pair[1], cls - idx);\n\t};\n};\n\nexport { interpolatorPiecewise };\n","import { lerp } from './lerp.js';\nimport { interpolatorPiecewise } from './piecewise.js';\n\nexport const interpolatorLinear = interpolatorPiecewise(lerp);\n","const fixupAlpha = arr => {\n\tlet some_defined = false;\n\tlet res = arr.map(v => {\n\t\tif (v !== undefined) {\n\t\t\tsome_defined = true;\n\t\t\treturn v;\n\t\t}\n\t\treturn 1;\n\t});\n\treturn some_defined ? res : arr;\n};\n\nexport { fixupAlpha };\n","import parseNamed from './parseNamed.js';\nimport parseHex from './parseHex.js';\nimport parseRgbLegacy from './parseRgbLegacy.js';\nimport parseRgb from './parseRgb.js';\nimport parseTransparent from './parseTransparent.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\n\n/*\n\tsRGB color space\n */\n\nconst definition = {\n\tmode: 'rgb',\n\tchannels: ['r', 'g', 'b', 'alpha'],\n\tparse: [\n\t\tparseRgb,\n\t\tparseHex,\n\t\tparseRgbLegacy,\n\t\tparseNamed,\n\t\tparseTransparent,\n\t\t'srgb'\n\t],\n\tserialize: 'srgb',\n\tinterpolate: {\n\t\tr: interpolatorLinear,\n\t\tg: interpolatorLinear,\n\t\tb: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t},\n\tgamut: true,\n\twhite: { r: 1, g: 1, b: 1 },\n\tblack: { r: 0, g: 0, b: 0 }\n};\n\nexport default definition;\n","/*\n\tConvert A98 RGB values to CIE XYZ D65\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n\t\t* https://www.adobe.com/digitalimag/pdfs/AdobeRGB1998.pdf\n*/\n\nconst linearize = (v = 0) => Math.pow(Math.abs(v), 563 / 256) * Math.sign(v);\n\nconst convertA98ToXyz65 = a98 => {\n\tlet r = linearize(a98.r);\n\tlet g = linearize(a98.g);\n\tlet b = linearize(a98.b);\n\tlet res = {\n\t\tmode: 'xyz65',\n\t\tx:\n\t\t\t0.5766690429101305 * r +\n\t\t\t0.1855582379065463 * g +\n\t\t\t0.1882286462349947 * b,\n\t\ty:\n\t\t\t0.297344975250536 * r +\n\t\t\t0.6273635662554661 * g +\n\t\t\t0.0752914584939979 * b,\n\t\tz:\n\t\t\t0.0270313613864123 * r +\n\t\t\t0.0706888525358272 * g +\n\t\t\t0.9913375368376386 * b\n\t};\n\tif (a98.alpha !== undefined) {\n\t\tres.alpha = a98.alpha;\n\t}\n\treturn res;\n};\n\nexport default convertA98ToXyz65;\n","/*\n\tConvert CIE XYZ D65 values to A98 RGB\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n*/\n\nconst gamma = v => Math.pow(Math.abs(v), 256 / 563) * Math.sign(v);\n\nconst convertXyz65ToA98 = ({ x, y, z, alpha }) => {\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet res = {\n\t\tmode: 'a98',\n\t\tr: gamma(\n\t\t\tx * 2.0415879038107465 -\n\t\t\t\ty * 0.5650069742788597 -\n\t\t\t\t0.3447313507783297 * z\n\t\t),\n\t\tg: gamma(\n\t\t\tx * -0.9692436362808798 +\n\t\t\t\ty * 1.8759675015077206 +\n\t\t\t\t0.0415550574071756 * z\n\t\t),\n\t\tb: gamma(\n\t\t\tx * 0.0134442806320312 -\n\t\t\t\ty * 0.1183623922310184 +\n\t\t\t\t1.0151749943912058 * z\n\t\t)\n\t};\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertXyz65ToA98;\n","const fn = (c = 0) => {\n\tconst abs = Math.abs(c);\n\tif (abs <= 0.04045) {\n\t\treturn c / 12.92;\n\t}\n\treturn (Math.sign(c) || 1) * Math.pow((abs + 0.055) / 1.055, 2.4);\n};\n\nconst convertRgbToLrgb = ({ r, g, b, alpha }) => {\n\tlet res = {\n\t\tmode: 'lrgb',\n\t\tr: fn(r),\n\t\tg: fn(g),\n\t\tb: fn(b)\n\t};\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertRgbToLrgb;\n","/*\n\tConvert sRGB values to CIE XYZ D65\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n\t\t* https://observablehq.com/@danburzo/color-matrix-calculator\n*/\n\nimport convertRgbToLrgb from '../lrgb/convertRgbToLrgb.js';\n\nconst convertRgbToXyz65 = rgb => {\n\tlet { r, g, b, alpha } = convertRgbToLrgb(rgb);\n\tlet res = {\n\t\tmode: 'xyz65',\n\t\tx:\n\t\t\t0.4123907992659593 * r +\n\t\t\t0.357584339383878 * g +\n\t\t\t0.1804807884018343 * b,\n\t\ty:\n\t\t\t0.2126390058715102 * r +\n\t\t\t0.715168678767756 * g +\n\t\t\t0.0721923153607337 * b,\n\t\tz:\n\t\t\t0.0193308187155918 * r +\n\t\t\t0.119194779794626 * g +\n\t\t\t0.9505321522496607 * b\n\t};\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertRgbToXyz65;\n","const fn = (c = 0) => {\n\tconst abs = Math.abs(c);\n\tif (abs > 0.0031308) {\n\t\treturn (Math.sign(c) || 1) * (1.055 * Math.pow(abs, 1 / 2.4) - 0.055);\n\t}\n\treturn c * 12.92;\n};\n\nconst convertLrgbToRgb = ({ r, g, b, alpha }, mode = 'rgb') => {\n\tlet res = {\n\t\tmode,\n\t\tr: fn(r),\n\t\tg: fn(g),\n\t\tb: fn(b)\n\t};\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertLrgbToRgb;\n","/*\n\tCIE XYZ D65 values to sRGB.\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n\t\t* https://observablehq.com/@danburzo/color-matrix-calculator\n*/\n\nimport convertLrgbToRgb from '../lrgb/convertLrgbToRgb.js';\n\nconst convertXyz65ToRgb = ({ x, y, z, alpha }) => {\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet res = convertLrgbToRgb({\n\t\tr:\n\t\t\tx * 3.2409699419045226 -\n\t\t\ty * 1.5373831775700939 -\n\t\t\t0.4986107602930034 * z,\n\t\tg:\n\t\t\tx * -0.9692436362808796 +\n\t\t\ty * 1.8759675015077204 +\n\t\t\t0.0415550574071756 * z,\n\t\tb:\n\t\t\tx * 0.0556300796969936 -\n\t\t\ty * 0.2039769588889765 +\n\t\t\t1.0569715142428784 * z\n\t});\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertXyz65ToRgb;\n","import rgb from '../rgb/definition.js';\n\nimport convertA98ToXyz65 from './convertA98ToXyz65.js';\nimport convertXyz65ToA98 from './convertXyz65ToA98.js';\nimport convertRgbToXyz65 from '../xyz65/convertRgbToXyz65.js';\nimport convertXyz65ToRgb from '../xyz65/convertXyz65ToRgb.js';\n\nconst definition = {\n\t...rgb,\n\tmode: 'a98',\n\tparse: ['a98-rgb'],\n\tserialize: 'a98-rgb',\n\n\tfromMode: {\n\t\trgb: color => convertXyz65ToA98(convertRgbToXyz65(color)),\n\t\txyz65: convertXyz65ToA98\n\t},\n\n\ttoMode: {\n\t\trgb: color => convertXyz65ToRgb(convertA98ToXyz65(color)),\n\t\txyz65: convertA98ToXyz65\n\t}\n};\n\nexport default definition;\n","const normalizeHue = hue => ((hue = hue % 360) < 0 ? hue + 360 : hue);\n\nexport default normalizeHue;\n","import normalizeHue from '../util/normalizeHue.js';\n\nconst hue = (hues, fn) => {\n\treturn hues\n\t\t.map((hue, idx, arr) => {\n\t\t\tif (hue === undefined) {\n\t\t\t\treturn hue;\n\t\t\t}\n\t\t\tlet normalized = normalizeHue(hue);\n\t\t\tif (idx === 0 || hues[idx - 1] === undefined) {\n\t\t\t\treturn normalized;\n\t\t\t}\n\t\t\treturn fn(normalized - normalizeHue(arr[idx - 1]));\n\t\t})\n\t\t.reduce((acc, curr) => {\n\t\t\tif (\n\t\t\t\t!acc.length ||\n\t\t\t\tcurr === undefined ||\n\t\t\t\tacc[acc.length - 1] === undefined\n\t\t\t) {\n\t\t\t\tacc.push(curr);\n\t\t\t\treturn acc;\n\t\t\t}\n\t\t\tacc.push(curr + acc[acc.length - 1]);\n\t\t\treturn acc;\n\t\t}, []);\n};\n\nconst fixupHueShorter = arr =>\n\thue(arr, d => (Math.abs(d) <= 180 ? d : d - 360 * Math.sign(d)));\nconst fixupHueLonger = arr =>\n\thue(arr, d => (Math.abs(d) >= 180 || d === 0 ? d : d - 360 * Math.sign(d)));\nconst fixupHueIncreasing = arr => hue(arr, d => (d >= 0 ? d : d + 360));\nconst fixupHueDecreasing = arr => hue(arr, d => (d <= 0 ? d : d - 360));\n\nexport {\n\tfixupHueShorter,\n\tfixupHueLonger,\n\tfixupHueIncreasing,\n\tfixupHueDecreasing\n};\n","export const M = [-0.14861, 1.78277, -0.29227, -0.90649, 1.97294, 0];\n\nexport const degToRad = Math.PI / 180;\nexport const radToDeg = 180 / Math.PI;\n","/*\n\tConvert a RGB color to the Cubehelix HSL color space.\n\n\tThis computation is not present in Green's paper:\n\thttps://arxiv.org/pdf/1108.5083.pdf\n\n\t...but can be derived from the inverse, HSL to RGB conversion.\n\n\tIt matches the math in Mike Bostock's D3 implementation:\n\n\thttps://github.com/d3/d3-color/blob/master/src/cubehelix.js\n */\n\nimport { radToDeg, M } from './constants.js';\n\nlet DE = M[3] * M[4];\nlet BE = M[1] * M[4];\nlet BCAD = M[1] * M[2] - M[0] * M[3];\n\nconst convertRgbToCubehelix = ({ r, g, b, alpha }) => {\n\tif (r === undefined) r = 0;\n\tif (g === undefined) g = 0;\n\tif (b === undefined) b = 0;\n\tlet l = (BCAD * b + r * DE - g * BE) / (BCAD + DE - BE);\n\tlet x = b - l;\n\tlet y = (M[4] * (g - l) - M[2] * x) / M[3];\n\n\tlet res = {\n\t\tmode: 'cubehelix',\n\t\tl: l,\n\t\ts:\n\t\t\tl === 0 || l === 1\n\t\t\t\t? undefined\n\t\t\t\t: Math.sqrt(x * x + y * y) / (M[4] * l * (1 - l))\n\t};\n\n\tif (res.s) res.h = Math.atan2(y, x) * radToDeg - 120;\n\tif (alpha !== undefined) res.alpha = alpha;\n\n\treturn res;\n};\n\nexport default convertRgbToCubehelix;\n","import { degToRad, M } from './constants.js';\n\nconst convertCubehelixToRgb = ({ h, s, l, alpha }) => {\n\tlet res = { mode: 'rgb' };\n\n\th = (h === undefined ? 0 : h + 120) * degToRad;\n\tif (l === undefined) l = 0;\n\n\tlet amp = s === undefined ? 0 : s * l * (1 - l);\n\n\tlet cosh = Math.cos(h);\n\tlet sinh = Math.sin(h);\n\n\tres.r = l + amp * (M[0] * cosh + M[1] * sinh);\n\tres.g = l + amp * (M[2] * cosh + M[3] * sinh);\n\tres.b = l + amp * (M[4] * cosh + M[5] * sinh);\n\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertCubehelixToRgb;\n","import { getMode } from './modes.js';\nimport converter from './converter.js';\nimport normalizeHue from './util/normalizeHue.js';\n\nconst differenceHueSaturation = (std, smp) => {\n\tif (std.h === undefined || smp.h === undefined || !std.s || !smp.s) {\n\t\treturn 0;\n\t}\n\tlet std_h = normalizeHue(std.h);\n\tlet smp_h = normalizeHue(smp.h);\n\tlet dH = Math.sin((((smp_h - std_h + 360) / 2) * Math.PI) / 180);\n\treturn 2 * Math.sqrt(std.s * smp.s) * dH;\n};\n\nconst differenceHueNaive = (std, smp) => {\n\tif (std.h === undefined || smp.h === undefined) {\n\t\treturn 0;\n\t}\n\tlet std_h = normalizeHue(std.h);\n\tlet smp_h = normalizeHue(smp.h);\n\tif (Math.abs(smp_h - std_h) > 180) {\n\t\t// todo should this be normalized once again?\n\t\treturn std_h - (smp_h - 360 * Math.sign(smp_h - std_h));\n\t}\n\treturn smp_h - std_h;\n};\n\nconst differenceHueChroma = (std, smp) => {\n\tif (std.h === undefined || smp.h === undefined || !std.c || !smp.c) {\n\t\treturn 0;\n\t}\n\tlet std_h = normalizeHue(std.h);\n\tlet smp_h = normalizeHue(smp.h);\n\tlet dH = Math.sin((((smp_h - std_h + 360) / 2) * Math.PI) / 180);\n\treturn 2 * Math.sqrt(std.c * smp.c) * dH;\n};\n\nconst differenceEuclidean = (mode = 'rgb', weights = [1, 1, 1, 0]) => {\n\tlet def = getMode(mode);\n\tlet channels = def.channels;\n\tlet diffs = def.difference;\n\tlet conv = converter(mode);\n\treturn (std, smp) => {\n\t\tlet ConvStd = conv(std);\n\t\tlet ConvSmp = conv(smp);\n\t\treturn Math.sqrt(\n\t\t\tchannels.reduce((sum, k, idx) => {\n\t\t\t\tlet delta = diffs[k]\n\t\t\t\t\t? diffs[k](ConvStd, ConvSmp)\n\t\t\t\t\t: ConvStd[k] - ConvSmp[k];\n\t\t\t\treturn (\n\t\t\t\t\tsum +\n\t\t\t\t\t(weights[idx] || 0) * Math.pow(isNaN(delta) ? 0 : delta, 2)\n\t\t\t\t);\n\t\t\t}, 0)\n\t\t);\n\t};\n};\n\nconst differenceCie76 = () => differenceEuclidean('lab65');\n\nconst differenceCie94 = (kL = 1, K1 = 0.045, K2 = 0.015) => {\n\tlet lab = converter('lab65');\n\n\treturn (std, smp) => {\n\t\tlet LabStd = lab(std);\n\t\tlet LabSmp = lab(smp);\n\n\t\t// Extract Lab values, and compute Chroma\n\t\tlet lStd = LabStd.l;\n\t\tlet aStd = LabStd.a;\n\t\tlet bStd = LabStd.b;\n\t\tlet cStd = Math.sqrt(aStd * aStd + bStd * bStd);\n\n\t\tlet lSmp = LabSmp.l;\n\t\tlet aSmp = LabSmp.a;\n\t\tlet bSmp = LabSmp.b;\n\t\tlet cSmp = Math.sqrt(aSmp * aSmp + bSmp * bSmp);\n\n\t\tlet dL2 = Math.pow(lStd - lSmp, 2);\n\t\tlet dC2 = Math.pow(cStd - cSmp, 2);\n\t\tlet dH2 = Math.pow(aStd - aSmp, 2) + Math.pow(bStd - bSmp, 2) - dC2;\n\n\t\treturn Math.sqrt(\n\t\t\tdL2 / Math.pow(kL, 2) +\n\t\t\t\tdC2 / Math.pow(1 + K1 * cStd, 2) +\n\t\t\t\tdH2 / Math.pow(1 + K2 * cStd, 2)\n\t\t);\n\t};\n};\n\n/*\n\tCIEDE2000 color difference, original Matlab implementation by Gaurav Sharma\n\tBased on \"The CIEDE2000 Color-Difference Formula: Implementation Notes, Supplementary Test Data, and Mathematical Observations\" \n\tby Gaurav Sharma, Wencheng Wu, Edul N. Dalal in Color Research and Application, vol. 30. No. 1, pp. 21-30, February 2005.\n\thttp://www2.ece.rochester.edu/~gsharma/ciede2000/\n */\n\nconst differenceCiede2000 = (Kl = 1, Kc = 1, Kh = 1) => {\n\tlet lab = converter('lab65');\n\treturn (std, smp) => {\n\t\tlet LabStd = lab(std);\n\t\tlet LabSmp = lab(smp);\n\n\t\tlet lStd = LabStd.l;\n\t\tlet aStd = LabStd.a;\n\t\tlet bStd = LabStd.b;\n\t\tlet cStd = Math.sqrt(aStd * aStd + bStd * bStd);\n\n\t\tlet lSmp = LabSmp.l;\n\t\tlet aSmp = LabSmp.a;\n\t\tlet bSmp = LabSmp.b;\n\t\tlet cSmp = Math.sqrt(aSmp * aSmp + bSmp * bSmp);\n\n\t\tlet cAvg = (cStd + cSmp) / 2;\n\n\t\tlet G =\n\t\t\t0.5 *\n\t\t\t(1 -\n\t\t\t\tMath.sqrt(\n\t\t\t\t\tMath.pow(cAvg, 7) / (Math.pow(cAvg, 7) + Math.pow(25, 7))\n\t\t\t\t));\n\n\t\tlet apStd = aStd * (1 + G);\n\t\tlet apSmp = aSmp * (1 + G);\n\n\t\tlet cpStd = Math.sqrt(apStd * apStd + bStd * bStd);\n\t\tlet cpSmp = Math.sqrt(apSmp * apSmp + bSmp * bSmp);\n\n\t\tlet hpStd =\n\t\t\tMath.abs(apStd) + Math.abs(bStd) === 0\n\t\t\t\t? 0\n\t\t\t\t: Math.atan2(bStd, apStd);\n\t\thpStd += (hpStd < 0) * 2 * Math.PI;\n\n\t\tlet hpSmp =\n\t\t\tMath.abs(apSmp) + Math.abs(bSmp) === 0\n\t\t\t\t? 0\n\t\t\t\t: Math.atan2(bSmp, apSmp);\n\t\thpSmp += (hpSmp < 0) * 2 * Math.PI;\n\n\t\tlet dL = lSmp - lStd;\n\t\tlet dC = cpSmp - cpStd;\n\n\t\tlet dhp = cpStd * cpSmp === 0 ? 0 : hpSmp - hpStd;\n\t\tdhp -= (dhp > Math.PI) * 2 * Math.PI;\n\t\tdhp += (dhp < -Math.PI) * 2 * Math.PI;\n\n\t\tlet dH = 2 * Math.sqrt(cpStd * cpSmp) * Math.sin(dhp / 2);\n\n\t\tlet Lp = (lStd + lSmp) / 2;\n\t\tlet Cp = (cpStd + cpSmp) / 2;\n\n\t\tlet hp;\n\t\tif (cpStd * cpSmp === 0) {\n\t\t\thp = hpStd + hpSmp;\n\t\t} else {\n\t\t\thp = (hpStd + hpSmp) / 2;\n\t\t\thp -= (Math.abs(hpStd - hpSmp) > Math.PI) * Math.PI;\n\t\t\thp += (hp < 0) * 2 * Math.PI;\n\t\t}\n\n\t\tlet Lpm50 = Math.pow(Lp - 50, 2);\n\t\tlet T =\n\t\t\t1 -\n\t\t\t0.17 * Math.cos(hp - Math.PI / 6) +\n\t\t\t0.24 * Math.cos(2 * hp) +\n\t\t\t0.32 * Math.cos(3 * hp + Math.PI / 30) -\n\t\t\t0.2 * Math.cos(4 * hp - (63 * Math.PI) / 180);\n\n\t\tlet Sl = 1 + (0.015 * Lpm50) / Math.sqrt(20 + Lpm50);\n\t\tlet Sc = 1 + 0.045 * Cp;\n\t\tlet Sh = 1 + 0.015 * Cp * T;\n\n\t\tlet deltaTheta =\n\t\t\t((30 * Math.PI) / 180) *\n\t\t\tMath.exp(-1 * Math.pow(((180 / Math.PI) * hp - 275) / 25, 2));\n\t\tlet Rc =\n\t\t\t2 *\n\t\t\tMath.sqrt(Math.pow(Cp, 7) / (Math.pow(Cp, 7) + Math.pow(25, 7)));\n\n\t\tlet Rt = -1 * Math.sin(2 * deltaTheta) * Rc;\n\n\t\treturn Math.sqrt(\n\t\t\tMath.pow(dL / (Kl * Sl), 2) +\n\t\t\t\tMath.pow(dC / (Kc * Sc), 2) +\n\t\t\t\tMath.pow(dH / (Kh * Sh), 2) +\n\t\t\t\t(((Rt * dC) / (Kc * Sc)) * dH) / (Kh * Sh)\n\t\t);\n\t};\n};\n\n/*\n\tCMC (l:c) difference formula\n\n\tReferences:\n\t\thttps://en.wikipedia.org/wiki/Color_difference#CMC_l:c_(1984)\n\t\thttp://www.brucelindbloom.com/index.html?Eqn_DeltaE_CMC.html\n */\nconst differenceCmc = (l = 1, c = 1) => {\n\tlet lab = converter('lab65');\n\n\t/*\n\t\tComparte two colors:\n\t\tstd - standard (first) color\n\t\tsmp - sample (second) color\n\t */\n\treturn (std, smp) => {\n\t\t// convert standard color to Lab\n\t\tlet LabStd = lab(std);\n\t\tlet lStd = LabStd.l;\n\t\tlet aStd = LabStd.a;\n\t\tlet bStd = LabStd.b;\n\n\t\t// Obtain hue/chroma\n\t\tlet cStd = Math.sqrt(aStd * aStd + bStd * bStd);\n\t\tlet hStd = Math.atan2(bStd, aStd);\n\t\thStd = hStd + 2 * Math.PI * (hStd < 0);\n\n\t\t// convert sample color to Lab, obtain LCh\n\t\tlet LabSmp = lab(smp);\n\t\tlet lSmp = LabSmp.l;\n\t\tlet aSmp = LabSmp.a;\n\t\tlet bSmp = LabSmp.b;\n\n\t\t// Obtain chroma\n\t\tlet cSmp = Math.sqrt(aSmp * aSmp + bSmp * bSmp);\n\n\t\t// lightness delta squared\n\t\tlet dL2 = Math.pow(lStd - lSmp, 2);\n\n\t\t// chroma delta squared\n\t\tlet dC2 = Math.pow(cStd - cSmp, 2);\n\n\t\t// hue delta squared\n\t\tlet dH2 = Math.pow(aStd - aSmp, 2) + Math.pow(bStd - bSmp, 2) - dC2;\n\n\t\tlet F = Math.sqrt(Math.pow(cStd, 4) / (Math.pow(cStd, 4) + 1900));\n\t\tlet T =\n\t\t\thStd >= (164 / 180) * Math.PI && hStd <= (345 / 180) * Math.PI\n\t\t\t\t? 0.56 + Math.abs(0.2 * Math.cos(hStd + (168 / 180) * Math.PI))\n\t\t\t\t: 0.36 + Math.abs(0.4 * Math.cos(hStd + (35 / 180) * Math.PI));\n\n\t\tlet Sl = lStd < 16 ? 0.511 : (0.040975 * lStd) / (1 + 0.01765 * lStd);\n\t\tlet Sc = (0.0638 * cStd) / (1 + 0.0131 * cStd) + 0.638;\n\t\tlet Sh = Sc * (F * T + 1 - F);\n\n\t\treturn Math.sqrt(\n\t\t\tdL2 / Math.pow(l * Sl, 2) +\n\t\t\t\tdC2 / Math.pow(c * Sc, 2) +\n\t\t\t\tdH2 / Math.pow(Sh, 2)\n\t\t);\n\t};\n};\n\n/*\n\n\tHyAB color difference formula, introduced in:\n\n\t\tAbasi S, Amani Tehran M, Fairchild MD. \n\t\t\"Distance metrics for very large color differences.\"\n\t\tColor Res Appl. 2019; 1–16. \n\t\thttps://doi.org/10.1002/col.22451\n\n\tPDF available at:\n\t\n\t\thttp://markfairchild.org/PDFs/PAP40.pdf\n */\nconst differenceHyab = () => {\n\tlet lab = converter('lab65');\n\treturn (std, smp) => {\n\t\tlet LabStd = lab(std);\n\t\tlet LabSmp = lab(smp);\n\t\tlet dL = LabStd.l - LabSmp.l;\n\t\tlet dA = LabStd.a - LabSmp.a;\n\t\tlet dB = LabStd.b - LabSmp.b;\n\t\treturn Math.abs(dL) + Math.sqrt(dA * dA + dB * dB);\n\t};\n};\n\n/*\n\t\"Measuring perceived color difference using YIQ NTSC\n\ttransmission color space in mobile applications\"\n\t\t\n\t\tby Yuriy Kotsarenko, Fernando Ramos in:\n\t\tProgramación Matemática y Software (2010) \n\n\tAvailable at:\n\t\t\n\t\thttp://www.progmat.uaem.mx:8080/artVol2Num2/Articulo3Vol2Num2.pdf\n */\nconst differenceKotsarenkoRamos = () =>\n\tdifferenceEuclidean('yiq', [0.5053, 0.299, 0.1957]);\n\n/*\n\tΔE_ITP, as defined in Rec. ITU-R BT.2124:\n\n\thttps://www.itu.int/rec/R-REC-BT.2124/en\n*/\nconst differenceItp = () =>\n\tdifferenceEuclidean('itp', [518400, 129600, 518400]);\n\nexport {\n\tdifferenceHueChroma,\n\tdifferenceHueSaturation,\n\tdifferenceHueNaive,\n\tdifferenceEuclidean,\n\tdifferenceCie76,\n\tdifferenceCie94,\n\tdifferenceCiede2000,\n\tdifferenceCmc,\n\tdifferenceHyab,\n\tdifferenceKotsarenkoRamos,\n\tdifferenceItp\n};\n","import converter from './converter.js';\nimport { getMode } from './modes.js';\n\nconst averageAngle = val => {\n\t// See: https://en.wikipedia.org/wiki/Mean_of_circular_quantities\n\tlet sum = val.reduce(\n\t\t(sum, val) => {\n\t\t\tif (val !== undefined) {\n\t\t\t\tlet rad = (val * Math.PI) / 180;\n\t\t\t\tsum.sin += Math.sin(rad);\n\t\t\t\tsum.cos += Math.cos(rad);\n\t\t\t}\n\t\t\treturn sum;\n\t\t},\n\t\t{ sin: 0, cos: 0 }\n\t);\n\tlet angle = (Math.atan2(sum.sin, sum.cos) * 180) / Math.PI;\n\treturn angle < 0 ? 360 + angle : angle;\n};\n\nconst averageNumber = val => {\n\tlet a = val.filter(v => v !== undefined);\n\treturn a.length ? a.reduce((sum, v) => sum + v, 0) / a.length : undefined;\n};\n\nconst isfn = o => typeof o === 'function';\n\nfunction average(colors, mode = 'rgb', overrides) {\n\tlet def = getMode(mode);\n\tlet cc = colors.map(converter(mode));\n\treturn def.channels.reduce(\n\t\t(res, ch) => {\n\t\t\tlet arr = cc.map(c => c[ch]).filter(val => val !== undefined);\n\t\t\tif (arr.length) {\n\t\t\t\tlet fn;\n\t\t\t\tif (isfn(overrides)) {\n\t\t\t\t\tfn = overrides;\n\t\t\t\t} else if (overrides && isfn(overrides[ch])) {\n\t\t\t\t\tfn = overrides[ch];\n\t\t\t\t} else if (def.average && isfn(def.average[ch])) {\n\t\t\t\t\tfn = def.average[ch];\n\t\t\t\t} else {\n\t\t\t\t\tfn = averageNumber;\n\t\t\t\t}\n\t\t\t\tres[ch] = fn(arr, ch);\n\t\t\t}\n\t\t\treturn res;\n\t\t},\n\t\t{ mode }\n\t);\n}\n\nexport { average, averageAngle, averageNumber };\n","/* \n\tDave Green's Cubehelix\n\t----------------------\n\n\tGreen, D. A., 2011, \"A colour scheme for the display of astronomical intensity images\", \n\tBulletin of the Astronomical Society of India, 39, 289. (2011BASI...39..289G at ADS.) \n\n\thttps://www.mrao.cam.ac.uk/%7Edag/CUBEHELIX/\n\thttps://arxiv.org/pdf/1108.5083.pdf\n\n\tAlthough Cubehelix was defined to be a method to obtain a colour scheme,\n\tit actually contains a definition of a colour space, as identified by \n\tMike Bostock and implemented in D3.js.\n\n\tGreen's paper introduces the following terminology:\n\n\t* \ta `lightness` dimension in the interval [0, 1] \n\t\ton which we interpolate to obtain the colour scheme\n\t*\ta `start` colour that is analogous to a Hue in HSL space\n\t*\ta number of `rotations` around the Hue cylinder.\n\t*\ta `hue` parameter which should more appropriately be called `saturation`\n\t\n\tAs such, the original definition of the Cubehelix scheme is actually an\n\tinterpolation between two colors in the Cubehelix space:\n\n\tH: start \t\t\t\tH: start + 360 * rotations\n\tS: hue \t\t\t->\t\tS: hue\n\tL: 0\t\t\t\t\tL: 1\n\n\tWe can therefore extend the interpolation to any two colors in this space,\n\twith a variable Saturation and a Lightness interval other than the fixed 0 -> 1.\n*/\n\nimport { fixupHueShorter } from '../fixup/hue.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport convertRgbToCubehelix from './convertRgbToCubehelix.js';\nimport convertCubehelixToRgb from './convertCubehelixToRgb.js';\nimport { differenceHueSaturation } from '../difference.js';\nimport { averageAngle } from '../average.js';\n\nconst definition = {\n\tmode: 'cubehelix',\n\tchannels: ['h', 's', 'l', 'alpha'],\n\tparse: ['--cubehelix'],\n\tserialize: '--cubehelix',\n\n\tranges: {\n\t\th: [0, 360],\n\t\ts: [0, 4.614],\n\t\tl: [0, 1]\n\t},\n\n\tfromMode: {\n\t\trgb: convertRgbToCubehelix\n\t},\n\n\ttoMode: {\n\t\trgb: convertCubehelixToRgb\n\t},\n\n\tinterpolate: {\n\t\th: {\n\t\t\tuse: interpolatorLinear,\n\t\t\tfixup: fixupHueShorter\n\t\t},\n\t\ts: interpolatorLinear,\n\t\tl: interpolatorLinear,\n\t\talpha: {\n\t\t\tuse: interpolatorLinear,\n\t\t\tfixup: fixupAlpha\n\t\t}\n\t},\n\n\tdifference: {\n\t\th: differenceHueSaturation\n\t},\n\n\taverage: {\n\t\th: averageAngle\n\t}\n};\n\nexport default definition;\n","import normalizeHue from '../util/normalizeHue.js';\n\n/* \n\tReferences: \n\t\t* https://drafts.csswg.org/css-color/#lab-to-lch\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n*/\nconst convertLabToLch = ({ l, a, b, alpha }, mode = 'lch') => {\n\tif (a === undefined) a = 0;\n\tif (b === undefined) b = 0;\n\tlet c = Math.sqrt(a * a + b * b);\n\tlet res = { mode, l, c };\n\tif (c) res.h = normalizeHue((Math.atan2(b, a) * 180) / Math.PI);\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertLabToLch;\n","/* \n\tReferences: \n\t\t* https://drafts.csswg.org/css-color/#lch-to-lab\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n*/\nconst convertLchToLab = ({ l, c, h, alpha }, mode = 'lab') => {\n\tif (h === undefined) h = 0;\n\tlet res = {\n\t\tmode,\n\t\tl,\n\t\ta: c ? c * Math.cos((h / 180) * Math.PI) : 0,\n\t\tb: c ? c * Math.sin((h / 180) * Math.PI) : 0\n\t};\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertLchToLab;\n","export const k = Math.pow(29, 3) / Math.pow(3, 3);\nexport const e = Math.pow(6, 3) / Math.pow(29, 3);\n","/*\n\tThe XYZ tristimulus values (white point)\n\tof standard illuminants for the CIE 1931 2° \n\tstandard observer.\n\n\tSee: https://en.wikipedia.org/wiki/Standard_illuminant\n */\n\nexport const D50 = {\n\tX: 0.3457 / 0.3585,\n\tY: 1,\n\tZ: (1 - 0.3457 - 0.3585) / 0.3585\n};\n\nexport const D65 = {\n\tX: 0.3127 / 0.329,\n\tY: 1,\n\tZ: (1 - 0.3127 - 0.329) / 0.329\n};\n\nexport const k = Math.pow(29, 3) / Math.pow(3, 3);\nexport const e = Math.pow(6, 3) / Math.pow(29, 3);\n","import { k, e } from '../xyz65/constants.js';\nimport { D65 } from '../constants.js';\n\nlet fn = v => (Math.pow(v, 3) > e ? Math.pow(v, 3) : (116 * v - 16) / k);\n\nconst convertLab65ToXyz65 = ({ l, a, b, alpha }) => {\n\tif (l === undefined) l = 0;\n\tif (a === undefined) a = 0;\n\tif (b === undefined) b = 0;\n\n\tlet fy = (l + 16) / 116;\n\tlet fx = a / 500 + fy;\n\tlet fz = fy - b / 200;\n\n\tlet res = {\n\t\tmode: 'xyz65',\n\t\tx: fn(fx) * D65.X,\n\t\ty: fn(fy) * D65.Y,\n\t\tz: fn(fz) * D65.Z\n\t};\n\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertLab65ToXyz65;\n","import convertLab65ToXyz65 from './convertLab65ToXyz65.js';\nimport convertXyz65ToRgb from '../xyz65/convertXyz65ToRgb.js';\n\nconst convertLab65ToRgb = lab => convertXyz65ToRgb(convertLab65ToXyz65(lab));\n\nexport default convertLab65ToRgb;\n","import { k, e } from '../xyz65/constants.js';\nimport { D65 } from '../constants.js';\n\nconst f = value => (value > e ? Math.cbrt(value) : (k * value + 16) / 116);\n\nconst convertXyz65ToLab65 = ({ x, y, z, alpha }) => {\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet f0 = f(x / D65.X);\n\tlet f1 = f(y / D65.Y);\n\tlet f2 = f(z / D65.Z);\n\n\tlet res = {\n\t\tmode: 'lab65',\n\t\tl: 116 * f1 - 16,\n\t\ta: 500 * (f0 - f1),\n\t\tb: 200 * (f1 - f2)\n\t};\n\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertXyz65ToLab65;\n","import convertRgbToXyz65 from '../xyz65/convertRgbToXyz65.js';\nimport convertXyz65ToLab65 from './convertXyz65ToLab65.js';\n\nconst convertRgbToLab65 = rgb => {\n\tlet res = convertXyz65ToLab65(convertRgbToXyz65(rgb));\n\n\t// Fixes achromatic RGB colors having a _slight_ chroma due to floating-point errors\n\t// and approximated computations in sRGB <-> CIELab.\n\t// See: https://github.com/d3/d3-color/pull/46\n\tif (rgb.r === rgb.b && rgb.b === rgb.g) {\n\t\tres.a = res.b = 0;\n\t}\n\treturn res;\n};\n\nexport default convertRgbToLab65;\n","export const kE = 1;\nexport const kCH = 1;\nexport const θ = (26 / 180) * Math.PI;\nexport const cosθ = Math.cos(θ);\nexport const sinθ = Math.sin(θ);\nexport const factor = 100 / Math.log(139 / 100); // ~ 303.67\n","import { kCH, kE, sinθ, cosθ, θ, factor } from './constants.js';\n\n/*\n\tConvert DIN99o LCh to CIELab D65\n\t--------------------------------\n */\n\nconst convertDlchToLab65 = ({ l, c, h, alpha }) => {\n\tif (l === undefined) l = 0;\n\tif (c === undefined) c = 0;\n\tif (h === undefined) h = 0;\n\tlet res = {\n\t\tmode: 'lab65',\n\t\tl: (Math.exp((l * kE) / factor) - 1) / 0.0039\n\t};\n\n\tlet G = (Math.exp(0.0435 * c * kCH * kE) - 1) / 0.075;\n\tlet e = G * Math.cos((h / 180) * Math.PI - θ);\n\tlet f = G * Math.sin((h / 180) * Math.PI - θ);\n\tres.a = e * cosθ - (f / 0.83) * sinθ;\n\tres.b = e * sinθ + (f / 0.83) * cosθ;\n\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertDlchToLab65;\n","import { kCH, kE, sinθ, cosθ, θ, factor } from './constants.js';\nimport normalizeHue from '../util/normalizeHue.js';\n\n/*\n\tConvert CIELab D65 to DIN99o LCh\n\t================================\n */\n\nconst convertLab65ToDlch = ({ l, a, b, alpha }) => {\n\tif (l === undefined) l = 0;\n\tif (a === undefined) a = 0;\n\tif (b === undefined) b = 0;\n\tlet e = a * cosθ + b * sinθ;\n\tlet f = 0.83 * (b * cosθ - a * sinθ);\n\tlet G = Math.sqrt(e * e + f * f);\n\tlet res = {\n\t\tmode: 'dlch',\n\t\tl: (factor / kE) * Math.log(1 + 0.0039 * l),\n\t\tc: Math.log(1 + 0.075 * G) / (0.0435 * kCH * kE)\n\t};\n\n\tif (res.c) {\n\t\tres.h = normalizeHue(((Math.atan2(f, e) + θ) / Math.PI) * 180);\n\t}\n\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertLab65ToDlch;\n","import convertLabToLch from '../lch/convertLabToLch.js';\nimport convertLchToLab from '../lch/convertLchToLab.js';\nimport convertLab65ToRgb from '../lab65/convertLab65ToRgb.js';\nimport convertRgbToLab65 from '../lab65/convertRgbToLab65.js';\nimport convertDlchToLab65 from '../dlch/convertDlchToLab65.js';\nimport convertLab65ToDlch from '../dlch/convertLab65ToDlch.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\n\nconst convertDlabToLab65 = c => convertDlchToLab65(convertLabToLch(c, 'dlch'));\nconst convertLab65ToDlab = c => convertLchToLab(convertLab65ToDlch(c), 'dlab');\n\nconst definition = {\n\tmode: 'dlab',\n\n\tparse: ['--din99o-lab'],\n\tserialize: '--din99o-lab',\n\n\ttoMode: {\n\t\tlab65: convertDlabToLab65,\n\t\trgb: c => convertLab65ToRgb(convertDlabToLab65(c))\n\t},\n\n\tfromMode: {\n\t\tlab65: convertLab65ToDlab,\n\t\trgb: c => convertLab65ToDlab(convertRgbToLab65(c))\n\t},\n\n\tchannels: ['l', 'a', 'b', 'alpha'],\n\n\tranges: {\n\t\tl: [0, 100],\n\t\ta: [-40.09, 45.501],\n\t\tb: [-40.469, 44.344]\n\t},\n\n\tinterpolate: {\n\t\tl: interpolatorLinear,\n\t\ta: interpolatorLinear,\n\t\tb: interpolatorLinear,\n\t\talpha: {\n\t\t\tuse: interpolatorLinear,\n\t\t\tfixup: fixupAlpha\n\t\t}\n\t}\n};\n\nexport default definition;\n","import convertLabToLch from '../lch/convertLabToLch.js';\nimport convertLchToLab from '../lch/convertLchToLab.js';\nimport convertDlchToLab65 from './convertDlchToLab65.js';\nimport convertLab65ToDlch from './convertLab65ToDlch.js';\nimport convertLab65ToRgb from '../lab65/convertLab65ToRgb.js';\nimport convertRgbToLab65 from '../lab65/convertRgbToLab65.js';\n\nimport { fixupHueShorter } from '../fixup/hue.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { differenceHueChroma } from '../difference.js';\nimport { averageAngle } from '../average.js';\n\nconst definition = {\n\tmode: 'dlch',\n\n\tparse: ['--din99o-lch'],\n\tserialize: '--din99o-lch',\n\n\ttoMode: {\n\t\tlab65: convertDlchToLab65,\n\t\tdlab: c => convertLchToLab(c, 'dlab'),\n\t\trgb: c => convertLab65ToRgb(convertDlchToLab65(c))\n\t},\n\n\tfromMode: {\n\t\tlab65: convertLab65ToDlch,\n\t\tdlab: c => convertLabToLch(c, 'dlch'),\n\t\trgb: c => convertLab65ToDlch(convertRgbToLab65(c))\n\t},\n\n\tchannels: ['l', 'c', 'h', 'alpha'],\n\n\tranges: {\n\t\tl: [0, 100],\n\t\tc: [0, 51.484],\n\t\th: [0, 360]\n\t},\n\n\tinterpolate: {\n\t\tl: interpolatorLinear,\n\t\tc: interpolatorLinear,\n\t\th: {\n\t\t\tuse: interpolatorLinear,\n\t\t\tfixup: fixupHueShorter\n\t\t},\n\t\talpha: {\n\t\t\tuse: interpolatorLinear,\n\t\t\tfixup: fixupAlpha\n\t\t}\n\t},\n\n\tdifference: {\n\t\th: differenceHueChroma\n\t},\n\n\taverage: {\n\t\th: averageAngle\n\t}\n};\n\nexport default definition;\n","import normalizeHue from '../util/normalizeHue.js';\n\n// Based on: https://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB\n\nexport default function convertHsiToRgb({ h, s, i, alpha }) {\n\th = normalizeHue(h !== undefined ? h : 0);\n\tif (s === undefined) s = 0;\n\tif (i === undefined) i = 0;\n\tlet f = Math.abs(((h / 60) % 2) - 1);\n\tlet res;\n\tswitch (Math.floor(h / 60)) {\n\t\tcase 0:\n\t\t\tres = {\n\t\t\t\tr: i * (1 + s * (3 / (2 - f) - 1)),\n\t\t\t\tg: i * (1 + s * ((3 * (1 - f)) / (2 - f) - 1)),\n\t\t\t\tb: i * (1 - s)\n\t\t\t};\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tres = {\n\t\t\t\tr: i * (1 + s * ((3 * (1 - f)) / (2 - f) - 1)),\n\t\t\t\tg: i * (1 + s * (3 / (2 - f) - 1)),\n\t\t\t\tb: i * (1 - s)\n\t\t\t};\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tres = {\n\t\t\t\tr: i * (1 - s),\n\t\t\t\tg: i * (1 + s * (3 / (2 - f) - 1)),\n\t\t\t\tb: i * (1 + s * ((3 * (1 - f)) / (2 - f) - 1))\n\t\t\t};\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tres = {\n\t\t\t\tr: i * (1 - s),\n\t\t\t\tg: i * (1 + s * ((3 * (1 - f)) / (2 - f) - 1)),\n\t\t\t\tb: i * (1 + s * (3 / (2 - f) - 1))\n\t\t\t};\n\t\t\tbreak;\n\t\tcase 4:\n\t\t\tres = {\n\t\t\t\tr: i * (1 + s * ((3 * (1 - f)) / (2 - f) - 1)),\n\t\t\t\tg: i * (1 - s),\n\t\t\t\tb: i * (1 + s * (3 / (2 - f) - 1))\n\t\t\t};\n\t\t\tbreak;\n\t\tcase 5:\n\t\t\tres = {\n\t\t\t\tr: i * (1 + s * (3 / (2 - f) - 1)),\n\t\t\t\tg: i * (1 - s),\n\t\t\t\tb: i * (1 + s * ((3 * (1 - f)) / (2 - f) - 1))\n\t\t\t};\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tres = { r: i * (1 - s), g: i * (1 - s), b: i * (1 - s) };\n\t}\n\n\tres.mode = 'rgb';\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n}\n","// Based on: https://en.wikipedia.org/wiki/HSL_and_HSV#Formal_derivation\n\nexport default function convertRgbToHsi({ r, g, b, alpha }) {\n\tif (r === undefined) r = 0;\n\tif (g === undefined) g = 0;\n\tif (b === undefined) b = 0;\n\tlet M = Math.max(r, g, b),\n\t\tm = Math.min(r, g, b);\n\tlet res = {\n\t\tmode: 'hsi',\n\t\ts: r + g + b === 0 ? 0 : 1 - (3 * m) / (r + g + b),\n\t\ti: (r + g + b) / 3\n\t};\n\tif (M - m !== 0)\n\t\tres.h =\n\t\t\t(M === r\n\t\t\t\t? (g - b) / (M - m) + (g < b) * 6\n\t\t\t\t: M === g\n\t\t\t\t? (b - r) / (M - m) + 2\n\t\t\t\t: (r - g) / (M - m) + 4) * 60;\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n}\n","import convertHsiToRgb from './convertHsiToRgb.js';\nimport convertRgbToHsi from './convertRgbToHsi.js';\nimport { fixupHueShorter } from '../fixup/hue.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { differenceHueSaturation } from '../difference.js';\nimport { averageAngle } from '../average.js';\n\nconst definition = {\n\tmode: 'hsi',\n\n\ttoMode: {\n\t\trgb: convertHsiToRgb\n\t},\n\n\tparse: ['--hsi'],\n\tserialize: '--hsi',\n\n\tfromMode: {\n\t\trgb: convertRgbToHsi\n\t},\n\n\tchannels: ['h', 's', 'i', 'alpha'],\n\n\tranges: {\n\t\th: [0, 360]\n\t},\n\n\tgamut: 'rgb',\n\n\tinterpolate: {\n\t\th: { use: interpolatorLinear, fixup: fixupHueShorter },\n\t\ts: interpolatorLinear,\n\t\ti: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t},\n\n\tdifference: {\n\t\th: differenceHueSaturation\n\t},\n\n\taverage: {\n\t\th: averageAngle\n\t}\n};\n\nexport default definition;\n","import normalizeHue from '../util/normalizeHue.js';\n// Based on: https://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB\n\nexport default function convertHslToRgb({ h, s, l, alpha }) {\n\th = normalizeHue(h !== undefined ? h : 0);\n\tif (s === undefined) s = 0;\n\tif (l === undefined) l = 0;\n\tlet m1 = l + s * (l < 0.5 ? l : 1 - l);\n\tlet m2 = m1 - (m1 - l) * 2 * Math.abs(((h / 60) % 2) - 1);\n\tlet res;\n\tswitch (Math.floor(h / 60)) {\n\t\tcase 0:\n\t\t\tres = { r: m1, g: m2, b: 2 * l - m1 };\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tres = { r: m2, g: m1, b: 2 * l - m1 };\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tres = { r: 2 * l - m1, g: m1, b: m2 };\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tres = { r: 2 * l - m1, g: m2, b: m1 };\n\t\t\tbreak;\n\t\tcase 4:\n\t\t\tres = { r: m2, g: 2 * l - m1, b: m1 };\n\t\t\tbreak;\n\t\tcase 5:\n\t\t\tres = { r: m1, g: 2 * l - m1, b: m2 };\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tres = { r: 2 * l - m1, g: 2 * l - m1, b: 2 * l - m1 };\n\t}\n\tres.mode = 'rgb';\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n}\n","// Based on: https://en.wikipedia.org/wiki/HSL_and_HSV#Formal_derivation\n\nexport default function convertRgbToHsl({ r, g, b, alpha }) {\n\tif (r === undefined) r = 0;\n\tif (g === undefined) g = 0;\n\tif (b === undefined) b = 0;\n\tlet M = Math.max(r, g, b),\n\t\tm = Math.min(r, g, b);\n\tlet res = {\n\t\tmode: 'hsl',\n\t\ts: M === m ? 0 : (M - m) / (1 - Math.abs(M + m - 1)),\n\t\tl: 0.5 * (M + m)\n\t};\n\tif (M - m !== 0)\n\t\tres.h =\n\t\t\t(M === r\n\t\t\t\t? (g - b) / (M - m) + (g < b) * 6\n\t\t\t\t: M === g\n\t\t\t\t? (b - r) / (M - m) + 2\n\t\t\t\t: (r - g) / (M - m) + 4) * 60;\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n}\n","const hueToDeg = (val, unit) => {\n\tswitch (unit) {\n\t\tcase 'deg':\n\t\t\treturn +val;\n\t\tcase 'rad':\n\t\t\treturn (val / Math.PI) * 180;\n\t\tcase 'grad':\n\t\t\treturn (val / 10) * 9;\n\t\tcase 'turn':\n\t\t\treturn val * 360;\n\t}\n};\n\nexport default hueToDeg;\n","import hueToDeg from '../util/hue.js';\nimport { hue, per, num_per, c } from '../util/regex.js';\n\n/*\n\thsl() regular expressions for legacy format\n\tReference: https://drafts.csswg.org/css-color/#the-hsl-notation\n */\nconst hsl_old = new RegExp(\n\t`^hsla?\\\\(\\\\s*${hue}${c}${per}${c}${per}\\\\s*(?:,\\\\s*${num_per}\\\\s*)?\\\\)$`\n);\n\nconst parseHslLegacy = color => {\n\tlet match = color.match(hsl_old);\n\tif (!match) return;\n\tlet res = { mode: 'hsl' };\n\n\tif (match[3] !== undefined) {\n\t\tres.h = +match[3];\n\t} else if (match[1] !== undefined && match[2] !== undefined) {\n\t\tres.h = hueToDeg(match[1], match[2]);\n\t}\n\n\tif (match[4] !== undefined) {\n\t\tres.s = Math.min(Math.max(0, match[4] / 100), 1);\n\t}\n\n\tif (match[5] !== undefined) {\n\t\tres.l = Math.min(Math.max(0, match[5] / 100), 1);\n\t}\n\n\tif (match[6] !== undefined) {\n\t\tres.alpha = Math.max(0, Math.min(1, match[6] / 100));\n\t} else if (match[7] !== undefined) {\n\t\tres.alpha = Math.max(0, Math.min(1, +match[7]));\n\t}\n\treturn res;\n};\n\nexport default parseHslLegacy;\n","import { Tok } from '../parse.js';\n\nfunction parseHsl(color, parsed) {\n\tif (!parsed || (parsed[0] !== 'hsl' && parsed[0] !== 'hsla')) {\n\t\treturn undefined;\n\t}\n\tconst res = { mode: 'hsl' };\n\tconst [, h, s, l, alpha] = parsed;\n\n\tif (h.type !== Tok.None) {\n\t\tif (h.type === Tok.Percentage) {\n\t\t\treturn undefined;\n\t\t}\n\t\tres.h = h.value;\n\t}\n\n\tif (s.type !== Tok.None) {\n\t\tif (s.type === Tok.Hue) {\n\t\t\treturn undefined;\n\t\t}\n\t\tres.s = s.value / 100;\n\t}\n\n\tif (l.type !== Tok.None) {\n\t\tif (l.type === Tok.Hue) {\n\t\t\treturn undefined;\n\t\t}\n\t\tres.l = l.value / 100;\n\t}\n\n\tif (alpha.type !== Tok.None) {\n\t\tres.alpha = Math.min(\n\t\t\t1,\n\t\t\tMath.max(\n\t\t\t\t0,\n\t\t\t\talpha.type === Tok.Number ? alpha.value : alpha.value / 100\n\t\t\t)\n\t\t);\n\t}\n\n\treturn res;\n}\n\nexport default parseHsl;\n","import convertHslToRgb from './convertHslToRgb.js';\nimport convertRgbToHsl from './convertRgbToHsl.js';\nimport parseHslLegacy from './parseHslLegacy.js';\nimport parseHsl from './parseHsl.js';\nimport { fixupHueShorter } from '../fixup/hue.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { differenceHueSaturation } from '../difference.js';\nimport { averageAngle } from '../average.js';\n\nconst definition = {\n\tmode: 'hsl',\n\n\ttoMode: {\n\t\trgb: convertHslToRgb\n\t},\n\n\tfromMode: {\n\t\trgb: convertRgbToHsl\n\t},\n\n\tchannels: ['h', 's', 'l', 'alpha'],\n\n\tranges: {\n\t\th: [0, 360]\n\t},\n\n\tgamut: 'rgb',\n\n\tparse: [parseHsl, parseHslLegacy],\n\tserialize: c =>\n\t\t`hsl(${c.h !== undefined ? c.h : 'none'} ${\n\t\t\tc.s !== undefined ? c.s * 100 + '%' : 'none'\n\t\t} ${c.l !== undefined ? c.l * 100 + '%' : 'none'}${\n\t\t\tc.alpha < 1 ? ` / ${c.alpha}` : ''\n\t\t})`,\n\n\tinterpolate: {\n\t\th: { use: interpolatorLinear, fixup: fixupHueShorter },\n\t\ts: interpolatorLinear,\n\t\tl: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t},\n\n\tdifference: {\n\t\th: differenceHueSaturation\n\t},\n\n\taverage: {\n\t\th: averageAngle\n\t}\n};\n\nexport default definition;\n","import normalizeHue from '../util/normalizeHue.js';\n\n// Based on: https://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB\n\nexport default function convertHsvToRgb({ h, s, v, alpha }) {\n\th = normalizeHue(h !== undefined ? h : 0);\n\tif (s === undefined) s = 0;\n\tif (v === undefined) v = 0;\n\tlet f = Math.abs(((h / 60) % 2) - 1);\n\tlet res;\n\tswitch (Math.floor(h / 60)) {\n\t\tcase 0:\n\t\t\tres = { r: v, g: v * (1 - s * f), b: v * (1 - s) };\n\t\t\tbreak;\n\t\tcase 1:\n\t\t\tres = { r: v * (1 - s * f), g: v, b: v * (1 - s) };\n\t\t\tbreak;\n\t\tcase 2:\n\t\t\tres = { r: v * (1 - s), g: v, b: v * (1 - s * f) };\n\t\t\tbreak;\n\t\tcase 3:\n\t\t\tres = { r: v * (1 - s), g: v * (1 - s * f), b: v };\n\t\t\tbreak;\n\t\tcase 4:\n\t\t\tres = { r: v * (1 - s * f), g: v * (1 - s), b: v };\n\t\t\tbreak;\n\t\tcase 5:\n\t\t\tres = { r: v, g: v * (1 - s), b: v * (1 - s * f) };\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tres = { r: v * (1 - s), g: v * (1 - s), b: v * (1 - s) };\n\t}\n\tres.mode = 'rgb';\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n}\n","// Based on: https://en.wikipedia.org/wiki/HSL_and_HSV#Formal_derivation\n\nexport default function convertRgbToHsv({ r, g, b, alpha }) {\n\tif (r === undefined) r = 0;\n\tif (g === undefined) g = 0;\n\tif (b === undefined) b = 0;\n\tlet M = Math.max(r, g, b),\n\t\tm = Math.min(r, g, b);\n\tlet res = {\n\t\tmode: 'hsv',\n\t\ts: M === 0 ? 0 : 1 - m / M,\n\t\tv: M\n\t};\n\tif (M - m !== 0)\n\t\tres.h =\n\t\t\t(M === r\n\t\t\t\t? (g - b) / (M - m) + (g < b) * 6\n\t\t\t\t: M === g\n\t\t\t\t? (b - r) / (M - m) + 2\n\t\t\t\t: (r - g) / (M - m) + 4) * 60;\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n}\n","import convertHsvToRgb from './convertHsvToRgb.js';\nimport convertRgbToHsv from './convertRgbToHsv.js';\nimport { fixupHueShorter } from '../fixup/hue.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { differenceHueSaturation } from '../difference.js';\nimport { averageAngle } from '../average.js';\n\nconst definition = {\n\tmode: 'hsv',\n\n\ttoMode: {\n\t\trgb: convertHsvToRgb\n\t},\n\n\tparse: ['--hsv'],\n\tserialize: '--hsv',\n\n\tfromMode: {\n\t\trgb: convertRgbToHsv\n\t},\n\n\tchannels: ['h', 's', 'v', 'alpha'],\n\n\tranges: {\n\t\th: [0, 360]\n\t},\n\n\tgamut: 'rgb',\n\n\tinterpolate: {\n\t\th: { use: interpolatorLinear, fixup: fixupHueShorter },\n\t\ts: interpolatorLinear,\n\t\tv: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t},\n\n\tdifference: {\n\t\th: differenceHueSaturation\n\t},\n\n\taverage: {\n\t\th: averageAngle\n\t}\n};\n\nexport default definition;\n","/*\n\tHWB to RGB converter\n\t--------------------\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#hwb-to-rgb\n\t\t* https://en.wikipedia.org/wiki/HWB_color_model\n\t\t* http://alvyray.com/Papers/CG/HWB_JGTv208.pdf\n */\n\nimport convertHsvToRgb from '../hsv/convertHsvToRgb.js';\n\nexport default function convertHwbToRgb({ h, w, b, alpha }) {\n\tif (w === undefined) w = 0;\n\tif (b === undefined) b = 0;\n\t// normalize w + b to 1\n\tif (w + b > 1) {\n\t\tlet s = w + b;\n\t\tw /= s;\n\t\tb /= s;\n\t}\n\treturn convertHsvToRgb({\n\t\th: h,\n\t\ts: b === 1 ? 1 : 1 - w / (1 - b),\n\t\tv: 1 - b,\n\t\talpha: alpha\n\t});\n}\n","/*\n\tRGB to HWB converter\n\t--------------------\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#hwb-to-rgb\n\t\t* https://en.wikipedia.org/wiki/HWB_color_model\n\t\t* http://alvyray.com/Papers/CG/HWB_JGTv208.pdf\n */\n\nimport convertRgbToHsv from '../hsv/convertRgbToHsv.js';\n\nexport default function convertRgbToHwb(rgba) {\n\tlet hsv = convertRgbToHsv(rgba);\n\tif (hsv === undefined) return undefined;\n\tlet s = hsv.s !== undefined ? hsv.s : 0;\n\tlet v = hsv.v !== undefined ? hsv.v : 0;\n\tlet res = {\n\t\tmode: 'hwb',\n\t\tw: (1 - s) * v,\n\t\tb: 1 - v\n\t};\n\tif (hsv.h !== undefined) res.h = hsv.h;\n\tif (hsv.alpha !== undefined) res.alpha = hsv.alpha;\n\treturn res;\n}\n","import { Tok } from '../parse.js';\n\nfunction ParseHwb(color, parsed) {\n\tif (!parsed || parsed[0] !== 'hwb') {\n\t\treturn undefined;\n\t}\n\tconst res = { mode: 'hwb' };\n\tconst [, h, w, b, alpha] = parsed;\n\n\tif (h.type !== Tok.None) {\n\t\tif (h.type === Tok.Percentage) {\n\t\t\treturn undefined;\n\t\t}\n\t\tres.h = h.value;\n\t}\n\n\tif (w.type !== Tok.None) {\n\t\tif (w.type === Tok.Hue) {\n\t\t\treturn undefined;\n\t\t}\n\t\tres.w = w.value / 100;\n\t}\n\n\tif (b.type !== Tok.None) {\n\t\tif (b.type === Tok.Hue) {\n\t\t\treturn undefined;\n\t\t}\n\t\tres.b = b.value / 100;\n\t}\n\n\tif (alpha.type !== Tok.None) {\n\t\tres.alpha = Math.min(\n\t\t\t1,\n\t\t\tMath.max(\n\t\t\t\t0,\n\t\t\t\talpha.type === Tok.Number ? alpha.value : alpha.value / 100\n\t\t\t)\n\t\t);\n\t}\n\n\treturn res;\n}\n\nexport default ParseHwb;\n","import convertHwbToRgb from './convertHwbToRgb.js';\nimport convertRgbToHwb from './convertRgbToHwb.js';\nimport parseHwb from './parseHwb.js';\nimport { fixupHueShorter } from '../fixup/hue.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { differenceHueNaive } from '../difference.js';\nimport { averageAngle } from '../average.js';\n\nconst definition = {\n\tmode: 'hwb',\n\n\ttoMode: {\n\t\trgb: convertHwbToRgb\n\t},\n\n\tfromMode: {\n\t\trgb: convertRgbToHwb\n\t},\n\n\tchannels: ['h', 'w', 'b', 'alpha'],\n\n\tranges: {\n\t\th: [0, 360]\n\t},\n\n\tgamut: 'rgb',\n\n\tparse: [parseHwb],\n\tserialize: c =>\n\t\t`hwb(${c.h !== undefined ? c.h : 'none'} ${\n\t\t\tc.w !== undefined ? c.w * 100 + '%' : 'none'\n\t\t} ${c.b !== undefined ? c.b * 100 + '%' : 'none'}${\n\t\t\tc.alpha < 1 ? ` / ${c.alpha}` : ''\n\t\t})`,\n\n\tinterpolate: {\n\t\th: { use: interpolatorLinear, fixup: fixupHueShorter },\n\t\tw: interpolatorLinear,\n\t\tb: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t},\n\n\tdifference: {\n\t\th: differenceHueNaive\n\t},\n\n\taverage: {\n\t\th: averageAngle\n\t}\n};\n\nexport default definition;\n","/*\n\tRelative XYZ has Y=1 for media white,\n\tBT.2048 says media white Y=203 (at PQ 58).\n\tSee: https://www.itu.int/dms_pub/itu-r/opb/rep/R-REP-BT.2408-3-2019-PDF-E.pdf\n*/\nexport const YW = 203;\n","/*\n\thttps://en.wikipedia.org/wiki/Transfer_functions_in_imaging\n*/\n\nexport const M1 = 0.1593017578125;\nexport const M2 = 78.84375;\nexport const C1 = 0.8359375;\nexport const C2 = 18.8515625;\nexport const C3 = 18.6875;\n\n/*\n\tPerceptual Quantizer, as defined in Rec. BT 2100-2 (2018)\n\n\t* https://www.itu.int/rec/R-REC-BT.2100-2-201807-I/en\n\t* https://en.wikipedia.org/wiki/Perceptual_quantizer\n*/\n\n/* PQ EOTF, defined for `v` in [0,1]. */\nexport function transferPqDecode(v) {\n\tif (v < 0) return 0;\n\tconst c = Math.pow(v, 1 / M2);\n\treturn 1e4 * Math.pow(Math.max(0, c - C1) / (C2 - C3 * c), 1 / M1);\n}\n\n/* PQ EOTF^-1, defined for `v` in [0, 1e4]. */\nexport function transferPqEncode(v) {\n\tif (v < 0) return 0;\n\tconst c = Math.pow(v / 1e4, M1);\n\treturn Math.pow((C1 + C2 * c) / (1 + C3 * c), M2);\n}\n","import { YW } from '../hdr/constants.js';\nimport { transferPqDecode } from '../hdr/transfer.js';\n\nconst toRel = c => Math.max(c / YW, 0);\n\nconst convertItpToXyz65 = ({ i, t, p, alpha }) => {\n\tif (i === undefined) i = 0;\n\tif (t === undefined) t = 0;\n\tif (p === undefined) p = 0;\n\n\tconst l = transferPqDecode(\n\t\ti + 0.008609037037932761 * t + 0.11102962500302593 * p\n\t);\n\tconst m = transferPqDecode(\n\t\ti - 0.00860903703793275 * t - 0.11102962500302599 * p\n\t);\n\tconst s = transferPqDecode(\n\t\ti + 0.5600313357106791 * t - 0.32062717498731885 * p\n\t);\n\n\tconst res = {\n\t\tmode: 'xyz65',\n\t\tx: toRel(\n\t\t\t2.0701522183894219 * l -\n\t\t\t\t1.3263473389671556 * m +\n\t\t\t\t0.2066510476294051 * s\n\t\t),\n\t\ty: toRel(\n\t\t\t0.3647385209748074 * l +\n\t\t\t\t0.680566024947227 * m -\n\t\t\t\t0.0453045459220346 * s\n\t\t),\n\t\tz: toRel(\n\t\t\t-0.049747207535812 * l -\n\t\t\t\t0.0492609666966138 * m +\n\t\t\t\t1.1880659249923042 * s\n\t\t)\n\t};\n\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertItpToXyz65;\n","import { YW } from '../hdr/constants.js';\nimport { transferPqEncode } from '../hdr/transfer.js';\n\nconst toAbs = (c = 0) => Math.max(c * YW, 0);\n\nconst convertXyz65ToItp = ({ x, y, z, alpha }) => {\n\tconst absX = toAbs(x);\n\tconst absY = toAbs(y);\n\tconst absZ = toAbs(z);\n\tconst l = transferPqEncode(\n\t\t0.3592832590121217 * absX +\n\t\t\t0.6976051147779502 * absY -\n\t\t\t0.0358915932320289 * absZ\n\t);\n\tconst m = transferPqEncode(\n\t\t-0.1920808463704995 * absX +\n\t\t\t1.1004767970374323 * absY +\n\t\t\t0.0753748658519118 * absZ\n\t);\n\tconst s = transferPqEncode(\n\t\t0.0070797844607477 * absX +\n\t\t\t0.0748396662186366 * absY +\n\t\t\t0.8433265453898765 * absZ\n\t);\n\n\tconst i = 0.5 * l + 0.5 * m;\n\tconst t = 1.61376953125 * l - 3.323486328125 * m + 1.709716796875 * s;\n\tconst p = 4.378173828125 * l - 4.24560546875 * m - 0.132568359375 * s;\n\n\tconst res = { mode: 'itp', i, t, p };\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertXyz65ToItp;\n","import { interpolatorLinear } from '../interpolate/linear.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport convertItpToXyz65 from './convertItpToXyz65.js';\nimport convertXyz65ToItp from './convertXyz65ToItp.js';\nimport convertRgbToXyz65 from '../xyz65/convertRgbToXyz65.js';\nimport convertXyz65ToRgb from '../xyz65/convertXyz65ToRgb.js';\n\n/*\n ICtCp (or ITP) color space, as defined in ITU-R Recommendation BT.2100.\n\n ICtCp is drafted to be supported in CSS within\n [CSS Color HDR Module Level 1](https://drafts.csswg.org/css-color-hdr/#ICtCp) spec.\n*/\n\nconst definition = {\n\tmode: 'itp',\n\tchannels: ['i', 't', 'p', 'alpha'],\n\tparse: ['--ictcp'],\n\tserialize: '--ictcp',\n\n\ttoMode: {\n\t\txyz65: convertItpToXyz65,\n\t\trgb: color => convertXyz65ToRgb(convertItpToXyz65(color))\n\t},\n\n\tfromMode: {\n\t\txyz65: convertXyz65ToItp,\n\t\trgb: color => convertXyz65ToItp(convertRgbToXyz65(color))\n\t},\n\n\tranges: {\n\t\ti: [0, 0.581],\n\t\tt: [-0.369, 0.272],\n\t\tp: [-0.164, 0.331]\n\t},\n\n\tinterpolate: {\n\t\ti: interpolatorLinear,\n\t\tt: interpolatorLinear,\n\t\tp: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t}\n};\n\nexport default definition;\n","import { M1 as n, C1, C2, C3 } from '../hdr/transfer.js';\nconst p = 134.03437499999998; // = 1.7 * 2523 / Math.pow(2, 5);\nconst d0 = 1.6295499532821566e-11;\n\n/* \n\tThe encoding function is derived from Perceptual Quantizer.\n*/\nconst jabPqEncode = v => {\n\tif (v < 0) return 0;\n\tlet vn = Math.pow(v / 10000, n);\n\treturn Math.pow((C1 + C2 * vn) / (1 + C3 * vn), p);\n};\n\n// Convert to Absolute XYZ\nconst abs = (v = 0) => Math.max(v * 203, 0);\n\nconst convertXyz65ToJab = ({ x, y, z, alpha }) => {\n\tx = abs(x);\n\ty = abs(y);\n\tz = abs(z);\n\n\tlet xp = 1.15 * x - 0.15 * z;\n\tlet yp = 0.66 * y + 0.34 * x;\n\n\tlet l = jabPqEncode(0.41478972 * xp + 0.579999 * yp + 0.014648 * z);\n\tlet m = jabPqEncode(-0.20151 * xp + 1.120649 * yp + 0.0531008 * z);\n\tlet s = jabPqEncode(-0.0166008 * xp + 0.2648 * yp + 0.6684799 * z);\n\n\tlet i = (l + m) / 2;\n\n\tlet res = {\n\t\tmode: 'jab',\n\t\tj: (0.44 * i) / (1 - 0.56 * i) - d0,\n\t\ta: 3.524 * l - 4.066708 * m + 0.542708 * s,\n\t\tb: 0.199076 * l + 1.096799 * m - 1.295875 * s\n\t};\n\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertXyz65ToJab;\n","import { M1 as n, C1, C2, C3 } from '../hdr/transfer.js';\nconst p = 134.03437499999998; // = 1.7 * 2523 / Math.pow(2, 5);\nconst d0 = 1.6295499532821566e-11;\n\n/* \n\tThe encoding function is derived from Perceptual Quantizer.\n*/\nconst jabPqDecode = v => {\n\tif (v < 0) return 0;\n\tlet vp = Math.pow(v, 1 / p);\n\treturn 10000 * Math.pow((C1 - vp) / (C3 * vp - C2), 1 / n);\n};\n\nconst rel = v => v / 203;\n\nconst convertJabToXyz65 = ({ j, a, b, alpha }) => {\n\tif (j === undefined) j = 0;\n\tif (a === undefined) a = 0;\n\tif (b === undefined) b = 0;\n\tlet i = (j + d0) / (0.44 + 0.56 * (j + d0));\n\n\tlet l = jabPqDecode(i + 0.13860504 * a + 0.058047316 * b);\n\tlet m = jabPqDecode(i - 0.13860504 * a - 0.058047316 * b);\n\tlet s = jabPqDecode(i - 0.096019242 * a - 0.8118919 * b);\n\n\tlet res = {\n\t\tmode: 'xyz65',\n\t\tx: rel(\n\t\t\t1.661373024652174 * l -\n\t\t\t\t0.914523081304348 * m +\n\t\t\t\t0.23136208173913045 * s\n\t\t),\n\t\ty: rel(\n\t\t\t-0.3250758611844533 * l +\n\t\t\t\t1.571847026732543 * m -\n\t\t\t\t0.21825383453227928 * s\n\t\t),\n\t\tz: rel(-0.090982811 * l - 0.31272829 * m + 1.5227666 * s)\n\t};\n\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertJabToXyz65;\n","/*\n\tConvert sRGB to JzAzBz.\n\n\tFor achromatic sRGB colors, adjust the equivalent JzAzBz color\n\tto be achromatic as well, insteading of having a very slight chroma.\n */\n\nimport convertXyz65ToJab from './convertXyz65ToJab.js';\nimport convertRgbToXyz65 from '../xyz65/convertRgbToXyz65.js';\n\nconst convertRgbToJab = rgb => {\n\tlet res = convertXyz65ToJab(convertRgbToXyz65(rgb));\n\tif (rgb.r === rgb.b && rgb.b === rgb.g) {\n\t\tres.a = res.b = 0;\n\t}\n\treturn res;\n};\n\nexport default convertRgbToJab;\n","import convertXyz65ToRgb from '../xyz65/convertXyz65ToRgb.js';\nimport convertJabToXyz65 from './convertJabToXyz65.js';\n\nconst convertJabToRgb = color => convertXyz65ToRgb(convertJabToXyz65(color));\n\nexport default convertJabToRgb;\n","/*\n\tThe JzAzBz color space.\n\n\tBased on:\n\n\tMuhammad Safdar, Guihua Cui, Youn Jin Kim, and Ming Ronnier Luo, \n\t\"Perceptually uniform color space for image signals \n\tincluding high dynamic range and wide gamut,\" \n\tOpt. Express 25, 15131-15151 (2017) \n\n\thttps://doi.org/10.1364/OE.25.015131\n */\n\nimport convertXyz65ToJab from './convertXyz65ToJab.js';\nimport convertJabToXyz65 from './convertJabToXyz65.js';\nimport convertRgbToJab from './convertRgbToJab.js';\nimport convertJabToRgb from './convertJabToRgb.js';\n\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\n\nconst definition = {\n\tmode: 'jab',\n\tchannels: ['j', 'a', 'b', 'alpha'],\n\n\tparse: ['--jzazbz'],\n\tserialize: '--jzazbz',\n\n\tfromMode: {\n\t\trgb: convertRgbToJab,\n\t\txyz65: convertXyz65ToJab\n\t},\n\n\ttoMode: {\n\t\trgb: convertJabToRgb,\n\t\txyz65: convertJabToXyz65\n\t},\n\n\tranges: {\n\t\tj: [0, 0.222],\n\t\ta: [-0.109, 0.129],\n\t\tb: [-0.185, 0.134]\n\t},\n\n\tinterpolate: {\n\t\tj: interpolatorLinear,\n\t\ta: interpolatorLinear,\n\t\tb: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t}\n};\n\nexport default definition;\n","import normalizeHue from '../util/normalizeHue.js';\n\nconst convertJabToJch = ({ j, a, b, alpha }) => {\n\tif (a === undefined) a = 0;\n\tif (b === undefined) b = 0;\n\tlet c = Math.sqrt(a * a + b * b);\n\tlet res = {\n\t\tmode: 'jch',\n\t\tj,\n\t\tc\n\t};\n\tif (c) {\n\t\tres.h = normalizeHue((Math.atan2(b, a) * 180) / Math.PI);\n\t}\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertJabToJch;\n","const convertJchToJab = ({ j, c, h, alpha }) => {\n\tif (h === undefined) h = 0;\n\tlet res = {\n\t\tmode: 'jab',\n\t\tj,\n\t\ta: c ? c * Math.cos((h / 180) * Math.PI) : 0,\n\t\tb: c ? c * Math.sin((h / 180) * Math.PI) : 0\n\t};\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertJchToJab;\n","import convertJabToJch from './convertJabToJch.js';\nimport convertJchToJab from './convertJchToJab.js';\nimport convertJabToRgb from '../jab/convertJabToRgb.js';\nimport convertRgbToJab from '../jab/convertRgbToJab.js';\n\nimport { fixupHueShorter } from '../fixup/hue.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { differenceHueChroma } from '../difference.js';\nimport { averageAngle } from '../average.js';\n\nconst definition = {\n\tmode: 'jch',\n\n\tparse: ['--jzczhz'],\n\tserialize: '--jzczhz',\n\n\ttoMode: {\n\t\tjab: convertJchToJab,\n\t\trgb: c => convertJabToRgb(convertJchToJab(c))\n\t},\n\n\tfromMode: {\n\t\trgb: c => convertJabToJch(convertRgbToJab(c)),\n\t\tjab: convertJabToJch\n\t},\n\n\tchannels: ['j', 'c', 'h', 'alpha'],\n\n\tranges: {\n\t\tj: [0, 0.221],\n\t\tc: [0, 0.19],\n\t\th: [0, 360]\n\t},\n\n\tinterpolate: {\n\t\th: { use: interpolatorLinear, fixup: fixupHueShorter },\n\t\tc: interpolatorLinear,\n\t\tj: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t},\n\n\tdifference: {\n\t\th: differenceHueChroma\n\t},\n\n\taverage: {\n\t\th: averageAngle\n\t}\n};\n\nexport default definition;\n","export const k = Math.pow(29, 3) / Math.pow(3, 3);\nexport const e = Math.pow(6, 3) / Math.pow(29, 3);\n","import { k, e } from '../xyz50/constants.js';\nimport { D50 } from '../constants.js';\n\nlet fn = v => (Math.pow(v, 3) > e ? Math.pow(v, 3) : (116 * v - 16) / k);\n\nconst convertLabToXyz50 = ({ l, a, b, alpha }) => {\n\tif (l === undefined) l = 0;\n\tif (a === undefined) a = 0;\n\tif (b === undefined) b = 0;\n\tlet fy = (l + 16) / 116;\n\tlet fx = a / 500 + fy;\n\tlet fz = fy - b / 200;\n\n\tlet res = {\n\t\tmode: 'xyz50',\n\t\tx: fn(fx) * D50.X,\n\t\ty: fn(fy) * D50.Y,\n\t\tz: fn(fz) * D50.Z\n\t};\n\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertLabToXyz50;\n","/*\n\tCIE XYZ D50 values to sRGB.\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n*/\n\nimport convertLrgbToRgb from '../lrgb/convertLrgbToRgb.js';\n\nconst convertXyz50ToRgb = ({ x, y, z, alpha }) => {\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet res = convertLrgbToRgb({\n\t\tr:\n\t\t\tx * 3.1341359569958707 -\n\t\t\ty * 1.6173863321612538 -\n\t\t\t0.4906619460083532 * z,\n\t\tg:\n\t\t\tx * -0.978795502912089 +\n\t\t\ty * 1.916254567259524 +\n\t\t\t0.03344273116131949 * z,\n\t\tb:\n\t\t\tx * 0.07195537988411677 -\n\t\t\ty * 0.2289768264158322 +\n\t\t\t1.405386058324125 * z\n\t});\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertXyz50ToRgb;\n","import convertLabToXyz50 from './convertLabToXyz50.js';\nimport convertXyz50ToRgb from '../xyz50/convertXyz50ToRgb.js';\n\nconst convertLabToRgb = lab => convertXyz50ToRgb(convertLabToXyz50(lab));\n\nexport default convertLabToRgb;\n","/*\n\tConvert sRGB values to CIE XYZ D50\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n\t\n*/\n\nimport convertRgbToLrgb from '../lrgb/convertRgbToLrgb.js';\n\nconst convertRgbToXyz50 = rgb => {\n\tlet { r, g, b, alpha } = convertRgbToLrgb(rgb);\n\tlet res = {\n\t\tmode: 'xyz50',\n\t\tx:\n\t\t\t0.436065742824811 * r +\n\t\t\t0.3851514688337912 * g +\n\t\t\t0.14307845442264197 * b,\n\t\ty:\n\t\t\t0.22249319175623702 * r +\n\t\t\t0.7168870538238823 * g +\n\t\t\t0.06061979053616537 * b,\n\t\tz:\n\t\t\t0.013923904500943465 * r +\n\t\t\t0.09708128566574634 * g +\n\t\t\t0.7140993584005155 * b\n\t};\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertRgbToXyz50;\n","import { k, e } from '../xyz50/constants.js';\nimport { D50 } from '../constants.js';\n\nconst f = value => (value > e ? Math.cbrt(value) : (k * value + 16) / 116);\n\nconst convertXyz50ToLab = ({ x, y, z, alpha }) => {\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet f0 = f(x / D50.X);\n\tlet f1 = f(y / D50.Y);\n\tlet f2 = f(z / D50.Z);\n\n\tlet res = {\n\t\tmode: 'lab',\n\t\tl: 116 * f1 - 16,\n\t\ta: 500 * (f0 - f1),\n\t\tb: 200 * (f1 - f2)\n\t};\n\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertXyz50ToLab;\n","import convertRgbToXyz50 from '../xyz50/convertRgbToXyz50.js';\nimport convertXyz50ToLab from './convertXyz50ToLab.js';\n\nconst convertRgbToLab = rgb => {\n\tlet res = convertXyz50ToLab(convertRgbToXyz50(rgb));\n\n\t// Fixes achromatic RGB colors having a _slight_ chroma due to floating-point errors\n\t// and approximated computations in sRGB <-> CIELab.\n\t// See: https://github.com/d3/d3-color/pull/46\n\tif (rgb.r === rgb.b && rgb.b === rgb.g) {\n\t\tres.a = res.b = 0;\n\t}\n\treturn res;\n};\n\nexport default convertRgbToLab;\n","import { Tok } from '../parse.js';\n\nfunction parseLab(color, parsed) {\n\tif (!parsed || parsed[0] !== 'lab') {\n\t\treturn undefined;\n\t}\n\tconst res = { mode: 'lab' };\n\tconst [, l, a, b, alpha] = parsed;\n\tif (l.type === Tok.Hue || a.type === Tok.Hue || b.type === Tok.Hue) {\n\t\treturn undefined;\n\t}\n\tif (l.type !== Tok.None) {\n\t\tres.l = Math.min(Math.max(0, l.value), 100);\n\t}\n\tif (a.type !== Tok.None) {\n\t\tres.a = a.type === Tok.Number ? a.value : (a.value * 125) / 100;\n\t}\n\tif (b.type !== Tok.None) {\n\t\tres.b = b.type === Tok.Number ? b.value : (b.value * 125) / 100;\n\t}\n\tif (alpha.type !== Tok.None) {\n\t\tres.alpha = Math.min(\n\t\t\t1,\n\t\t\tMath.max(\n\t\t\t\t0,\n\t\t\t\talpha.type === Tok.Number ? alpha.value : alpha.value / 100\n\t\t\t)\n\t\t);\n\t}\n\n\treturn res;\n}\n\nexport default parseLab;\n","import convertLabToRgb from './convertLabToRgb.js';\nimport convertLabToXyz50 from './convertLabToXyz50.js';\nimport convertRgbToLab from './convertRgbToLab.js';\nimport convertXyz50ToLab from './convertXyz50ToLab.js';\nimport parseLab from './parseLab.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\n\nconst definition = {\n\tmode: 'lab',\n\n\ttoMode: {\n\t\txyz50: convertLabToXyz50,\n\t\trgb: convertLabToRgb\n\t},\n\n\tfromMode: {\n\t\txyz50: convertXyz50ToLab,\n\t\trgb: convertRgbToLab\n\t},\n\n\tchannels: ['l', 'a', 'b', 'alpha'],\n\n\tranges: {\n\t\tl: [0, 100],\n\t\ta: [-125, 125],\n\t\tb: [-125, 125]\n\t},\n\n\tparse: [parseLab],\n\tserialize: c =>\n\t\t`lab(${c.l !== undefined ? c.l : 'none'} ${\n\t\t\tc.a !== undefined ? c.a : 'none'\n\t\t} ${c.b !== undefined ? c.b : 'none'}${\n\t\t\tc.alpha < 1 ? ` / ${c.alpha}` : ''\n\t\t})`,\n\n\tinterpolate: {\n\t\tl: interpolatorLinear,\n\t\ta: interpolatorLinear,\n\t\tb: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t}\n};\n\nexport default definition;\n","import convertLab65ToRgb from './convertLab65ToRgb.js';\nimport convertLab65ToXyz65 from './convertLab65ToXyz65.js';\nimport convertRgbToLab65 from './convertRgbToLab65.js';\nimport convertXyz65ToLab65 from './convertXyz65ToLab65.js';\nimport lab from '../lab/definition.js';\n\nconst definition = {\n\t...lab,\n\tmode: 'lab65',\n\n\tparse: ['--lab-d65'],\n\tserialize: '--lab-d65',\n\n\ttoMode: {\n\t\txyz65: convertLab65ToXyz65,\n\t\trgb: convertLab65ToRgb\n\t},\n\n\tfromMode: {\n\t\txyz65: convertXyz65ToLab65,\n\t\trgb: convertRgbToLab65\n\t},\n\n\tranges: {\n\t\tl: [0, 100],\n\t\ta: [-125, 125],\n\t\tb: [-125, 125]\n\t}\n};\n\nexport default definition;\n","import { Tok } from '../parse.js';\n\nfunction parseLch(color, parsed) {\n\tif (!parsed || parsed[0] !== 'lch') {\n\t\treturn undefined;\n\t}\n\tconst res = { mode: 'lch' };\n\tconst [, l, c, h, alpha] = parsed;\n\tif (l.type !== Tok.None) {\n\t\tif (l.type === Tok.Hue) {\n\t\t\treturn undefined;\n\t\t}\n\t\tres.l = Math.min(Math.max(0, l.value), 100);\n\t}\n\tif (c.type !== Tok.None) {\n\t\tres.c = Math.max(\n\t\t\t0,\n\t\t\tc.type === Tok.Number ? c.value : (c.value * 150) / 100\n\t\t);\n\t}\n\tif (h.type !== Tok.None) {\n\t\tif (h.type === Tok.Percentage) {\n\t\t\treturn undefined;\n\t\t}\n\t\tres.h = h.value;\n\t}\n\tif (alpha.type !== Tok.None) {\n\t\tres.alpha = Math.min(\n\t\t\t1,\n\t\t\tMath.max(\n\t\t\t\t0,\n\t\t\t\talpha.type === Tok.Number ? alpha.value : alpha.value / 100\n\t\t\t)\n\t\t);\n\t}\n\n\treturn res;\n}\n\nexport default parseLch;\n","import convertLabToLch from './convertLabToLch.js';\nimport convertLchToLab from './convertLchToLab.js';\nimport convertLabToRgb from '../lab/convertLabToRgb.js';\nimport convertRgbToLab from '../lab/convertRgbToLab.js';\nimport parseLch from './parseLch.js';\nimport { fixupHueShorter } from '../fixup/hue.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { differenceHueChroma } from '../difference.js';\nimport { averageAngle } from '../average.js';\n\nconst definition = {\n\tmode: 'lch',\n\n\ttoMode: {\n\t\tlab: convertLchToLab,\n\t\trgb: c => convertLabToRgb(convertLchToLab(c))\n\t},\n\n\tfromMode: {\n\t\trgb: c => convertLabToLch(convertRgbToLab(c)),\n\t\tlab: convertLabToLch\n\t},\n\n\tchannels: ['l', 'c', 'h', 'alpha'],\n\n\tranges: {\n\t\tl: [0, 100],\n\t\tc: [0, 150],\n\t\th: [0, 360]\n\t},\n\n\tparse: [parseLch],\n\tserialize: c =>\n\t\t`lch(${c.l !== undefined ? c.l : 'none'} ${\n\t\t\tc.c !== undefined ? c.c : 'none'\n\t\t} ${c.h !== undefined ? c.h : 'none'}${\n\t\t\tc.alpha < 1 ? ` / ${c.alpha}` : ''\n\t\t})`,\n\n\tinterpolate: {\n\t\th: { use: interpolatorLinear, fixup: fixupHueShorter },\n\t\tc: interpolatorLinear,\n\t\tl: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t},\n\n\tdifference: {\n\t\th: differenceHueChroma\n\t},\n\n\taverage: {\n\t\th: averageAngle\n\t}\n};\n\nexport default definition;\n","import convertLabToLch from '../lch/convertLabToLch.js';\nimport convertLchToLab from '../lch/convertLchToLab.js';\nimport convertLab65ToRgb from '../lab65/convertLab65ToRgb.js';\nimport convertRgbToLab65 from '../lab65/convertRgbToLab65.js';\nimport lch from '../lch/definition.js';\n\nconst definition = {\n\t...lch,\n\tmode: 'lch65',\n\n\tparse: ['--lch-d65'],\n\tserialize: '--lch-d65',\n\n\ttoMode: {\n\t\tlab65: c => convertLchToLab(c, 'lab65'),\n\t\trgb: c => convertLab65ToRgb(convertLchToLab(c, 'lab65'))\n\t},\n\n\tfromMode: {\n\t\trgb: c => convertLabToLch(convertRgbToLab65(c), 'lch65'),\n\t\tlab65: c => convertLabToLch(c, 'lch65')\n\t},\n\n\tranges: {\n\t\tl: [0, 100],\n\t\tc: [0, 150],\n\t\th: [0, 360]\n\t}\n};\n\nexport default definition;\n","import normalizeHue from '../util/normalizeHue.js';\n\nconst convertLuvToLchuv = ({ l, u, v, alpha }) => {\n\tif (u === undefined) u = 0;\n\tif (v === undefined) v = 0;\n\tlet c = Math.sqrt(u * u + v * v);\n\tlet res = {\n\t\tmode: 'lchuv',\n\t\tl: l,\n\t\tc: c\n\t};\n\tif (c) {\n\t\tres.h = normalizeHue((Math.atan2(v, u) * 180) / Math.PI);\n\t}\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertLuvToLchuv;\n","const convertLchuvToLuv = ({ l, c, h, alpha }) => {\n\tif (h === undefined) h = 0;\n\tlet res = {\n\t\tmode: 'luv',\n\t\tl: l,\n\t\tu: c ? c * Math.cos((h / 180) * Math.PI) : 0,\n\t\tv: c ? c * Math.sin((h / 180) * Math.PI) : 0\n\t};\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertLchuvToLuv;\n","import { k, e } from '../xyz50/constants.js';\nimport { D50 } from '../constants.js';\n\nexport const u_fn = (x, y, z) => (4 * x) / (x + 15 * y + 3 * z);\nexport const v_fn = (x, y, z) => (9 * y) / (x + 15 * y + 3 * z);\n\nexport const un = u_fn(D50.X, D50.Y, D50.Z);\nexport const vn = v_fn(D50.X, D50.Y, D50.Z);\n\nconst l_fn = value => (value <= e ? k * value : 116 * Math.cbrt(value) - 16);\n\nconst convertXyz50ToLuv = ({ x, y, z, alpha }) => {\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet l = l_fn(y / D50.Y);\n\tlet u = u_fn(x, y, z);\n\tlet v = v_fn(x, y, z);\n\n\t// guard against NaNs produced by `xyz(0 0 0)` black\n\tif (!isFinite(u) || !isFinite(v)) {\n\t\tl = u = v = 0;\n\t} else {\n\t\tu = 13 * l * (u - un);\n\t\tv = 13 * l * (v - vn);\n\t}\n\n\tlet res = {\n\t\tmode: 'luv',\n\t\tl,\n\t\tu,\n\t\tv\n\t};\n\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertXyz50ToLuv;\n","import { k } from '../xyz50/constants.js';\nimport { D50 } from '../constants.js';\n\nexport const u_fn = (x, y, z) => (4 * x) / (x + 15 * y + 3 * z);\nexport const v_fn = (x, y, z) => (9 * y) / (x + 15 * y + 3 * z);\n\nexport const un = u_fn(D50.X, D50.Y, D50.Z);\nexport const vn = v_fn(D50.X, D50.Y, D50.Z);\n\nconst convertLuvToXyz50 = ({ l, u, v, alpha }) => {\n\tif (l === undefined) l = 0;\n\tif (l === 0) {\n\t\treturn { mode: 'xyz50', x: 0, y: 0, z: 0 };\n\t}\n\n\tif (u === undefined) u = 0;\n\tif (v === undefined) v = 0;\n\n\tlet up = u / (13 * l) + un;\n\tlet vp = v / (13 * l) + vn;\n\tlet y = D50.Y * (l <= 8 ? l / k : Math.pow((l + 16) / 116, 3));\n\tlet x = (y * (9 * up)) / (4 * vp);\n\tlet z = (y * (12 - 3 * up - 20 * vp)) / (4 * vp);\n\n\tlet res = { mode: 'xyz50', x, y, z };\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertLuvToXyz50;\n","/*\n\tCIELChuv color space\n\t--------------------\n\n\tReference: \n\n\t\thttps://en.wikipedia.org/wiki/CIELUV\n */\n\nimport convertLuvToLchuv from './convertLuvToLchuv.js';\nimport convertLchuvToLuv from './convertLchuvToLuv.js';\nimport convertXyz50ToLuv from '../luv/convertXyz50ToLuv.js';\nimport convertLuvToXyz50 from '../luv/convertLuvToXyz50.js';\nimport convertXyz50ToRgb from '../xyz50/convertXyz50ToRgb.js';\nimport convertRgbToXyz50 from '../xyz50/convertRgbToXyz50.js';\n\nimport { fixupHueShorter } from '../fixup/hue.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { differenceHueChroma } from '../difference.js';\nimport { averageAngle } from '../average.js';\n\nconst convertRgbToLchuv = rgb =>\n\tconvertLuvToLchuv(convertXyz50ToLuv(convertRgbToXyz50(rgb)));\nconst convertLchuvToRgb = lchuv =>\n\tconvertXyz50ToRgb(convertLuvToXyz50(convertLchuvToLuv(lchuv)));\n\nconst definition = {\n\tmode: 'lchuv',\n\n\ttoMode: {\n\t\tluv: convertLchuvToLuv,\n\t\trgb: convertLchuvToRgb\n\t},\n\n\tfromMode: {\n\t\trgb: convertRgbToLchuv,\n\t\tluv: convertLuvToLchuv\n\t},\n\n\tchannels: ['l', 'c', 'h', 'alpha'],\n\n\tparse: ['--lchuv'],\n\tserialize: '--lchuv',\n\n\tranges: {\n\t\tl: [0, 100],\n\t\tc: [0, 176.956],\n\t\th: [0, 360]\n\t},\n\n\tinterpolate: {\n\t\th: { use: interpolatorLinear, fixup: fixupHueShorter },\n\t\tc: interpolatorLinear,\n\t\tl: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t},\n\n\tdifference: {\n\t\th: differenceHueChroma\n\t},\n\n\taverage: {\n\t\th: averageAngle\n\t}\n};\n\nexport default definition;\n","import rgb from '../rgb/definition.js';\nimport convertRgbToLrgb from './convertRgbToLrgb.js';\nimport convertLrgbToRgb from './convertLrgbToRgb.js';\n\nconst definition = {\n\t...rgb,\n\tmode: 'lrgb',\n\n\ttoMode: {\n\t\trgb: convertLrgbToRgb\n\t},\n\n\tfromMode: {\n\t\trgb: convertRgbToLrgb\n\t},\n\n\tparse: ['srgb-linear'],\n\tserialize: 'srgb-linear'\n};\n\nexport default definition;\n","/*\n\tCIELUV color space\n\t------------------\n\n\tReference: \n\n\t\thttps://en.wikipedia.org/wiki/CIELUV\n */\n\nimport convertXyz50ToLuv from './convertXyz50ToLuv.js';\nimport convertLuvToXyz50 from './convertLuvToXyz50.js';\nimport convertXyz50ToRgb from '../xyz50/convertXyz50ToRgb.js';\nimport convertRgbToXyz50 from '../xyz50/convertRgbToXyz50.js';\n\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\n\nconst definition = {\n\tmode: 'luv',\n\n\ttoMode: {\n\t\txyz50: convertLuvToXyz50,\n\t\trgb: luv => convertXyz50ToRgb(convertLuvToXyz50(luv))\n\t},\n\n\tfromMode: {\n\t\txyz50: convertXyz50ToLuv,\n\t\trgb: rgb => convertXyz50ToLuv(convertRgbToXyz50(rgb))\n\t},\n\n\tchannels: ['l', 'u', 'v', 'alpha'],\n\n\tparse: ['--luv'],\n\tserialize: '--luv',\n\n\tranges: {\n\t\tl: [0, 100],\n\t\tu: [-84.936, 175.042],\n\t\tv: [-125.882, 87.243]\n\t},\n\n\tinterpolate: {\n\t\tl: interpolatorLinear,\n\t\tu: interpolatorLinear,\n\t\tv: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t}\n};\n\nexport default definition;\n","const convertLrgbToOklab = ({ r, g, b, alpha }) => {\n\tif (r === undefined) r = 0;\n\tif (g === undefined) g = 0;\n\tif (b === undefined) b = 0;\n\n\tlet L = Math.cbrt(\n\t\t0.412221469470763 * r + 0.5363325372617348 * g + 0.0514459932675022 * b\n\t);\n\tlet M = Math.cbrt(\n\t\t0.2119034958178252 * r + 0.6806995506452344 * g + 0.1073969535369406 * b\n\t);\n\tlet S = Math.cbrt(\n\t\t0.0883024591900564 * r + 0.2817188391361215 * g + 0.6299787016738222 * b\n\t);\n\n\tlet res = {\n\t\tmode: 'oklab',\n\t\tl:\n\t\t\t0.210454268309314 * L +\n\t\t\t0.7936177747023054 * M -\n\t\t\t0.0040720430116193 * S,\n\t\ta:\n\t\t\t1.9779985324311684 * L -\n\t\t\t2.4285922420485799 * M +\n\t\t\t0.450593709617411 * S,\n\t\tb:\n\t\t\t0.0259040424655478 * L +\n\t\t\t0.7827717124575296 * M -\n\t\t\t0.8086757549230774 * S\n\t};\n\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertLrgbToOklab;\n","import convertRgbToLrgb from '../lrgb/convertRgbToLrgb.js';\nimport convertLrgbToOklab from './convertLrgbToOklab.js';\n\nconst convertRgbToOklab = rgb => {\n\tlet res = convertLrgbToOklab(convertRgbToLrgb(rgb));\n\tif (rgb.r === rgb.b && rgb.b === rgb.g) {\n\t\tres.a = res.b = 0;\n\t}\n\treturn res;\n};\n\nexport default convertRgbToOklab;\n","const convertOklabToLrgb = ({ l, a, b, alpha }) => {\n\tif (l === undefined) l = 0;\n\tif (a === undefined) a = 0;\n\tif (b === undefined) b = 0;\n\n\tlet L = Math.pow(l + 0.3963377773761749 * a + 0.2158037573099136 * b, 3);\n\tlet M = Math.pow(l - 0.1055613458156586 * a - 0.0638541728258133 * b, 3);\n\tlet S = Math.pow(l - 0.0894841775298119 * a - 1.2914855480194092 * b, 3);\n\n\tlet res = {\n\t\tmode: 'lrgb',\n\t\tr:\n\t\t\t4.0767416360759574 * L -\n\t\t\t3.3077115392580616 * M +\n\t\t\t0.2309699031821044 * S,\n\t\tg:\n\t\t\t-1.2684379732850317 * L +\n\t\t\t2.6097573492876887 * M -\n\t\t\t0.3413193760026573 * S,\n\t\tb:\n\t\t\t-0.0041960761386756 * L -\n\t\t\t0.7034186179359362 * M +\n\t\t\t1.7076146940746117 * S\n\t};\n\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\n\treturn res;\n};\n\nexport default convertOklabToLrgb;\n","import convertLrgbToRgb from '../lrgb/convertLrgbToRgb.js';\nimport convertOklabToLrgb from './convertOklabToLrgb.js';\n\nconst convertOklabToRgb = c => convertLrgbToRgb(convertOklabToLrgb(c));\n\nexport default convertOklabToRgb;\n","/*\n\tAdapted from code by Björn Ottosson,\n\treleased under the MIT license:\n\n\tCopyright (c) 2021 Björn Ottosson\n\n\tPermission is hereby granted, free of charge, to any person obtaining a copy of\n\tthis software and associated documentation files (the \"Software\"), to deal in\n\tthe Software without restriction, including without limitation the rights to\n\tuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n\tof the Software, and to permit persons to whom the Software is furnished to do\n\tso, subject to the following conditions:\n\n\tThe above copyright notice and this permission notice shall be included in all\n\tcopies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\tIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\tFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n\tAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n\tLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n\tOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n\tSOFTWARE.\n */\n\nimport convertOklabToLrgb from '../oklab/convertOklabToLrgb.js';\n\nexport function toe(x) {\n\tconst k_1 = 0.206;\n\tconst k_2 = 0.03;\n\tconst k_3 = (1 + k_1) / (1 + k_2);\n\treturn (\n\t\t0.5 *\n\t\t(k_3 * x -\n\t\t\tk_1 +\n\t\t\tMath.sqrt((k_3 * x - k_1) * (k_3 * x - k_1) + 4 * k_2 * k_3 * x))\n\t);\n}\n\nexport function toe_inv(x) {\n\tconst k_1 = 0.206;\n\tconst k_2 = 0.03;\n\tconst k_3 = (1 + k_1) / (1 + k_2);\n\treturn (x * x + k_1 * x) / (k_3 * (x + k_2));\n}\n\n// Finds the maximum saturation possible for a given hue that fits in sRGB\n// Saturation here is defined as S = C/L\n// a and b must be normalized so a^2 + b^2 == 1\nfunction compute_max_saturation(a, b) {\n\t// Max saturation will be when one of r, g or b goes below zero.\n\n\t// Select different coefficients depending on which component goes below zero first\n\tlet k0, k1, k2, k3, k4, wl, wm, ws;\n\n\tif (-1.88170328 * a - 0.80936493 * b > 1) {\n\t\t// Red component\n\t\tk0 = +1.19086277;\n\t\tk1 = +1.76576728;\n\t\tk2 = +0.59662641;\n\t\tk3 = +0.75515197;\n\t\tk4 = +0.56771245;\n\t\twl = +4.0767416621;\n\t\twm = -3.3077115913;\n\t\tws = +0.2309699292;\n\t} else if (1.81444104 * a - 1.19445276 * b > 1) {\n\t\t// Green component\n\t\tk0 = +0.73956515;\n\t\tk1 = -0.45954404;\n\t\tk2 = +0.08285427;\n\t\tk3 = +0.1254107;\n\t\tk4 = +0.14503204;\n\t\twl = -1.2684380046;\n\t\twm = +2.6097574011;\n\t\tws = -0.3413193965;\n\t} else {\n\t\t// Blue component\n\t\tk0 = +1.35733652;\n\t\tk1 = -0.00915799;\n\t\tk2 = -1.1513021;\n\t\tk3 = -0.50559606;\n\t\tk4 = +0.00692167;\n\t\twl = -0.0041960863;\n\t\twm = -0.7034186147;\n\t\tws = +1.707614701;\n\t}\n\n\t// Approximate max saturation using a polynomial:\n\tlet S = k0 + k1 * a + k2 * b + k3 * a * a + k4 * a * b;\n\n\t// Do one step Halley's method to get closer\n\t// this gives an error less than 10e6, except for some blue hues where the dS/dh is close to infinite\n\t// this should be sufficient for most applications, otherwise do two/three steps\n\n\tlet k_l = +0.3963377774 * a + 0.2158037573 * b;\n\tlet k_m = -0.1055613458 * a - 0.0638541728 * b;\n\tlet k_s = -0.0894841775 * a - 1.291485548 * b;\n\n\t{\n\t\tlet l_ = 1 + S * k_l;\n\t\tlet m_ = 1 + S * k_m;\n\t\tlet s_ = 1 + S * k_s;\n\n\t\tlet l = l_ * l_ * l_;\n\t\tlet m = m_ * m_ * m_;\n\t\tlet s = s_ * s_ * s_;\n\n\t\tlet l_dS = 3 * k_l * l_ * l_;\n\t\tlet m_dS = 3 * k_m * m_ * m_;\n\t\tlet s_dS = 3 * k_s * s_ * s_;\n\n\t\tlet l_dS2 = 6 * k_l * k_l * l_;\n\t\tlet m_dS2 = 6 * k_m * k_m * m_;\n\t\tlet s_dS2 = 6 * k_s * k_s * s_;\n\n\t\tlet f = wl * l + wm * m + ws * s;\n\t\tlet f1 = wl * l_dS + wm * m_dS + ws * s_dS;\n\t\tlet f2 = wl * l_dS2 + wm * m_dS2 + ws * s_dS2;\n\n\t\tS = S - (f * f1) / (f1 * f1 - 0.5 * f * f2);\n\t}\n\n\treturn S;\n}\n\nexport function find_cusp(a, b) {\n\t// First, find the maximum saturation (saturation S = C/L)\n\tlet S_cusp = compute_max_saturation(a, b);\n\n\t// Convert to linear sRGB to find the first point where at least one of r,g or b >= 1:\n\tlet rgb = convertOklabToLrgb({ l: 1, a: S_cusp * a, b: S_cusp * b });\n\tlet L_cusp = Math.cbrt(1 / Math.max(rgb.r, rgb.g, rgb.b));\n\tlet C_cusp = L_cusp * S_cusp;\n\n\treturn [L_cusp, C_cusp];\n}\n\n// Finds intersection of the line defined by\n// L = L0 * (1 - t) + t * L1;\n// C = t * C1;\n// a and b must be normalized so a^2 + b^2 == 1\nfunction find_gamut_intersection(a, b, L1, C1, L0, cusp = null) {\n\tif (!cusp) {\n\t\t// Find the cusp of the gamut triangle\n\t\tcusp = find_cusp(a, b);\n\t}\n\n\t// Find the intersection for upper and lower half seprately\n\tlet t;\n\tif ((L1 - L0) * cusp[1] - (cusp[0] - L0) * C1 <= 0) {\n\t\t// Lower half\n\n\t\tt = (cusp[1] * L0) / (C1 * cusp[0] + cusp[1] * (L0 - L1));\n\t} else {\n\t\t// Upper half\n\n\t\t// First intersect with triangle\n\t\tt = (cusp[1] * (L0 - 1)) / (C1 * (cusp[0] - 1) + cusp[1] * (L0 - L1));\n\n\t\t// Then one step Halley's method\n\t\t{\n\t\t\tlet dL = L1 - L0;\n\t\t\tlet dC = C1;\n\n\t\t\tlet k_l = +0.3963377774 * a + 0.2158037573 * b;\n\t\t\tlet k_m = -0.1055613458 * a - 0.0638541728 * b;\n\t\t\tlet k_s = -0.0894841775 * a - 1.291485548 * b;\n\n\t\t\tlet l_dt = dL + dC * k_l;\n\t\t\tlet m_dt = dL + dC * k_m;\n\t\t\tlet s_dt = dL + dC * k_s;\n\n\t\t\t// If higher accuracy is required, 2 or 3 iterations of the following block can be used:\n\t\t\t{\n\t\t\t\tlet L = L0 * (1 - t) + t * L1;\n\t\t\t\tlet C = t * C1;\n\n\t\t\t\tlet l_ = L + C * k_l;\n\t\t\t\tlet m_ = L + C * k_m;\n\t\t\t\tlet s_ = L + C * k_s;\n\n\t\t\t\tlet l = l_ * l_ * l_;\n\t\t\t\tlet m = m_ * m_ * m_;\n\t\t\t\tlet s = s_ * s_ * s_;\n\n\t\t\t\tlet ldt = 3 * l_dt * l_ * l_;\n\t\t\t\tlet mdt = 3 * m_dt * m_ * m_;\n\t\t\t\tlet sdt = 3 * s_dt * s_ * s_;\n\n\t\t\t\tlet ldt2 = 6 * l_dt * l_dt * l_;\n\t\t\t\tlet mdt2 = 6 * m_dt * m_dt * m_;\n\t\t\t\tlet sdt2 = 6 * s_dt * s_dt * s_;\n\n\t\t\t\tlet r =\n\t\t\t\t\t4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s - 1;\n\t\t\t\tlet r1 =\n\t\t\t\t\t4.0767416621 * ldt -\n\t\t\t\t\t3.3077115913 * mdt +\n\t\t\t\t\t0.2309699292 * sdt;\n\t\t\t\tlet r2 =\n\t\t\t\t\t4.0767416621 * ldt2 -\n\t\t\t\t\t3.3077115913 * mdt2 +\n\t\t\t\t\t0.2309699292 * sdt2;\n\n\t\t\t\tlet u_r = r1 / (r1 * r1 - 0.5 * r * r2);\n\t\t\t\tlet t_r = -r * u_r;\n\n\t\t\t\tlet g =\n\t\t\t\t\t-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s - 1;\n\t\t\t\tlet g1 =\n\t\t\t\t\t-1.2684380046 * ldt +\n\t\t\t\t\t2.6097574011 * mdt -\n\t\t\t\t\t0.3413193965 * sdt;\n\t\t\t\tlet g2 =\n\t\t\t\t\t-1.2684380046 * ldt2 +\n\t\t\t\t\t2.6097574011 * mdt2 -\n\t\t\t\t\t0.3413193965 * sdt2;\n\n\t\t\t\tlet u_g = g1 / (g1 * g1 - 0.5 * g * g2);\n\t\t\t\tlet t_g = -g * u_g;\n\n\t\t\t\tlet b =\n\t\t\t\t\t-0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s - 1;\n\t\t\t\tlet b1 =\n\t\t\t\t\t-0.0041960863 * ldt -\n\t\t\t\t\t0.7034186147 * mdt +\n\t\t\t\t\t1.707614701 * sdt;\n\t\t\t\tlet b2 =\n\t\t\t\t\t-0.0041960863 * ldt2 -\n\t\t\t\t\t0.7034186147 * mdt2 +\n\t\t\t\t\t1.707614701 * sdt2;\n\n\t\t\t\tlet u_b = b1 / (b1 * b1 - 0.5 * b * b2);\n\t\t\t\tlet t_b = -b * u_b;\n\n\t\t\t\tt_r = u_r >= 0 ? t_r : 10e5;\n\t\t\t\tt_g = u_g >= 0 ? t_g : 10e5;\n\t\t\t\tt_b = u_b >= 0 ? t_b : 10e5;\n\n\t\t\t\tt += Math.min(t_r, Math.min(t_g, t_b));\n\t\t\t}\n\t\t}\n\t}\n\n\treturn t;\n}\n\nexport function get_ST_max(a_, b_, cusp = null) {\n\tif (!cusp) {\n\t\tcusp = find_cusp(a_, b_);\n\t}\n\tlet L = cusp[0];\n\tlet C = cusp[1];\n\treturn [C / L, C / (1 - L)];\n}\n\nexport function get_ST_mid(a_, b_) {\n\tlet S =\n\t\t0.11516993 +\n\t\t1 /\n\t\t\t(+7.4477897 +\n\t\t\t\t4.1590124 * b_ +\n\t\t\t\ta_ *\n\t\t\t\t\t(-2.19557347 +\n\t\t\t\t\t\t1.75198401 * b_ +\n\t\t\t\t\t\ta_ *\n\t\t\t\t\t\t\t(-2.13704948 -\n\t\t\t\t\t\t\t\t10.02301043 * b_ +\n\t\t\t\t\t\t\t\ta_ *\n\t\t\t\t\t\t\t\t\t(-4.24894561 +\n\t\t\t\t\t\t\t\t\t\t5.38770819 * b_ +\n\t\t\t\t\t\t\t\t\t\t4.69891013 * a_))));\n\n\tlet T =\n\t\t0.11239642 +\n\t\t1 /\n\t\t\t(+1.6132032 -\n\t\t\t\t0.68124379 * b_ +\n\t\t\t\ta_ *\n\t\t\t\t\t(+0.40370612 +\n\t\t\t\t\t\t0.90148123 * b_ +\n\t\t\t\t\t\ta_ *\n\t\t\t\t\t\t\t(-0.27087943 +\n\t\t\t\t\t\t\t\t0.6122399 * b_ +\n\t\t\t\t\t\t\t\ta_ *\n\t\t\t\t\t\t\t\t\t(+0.00299215 -\n\t\t\t\t\t\t\t\t\t\t0.45399568 * b_ -\n\t\t\t\t\t\t\t\t\t\t0.14661872 * a_))));\n\n\treturn [S, T];\n}\n\nexport function get_Cs(L, a_, b_) {\n\tlet cusp = find_cusp(a_, b_);\n\n\tlet C_max = find_gamut_intersection(a_, b_, L, 1, L, cusp);\n\tlet ST_max = get_ST_max(a_, b_, cusp);\n\n\tlet S_mid =\n\t\t0.11516993 +\n\t\t1 /\n\t\t\t(+7.4477897 +\n\t\t\t\t4.1590124 * b_ +\n\t\t\t\ta_ *\n\t\t\t\t\t(-2.19557347 +\n\t\t\t\t\t\t1.75198401 * b_ +\n\t\t\t\t\t\ta_ *\n\t\t\t\t\t\t\t(-2.13704948 -\n\t\t\t\t\t\t\t\t10.02301043 * b_ +\n\t\t\t\t\t\t\t\ta_ *\n\t\t\t\t\t\t\t\t\t(-4.24894561 +\n\t\t\t\t\t\t\t\t\t\t5.38770819 * b_ +\n\t\t\t\t\t\t\t\t\t\t4.69891013 * a_))));\n\n\tlet T_mid =\n\t\t0.11239642 +\n\t\t1 /\n\t\t\t(+1.6132032 -\n\t\t\t\t0.68124379 * b_ +\n\t\t\t\ta_ *\n\t\t\t\t\t(+0.40370612 +\n\t\t\t\t\t\t0.90148123 * b_ +\n\t\t\t\t\t\ta_ *\n\t\t\t\t\t\t\t(-0.27087943 +\n\t\t\t\t\t\t\t\t0.6122399 * b_ +\n\t\t\t\t\t\t\t\ta_ *\n\t\t\t\t\t\t\t\t\t(+0.00299215 -\n\t\t\t\t\t\t\t\t\t\t0.45399568 * b_ -\n\t\t\t\t\t\t\t\t\t\t0.14661872 * a_))));\n\n\tlet k = C_max / Math.min(L * ST_max[0], (1 - L) * ST_max[1]);\n\n\tlet C_a = L * S_mid;\n\tlet C_b = (1 - L) * T_mid;\n\tlet C_mid =\n\t\t0.9 *\n\t\tk *\n\t\tMath.sqrt(\n\t\t\tMath.sqrt(\n\t\t\t\t1 / (1 / (C_a * C_a * C_a * C_a) + 1 / (C_b * C_b * C_b * C_b))\n\t\t\t)\n\t\t);\n\n\tC_a = L * 0.4;\n\tC_b = (1 - L) * 0.8;\n\tlet C_0 = Math.sqrt(1 / (1 / (C_a * C_a) + 1 / (C_b * C_b)));\n\treturn [C_0, C_mid, C_max];\n}\n","/*\n\tAdapted from code by Björn Ottosson,\n\treleased under the MIT license:\n\n\tCopyright (c) 2021 Björn Ottosson\n\n\tPermission is hereby granted, free of charge, to any person obtaining a copy of\n\tthis software and associated documentation files (the \"Software\"), to deal in\n\tthe Software without restriction, including without limitation the rights to\n\tuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n\tof the Software, and to permit persons to whom the Software is furnished to do\n\tso, subject to the following conditions:\n\n\tThe above copyright notice and this permission notice shall be included in all\n\tcopies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\tIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\tFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n\tAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n\tLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n\tOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n\tSOFTWARE.\n */\n\nimport normalizeHue from '../util/normalizeHue.js';\nimport { get_Cs, toe } from './helpers.js';\n\nexport default function convertOklabToOkhsl(lab) {\n\tconst l = lab.l !== undefined ? lab.l : 0;\n\tconst a = lab.a !== undefined ? lab.a : 0;\n\tconst b = lab.b !== undefined ? lab.b : 0;\n\n\tconst ret = { mode: 'okhsl', l: toe(l) };\n\n\tif (lab.alpha !== undefined) {\n\t\tret.alpha = lab.alpha;\n\t}\n\tlet c = Math.sqrt(a * a + b * b);\n\tif (!c) {\n\t\tret.s = 0;\n\t\treturn ret;\n\t}\n\tlet [C_0, C_mid, C_max] = get_Cs(l, a / c, b / c);\n\tlet s;\n\tif (c < C_mid) {\n\t\tlet k_0 = 0;\n\t\tlet k_1 = 0.8 * C_0;\n\t\tlet k_2 = 1 - k_1 / C_mid;\n\t\tlet t = (c - k_0) / (k_1 + k_2 * (c - k_0));\n\t\ts = t * 0.8;\n\t} else {\n\t\tlet k_0 = C_mid;\n\t\tlet k_1 = (0.2 * C_mid * C_mid * 1.25 * 1.25) / C_0;\n\t\tlet k_2 = 1 - k_1 / (C_max - C_mid);\n\t\tlet t = (c - k_0) / (k_1 + k_2 * (c - k_0));\n\t\ts = 0.8 + 0.2 * t;\n\t}\n\tif (s) {\n\t\tret.s = s;\n\t\tret.h = normalizeHue((Math.atan2(b, a) * 180) / Math.PI);\n\t}\n\treturn ret;\n}\n","/*\n\tAdapted from code by Björn Ottosson,\n\treleased under the MIT license:\n\n\tCopyright (c) 2021 Björn Ottosson\n\n\tPermission is hereby granted, free of charge, to any person obtaining a copy of\n\tthis software and associated documentation files (the \"Software\"), to deal in\n\tthe Software without restriction, including without limitation the rights to\n\tuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n\tof the Software, and to permit persons to whom the Software is furnished to do\n\tso, subject to the following conditions:\n\n\tThe above copyright notice and this permission notice shall be included in all\n\tcopies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\tIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\tFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n\tAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n\tLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n\tOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n\tSOFTWARE.\n */\n\nimport { toe_inv, get_Cs } from './helpers.js';\n\nexport default function convertOkhslToOklab(hsl) {\n\tlet h = hsl.h !== undefined ? hsl.h : 0;\n\tlet s = hsl.s !== undefined ? hsl.s : 0;\n\tlet l = hsl.l !== undefined ? hsl.l : 0;\n\n\tconst ret = { mode: 'oklab', l: toe_inv(l) };\n\n\tif (hsl.alpha !== undefined) {\n\t\tret.alpha = hsl.alpha;\n\t}\n\n\tif (!s || l === 1) {\n\t\tret.a = ret.b = 0;\n\t\treturn ret;\n\t}\n\n\tlet a_ = Math.cos((h / 180) * Math.PI);\n\tlet b_ = Math.sin((h / 180) * Math.PI);\n\tlet [C_0, C_mid, C_max] = get_Cs(ret.l, a_, b_);\n\tlet t, k_0, k_1, k_2;\n\tif (s < 0.8) {\n\t\tt = 1.25 * s;\n\t\tk_0 = 0;\n\t\tk_1 = 0.8 * C_0;\n\t\tk_2 = 1 - k_1 / C_mid;\n\t} else {\n\t\tt = 5 * (s - 0.8);\n\t\tk_0 = C_mid;\n\t\tk_1 = (0.2 * C_mid * C_mid * 1.25 * 1.25) / C_0;\n\t\tk_2 = 1 - k_1 / (C_max - C_mid);\n\t}\n\tlet C = k_0 + (t * k_1) / (1 - k_2 * t);\n\tret.a = C * a_;\n\tret.b = C * b_;\n\n\treturn ret;\n}\n","import convertRgbToOklab from '../oklab/convertRgbToOklab.js';\nimport convertOklabToRgb from '../oklab/convertOklabToRgb.js';\nimport convertOklabToOkhsl from './convertOklabToOkhsl.js';\nimport convertOkhslToOklab from './convertOkhslToOklab.js';\n\nimport modeHsl from '../hsl/definition.js';\n\nconst modeOkhsl = {\n\t...modeHsl,\n\tmode: 'okhsl',\n\tchannels: ['h', 's', 'l', 'alpha'],\n\tparse: ['--okhsl'],\n\tserialize: '--okhsl',\n\tfromMode: {\n\t\toklab: convertOklabToOkhsl,\n\t\trgb: c => convertOklabToOkhsl(convertRgbToOklab(c))\n\t},\n\ttoMode: {\n\t\toklab: convertOkhslToOklab,\n\t\trgb: c => convertOklabToRgb(convertOkhslToOklab(c))\n\t}\n};\n\nexport default modeOkhsl;\n","/*\n\tAdapted from code by Björn Ottosson,\n\treleased under the MIT license:\n\n\tCopyright (c) 2021 Björn Ottosson\n\n\tPermission is hereby granted, free of charge, to any person obtaining a copy of\n\tthis software and associated documentation files (the \"Software\"), to deal in\n\tthe Software without restriction, including without limitation the rights to\n\tuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n\tof the Software, and to permit persons to whom the Software is furnished to do\n\tso, subject to the following conditions:\n\n\tThe above copyright notice and this permission notice shall be included in all\n\tcopies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\tIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\tFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n\tAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n\tLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n\tOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n\tSOFTWARE.\n */\n\nimport normalizeHue from '../util/normalizeHue.js';\nimport convertOklabToLrgb from '../oklab/convertOklabToLrgb.js';\nimport { get_ST_max, toe_inv, toe } from '../okhsl/helpers.js';\n\nexport default function convertOklabToOkhsv(lab) {\n\tlet l = lab.l !== undefined ? lab.l : 0;\n\tlet a = lab.a !== undefined ? lab.a : 0;\n\tlet b = lab.b !== undefined ? lab.b : 0;\n\n\tlet c = Math.sqrt(a * a + b * b);\n\n\t// TODO: c = 0\n\tlet a_ = c ? a / c : 1;\n\tlet b_ = c ? b / c : 1;\n\n\tlet [S_max, T] = get_ST_max(a_, b_);\n\tlet S_0 = 0.5;\n\tlet k = 1 - S_0 / S_max;\n\n\tlet t = T / (c + l * T);\n\tlet L_v = t * l;\n\tlet C_v = t * c;\n\n\tlet L_vt = toe_inv(L_v);\n\tlet C_vt = (C_v * L_vt) / L_v;\n\n\tlet rgb_scale = convertOklabToLrgb({ l: L_vt, a: a_ * C_vt, b: b_ * C_vt });\n\tlet scale_L = Math.cbrt(\n\t\t1 / Math.max(rgb_scale.r, rgb_scale.g, rgb_scale.b, 0)\n\t);\n\n\tl = l / scale_L;\n\tc = ((c / scale_L) * toe(l)) / l;\n\tl = toe(l);\n\n\tconst ret = {\n\t\tmode: 'okhsv',\n\t\ts: c ? ((S_0 + T) * C_v) / (T * S_0 + T * k * C_v) : 0,\n\t\tv: l ? l / L_v : 0\n\t};\n\tif (ret.s) {\n\t\tret.h = normalizeHue((Math.atan2(b, a) * 180) / Math.PI);\n\t}\n\tif (lab.alpha !== undefined) {\n\t\tret.alpha = lab.alpha;\n\t}\n\treturn ret;\n}\n","/*\n\tCopyright (c) 2021 Björn Ottosson\n\n\tPermission is hereby granted, free of charge, to any person obtaining a copy of\n\tthis software and associated documentation files (the \"Software\"), to deal in\n\tthe Software without restriction, including without limitation the rights to\n\tuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n\tof the Software, and to permit persons to whom the Software is furnished to do\n\tso, subject to the following conditions:\n\n\tThe above copyright notice and this permission notice shall be included in all\n\tcopies or substantial portions of the Software.\n\n\tTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n\tIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n\tFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n\tAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n\tLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n\tOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n\tSOFTWARE.\n */\n\nimport convertOklabToLrgb from '../oklab/convertOklabToLrgb.js';\nimport { get_ST_max, toe_inv } from '../okhsl/helpers.js';\n\nexport default function convertOkhsvToOklab(hsv) {\n\tconst ret = { mode: 'oklab' };\n\tif (hsv.alpha !== undefined) {\n\t\tret.alpha = hsv.alpha;\n\t}\n\n\tconst h = hsv.h !== undefined ? hsv.h : 0;\n\tconst s = hsv.s !== undefined ? hsv.s : 0;\n\tconst v = hsv.v !== undefined ? hsv.v : 0;\n\n\tconst a_ = Math.cos((h / 180) * Math.PI);\n\tconst b_ = Math.sin((h / 180) * Math.PI);\n\n\tconst [S_max, T] = get_ST_max(a_, b_);\n\tconst S_0 = 0.5;\n\tconst k = 1 - S_0 / S_max;\n\tconst L_v = 1 - (s * S_0) / (S_0 + T - T * k * s);\n\tconst C_v = (s * T * S_0) / (S_0 + T - T * k * s);\n\n\tconst L_vt = toe_inv(L_v);\n\tconst C_vt = (C_v * L_vt) / L_v;\n\tconst rgb_scale = convertOklabToLrgb({\n\t\tl: L_vt,\n\t\ta: a_ * C_vt,\n\t\tb: b_ * C_vt\n\t});\n\tconst scale_L = Math.cbrt(\n\t\t1 / Math.max(rgb_scale.r, rgb_scale.g, rgb_scale.b, 0)\n\t);\n\n\tconst L_new = toe_inv(v * L_v);\n\tconst C = (C_v * L_new) / L_v;\n\n\tret.l = L_new * scale_L;\n\tret.a = C * a_ * scale_L;\n\tret.b = C * b_ * scale_L;\n\n\treturn ret;\n}\n","import convertRgbToOklab from '../oklab/convertRgbToOklab.js';\nimport convertOklabToRgb from '../oklab/convertOklabToRgb.js';\nimport convertOklabToOkhsv from './convertOklabToOkhsv.js';\nimport convertOkhsvToOklab from './convertOkhsvToOklab.js';\n\nimport modeHsv from '../hsv/definition.js';\n\nconst modeOkhsv = {\n\t...modeHsv,\n\tmode: 'okhsv',\n\tchannels: ['h', 's', 'v', 'alpha'],\n\tparse: ['--okhsv'],\n\tserialize: '--okhsv',\n\tfromMode: {\n\t\toklab: convertOklabToOkhsv,\n\t\trgb: c => convertOklabToOkhsv(convertRgbToOklab(c))\n\t},\n\ttoMode: {\n\t\toklab: convertOkhsvToOklab,\n\t\trgb: c => convertOklabToRgb(convertOkhsvToOklab(c))\n\t}\n};\n\nexport default modeOkhsv;\n","import { Tok } from '../parse.js';\n\nfunction parseOklab(color, parsed) {\n\tif (!parsed || parsed[0] !== 'oklab') {\n\t\treturn undefined;\n\t}\n\tconst res = { mode: 'oklab' };\n\tconst [, l, a, b, alpha] = parsed;\n\tif (l.type === Tok.Hue || a.type === Tok.Hue || b.type === Tok.Hue) {\n\t\treturn undefined;\n\t}\n\tif (l.type !== Tok.None) {\n\t\tres.l = Math.min(\n\t\t\tMath.max(0, l.type === Tok.Number ? l.value : l.value / 100),\n\t\t\t1\n\t\t);\n\t}\n\tif (a.type !== Tok.None) {\n\t\tres.a = a.type === Tok.Number ? a.value : (a.value * 0.4) / 100;\n\t}\n\tif (b.type !== Tok.None) {\n\t\tres.b = b.type === Tok.Number ? b.value : (b.value * 0.4) / 100;\n\t}\n\tif (alpha.type !== Tok.None) {\n\t\tres.alpha = Math.min(\n\t\t\t1,\n\t\t\tMath.max(\n\t\t\t\t0,\n\t\t\t\talpha.type === Tok.Number ? alpha.value : alpha.value / 100\n\t\t\t)\n\t\t);\n\t}\n\n\treturn res;\n}\n\nexport default parseOklab;\n","import convertOklabToLrgb from './convertOklabToLrgb.js';\nimport convertLrgbToOklab from './convertLrgbToOklab.js';\nimport convertRgbToOklab from './convertRgbToOklab.js';\nimport convertOklabToRgb from './convertOklabToRgb.js';\nimport parseOklab from './parseOklab.js';\n\nimport lab from '../lab/definition.js';\n\n/*\n\tOklab, a perceptual color space for image processing by Björn Ottosson\n\tReference: https://bottosson.github.io/posts/oklab/\n */\n\nconst definition = {\n\t...lab,\n\tmode: 'oklab',\n\n\ttoMode: {\n\t\tlrgb: convertOklabToLrgb,\n\t\trgb: convertOklabToRgb\n\t},\n\n\tfromMode: {\n\t\tlrgb: convertLrgbToOklab,\n\t\trgb: convertRgbToOklab\n\t},\n\n\tranges: {\n\t\tl: [0, 1],\n\t\ta: [-0.4, 0.4],\n\t\tb: [-0.4, 0.4]\n\t},\n\n\tparse: [parseOklab],\n\tserialize: c =>\n\t\t`oklab(${c.l !== undefined ? c.l : 'none'} ${\n\t\t\tc.a !== undefined ? c.a : 'none'\n\t\t} ${c.b !== undefined ? c.b : 'none'}${\n\t\t\tc.alpha < 1 ? ` / ${c.alpha}` : ''\n\t\t})`\n};\n\nexport default definition;\n","import { Tok } from '../parse.js';\n\nfunction parseOklch(color, parsed) {\n\tif (!parsed || parsed[0] !== 'oklch') {\n\t\treturn undefined;\n\t}\n\tconst res = { mode: 'oklch' };\n\tconst [, l, c, h, alpha] = parsed;\n\tif (l.type !== Tok.None) {\n\t\tif (l.type === Tok.Hue) {\n\t\t\treturn undefined;\n\t\t}\n\t\tres.l = Math.min(\n\t\t\tMath.max(0, l.type === Tok.Number ? l.value : l.value / 100),\n\t\t\t1\n\t\t);\n\t}\n\tif (c.type !== Tok.None) {\n\t\tres.c = Math.max(\n\t\t\t0,\n\t\t\tc.type === Tok.Number ? c.value : (c.value * 0.4) / 100\n\t\t);\n\t}\n\tif (h.type !== Tok.None) {\n\t\tif (h.type === Tok.Percentage) {\n\t\t\treturn undefined;\n\t\t}\n\t\tres.h = h.value;\n\t}\n\tif (alpha.type !== Tok.None) {\n\t\tres.alpha = Math.min(\n\t\t\t1,\n\t\t\tMath.max(\n\t\t\t\t0,\n\t\t\t\talpha.type === Tok.Number ? alpha.value : alpha.value / 100\n\t\t\t)\n\t\t);\n\t}\n\n\treturn res;\n}\n\nexport default parseOklch;\n","import lch from '../lch/definition.js';\nimport convertLabToLch from '../lch/convertLabToLch.js';\nimport convertLchToLab from '../lch/convertLchToLab.js';\nimport convertOklabToRgb from '../oklab/convertOklabToRgb.js';\nimport convertRgbToOklab from '../oklab/convertRgbToOklab.js';\nimport parseOklch from './parseOklch.js';\n\nconst definition = {\n\t...lch,\n\tmode: 'oklch',\n\n\ttoMode: {\n\t\toklab: c => convertLchToLab(c, 'oklab'),\n\t\trgb: c => convertOklabToRgb(convertLchToLab(c, 'oklab'))\n\t},\n\n\tfromMode: {\n\t\trgb: c => convertLabToLch(convertRgbToOklab(c), 'oklch'),\n\t\toklab: c => convertLabToLch(c, 'oklch')\n\t},\n\n\tparse: [parseOklch],\n\tserialize: c =>\n\t\t`oklch(${c.l !== undefined ? c.l : 'none'} ${\n\t\t\tc.c !== undefined ? c.c : 'none'\n\t\t} ${c.h !== undefined ? c.h : 'none'}${\n\t\t\tc.alpha < 1 ? ` / ${c.alpha}` : ''\n\t\t})`,\n\n\tranges: {\n\t\tl: [0, 1],\n\t\tc: [0, 0.4],\n\t\th: [0, 360]\n\t}\n};\n\nexport default definition;\n","/*\n\tConvert Display P3 values to CIE XYZ D65\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n*/\n\nimport convertRgbToLrgb from '../lrgb/convertRgbToLrgb.js';\n\nconst convertP3ToXyz65 = rgb => {\n\tlet { r, g, b, alpha } = convertRgbToLrgb(rgb);\n\tlet res = {\n\t\tmode: 'xyz65',\n\t\tx:\n\t\t\t0.486570948648216 * r +\n\t\t\t0.265667693169093 * g +\n\t\t\t0.1982172852343625 * b,\n\t\ty:\n\t\t\t0.2289745640697487 * r +\n\t\t\t0.6917385218365062 * g +\n\t\t\t0.079286914093745 * b,\n\t\tz: 0.0 * r + 0.0451133818589026 * g + 1.043944368900976 * b\n\t};\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertP3ToXyz65;\n","/*\n\tCIE XYZ D65 values to Display P3.\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n*/\n\nimport convertLrgbToRgb from '../lrgb/convertLrgbToRgb.js';\n\nconst convertXyz65ToP3 = ({ x, y, z, alpha }) => {\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet res = convertLrgbToRgb(\n\t\t{\n\t\t\tr:\n\t\t\t\tx * 2.4934969119414263 -\n\t\t\t\ty * 0.9313836179191242 -\n\t\t\t\t0.402710784450717 * z,\n\t\t\tg:\n\t\t\t\tx * -0.8294889695615749 +\n\t\t\t\ty * 1.7626640603183465 +\n\t\t\t\t0.0236246858419436 * z,\n\t\t\tb:\n\t\t\t\tx * 0.0358458302437845 -\n\t\t\t\ty * 0.0761723892680418 +\n\t\t\t\t0.9568845240076871 * z\n\t\t},\n\t\t'p3'\n\t);\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertXyz65ToP3;\n","import rgb from '../rgb/definition.js';\nimport convertP3ToXyz65 from './convertP3ToXyz65.js';\nimport convertXyz65ToP3 from './convertXyz65ToP3.js';\nimport convertRgbToXyz65 from '../xyz65/convertRgbToXyz65.js';\nimport convertXyz65ToRgb from '../xyz65/convertXyz65ToRgb.js';\n\nconst definition = {\n\t...rgb,\n\tmode: 'p3',\n\tparse: ['display-p3'],\n\tserialize: 'display-p3',\n\n\tfromMode: {\n\t\trgb: color => convertXyz65ToP3(convertRgbToXyz65(color)),\n\t\txyz65: convertXyz65ToP3\n\t},\n\n\ttoMode: {\n\t\trgb: color => convertXyz65ToRgb(convertP3ToXyz65(color)),\n\t\txyz65: convertP3ToXyz65\n\t}\n};\n\nexport default definition;\n","/*\n\tConvert CIE XYZ D50 values to ProPhoto RGB\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n*/\n\nconst gamma = v => {\n\tlet abs = Math.abs(v);\n\tif (abs >= 1 / 512) {\n\t\treturn Math.sign(v) * Math.pow(abs, 1 / 1.8);\n\t}\n\treturn 16 * v;\n};\n\nconst convertXyz50ToProphoto = ({ x, y, z, alpha }) => {\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet res = {\n\t\tmode: 'prophoto',\n\t\tr: gamma(\n\t\t\tx * 1.3457868816471585 -\n\t\t\t\ty * 0.2555720873797946 -\n\t\t\t\t0.0511018649755453 * z\n\t\t),\n\t\tg: gamma(\n\t\t\tx * -0.5446307051249019 +\n\t\t\t\ty * 1.5082477428451466 +\n\t\t\t\t0.0205274474364214 * z\n\t\t),\n\t\tb: gamma(x * 0.0 + y * 0.0 + 1.2119675456389452 * z)\n\t};\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertXyz50ToProphoto;\n","/*\n\tConvert ProPhoto RGB values to CIE XYZ D50\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n*/\n\nconst linearize = (v = 0) => {\n\tlet abs = Math.abs(v);\n\tif (abs >= 16 / 512) {\n\t\treturn Math.sign(v) * Math.pow(abs, 1.8);\n\t}\n\treturn v / 16;\n};\n\nconst convertProphotoToXyz50 = prophoto => {\n\tlet r = linearize(prophoto.r);\n\tlet g = linearize(prophoto.g);\n\tlet b = linearize(prophoto.b);\n\tlet res = {\n\t\tmode: 'xyz50',\n\t\tx:\n\t\t\t0.7977666449006423 * r +\n\t\t\t0.1351812974005331 * g +\n\t\t\t0.0313477341283922 * b,\n\t\ty:\n\t\t\t0.2880748288194013 * r +\n\t\t\t0.7118352342418731 * g +\n\t\t\t0.0000899369387256 * b,\n\t\tz: 0 * r + 0 * g + 0.8251046025104602 * b\n\t};\n\tif (prophoto.alpha !== undefined) {\n\t\tres.alpha = prophoto.alpha;\n\t}\n\treturn res;\n};\n\nexport default convertProphotoToXyz50;\n","import rgb from '../rgb/definition.js';\n\nimport convertXyz50ToProphoto from './convertXyz50ToProphoto.js';\nimport convertProphotoToXyz50 from './convertProphotoToXyz50.js';\n\nimport convertXyz50ToRgb from '../xyz50/convertXyz50ToRgb.js';\nimport convertRgbToXyz50 from '../xyz50/convertRgbToXyz50.js';\n\n/*\n\tProPhoto RGB Color space\n\n\tReferences:\n\t\t* https://en.wikipedia.org/wiki/ProPhoto_RGB_color_space\n */\n\nconst definition = {\n\t...rgb,\n\tmode: 'prophoto',\n\tparse: ['prophoto-rgb'],\n\tserialize: 'prophoto-rgb',\n\n\tfromMode: {\n\t\txyz50: convertXyz50ToProphoto,\n\t\trgb: color => convertXyz50ToProphoto(convertRgbToXyz50(color))\n\t},\n\n\ttoMode: {\n\t\txyz50: convertProphotoToXyz50,\n\t\trgb: color => convertXyz50ToRgb(convertProphotoToXyz50(color))\n\t}\n};\n\nexport default definition;\n","/*\n\tConvert CIE XYZ D65 values to Rec. 2020\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n\t\t* https://www.itu.int/rec/R-REC-BT.2020/en\n*/\n\nconst α = 1.09929682680944;\nconst β = 0.018053968510807;\nconst gamma = v => {\n\tconst abs = Math.abs(v);\n\tif (abs > β) {\n\t\treturn (Math.sign(v) || 1) * (α * Math.pow(abs, 0.45) - (α - 1));\n\t}\n\treturn 4.5 * v;\n};\n\nconst convertXyz65ToRec2020 = ({ x, y, z, alpha }) => {\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet res = {\n\t\tmode: 'rec2020',\n\t\tr: gamma(\n\t\t\tx * 1.7166511879712683 -\n\t\t\t\ty * 0.3556707837763925 -\n\t\t\t\t0.2533662813736599 * z\n\t\t),\n\t\tg: gamma(\n\t\t\tx * -0.6666843518324893 +\n\t\t\t\ty * 1.6164812366349395 +\n\t\t\t\t0.0157685458139111 * z\n\t\t),\n\t\tb: gamma(\n\t\t\tx * 0.0176398574453108 -\n\t\t\t\ty * 0.0427706132578085 +\n\t\t\t\t0.9421031212354739 * z\n\t\t)\n\t};\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertXyz65ToRec2020;\n","/*\n\tConvert Rec. 2020 values to CIE XYZ D65\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html\n\t\t* https://www.itu.int/rec/R-REC-BT.2020/en\n*/\n\nconst α = 1.09929682680944;\nconst β = 0.018053968510807;\n\nconst linearize = (v = 0) => {\n\tlet abs = Math.abs(v);\n\tif (abs < β * 4.5) {\n\t\treturn v / 4.5;\n\t}\n\treturn (Math.sign(v) || 1) * Math.pow((abs + α - 1) / α, 1 / 0.45);\n};\n\nconst convertRec2020ToXyz65 = rec2020 => {\n\tlet r = linearize(rec2020.r);\n\tlet g = linearize(rec2020.g);\n\tlet b = linearize(rec2020.b);\n\tlet res = {\n\t\tmode: 'xyz65',\n\t\tx:\n\t\t\t0.6369580483012911 * r +\n\t\t\t0.1446169035862083 * g +\n\t\t\t0.1688809751641721 * b,\n\t\ty:\n\t\t\t0.262700212011267 * r +\n\t\t\t0.6779980715188708 * g +\n\t\t\t0.059301716469862 * b,\n\t\tz: 0 * r + 0.0280726930490874 * g + 1.0609850577107909 * b\n\t};\n\tif (rec2020.alpha !== undefined) {\n\t\tres.alpha = rec2020.alpha;\n\t}\n\treturn res;\n};\n\nexport default convertRec2020ToXyz65;\n","import rgb from '../rgb/definition.js';\n\nimport convertXyz65ToRec2020 from './convertXyz65ToRec2020.js';\nimport convertRec2020ToXyz65 from './convertRec2020ToXyz65.js';\n\nimport convertRgbToXyz65 from '../xyz65/convertRgbToXyz65.js';\nimport convertXyz65ToRgb from '../xyz65/convertXyz65ToRgb.js';\n\nconst definition = {\n\t...rgb,\n\tmode: 'rec2020',\n\n\tfromMode: {\n\t\txyz65: convertXyz65ToRec2020,\n\t\trgb: color => convertXyz65ToRec2020(convertRgbToXyz65(color))\n\t},\n\n\ttoMode: {\n\t\txyz65: convertRec2020ToXyz65,\n\t\trgb: color => convertXyz65ToRgb(convertRec2020ToXyz65(color))\n\t},\n\n\tparse: ['rec2020'],\n\tserialize: 'rec2020'\n};\n\nexport default definition;\n","export const bias = 0.00379307325527544933;\nexport const bias_cbrt = Math.cbrt(bias);\n","import convertRgbToLrgb from '../lrgb/convertRgbToLrgb.js';\nimport { bias, bias_cbrt } from './constants.js';\n\nconst transfer = v => Math.cbrt(v) - bias_cbrt;\n\nconst convertRgbToXyb = color => {\n\tconst { r, g, b, alpha } = convertRgbToLrgb(color);\n\tconst l = transfer(0.3 * r + 0.622 * g + 0.078 * b + bias);\n\tconst m = transfer(0.23 * r + 0.692 * g + 0.078 * b + bias);\n\tconst s = transfer(\n\t\t0.24342268924547819 * r +\n\t\t\t0.20476744424496821 * g +\n\t\t\t0.5518098665095536 * b +\n\t\t\tbias\n\t);\n\tconst res = {\n\t\tmode: 'xyb',\n\t\tx: (l - m) / 2,\n\t\ty: (l + m) / 2,\n\t\t/* Apply default chroma from luma (subtract Y from B) */\n\t\tb: s - (l + m) / 2\n\t};\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertRgbToXyb;\n","import convertLrgbToRgb from '../lrgb/convertLrgbToRgb.js';\nimport { bias, bias_cbrt } from './constants.js';\n\nconst transfer = v => Math.pow(v + bias_cbrt, 3);\n\nconst convertXybToRgb = ({ x, y, b, alpha }) => {\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (b === undefined) b = 0;\n\tconst l = transfer(x + y) - bias;\n\tconst m = transfer(y - x) - bias;\n\t/* Account for chroma from luma: add Y back to B */\n\tconst s = transfer(b + y) - bias;\n\n\tconst res = convertLrgbToRgb({\n\t\tr:\n\t\t\t11.031566904639861 * l -\n\t\t\t9.866943908131562 * m -\n\t\t\t0.16462299650829934 * s,\n\t\tg:\n\t\t\t-3.2541473810744237 * l +\n\t\t\t4.418770377582723 * m -\n\t\t\t0.16462299650829934 * s,\n\t\tb:\n\t\t\t-3.6588512867136815 * l +\n\t\t\t2.7129230459360922 * m +\n\t\t\t1.9459282407775895 * s\n\t});\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertXybToRgb;\n","import { interpolatorLinear } from '../interpolate/linear.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\nimport convertRgbToXyb from './convertRgbToXyb.js';\nimport convertXybToRgb from './convertXybToRgb.js';\n\n/*\n\tThe XYB color space, used in JPEG XL.\n\tReference: https://ds.jpeg.org/whitepapers/jpeg-xl-whitepaper.pdf\n*/\n\nconst definition = {\n\tmode: 'xyb',\n\tchannels: ['x', 'y', 'b', 'alpha'],\n\tparse: ['--xyb'],\n\tserialize: '--xyb',\n\n\ttoMode: {\n\t\trgb: convertXybToRgb\n\t},\n\n\tfromMode: {\n\t\trgb: convertRgbToXyb\n\t},\n\n\tranges: {\n\t\tx: [-0.0154, 0.0281],\n\t\ty: [0, 0.8453],\n\t\tb: [-0.2778, 0.388]\n\t},\n\n\tinterpolate: {\n\t\tx: interpolatorLinear,\n\t\ty: interpolatorLinear,\n\t\tb: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t}\n};\n\nexport default definition;\n","/*\n\tThe XYZ D50 color space\n\t-----------------------\n */\n\nimport convertXyz50ToRgb from './convertXyz50ToRgb.js';\nimport convertXyz50ToLab from '../lab/convertXyz50ToLab.js';\nimport convertRgbToXyz50 from './convertRgbToXyz50.js';\nimport convertLabToXyz50 from '../lab/convertLabToXyz50.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\n\nconst definition = {\n\tmode: 'xyz50',\n\tparse: ['xyz-d50'],\n\tserialize: 'xyz-d50',\n\n\ttoMode: {\n\t\trgb: convertXyz50ToRgb,\n\t\tlab: convertXyz50ToLab\n\t},\n\n\tfromMode: {\n\t\trgb: convertRgbToXyz50,\n\t\tlab: convertLabToXyz50\n\t},\n\n\tchannels: ['x', 'y', 'z', 'alpha'],\n\n\tranges: {\n\t\tx: [0, 0.964],\n\t\ty: [0, 0.999],\n\t\tz: [0, 0.825]\n\t},\n\n\tinterpolate: {\n\t\tx: interpolatorLinear,\n\t\ty: interpolatorLinear,\n\t\tz: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t}\n};\n\nexport default definition;\n","/*\n\tChromatic adaptation of CIE XYZ from D65 to D50 white point\n\tusing the Bradford method.\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html\t\n*/\n\nconst convertXyz65ToXyz50 = xyz65 => {\n\tlet { x, y, z, alpha } = xyz65;\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet res = {\n\t\tmode: 'xyz50',\n\t\tx:\n\t\t\t1.0479298208405488 * x +\n\t\t\t0.0229467933410191 * y -\n\t\t\t0.0501922295431356 * z,\n\t\ty:\n\t\t\t0.0296278156881593 * x +\n\t\t\t0.990434484573249 * y -\n\t\t\t0.0170738250293851 * z,\n\t\tz:\n\t\t\t-0.0092430581525912 * x +\n\t\t\t0.0150551448965779 * y +\n\t\t\t0.7518742899580008 * z\n\t};\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertXyz65ToXyz50;\n","/*\n\tChromatic adaptation of CIE XYZ from D50 to D65 white point\n\tusing the Bradford method.\n\n\tReferences:\n\t\t* https://drafts.csswg.org/css-color/#color-conversion-code\n\t\t* http://www.brucelindbloom.com/index.html?Eqn_ChromAdapt.html\t\n*/\n\nconst convertXyz50ToXyz65 = xyz50 => {\n\tlet { x, y, z, alpha } = xyz50;\n\tif (x === undefined) x = 0;\n\tif (y === undefined) y = 0;\n\tif (z === undefined) z = 0;\n\tlet res = {\n\t\tmode: 'xyz65',\n\t\tx:\n\t\t\t0.9554734527042182 * x -\n\t\t\t0.0230985368742614 * y +\n\t\t\t0.0632593086610217 * z,\n\t\ty:\n\t\t\t-0.0283697069632081 * x +\n\t\t\t1.0099954580058226 * y +\n\t\t\t0.021041398966943 * z,\n\t\tz:\n\t\t\t0.0123140016883199 * x -\n\t\t\t0.0205076964334779 * y +\n\t\t\t1.3303659366080753 * z\n\t};\n\tif (alpha !== undefined) {\n\t\tres.alpha = alpha;\n\t}\n\treturn res;\n};\n\nexport default convertXyz50ToXyz65;\n","/*\n\tThe XYZ D65 color space\n\t-----------------------\n */\n\nimport convertXyz65ToRgb from './convertXyz65ToRgb.js';\nimport convertRgbToXyz65 from './convertRgbToXyz65.js';\n\nimport convertXyz65ToXyz50 from './convertXyz65ToXyz50.js';\nimport convertXyz50ToXyz65 from './convertXyz50ToXyz65.js';\n\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\n\nconst definition = {\n\tmode: 'xyz65',\n\n\ttoMode: {\n\t\trgb: convertXyz65ToRgb,\n\t\txyz50: convertXyz65ToXyz50\n\t},\n\n\tfromMode: {\n\t\trgb: convertRgbToXyz65,\n\t\txyz50: convertXyz50ToXyz65\n\t},\n\n\tranges: {\n\t\tx: [0, 0.95],\n\t\ty: [0, 1],\n\t\tz: [0, 1.088]\n\t},\n\n\tchannels: ['x', 'y', 'z', 'alpha'],\n\n\tparse: ['xyz', 'xyz-d65'],\n\tserialize: 'xyz-d65',\n\n\tinterpolate: {\n\t\tx: interpolatorLinear,\n\t\ty: interpolatorLinear,\n\t\tz: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t}\n};\n\nexport default definition;\n","const convertRgbToYiq = ({ r, g, b, alpha }) => {\n\tif (r === undefined) r = 0;\n\tif (g === undefined) g = 0;\n\tif (b === undefined) b = 0;\n\tconst res = {\n\t\tmode: 'yiq',\n\t\ty: 0.29889531 * r + 0.58662247 * g + 0.11448223 * b,\n\t\ti: 0.59597799 * r - 0.2741761 * g - 0.32180189 * b,\n\t\tq: 0.21147017 * r - 0.52261711 * g + 0.31114694 * b\n\t};\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertRgbToYiq;\n","const convertYiqToRgb = ({ y, i, q, alpha }) => {\n\tif (y === undefined) y = 0;\n\tif (i === undefined) i = 0;\n\tif (q === undefined) q = 0;\n\tconst res = {\n\t\tmode: 'rgb',\n\t\tr: y + 0.95608445 * i + 0.6208885 * q,\n\t\tg: y - 0.27137664 * i - 0.6486059 * q,\n\t\tb: y - 1.10561724 * i + 1.70250126 * q\n\t};\n\tif (alpha !== undefined) res.alpha = alpha;\n\treturn res;\n};\n\nexport default convertYiqToRgb;\n","import convertRgbToYiq from './convertRgbToYiq.js';\nimport convertYiqToRgb from './convertYiqToRgb.js';\nimport { interpolatorLinear } from '../interpolate/linear.js';\nimport { fixupAlpha } from '../fixup/alpha.js';\n\n/*\n\tYIQ Color Space\n\n\tReferences\n\t----------\n\n\tWikipedia:\n\t\thttps://en.wikipedia.org/wiki/YIQ\n\n\t\"Measuring perceived color difference using YIQ NTSC\n\ttransmission color space in mobile applications\"\n\t\t\n\t\tby Yuriy Kotsarenko, Fernando Ramos in:\n\t\tProgramación Matemática y Software (2010) \n\n\tAvailable at:\n\t\t\n\t\thttp://www.progmat.uaem.mx:8080/artVol2Num2/Articulo3Vol2Num2.pdf\n */\n\nconst definition = {\n\tmode: 'yiq',\n\n\ttoMode: {\n\t\trgb: convertYiqToRgb\n\t},\n\n\tfromMode: {\n\t\trgb: convertRgbToYiq\n\t},\n\n\tchannels: ['y', 'i', 'q', 'alpha'],\n\n\tparse: ['--yiq'],\n\tserialize: '--yiq',\n\n\tranges: {\n\t\ti: [-0.595, 0.595],\n\t\tq: [-0.522, 0.522]\n\t},\n\n\tinterpolate: {\n\t\ty: interpolatorLinear,\n\t\ti: interpolatorLinear,\n\t\tq: interpolatorLinear,\n\t\talpha: { use: interpolatorLinear, fixup: fixupAlpha }\n\t}\n};\n\nexport default definition;\n","import converter from './converter.js';\nimport round from './round.js';\nimport prepare from './_prepare.js';\nimport { getMode } from './modes.js';\n\nlet twoDecimals = round(2);\n\nconst clamp = value => Math.max(0, Math.min(1, value || 0));\nconst fixup = value => Math.round(clamp(value) * 255);\n\nconst rgb = converter('rgb');\nconst hsl = converter('hsl');\n\nexport const serializeHex = color => {\n\tif (color === undefined) {\n\t\treturn undefined;\n\t}\n\n\tlet r = fixup(color.r);\n\tlet g = fixup(color.g);\n\tlet b = fixup(color.b);\n\n\treturn '#' + ((1 << 24) | (r << 16) | (g << 8) | b).toString(16).slice(1);\n};\n\nexport const serializeHex8 = color => {\n\tif (color === undefined) {\n\t\treturn undefined;\n\t}\n\n\tlet a = fixup(color.alpha !== undefined ? color.alpha : 1);\n\treturn serializeHex(color) + ((1 << 8) | a).toString(16).slice(1);\n};\n\nexport const serializeRgb = color => {\n\tif (color === undefined) {\n\t\treturn undefined;\n\t}\n\n\tlet r = fixup(color.r);\n\tlet g = fixup(color.g);\n\tlet b = fixup(color.b);\n\n\tif (color.alpha === undefined || color.alpha === 1) {\n\t\t// opaque color\n\t\treturn `rgb(${r}, ${g}, ${b})`;\n\t} else {\n\t\t// transparent color\n\t\treturn `rgba(${r}, ${g}, ${b}, ${twoDecimals(clamp(color.alpha))})`;\n\t}\n};\n\nexport const serializeHsl = color => {\n\tif (color === undefined) {\n\t\treturn undefined;\n\t}\n\n\tconst h = twoDecimals(color.h || 0);\n\tconst s = twoDecimals(clamp(color.s) * 100) + '%';\n\tconst l = twoDecimals(clamp(color.l) * 100) + '%';\n\n\tif (color.alpha === undefined || color.alpha === 1) {\n\t\t// opaque color\n\t\treturn `hsl(${h}, ${s}, ${l})`;\n\t} else {\n\t\t// transparent color\n\t\treturn `hsla(${h}, ${s}, ${l}, ${twoDecimals(clamp(color.alpha))})`;\n\t}\n};\n\nexport const formatCss = c => {\n\tconst color = prepare(c);\n\tif (!color) {\n\t\treturn undefined;\n\t}\n\tconst def = getMode(color.mode);\n\tif (!def.serialize || typeof def.serialize === 'string') {\n\t\tlet res = `color(${def.serialize || `--${color.mode}`} `;\n\t\tdef.channels.forEach((ch, i) => {\n\t\t\tif (ch !== 'alpha') {\n\t\t\t\tres +=\n\t\t\t\t\t(i ? ' ' : '') +\n\t\t\t\t\t(color[ch] !== undefined ? color[ch] : 'none');\n\t\t\t}\n\t\t});\n\t\tif (color.alpha !== undefined && color.alpha < 1) {\n\t\t\tres += ` / ${color.alpha}`;\n\t\t}\n\t\treturn res + ')';\n\t}\n\tif (typeof def.serialize === 'function') {\n\t\treturn def.serialize(color);\n\t}\n\treturn undefined;\n};\n\nexport const formatHex = c => serializeHex(rgb(c));\nexport const formatHex8 = c => serializeHex8(rgb(c));\nexport const formatRgb = c => serializeRgb(rgb(c));\nexport const formatHsl = c => serializeHsl(hsl(c));\n","import converter from './converter.js';\nimport prepare from './_prepare.js';\nimport { getMode } from './modes.js';\nimport { differenceEuclidean } from './difference.js';\n\nconst rgb = converter('rgb');\nconst fixup_rgb = c => {\n\tconst res = {\n\t\tmode: c.mode,\n\t\tr: Math.max(0, Math.min(c.r !== undefined ? c.r : 0, 1)),\n\t\tg: Math.max(0, Math.min(c.g !== undefined ? c.g : 0, 1)),\n\t\tb: Math.max(0, Math.min(c.b !== undefined ? c.b : 0, 1))\n\t};\n\tif (c.alpha !== undefined) {\n\t\tres.alpha = c.alpha;\n\t}\n\treturn res;\n};\n\nconst to_displayable_srgb = c => fixup_rgb(rgb(c));\n\nconst inrange_rgb = c => {\n\treturn (\n\t\tc !== undefined &&\n\t\t(c.r === undefined || (c.r >= 0 && c.r <= 1)) &&\n\t\t(c.g === undefined || (c.g >= 0 && c.g <= 1)) &&\n\t\t(c.b === undefined || (c.b >= 0 && c.b <= 1))\n\t);\n};\n\n/*\n\tReturns whether the color is in the sRGB gamut.\n */\nexport function displayable(color) {\n\treturn inrange_rgb(rgb(color));\n}\n\n/*\n\tGiven a color space `mode`, returns a function\n\twith which to check whether a color is \n\tin that color space's gamut.\n */\nexport function inGamut(mode = 'rgb') {\n\tconst { gamut } = getMode(mode);\n\tif (!gamut) {\n\t\treturn color => true;\n\t}\n\tconst conv = converter(typeof gamut === 'string' ? gamut : mode);\n\treturn color => inrange_rgb(conv(color));\n}\n\n/*\n\tObtain a color that's in the sRGB gamut\n\tby converting it to sRGB and clipping the channel values\n\tso that they're within the [0, 1] range.\n\n\tThe result is returned in the color's original color space.\n */\nexport function clampRgb(color) {\n\tcolor = prepare(color);\n\n\t// if the color is undefined or displayable, return it directly\n\tif (color === undefined || displayable(color)) return color;\n\n\t// keep track of color's original mode\n\tlet conv = converter(color.mode);\n\n\treturn conv(to_displayable_srgb(color));\n}\n\n/*\n\tGiven the `mode` color space, returns a function\n\twith which to obtain a color that's in gamut for\n\tthe `mode` color space by clipping the channel values\n\tso that they fit in their respective ranges.\n\n\tIt's similar to `clampRgb`, but works for any \n\tbounded color space (RGB or not) for which \n\tany combination of in-range channel values\n\tproduces an in-gamut color.\n */\nexport function clampGamut(mode = 'rgb') {\n\tconst { gamut } = getMode(mode);\n\tif (!gamut) {\n\t\treturn color => prepare(color);\n\t}\n\tconst destMode = typeof gamut === 'string' ? gamut : mode;\n\tconst destConv = converter(destMode);\n\tconst inDestGamut = inGamut(destMode);\n\treturn color => {\n\t\tconst original = prepare(color);\n\t\tif (!original) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst converted = destConv(original);\n\t\tif (inDestGamut(converted)) {\n\t\t\treturn original;\n\t\t}\n\t\tconst clamped = fixup_rgb(converted);\n\t\tif (original.mode === clamped.mode) {\n\t\t\treturn clamped;\n\t\t}\n\t\treturn converter(original.mode)(clamped);\n\t};\n}\n\n/*\n\tObtain a color that’s in a RGB gamut (by default sRGB)\n\tby first converting it to `mode` and then finding \n\tthe greatest chroma value that fits the gamut.\n\n\tBy default, the CIELCh color space is used,\n\tbut any color that has a chroma component will do.\n\n\tThe result is returned in the color's original color space.\n */\nexport function clampChroma(color, mode = 'lch', rgbGamut = 'rgb') {\n\tcolor = prepare(color);\n\n\tlet inDestinationGamut =\n\t\trgbGamut === 'rgb' ? displayable : inGamut(rgbGamut);\n\tlet clipToGamut =\n\t\trgbGamut === 'rgb' ? to_displayable_srgb : clampGamut(rgbGamut);\n\n\t// if the color is undefined or displayable, return it directly\n\tif (color === undefined || inDestinationGamut(color)) return color;\n\n\t// keep track of color's original mode\n\tlet conv = converter(color.mode);\n\n\t// convert to the provided `mode` for clamping\n\tcolor = converter(mode)(color);\n\n\t// try with chroma = 0\n\tlet clamped = { ...color, c: 0 };\n\n\t// if not even chroma = 0 is displayable\n\t// fall back to RGB clamping\n\tif (!inDestinationGamut(clamped)) {\n\t\treturn conv(clipToGamut(clamped));\n\t}\n\n\t// By this time we know chroma = 0 is displayable and our current chroma is not.\n\t// Find the displayable chroma through the bisection method.\n\tlet start = 0;\n\tlet end = color.c !== undefined ? color.c : 0;\n\tlet range = getMode(mode).ranges.c;\n\tlet resolution = (range[1] - range[0]) / Math.pow(2, 13);\n\tlet _last_good_c = clamped.c;\n\n\twhile (end - start > resolution) {\n\t\tclamped.c = start + (end - start) * 0.5;\n\t\tif (inDestinationGamut(clamped)) {\n\t\t\t_last_good_c = clamped.c;\n\t\t\tstart = clamped.c;\n\t\t} else {\n\t\t\tend = clamped.c;\n\t\t}\n\t}\n\n\treturn conv(\n\t\tinDestinationGamut(clamped) ? clamped : { ...clamped, c: _last_good_c }\n\t);\n}\n\n/*\n\tObtain a color that's in the `dest` gamut,\n\tby first converting it to the `mode` color space\n\tand then finding the largest chroma that's in gamut,\n\tsimilar to `clampChroma`. \n\n\tThe color returned is in the `dest` color space.\n\n\tTo address the shortcomings of `clampChroma`, which can\n\tsometimes produce colors more desaturated than necessary,\n\tthe test used in the binary search is replaced with\n\t\"is color is roughly in gamut\", by comparing the candidate \n\tto the clipped version (obtained with `clampGamut`).\n\tThe test passes if the colors are not too dissimilar, \n\tjudged by the `delta` color difference function \n\tand an associated `jnd` just-noticeable difference value.\n\n\tThe default arguments for this function correspond to the\n\tgamut mapping algorithm defined in CSS Color Level 4:\n\thttps://drafts.csswg.org/css-color/#css-gamut-mapping\n\n\tTo disable the “roughly in gamut” part, pass either\n\t`null` for the `delta` parameter, or zero for `jnd`.\n */\nexport function toGamut(\n\tdest = 'rgb',\n\tmode = 'oklch',\n\tdelta = differenceEuclidean('oklch'),\n\tjnd = 0.02\n) {\n\tconst destConv = converter(dest);\n\tconst destMode = getMode(dest);\n\n\tif (!destMode.gamut) {\n\t\treturn color => destConv(color);\n\t}\n\n\tconst inDestinationGamut = inGamut(dest);\n\tconst clipToGamut = clampGamut(dest);\n\n\tconst ucs = converter(mode);\n\tconst { ranges } = getMode(mode);\n\n\tif (!ranges.l || !ranges.c) {\n\t\tthrow new Error('LCH-like space expected');\n\t}\n\n\treturn color => {\n\t\tcolor = prepare(color);\n\t\tif (color === undefined) {\n\t\t\treturn undefined;\n\t\t}\n\t\tconst candidate = { ...ucs(color) };\n\n\t\t// account for missing components\n\t\tif (candidate.l === undefined) candidate.l = 0;\n\t\tif (candidate.c === undefined) candidate.c = 0;\n\n\t\tif (candidate.l >= ranges.l[1]) {\n\t\t\tconst res = { ...destMode.white, mode: dest };\n\t\t\tif (color.alpha !== undefined) {\n\t\t\t\tres.alpha = color.alpha;\n\t\t\t}\n\t\t\treturn res;\n\t\t}\n\t\tif (candidate.l <= ranges.l[0]) {\n\t\t\tconst res = { ...destMode.black, mode: dest };\n\t\t\tif (color.alpha !== undefined) {\n\t\t\t\tres.alpha = color.alpha;\n\t\t\t}\n\t\t\treturn res;\n\t\t}\n\t\tif (inDestinationGamut(candidate)) {\n\t\t\treturn destConv(candidate);\n\t\t}\n\t\tlet start = 0;\n\t\tlet end = candidate.c;\n\t\tlet epsilon = (ranges.c[1] - ranges.c[0]) / 4000; // 0.0001 for oklch()\n\t\tlet clipped = clipToGamut(candidate);\n\t\twhile (end - start > epsilon) {\n\t\t\tcandidate.c = (start + end) * 0.5;\n\t\t\tclipped = clipToGamut(candidate);\n\t\t\tif (\n\t\t\t\tinDestinationGamut(candidate) ||\n\t\t\t\t(delta && jnd > 0 && delta(candidate, clipped) <= jnd)\n\t\t\t) {\n\t\t\t\tstart = candidate.c;\n\t\t\t} else {\n\t\t\t\tend = candidate.c;\n\t\t\t}\n\t\t}\n\t\treturn destConv(inDestinationGamut(candidate) ? candidate : clipped);\n\t};\n}\n","import converter from './converter.js';\n\n/*\n\tWCAG luminance\n\tReferences: \n\n\thttps://en.wikipedia.org/wiki/Relative_luminance\n\thttps://github.com/w3c/wcag/issues/236#issuecomment-379526596\n */\nexport function luminance(color) {\n\tlet c = converter('lrgb')(color);\n\treturn 0.2126 * c.r + 0.7152 * c.g + 0.0722 * c.b;\n}\n\n/*\n\tWCAG contrast\n */\nexport function contrast(a, b) {\n\tlet L1 = luminance(a);\n\tlet L2 = luminance(b);\n\treturn (Math.max(L1, L2) + 0.05) / (Math.min(L1, L2) + 0.05);\n}\n","// Color space definitions\nimport modeA98 from './a98/definition.js';\nimport modeCubehelix from './cubehelix/definition.js';\nimport modeDlab from './dlab/definition.js';\nimport modeDlch from './dlch/definition.js';\nimport modeHsi from './hsi/definition.js';\nimport modeHsl from './hsl/definition.js';\nimport modeHsv from './hsv/definition.js';\nimport modeHwb from './hwb/definition.js';\nimport modeItp from './itp/definition.js';\nimport modeJab from './jab/definition.js';\nimport modeJch from './jch/definition.js';\nimport modeLab from './lab/definition.js';\nimport modeLab65 from './lab65/definition.js';\nimport modeLch from './lch/definition.js';\nimport modeLch65 from './lch65/definition.js';\nimport modeLchuv from './lchuv/definition.js';\nimport modeLrgb from './lrgb/definition.js';\nimport modeLuv from './luv/definition.js';\nimport modeOkhsl from './okhsl/modeOkhsl.js';\nimport modeOkhsv from './okhsv/modeOkhsv.js';\nimport modeOklab from './oklab/definition.js';\nimport modeOklch from './oklch/definition.js';\nimport modeP3 from './p3/definition.js';\nimport modeProphoto from './prophoto/definition.js';\nimport modeRec2020 from './rec2020/definition.js';\nimport modeRgb from './rgb/definition.js';\nimport modeXyb from './xyb/definition.js';\nimport modeXyz50 from './xyz50/definition.js';\nimport modeXyz65 from './xyz65/definition.js';\nimport modeYiq from './yiq/definition.js';\nimport { useMode } from './modes.js';\n\nexport { default as converter } from './converter.js';\n\nexport {\n\tserializeHex,\n\tserializeHex8,\n\tserializeRgb,\n\tserializeHsl,\n\tformatHex,\n\tformatHex8,\n\tformatRgb,\n\tformatHsl,\n\tformatCss\n} from './formatter.js';\n\nexport { default as colorsNamed } from './colors/named.js';\nexport { default as blend } from './blend.js';\nexport { default as random } from './random.js';\n\nexport {\n\tfixupHueShorter,\n\tfixupHueLonger,\n\tfixupHueIncreasing,\n\tfixupHueDecreasing\n} from './fixup/hue.js';\n\nexport { fixupAlpha } from './fixup/alpha.js';\n\nexport {\n\tmapper,\n\tmapAlphaMultiply,\n\tmapAlphaDivide,\n\tmapTransferLinear,\n\tmapTransferGamma\n} from './map.js';\n\nexport { average, averageAngle, averageNumber } from './average.js';\n\nexport { default as round } from './round.js';\nexport {\n\tinterpolate,\n\tinterpolateWith,\n\tinterpolateWithPremultipliedAlpha\n} from './interpolate/interpolate.js';\n\nexport { interpolatorLinear } from './interpolate/linear.js';\n\nexport { interpolatorPiecewise } from './interpolate/piecewise.js';\n\nexport {\n\tinterpolatorSplineBasis,\n\tinterpolatorSplineBasisClosed\n} from './interpolate/splineBasis.js';\n\nexport {\n\tinterpolatorSplineNatural,\n\tinterpolatorSplineNaturalClosed\n} from './interpolate/splineNatural.js';\n\nexport {\n\tinterpolatorSplineMonotone,\n\tinterpolatorSplineMonotone2,\n\tinterpolatorSplineMonotoneClosed\n} from './interpolate/splineMonotone.js';\n\nexport { lerp, unlerp, blerp, trilerp } from './interpolate/lerp.js';\nexport { default as samples } from './samples.js';\nexport {\n\tdisplayable,\n\tinGamut,\n\tclampRgb,\n\tclampChroma,\n\tclampGamut,\n\ttoGamut\n} from './clamp.js';\nexport { default as nearest } from './nearest.js';\nexport { useMode, getMode, useParser, removeParser } from './modes.js';\nexport { default as parse } from './parse.js';\n\nexport {\n\tdifferenceEuclidean,\n\tdifferenceCie76,\n\tdifferenceCie94,\n\tdifferenceCiede2000,\n\tdifferenceCmc,\n\tdifferenceHyab,\n\tdifferenceHueSaturation,\n\tdifferenceHueChroma,\n\tdifferenceHueNaive,\n\tdifferenceKotsarenkoRamos,\n\tdifferenceItp\n} from './difference.js';\n\nexport {\n\tfilterBrightness,\n\tfilterContrast,\n\tfilterSepia,\n\tfilterInvert,\n\tfilterSaturate,\n\tfilterGrayscale,\n\tfilterHueRotate\n} from './filter.js';\n\nexport {\n\tfilterDeficiencyProt,\n\tfilterDeficiencyDeuter,\n\tfilterDeficiencyTrit\n} from './deficiency.js';\n\n// Easings\nexport { default as easingMidpoint } from './easing/midpoint.js';\nexport {\n\teasingSmoothstep,\n\teasingSmoothstepInverse\n} from './easing/smoothstep.js';\nexport { default as easingSmootherstep } from './easing/smootherstep.js';\nexport { default as easingInOutSine } from './easing/inOutSine.js';\nexport { default as easingGamma } from './easing/gamma.js';\n\nexport {\n\tluminance as wcagLuminance,\n\tcontrast as wcagContrast\n} from './wcag.js';\n\nexport { default as parseHsl } from './hsl/parseHsl.js';\nexport { default as parseHwb } from './hwb/parseHwb.js';\nexport { default as parseLab } from './lab/parseLab.js';\nexport { default as parseLch } from './lch/parseLch.js';\nexport { default as parseNamed } from './rgb/parseNamed.js';\nexport { default as parseTransparent } from './rgb/parseTransparent.js';\nexport { default as parseHex } from './rgb/parseHex.js';\nexport { default as parseRgb } from './rgb/parseRgb.js';\nexport { default as parseHslLegacy } from './hsl/parseHslLegacy.js';\nexport { default as parseRgbLegacy } from './rgb/parseRgbLegacy.js';\nexport { default as parseOklab } from './oklab/parseOklab.js';\nexport { default as parseOklch } from './oklch/parseOklch.js';\n\nexport { default as convertA98ToXyz65 } from './a98/convertA98ToXyz65.js';\nexport { default as convertCubehelixToRgb } from './cubehelix/convertCubehelixToRgb.js';\nexport { default as convertDlchToLab65 } from './dlch/convertDlchToLab65.js';\nexport { default as convertHsiToRgb } from './hsi/convertHsiToRgb.js';\nexport { default as convertHslToRgb } from './hsl/convertHslToRgb.js';\nexport { default as convertHsvToRgb } from './hsv/convertHsvToRgb.js';\nexport { default as convertHwbToRgb } from './hwb/convertHwbToRgb.js';\nexport { default as convertItpToXyz65 } from './itp/convertItpToXyz65.js';\nexport { default as convertJabToJch } from './jch/convertJabToJch.js';\nexport { default as convertJabToRgb } from './jab/convertJabToRgb.js';\nexport { default as convertJabToXyz65 } from './jab/convertJabToXyz65.js';\nexport { default as convertJchToJab } from './jch/convertJchToJab.js';\nexport { default as convertLab65ToDlch } from './dlch/convertLab65ToDlch.js';\nexport { default as convertLab65ToRgb } from './lab65/convertLab65ToRgb.js';\nexport { default as convertLab65ToXyz65 } from './lab65/convertLab65ToXyz65.js';\nexport { default as convertLabToLch } from './lch/convertLabToLch.js';\nexport { default as convertLabToRgb } from './lab/convertLabToRgb.js';\nexport { default as convertLabToXyz50 } from './lab/convertLabToXyz50.js';\nexport { default as convertLchToLab } from './lch/convertLchToLab.js';\nexport { default as convertLchuvToLuv } from './lchuv/convertLchuvToLuv.js';\nexport { default as convertLrgbToOklab } from './oklab/convertLrgbToOklab.js';\nexport { default as convertLrgbToRgb } from './lrgb/convertLrgbToRgb.js';\nexport { default as convertLuvToLchuv } from './lchuv/convertLuvToLchuv.js';\nexport { default as convertLuvToXyz50 } from './luv/convertLuvToXyz50.js';\nexport { default as convertOkhslToOklab } from './okhsl/convertOkhslToOklab.js';\nexport { default as convertOkhsvToOklab } from './okhsv/convertOkhsvToOklab.js';\nexport { default as convertOklabToLrgb } from './oklab/convertOklabToLrgb.js';\nexport { default as convertOklabToOkhsl } from './okhsl/convertOklabToOkhsl.js';\nexport { default as convertOklabToOkhsv } from './okhsv/convertOklabToOkhsv.js';\nexport { default as convertOklabToRgb } from './oklab/convertOklabToRgb.js';\nexport { default as convertP3ToXyz65 } from './p3/convertP3ToXyz65.js';\nexport { default as convertProphotoToXyz50 } from './prophoto/convertProphotoToXyz50.js';\nexport { default as convertRec2020ToXyz65 } from './rec2020/convertRec2020ToXyz65.js';\nexport { default as convertRgbToCubehelix } from './cubehelix/convertRgbToCubehelix.js';\nexport { default as convertRgbToHsi } from './hsi/convertRgbToHsi.js';\nexport { default as convertRgbToHsl } from './hsl/convertRgbToHsl.js';\nexport { default as convertRgbToHsv } from './hsv/convertRgbToHsv.js';\nexport { default as convertRgbToHwb } from './hwb/convertRgbToHwb.js';\nexport { default as convertRgbToJab } from './jab/convertRgbToJab.js';\nexport { default as convertRgbToLab } from './lab/convertRgbToLab.js';\nexport { default as convertRgbToLab65 } from './lab65/convertRgbToLab65.js';\nexport { default as convertRgbToLrgb } from './lrgb/convertRgbToLrgb.js';\nexport { default as convertRgbToOklab } from './oklab/convertRgbToOklab.js';\nexport { default as convertRgbToXyb } from './xyb/convertRgbToXyb.js';\nexport { default as convertRgbToXyz50 } from './xyz50/convertRgbToXyz50.js';\nexport { default as convertRgbToXyz65 } from './xyz65/convertRgbToXyz65.js';\nexport { default as convertRgbToYiq } from './yiq/convertRgbToYiq.js';\nexport { default as convertXybToRgb } from './xyb/convertXybToRgb.js';\nexport { default as convertXyz50ToLab } from './lab/convertXyz50ToLab.js';\nexport { default as convertXyz50ToLuv } from './luv/convertXyz50ToLuv.js';\nexport { default as convertXyz50ToProphoto } from './prophoto/convertXyz50ToProphoto.js';\nexport { default as convertXyz50ToRgb } from './xyz50/convertXyz50ToRgb.js';\nexport { default as convertXyz50ToXyz65 } from './xyz65/convertXyz50ToXyz65.js';\nexport { default as convertXyz65ToA98 } from './a98/convertXyz65ToA98.js';\nexport { default as convertXyz65ToItp } from './itp/convertXyz65ToItp.js';\nexport { default as convertXyz65ToJab } from './jab/convertXyz65ToJab.js';\nexport { default as convertXyz65ToLab65 } from './lab65/convertXyz65ToLab65.js';\nexport { default as convertXyz65ToP3 } from './p3/convertXyz65ToP3.js';\nexport { default as convertXyz65ToRec2020 } from './rec2020/convertXyz65ToRec2020.js';\nexport { default as convertXyz65ToRgb } from './xyz65/convertXyz65ToRgb.js';\nexport { default as convertXyz65ToXyz50 } from './xyz65/convertXyz65ToXyz50.js';\nexport { default as convertYiqToRgb } from './yiq/convertYiqToRgb.js';\n\nexport {\n\tmodeA98,\n\tmodeCubehelix,\n\tmodeDlab,\n\tmodeDlch,\n\tmodeHsi,\n\tmodeHsl,\n\tmodeHsv,\n\tmodeHwb,\n\tmodeItp,\n\tmodeJab,\n\tmodeJch,\n\tmodeLab,\n\tmodeLab65,\n\tmodeLch,\n\tmodeLch65,\n\tmodeLchuv,\n\tmodeLrgb,\n\tmodeLuv,\n\tmodeOkhsl,\n\tmodeOkhsv,\n\tmodeOklab,\n\tmodeOklch,\n\tmodeP3,\n\tmodeProphoto,\n\tmodeRec2020,\n\tmodeRgb,\n\tmodeXyb,\n\tmodeXyz50,\n\tmodeXyz65,\n\tmodeYiq\n};\n\nexport const a98 = useMode(modeA98);\nexport const cubehelix = useMode(modeCubehelix);\nexport const dlab = useMode(modeDlab);\nexport const dlch = useMode(modeDlch);\nexport const hsi = useMode(modeHsi);\nexport const hsl = useMode(modeHsl);\nexport const hsv = useMode(modeHsv);\nexport const hwb = useMode(modeHwb);\nexport const itp = useMode(modeItp);\nexport const jab = useMode(modeJab);\nexport const jch = useMode(modeJch);\nexport const lab = useMode(modeLab);\nexport const lab65 = useMode(modeLab65);\nexport const lch = useMode(modeLch);\nexport const lch65 = useMode(modeLch65);\nexport const lchuv = useMode(modeLchuv);\nexport const lrgb = useMode(modeLrgb);\nexport const luv = useMode(modeLuv);\nexport const okhsl = useMode(modeOkhsl);\nexport const okhsv = useMode(modeOkhsv);\nexport const oklab = useMode(modeOklab);\nexport const oklch = useMode(modeOklch);\nexport const p3 = useMode(modeP3);\nexport const prophoto = useMode(modeProphoto);\nexport const rec2020 = useMode(modeRec2020);\nexport const rgb = useMode(modeRgb);\nexport const xyb = useMode(modeXyb);\nexport const xyz50 = useMode(modeXyz50);\nexport const xyz65 = useMode(modeXyz65);\nexport const yiq = useMode(modeYiq);\n","/**\n * The hex contract shared by `chinContrast` and `accentSurface`.\n *\n * `culori` does the parsing, and it accepts every CSS colour — including names\n * like `rebeccapurple` and formats with alpha. Every colour reaching these two\n * modules comes from `getDominantColorFromImageUrl` via a Stream attachment\n * field, or from a constant in this directory, so both narrow the input to a hex\n * before handing it over rather than widening their contract by accident.\n */\n\n/**\n * `#abc`, `#aabbcc`, or either without the leading `#`.\n *\n * The missing hash is deliberate: the extractor returns bare hexes often enough\n * that rejecting them would silently drop the colour. It is also why `toCssHex`\n * exists — `background-color: 738883` is invalid and the DOM drops it, which is\n * how a card once rendered unaccented while every calculation behind it had\n * succeeded (MES-1349).\n */\nexport const HEX_PATTERN = /^#?(?:[0-9a-f]{3}|[0-9a-f]{6})$/i\n\n/** Normalizes a hex for CSS and for culori, adding the `#` the extractor omits. */\nexport function toCssHex(hex: string): string {\n const trimmed = hex.trim()\n return trimmed.startsWith('#') ? trimmed : `#${trimmed}`\n}\n","/**\n * Ink and fallback fills for the `LinkAttachment` card, whose background is a\n * colour derived from the attachment image (see `accentSurface`).\n *\n * The card's text is chosen by measuring contrast against whatever surface the\n * card actually paints. Ink used to be fixed per variant, which left any\n * background the card imposed on *itself* unchecked: `AUDIO_BG_CLASS`\n * (`#F2F3F4`) is applied on either variant, so a sent audio card drew white ink\n * on near-white at 1.13:1 and the title was invisible (MES-1388).\n *\n * The ratio itself is `culori`'s `wcagContrast`. A previous revision computed\n * relative luminance here by hand; the only thing this module adds now is the\n * decision of *which* ink, and the hex validation that keeps the surface a hex\n * rather than any CSS colour.\n */\nimport { wcagContrast } from 'culori'\n\nimport type { LinkAttachmentVariant } from './CardShell'\nimport { HEX_PATTERN, toCssHex } from './hex'\n\n/** WCAG 2.1 SC 1.4.3 (AA), normal text. Both chin lines are normal text. */\nexport const WCAG_AA_NORMAL_TEXT = 4.5\n\n/**\n * Fill each side falls back to when no accent is paintable: the plain message\n * bubble's own background, so a link card without a usable colour is indistinct\n * from the text bubbles around it rather than a third colour nobody chose.\n *\n * These are the literal values behind `--str-chat__own-message-bubble-background-color`\n * and `--str-chat__message-bubble-background-color` in `styles.css`. Duplicated\n * as hex because the bubble tail paints *outside* the shell's box via an inline\n * style, and because the contrast arithmetic needs a colour, not a `var()`.\n * Keep in sync with those two custom properties.\n */\nexport const BUBBLE_BG_BY_VARIANT: Record<LinkAttachmentVariant, string> = {\n dark: '#1e2330',\n light: '#f1f0ee',\n}\n\n/** Ink candidates for a surface the card cannot refuse. */\nexport const INK_ON_DARK = '#FFFFFF'\n/** The near-black used across the Figma frames. */\nexport const INK_ON_LIGHT = '#040403'\n\n/**\n * WCAG contrast ratio between two hex colours, or `NaN` if either is not a hex.\n *\n * The hex guard is deliberate: `culori` resolves any CSS colour, and every\n * colour reaching this module comes from an image extractor or from the two\n * constants above. `NaN` rather than a throw so callers can branch on\n * `Number.isNaN` and fall back.\n */\nexport function contrastRatio(a: string, b: string): number {\n if (typeof a !== 'string' || typeof b !== 'string') return Number.NaN\n if (!HEX_PATTERN.test(a.trim()) || !HEX_PATTERN.test(b.trim())) {\n return Number.NaN\n }\n\n return wcagContrast(toCssHex(a), toCssHex(b))\n}\n\n/**\n * Ink for a surface the card did not choose — the audio strip's flat neutral, or\n * a variant fallback fill — picking whichever candidate scores the higher ratio\n * against it. `undefined` when the surface is not a hex, so callers keep the\n * variant's own `text-*` classes.\n *\n * This is the rule the accent derivation cannot cover. A derived accent suits\n * its side's ink by construction; an imposed background has to be met the other\n * way round, by moving the ink. Only decoration can be refused (MES-1388).\n */\nexport function inkFor(background: string): string | undefined {\n const againstDarkInk = contrastRatio(background, INK_ON_LIGHT)\n if (Number.isNaN(againstDarkInk)) return undefined\n\n return againstDarkInk >= contrastRatio(background, INK_ON_DARK)\n ? INK_ON_LIGHT\n : INK_ON_DARK\n}\n","/**\n * Turns the colour extracted from an attachment image into a card surface that\n * the card's own text can survive.\n *\n * `ugc-kit`'s `ImageAnalysis` (`getDominantColorFromImageUrl`) answers only\n * \"what colour is this image?\" — it has no notion of contrast or readability.\n * Painting that colour straight onto the card is what broke: the extracted\n * colour is whatever the photo happened to be, so roughly half of them left the\n * title illegible against the side's ink, and refusing those threw away the\n * colour the feature exists to add (MES-1349, MES-1388).\n *\n * So the hue is kept and the *lightness* is replaced with a fixed stop chosen\n * per side — dark behind the sender's white ink, pale behind the receiver's\n * near-black. This is the approach already used in `linktr.ee-profiles`\n * (`ui/src/utils/rgbToTheme.ts`), whose `getPaletteFromColor` generates a\n * 16-stop OKLCH ramp from one colour and has callers pick a background stop and\n * a text stop from it. We need exactly one stop per side rather than a whole\n * theme, so the ramp is collapsed to a single lightness target.\n *\n * OKLCH rather than HSL because its lightness axis is perceptually uniform: one\n * L value gives the same *apparent* lightness — and therefore the same contrast\n * — across every hue. In HSL, `50%` lightness yellow and `50%` blue differ by\n * several stops of contrast, so no single target would hold.\n *\n * The conversion, the sRGB gamut mapping and the WCAG ratio are all `culori`'s.\n * An earlier revision of this module hand-rolled them (~90 lines of OKLab\n * matrices and a bisecting chroma search); `culori` is zero-dependency and ships\n * a real CJS build, so it is safe for both frontyard's Jest and profiles' build.\n */\nimport { clampChroma, converter, formatHex, wcagContrast } from 'culori'\n\nimport type { LinkAttachmentVariant } from './CardShell'\nimport { INK_ON_DARK, INK_ON_LIGHT, WCAG_AA_NORMAL_TEXT } from './chinContrast'\nimport { HEX_PATTERN, toCssHex } from './hex'\n\n/**\n * Perceived-lightness stop each side paints at, in OKLCH L (0..1) — profiles'\n * `color12` / `color2` equivalent. Both sit far enough from their ink to clear\n * AA at any hue and chroma: swept across every hue at maximum chroma the worst\n * case is comfortably above the 4.5:1 floor (see `accentSurface.test.ts`).\n */\nconst SURFACE_LIGHTNESS: Record<LinkAttachmentVariant, number> = {\n dark: 0.3,\n light: 0.9,\n}\n\n/** Ink each side draws, so the derived surface can be checked against it. */\nconst INK_BY_VARIANT: Record<LinkAttachmentVariant, string> = {\n dark: INK_ON_DARK,\n light: INK_ON_LIGHT,\n}\n\nconst toOklch = converter('oklch')\n\n/**\n * The card surface for an extracted colour: the image's hue at this side's\n * lightness stop, or `undefined` when there was no colour to work from.\n *\n * The input is validated as a hex rather than handed to `culori` directly.\n * `culori` accepts every CSS colour, including names like `rebeccapurple`, and\n * `accent_color` is always a hex from `getDominantColorFromImageUrl` — widening\n * that contract by accident would let a caller pass something no other part of\n * this module can reason about. The bare-hex case *is* supported, because the\n * extractor omits the `#` often enough that dropping it would silently lose the\n * colour (MES-1349).\n *\n * The AA check at the end is a guard, not a branch anyone expects to take: the\n * lightness stops were chosen to clear it everywhere. It exists so that a future\n * change to `SURFACE_LIGHTNESS` or to the ink cannot quietly reintroduce an\n * illegible card — it degrades to the plain bubble fill instead.\n */\nexport function accentSurface(\n accentColor: string | undefined,\n variant: LinkAttachmentVariant\n): string | undefined {\n if (accentColor == null || !HEX_PATTERN.test(accentColor.trim())) {\n return undefined\n }\n\n const base = toOklch(toCssHex(accentColor))\n if (!base) return undefined\n\n // `clampChroma`, not `toGamut`: both bring an out-of-sRGB colour back into\n // range, but `toGamut` follows the CSS Color 4 path and drifts hue by up to\n // 12° on saturated bases, while `clampChroma` reduces chroma at constant hue\n // and lightness — 2.8° worst case. Vivid hues desaturate rather than shift,\n // which is what keeps the card recognisably the image's colour.\n const surface = formatHex(\n clampChroma({ ...base, l: SURFACE_LIGHTNESS[variant] }, 'oklch')\n )\n\n return wcagContrast(surface, INK_BY_VARIANT[variant]) >= WCAG_AA_NORMAL_TEXT\n ? surface\n : undefined\n}\n","/* eslint-disable react-hooks/set-state-in-effect -- pre-existing pattern flagged by the React\n Compiler rules added in eslint-plugin-react-hooks v7; refactoring it is\n out of scope for the lint toolchain upgrade. */\nimport React from 'react'\n\nimport type { LinkAttachmentLayout, LinkAttachmentStatus } from '../../types'\n\nimport { accentSurface } from './accentSurface'\nimport type { LinkAttachmentVariant } from './CardShell'\nimport { AUDIO_BG, isPlayableAudio } from './CardThumbnail'\nimport { BUBBLE_BG_BY_VARIANT, inkFor } from './chinContrast'\n\nexport interface ChinPaletteInput {\n variant: LinkAttachmentVariant\n accentColor?: string\n status?: LinkAttachmentStatus\n layout?: LinkAttachmentLayout\n thumbnailUrl?: string\n /**\n * Together with `sourceUrl`, identifies the playable-audio card whose hero\n * region is the native player rather than an image. See `hasHero` below.\n */\n mimeType?: string\n sourceUrl?: string\n}\n\nexport interface ChinPalette {\n /**\n * Hero URL to render. Cleared once the image has errored so `CardThumbnail`\n * falls through to its type-icon placeholder instead of a broken `<img>`.\n */\n thumbnailUrl?: string\n /**\n * Inline background for the card shell, or `undefined` to keep the variant's\n * own `bg-*` class.\n */\n accentStyle?: React.CSSProperties\n /**\n * Ink for both chin lines, chosen against the surface the card actually\n * paints — the derived accent, the audio strip, or the fallback fill. Always\n * defined for a parseable surface.\n */\n chinTextColor?: string\n /**\n * Colour the bubble tail paints in, always defined: the accent when one is\n * paintable, otherwise this side's plain bubble fill.\n */\n tailColor: string\n /** True while the card renders as a skeleton. */\n isLoading: boolean\n /** Hand to `CardThumbnail` so a broken hero drops the accent with it. */\n onImageError: () => void\n}\n\n/**\n * Resolves a link card's accent-derived colours and tracks hero-image failure.\n *\n * The accent is a claim about an image the viewer can see, so it only paints\n * when `CardThumbnail` actually mounts that image. Mirroring its branches\n * (`CardThumbnail.tsx:98-160`), the hero is *not* the accent's source when:\n *\n * - `layout: 'classic'` — there is no hero region at all;\n * - `status` is not `'ready'` — the hero is the pulsing skeleton and there is\n * no image yet;\n * - `thumbnailUrl` is absent — the hero is the type-icon placeholder, or for a\n * playable video a bare `bg-black` box with no poster;\n * - the attachment is playable audio — the hero collapses to the native\n * `<audio>` player and the `<img>` never mounts *even though `thumbnailUrl`\n * is set*, so `onImageError` can never rescue this one. Left ungated, an\n * artwork-backed audio link preview shipped a coloured card with no visible\n * source image, and the accent beat `AUDIO_BG_CLASS` on Sent / Received\n * because `CardShell` applies it as an inline `style`, which outranks any\n * `bg-*` class. `ComposerCard` already dodged that by returning early before\n * it passes `accentStyle`; this is that same rule, stated once instead of\n * three times (MES-1349);\n * - the image 404s — an accent extracted from something the viewer cannot see.\n * `onImageError` covers both hero shapes: the `<img>` reports directly, and a\n * playable video's `poster` (which raises no event of its own) is verified by\n * the hidden probe image in `CardThumbnail`.\n *\n * Every case falls back to the variant's own fill, which already pairs with\n * the variant's own text colours.\n */\nexport function useChinPalette({\n variant,\n accentColor,\n status = 'ready',\n layout = 'featured',\n thumbnailUrl,\n mimeType,\n sourceUrl,\n}: ChinPaletteInput): ChinPalette {\n const [heroFailed, setHeroFailed] = React.useState(false)\n\n // A new hero URL is a new chance to load — otherwise a card that recycles\n // (same element, different attachment) would stay stuck on the placeholder.\n React.useEffect(() => {\n setHeroFailed(false)\n }, [thumbnailUrl])\n\n const onImageError = React.useCallback(() => {\n setHeroFailed(true)\n }, [])\n\n // Truthiness rather than `!= null` so this tracks `CardThumbnail`'s own\n // `thumbnailUrl ?` branch, which renders the placeholder for `''` too.\n //\n // Playable audio stays excluded, as MES-1349 decided: its hero collapses to\n // the native `<audio>` player, so the artwork never appears and an accent\n // taken from it would be a claim about an image the viewer cannot see. The\n // `<img>` never mounts either, so `onImageError` could not withdraw the colour\n // if the artwork 404'd. Colouring audio cards from their artwork is a change\n // to the audio tickets (MES-1360 / MES-1361), not to this one.\n const isAudio = isPlayableAudio(mimeType, sourceUrl)\n const hasHero =\n layout === 'featured' && !!thumbnailUrl && !isAudio && !heroFailed\n const surface =\n hasHero && status === 'ready'\n ? accentSurface(accentColor, variant)\n : undefined\n\n // Whatever the card ends up painted with, legible or not, the ink is chosen\n // against it. The accent is derived to suit this side's ink, but the audio\n // strip and the fallback fill are imposed and cannot be refused — a sent\n // audio card put white ink on `AUDIO_BG`'s near-white at 1.13:1 (MES-1388).\n const painted =\n surface ?? (isAudio ? AUDIO_BG : BUBBLE_BG_BY_VARIANT[variant])\n\n return {\n thumbnailUrl: heroFailed ? undefined : thumbnailUrl,\n accentStyle: surface ? { backgroundColor: surface } : undefined,\n chinTextColor: inkFor(painted),\n tailColor: painted,\n isLoading: status === 'loading',\n onImageError,\n }\n}\n","import { PencilSimpleIcon, XIcon } from '@phosphor-icons/react'\nimport classNames from 'classnames'\nimport React from 'react'\n\nimport type { LinkAttachmentBaseProps } from '../../types'\nimport CardBody from '../_shared/CardBody'\nimport CardShell from '../_shared/CardShell'\nimport CardThumbnail, {\n AUDIO_BG_CLASS,\n isPlayableAudio,\n} from '../_shared/CardThumbnail'\nimport { useChinPalette } from '../_shared/useChinPalette'\n\nexport interface ComposerCardProps extends LinkAttachmentBaseProps {\n /**\n * When provided, renders a dismiss X in the thumbnail corner. Called when\n * the composer clicks it to remove the attachment.\n */\n onDismiss?: () => void\n /**\n * When provided, renders a pencil button to the right of the description\n * that the composer can use to edit the attachment metadata.\n */\n onEditClick?: () => void\n /**\n * Accessible name for the dismiss button. Defaults to English because the\n * toolkit has no i18n layer; consumers that do (frontyard passes\n * `ComposerLinkPreviewList.closeLinkPreview`) should supply their own.\n */\n dismissLabel?: string\n}\n\n// 24x24 circle with a 12x12 white X — already Figma-exact.\nconst DISMISS_CLASS =\n 'flex size-6 items-center justify-center rounded-full bg-[#121110] text-white focus-ring'\n\n// Grows only the *clickable* area to 44x44 (24 + 10 + 10) for the platform\n// touch minimum (MES-1350 / MES-1358), leaving the visual box alone — this\n// same card renders in profiles' touch-first visitor composer, so a\n// consumer-scoped fix could not reach it. Same idiom as the send button in\n// `CustomMessageInput/index.tsx`. Not applied on the audio variant, where the\n// button is an inline sibling of the native controls rather than an overlay\n// and the halo would sit on top of them.\nconst DISMISS_TOUCH_TARGET_CLASS =\n \"relative before:absolute before:-inset-[10px] before:content-['']\"\n\n/**\n * The card the composer sees while drafting a link attachment.\n * Matches the Composer column of the messaging design system in Figma.\n */\nconst ComposerCard: React.FC<ComposerCardProps> = ({\n title,\n placeholderTitle,\n description,\n url,\n mimeType,\n thumbnailUrl,\n sourceUrl,\n layout = 'featured',\n appIcon,\n cta,\n accentColor,\n status = 'ready',\n onDismiss,\n onEditClick,\n dismissLabel = 'Dismiss attachment',\n}) => {\n const isClassic = layout === 'classic'\n const isAudio = isPlayableAudio(mimeType, sourceUrl)\n const chin = useChinPalette({\n variant: 'dark',\n accentColor,\n status,\n layout,\n thumbnailUrl,\n mimeType,\n sourceUrl,\n })\n\n const dismissButton = onDismiss ? (\n <button\n type=\"button\"\n onClick={onDismiss}\n aria-label={dismissLabel}\n className={classNames(\n DISMISS_CLASS,\n !isAudio && DISMISS_TOUCH_TARGET_CLASS\n )}\n >\n <XIcon className=\"size-3\" weight=\"bold\" />\n </button>\n ) : undefined\n\n const editButton = onEditClick ? (\n <button\n type=\"button\"\n onClick={onEditClick}\n aria-label=\"Edit attachment\"\n className=\"flex size-10 items-center justify-center rounded-full bg-white/10 text-white hover:bg-white/15\"\n >\n <PencilSimpleIcon className=\"size-5\" weight=\"regular\" />\n </button>\n ) : undefined\n\n // Audio cards collapse to just the native player — render the dismiss\n // button as an inline sibling so it always has its own space and never\n // overlaps the audio control's volume/menu buttons. Skipped while loading:\n // this path has no `CardBody` and no `busy`, so taking it during a scrape\n // would drop the skeleton and its `aria-busy` region entirely, and we do not\n // yet know the asset is audio anyway.\n if (isAudio && !chin.isLoading) {\n return (\n <CardShell variant=\"dark\" bgClassName={AUDIO_BG_CLASS}>\n <div className=\"flex items-center gap-2 pr-3\">\n <div className=\"min-w-0 flex-1\">\n <CardThumbnail\n variant=\"dark\"\n sourceUrl={sourceUrl}\n title={title}\n mimeType={mimeType}\n />\n </div>\n {dismissButton && <div className=\"shrink-0\">{dismissButton}</div>}\n </div>\n </CardShell>\n )\n }\n\n return (\n <CardShell\n variant=\"dark\"\n fixedHeight={!isClassic}\n accentStyle={chin.accentStyle}\n busy={chin.isLoading}\n topRight={isClassic ? dismissButton : undefined}\n >\n {!isClassic && (\n <CardThumbnail\n variant=\"dark\"\n thumbnailUrl={chin.thumbnailUrl}\n sourceUrl={sourceUrl}\n title={title}\n mimeType={mimeType}\n topRight={dismissButton}\n isLoading={chin.isLoading}\n onImageError={chin.onImageError}\n />\n )}\n <CardBody\n chinTextColor={chin.chinTextColor}\n variant=\"dark\"\n title={title}\n placeholderTitle={placeholderTitle}\n description={description}\n url={url}\n appIcon={appIcon}\n cta={cta}\n trailingAction={editButton}\n isLoading={chin.isLoading}\n />\n </CardShell>\n )\n}\n\nexport default ComposerCard\n","import classNames from 'classnames'\nimport React from 'react'\n\nexport interface BubbleTailProps {\n /**\n * Hex the tail paints in — the card's accent colour, or its variant\n * fallback fill. Inline rather than a class because the accent is a\n * runtime value extracted from the attachment image.\n */\n color: string\n /** Sender tails hang off the right edge, receiver tails mirror to the left. */\n side: 'sender' | 'receiver'\n /**\n * `false` renders `children` untouched — a card mid-run has no tail because\n * a later bubble in the run owns it.\n */\n visible: boolean\n children: React.ReactNode\n}\n\n/**\n * Wraps a `LinkAttachment` card in the chat bubble tail from the messaging\n * design system, painted to match the card's own bottom edge.\n *\n * The geometry and mask live in `styles.css` alongside the text-bubble tails\n * they mirror. They cannot be reused directly: those rules key off\n * `.str-chat__message-bubble:last-child`, which only exists when the card is\n * rendered inside a Stream thread — and `StreamAttachmentMessage` marks that\n * bubble `data-attachment-bubble` precisely to opt out of them, since a tail\n * tinted from the text-bubble surface would clash with a coloured card.\n */\nconst BubbleTail: React.FC<BubbleTailProps> = ({\n color,\n side,\n visible,\n children,\n}) => {\n if (!visible) return <>{children}</>\n\n return (\n // `isolate` keeps the tail's negative z-index from escaping behind the\n // thread background; `w-fit` stops the wrapper from stretching in the\n // composer's flex list.\n <div className=\"relative isolate w-fit\">\n {children}\n <span\n aria-hidden\n data-testid=\"link-card-tail\"\n style={{ backgroundColor: color }}\n className={classNames(\n 'messaging-link-card-tail',\n side === 'receiver' && 'messaging-link-card-tail--received'\n )}\n />\n </div>\n )\n}\n\nexport default BubbleTail\n","import React from 'react'\n\nimport type { BubbleGroupPosition } from '../../../MessageAttachment/types'\nimport type { LinkAttachmentBaseProps } from '../../types'\nimport BubbleTail from '../_shared/BubbleTail'\nimport CardBody from '../_shared/CardBody'\nimport CardShell from '../_shared/CardShell'\nimport CardThumbnail, {\n AUDIO_BG_CLASS,\n isPlayableAudio,\n isPlayableMedia,\n} from '../_shared/CardThumbnail'\nimport { normalizeExternalHref } from '../_shared/normalizeExternalHref'\nimport { useChinPalette } from '../_shared/useChinPalette'\n\nexport interface ReceivedCardProps extends LinkAttachmentBaseProps {\n /**\n * Fired when the recipient activates the card. Behavior depends on how\n * the card is configured:\n * - **Link app with a CTA** (FAQ / Form): the CTA owns navigation;\n * `onClick` fires when the recipient taps the CTA itself, alongside\n * `cta.onClick` (use for analytics).\n * - **Link app with a URL** (Spotify / TikTok / generic link): the card\n * chrome is an `<a target=\"_blank\">` opening `url` — `onClick` fires\n * alongside the navigation (use for analytics).\n * - **Hero-image only card**: the card has no URL, so it renders as\n * a button. `onClick` is the consumer's hook for opening a preview.\n * - **Video / audio link previews**: the shell stays non-interactive\n * so the native media controls remain operable — `onClick` is\n * ignored in this configuration.\n */\n onClick?: () => void\n /**\n * Position of this card inside its same-author run. `'single'` / `'end'`\n * paint the accent-coloured tail, mirrored to the card's left edge;\n * `'first'` / `'middle'` omit it because a later bubble in the run owns it.\n * Defaults to `'single'`.\n */\n groupPosition?: BubbleGroupPosition\n}\n\n/**\n * The card the recipient sees in chat for a link attachment. Matches the\n * Received column of the messaging design system in Figma.\n */\nconst ReceivedCard: React.FC<ReceivedCardProps> = ({\n title,\n description,\n url,\n mimeType,\n thumbnailUrl,\n sourceUrl,\n layout = 'featured',\n appIcon,\n cta,\n accentColor,\n status = 'ready',\n onClick,\n groupPosition = 'single',\n}) => {\n // Video / audio link previews wrap the native media element — render a\n // plain non-interactive shell and let the media controls own clicks so\n // taps on play/pause/scrubber don't fire the outer card action.\n const isPlayingMedia = isPlayableMedia(mimeType, sourceUrl)\n // Normalize the URL so a bare hostname like `tr.ee/briemix` (used in\n // our own docs / stories) is treated as an external link instead of a\n // relative path. Returns `undefined` for empty / whitespace-only\n // values, so those fall through to the preview path instead of\n // producing an empty `href` on the shell anchor.\n const normalizedUrl = normalizeExternalHref(url)\n const shellHref =\n cta == null && normalizedUrl != null && !isPlayingMedia\n ? normalizedUrl\n : undefined\n const shellOnClick = cta == null && !isPlayingMedia ? onClick : undefined\n // A loading card is not yet an audio card: the scrape that would tell us has\n // not returned, so it keeps the ordinary 250px skeleton rather than the\n // intrinsic-height audio shell (whose `flex-1` hero would collapse to 0).\n const audioBg =\n status !== 'loading' && isPlayableAudio(mimeType, sourceUrl)\n ? AUDIO_BG_CLASS\n : undefined\n\n // When a CTA is set the shell isn't interactive — the CTA owns the\n // click target. Forward the card-level `onClick` to the CTA so\n // analytics / side-effect consumers still fire on activation while\n // preserving the CTA's own `onClick` callback.\n const wrappedCta =\n cta && onClick\n ? {\n ...cta,\n onClick: () => {\n onClick()\n cta.onClick?.()\n },\n }\n : cta\n\n const chin = useChinPalette({\n variant: 'light',\n accentColor,\n status,\n layout,\n thumbnailUrl,\n mimeType,\n sourceUrl,\n })\n\n return (\n <BubbleTail\n color={chin.tailColor}\n side=\"receiver\"\n // Only the last card in a same-author run carries the tail; the audio\n // player card is not a bubble, so it never does.\n visible={\n audioBg == null &&\n (groupPosition === 'single' || groupPosition === 'end')\n }\n >\n <CardShell\n variant=\"light\"\n href={shellHref}\n onClick={shellOnClick}\n ariaLabel={title ?? 'Open attachment preview'}\n fixedHeight={layout === 'featured' && audioBg == null}\n accentStyle={chin.accentStyle}\n busy={chin.isLoading}\n bgClassName={audioBg}\n data-testid=\"link-attachment\"\n >\n {layout === 'featured' && (\n <CardThumbnail\n variant=\"light\"\n thumbnailUrl={chin.thumbnailUrl}\n sourceUrl={sourceUrl}\n title={title}\n mimeType={mimeType}\n isLoading={chin.isLoading}\n onImageError={chin.onImageError}\n />\n )}\n <CardBody\n chinTextColor={chin.chinTextColor}\n variant=\"light\"\n title={title}\n description={description}\n url={url}\n appIcon={appIcon}\n cta={wrappedCta}\n isLoading={chin.isLoading}\n />\n </CardShell>\n </BubbleTail>\n )\n}\n\nexport default ReceivedCard\n","import React from 'react'\n\nimport type { BubbleGroupPosition } from '../../../MessageAttachment/types'\nimport type { LinkAttachmentBaseProps } from '../../types'\nimport BubbleTail from '../_shared/BubbleTail'\nimport CardBody from '../_shared/CardBody'\nimport CardShell from '../_shared/CardShell'\nimport CardThumbnail, {\n AUDIO_BG_CLASS,\n isPlayableAudio,\n isPlayableMedia,\n} from '../_shared/CardThumbnail'\nimport { normalizeExternalHref } from '../_shared/normalizeExternalHref'\nimport { useChinPalette } from '../_shared/useChinPalette'\n\nexport interface SentCardProps extends LinkAttachmentBaseProps {\n /**\n * Fired when the sender activates their own posted card. Mirrors the\n * `Received` variant so analytics fires symmetrically on both sides\n * of the conversation. Behavior depends on configuration:\n * - **Link app with a URL**: the card chrome is an `<a target=\"_blank\">`\n * opening `url`; `onClick` fires alongside the navigation.\n * - **Link app with a CTA**: the CTA owns navigation; `onClick` is\n * ignored (the CTA's own `onClick` is the analytics hook).\n * - **Video / audio link previews**: the shell stays non-interactive\n * so the native media controls remain operable; `onClick` is ignored.\n */\n onClick?: () => void\n /**\n * Position of this card inside its same-author run. `'single'` / `'end'`\n * paint the accent-coloured tail; `'first'` / `'middle'` omit it because a\n * later bubble in the run owns it. Defaults to `'single'`.\n */\n groupPosition?: BubbleGroupPosition\n}\n\n/**\n * The card the sender sees in chat after a link attachment has been posted.\n * Matches the Sent column of the messaging design system in Figma — same\n * dark chrome as the Composer card minus the dismiss / edit affordances.\n *\n * The sender's own copy is clickable when a `url` is set so they can open\n * the link they just sent — symmetric with `LinkAttachment.Received`.\n */\nconst SentCard: React.FC<SentCardProps> = ({\n title,\n placeholderTitle,\n description,\n url,\n mimeType,\n thumbnailUrl,\n sourceUrl,\n layout = 'featured',\n appIcon,\n cta,\n accentColor,\n status = 'ready',\n onClick,\n groupPosition = 'single',\n}) => {\n // Video / audio link previews wrap the native media element — render a\n // plain non-interactive shell and let the media controls own clicks so\n // taps on play/pause/scrubber don't fire the outer card action. Same\n // rationale as `ReceivedCard`.\n const isPlayingMedia = isPlayableMedia(mimeType, sourceUrl)\n // Normalize the URL so a bare hostname like `tr.ee/briemix` is treated\n // as an external link instead of resolving against the current host.\n // Returns `undefined` for empty / whitespace-only values, so those fall\n // through to a non-navigational shell instead of producing an empty\n // `href` on the anchor.\n const normalizedUrl = normalizeExternalHref(url)\n const shellHref =\n cta == null && normalizedUrl != null && !isPlayingMedia\n ? normalizedUrl\n : undefined\n const shellOnClick =\n cta == null && !isPlayingMedia && shellHref != null ? onClick : undefined\n\n // A loading card is not yet an audio card: the scrape that would tell us has\n // not returned, so it keeps the ordinary 250px skeleton rather than the\n // intrinsic-height audio shell (whose `flex-1` hero would collapse to 0).\n const isAudio = status !== 'loading' && isPlayableAudio(mimeType, sourceUrl)\n const chin = useChinPalette({\n variant: 'dark',\n accentColor,\n status,\n layout,\n thumbnailUrl,\n mimeType,\n sourceUrl,\n })\n\n return (\n <BubbleTail\n color={chin.tailColor}\n side=\"sender\"\n // Only the last card in a same-author run carries the tail; the audio\n // player card is not a bubble, so it never does.\n visible={\n !isAudio && (groupPosition === 'single' || groupPosition === 'end')\n }\n >\n <CardShell\n variant=\"dark\"\n href={shellHref}\n onClick={shellOnClick}\n fixedHeight={layout === 'featured' && !isAudio}\n accentStyle={chin.accentStyle}\n busy={chin.isLoading}\n bgClassName={isAudio ? AUDIO_BG_CLASS : undefined}\n >\n {layout === 'featured' && (\n <CardThumbnail\n variant=\"dark\"\n thumbnailUrl={chin.thumbnailUrl}\n sourceUrl={sourceUrl}\n title={title}\n mimeType={mimeType}\n isLoading={chin.isLoading}\n onImageError={chin.onImageError}\n />\n )}\n <CardBody\n chinTextColor={chin.chinTextColor}\n variant=\"dark\"\n title={title}\n placeholderTitle={placeholderTitle}\n description={description}\n url={url}\n appIcon={appIcon}\n cta={cta}\n isLoading={chin.isLoading}\n />\n </CardShell>\n </BubbleTail>\n )\n}\n\nexport default SentCard\n","import ComposerCard, {\n type ComposerCardProps,\n} from './components/Composer/Card'\nimport ReceivedCard, {\n type ReceivedCardProps,\n} from './components/Received/Card'\nimport SentCard, { type SentCardProps } from './components/Sent/Card'\n\n/**\n * Link previews (1P / 3P Link Apps) shown in the chat thread. Mirrors\n * the `LockedAttachment` API — render `LinkAttachment.Composer` while\n * drafting, `LinkAttachment.Sent` after posting, and\n * `LinkAttachment.Received` in the recipient's thread. Maps to the\n * \"LinkApps\" section of the messaging design system.\n *\n * Two visual layouts via the `layout` prop:\n * - **Featured** (default) — a hero thumbnail filling the card above the\n * chin, inside a fixed 290x250 box. Used by hero-image LinkApps\n * (Spotify with cover art, TikTok with a frame, etc.) and by link\n * previews carrying OG imagery.\n * - **Classic** — compact card with no hero thumbnail; title /\n * description / URL / CTA only, sized to its content. Used for LinkApp\n * embeds without artwork (FAQ, Form) and any link preview that lacks\n * OG imagery.\n *\n * Pass `accentColor` (a hex extracted from the thumbnail) to paint the card\n * and its bubble tail; the card derives its own WCAG AA text colour.\n *\n * For chat **document / image / video / audio attachments**, reach for\n * `MessageAttachment.{Image,Video,Audio,Pdf,File}` instead — those\n * render as bubbles with built-in viewers (zoom-capable image\n * lightbox, native PDF viewer, video / audio with download) and a\n * caption slot for accompanying text.\n */\nconst LinkAttachment = {\n Composer: ComposerCard,\n Sent: SentCard,\n Received: ReceivedCard,\n}\n\nexport default LinkAttachment\nexport type { ComposerCardProps, SentCardProps, ReceivedCardProps }\nexport type {\n LinkAttachmentBaseProps,\n LinkAttachmentCta,\n LinkAttachmentLayout,\n LinkAttachmentStatus,\n} from './types'\n","import React from 'react'\nimport type { Attachment, LocalMessage } from 'stream-chat'\nimport {\n MessageErrorIcon,\n MessageText,\n type MessageContextValue,\n} from 'stream-chat-react'\n\nimport { optimizeMessagingAttachmentUrl } from '../../utils/cdnImageUrl'\nimport LinkAttachment from '../LinkAttachment'\nimport { isPlayableMedia } from '../LinkAttachment/components/_shared/CardThumbnail'\nimport MessageAttachment from '../MessageAttachment'\nimport type { BubbleGroupPosition } from '../MessageAttachment/types'\n\ntype StreamMediaKind = 'image' | 'video' | 'audio' | 'pdf' | 'file'\n\nexport type AttachmentSegment =\n | { type: 'link'; attachments: Attachment[] }\n | { type: 'media'; kind: StreamMediaKind; attachments: Attachment[] }\n\nfunction trimToUndefined(value?: string | null): string | undefined {\n const trimmed = value?.trim()\n return trimmed ? trimmed : undefined\n}\n\nexport function normalizeLinkUrl(url: string): string {\n return url\n .trim()\n .replace(/^https?:\\/\\//i, '')\n .replace(/\\/+$/, '')\n .toLowerCase()\n}\n\nexport function linkCaptionDuplicatesAttachmentUrl(\n caption: string | undefined,\n attachmentUrl?: string\n): boolean {\n if (!caption?.trim() || !attachmentUrl?.trim()) {\n return false\n }\n\n const normalizedCaption = normalizeLinkUrl(caption)\n const normalizedUrl = normalizeLinkUrl(attachmentUrl)\n\n if (normalizedCaption === normalizedUrl) {\n return true\n }\n\n if (!normalizedCaption.includes(normalizedUrl)) {\n return false\n }\n\n const remainder = normalizedCaption.split(normalizedUrl).join('')\n return !/[^\\p{P}\\p{Z}\\p{C}]/u.test(remainder)\n}\n\nexport function linkCardPropsFromStreamAttachment(a: Attachment) {\n const url = trimToUndefined(a.og_scrape_url) ?? trimToUndefined(a.title_link)\n const thumbnailUrl =\n trimToUndefined((a as { image_url?: string }).image_url) ??\n trimToUndefined((a as { thumb_url?: string }).thumb_url)\n const sourceUrl = trimToUndefined(a.asset_url)\n const mimeType = trimToUndefined(a.mime_type)\n\n return {\n title: trimToUndefined((a as { title?: string }).title),\n description: trimToUndefined((a as { text?: string }).text),\n url,\n thumbnailUrl: optimizeMessagingAttachmentUrl(thumbnailUrl),\n // Playable clip embedded in a link preview — lets LinkAttachment render its\n // native video/audio player in the hero instead of a static thumbnail.\n sourceUrl,\n layout:\n thumbnailUrl || isPlayableMedia(mimeType, sourceUrl)\n ? 'featured'\n : 'classic',\n mimeType,\n // Dominant colour of the image, resolved by the sender at stage time and\n // persisted on the attachment (`stream-custom-data.ts`), so every viewer\n // paints an identical chin without re-extracting — visitors in\n // linktr.ee-profiles cannot call the extraction query at all. Absent on\n // messages sent before MES-1349, which render the fallback chin.\n accentColor: trimToUndefined(a.accent_color),\n // A persisted attachment is by definition fully scraped.\n status: 'ready',\n } as const\n}\n\nexport function getAttachmentMediaKind(\n attachment: Attachment\n): StreamMediaKind | null {\n if (isLinkAttachment(attachment)) return null\n\n if (attachment.type === 'image') {\n const imageUrl = (attachment as { image_url?: string }).image_url\n if (imageUrl || attachment.asset_url) return 'image'\n return null\n }\n\n if (attachment.type === 'video' && attachment.asset_url) return 'video'\n if (attachment.type === 'audio' && attachment.asset_url) return 'audio'\n\n if (attachment.type === 'file' && attachment.asset_url) {\n if (attachment.mime_type === 'application/pdf') return 'pdf'\n if (attachment.mime_type?.startsWith('audio/')) return 'audio'\n return 'file'\n }\n\n return null\n}\n\nexport function isLinkAttachment(a: Attachment): boolean {\n const ogScrapeUrl = trimToUndefined(a.og_scrape_url)\n return a.type === 'link' || (!!ogScrapeUrl && !a.asset_url)\n}\n\nexport function buildOrderedAttachmentSegments(\n attachments: Attachment[] | undefined\n): AttachmentSegment[] {\n if (!attachments?.length) return []\n\n const segments: AttachmentSegment[] = []\n\n const pushOrMergeMedia = (kind: StreamMediaKind, attachment: Attachment) => {\n const last = segments[segments.length - 1]\n if (last?.type === 'media' && last.kind === kind) {\n last.attachments.push(attachment)\n return\n }\n\n segments.push({ type: 'media', kind, attachments: [attachment] })\n }\n\n const pushOrMergeLink = (attachment: Attachment) => {\n const last = segments[segments.length - 1]\n if (last?.type === 'link') {\n last.attachments.push(attachment)\n return\n }\n\n segments.push({ type: 'link', attachments: [attachment] })\n }\n\n for (const attachment of attachments) {\n if (isLinkAttachment(attachment)) {\n pushOrMergeLink(attachment)\n continue\n }\n\n const kind = getAttachmentMediaKind(attachment)\n if (!kind) continue\n\n pushOrMergeMedia(kind, attachment)\n }\n\n return segments\n}\n\nexport function countMediaSegmentBubbles(\n segments: AttachmentSegment[]\n): number {\n return segments.filter((segment) => segment.type === 'media').length\n}\n\nexport function bubblePositionInRun(\n index: number,\n total: number,\n streamPosition: BubbleGroupPosition\n): BubbleGroupPosition {\n if (total <= 1) return streamPosition\n if (index === 0) return 'first'\n if (index === total - 1) return 'end'\n return 'middle'\n}\n\nfunction imageSrcFromAttachment(attachment: Attachment): string {\n return (\n trimToUndefined((attachment as { image_url?: string }).image_url) ??\n trimToUndefined(attachment.asset_url) ??\n ''\n )\n}\n\nfunction messageAttachmentNamespaceForKind(kind: StreamMediaKind) {\n switch (kind) {\n case 'image':\n return MessageAttachment.Image\n case 'video':\n return MessageAttachment.Video\n case 'audio':\n return MessageAttachment.Audio\n case 'pdf':\n return MessageAttachment.Pdf\n default:\n return MessageAttachment.File\n }\n}\n\nfunction buildMediaClusterRenderProps(\n kind: StreamMediaKind,\n attachments: Attachment[]\n): Record<string, unknown> {\n if (attachments.length > 1) {\n switch (kind) {\n case 'image':\n return {\n items: attachments.map((attachment) => ({\n src: imageSrcFromAttachment(attachment),\n alt: trimToUndefined((attachment as { title?: string }).title),\n })),\n }\n case 'video':\n return {\n items: attachments.map((attachment) => ({\n src: trimToUndefined(attachment.asset_url) ?? '',\n poster: trimToUndefined(\n (attachment as { thumb_url?: string }).thumb_url\n ),\n mimeType: trimToUndefined(attachment.mime_type),\n })),\n }\n case 'audio':\n return {\n items: attachments.map((attachment) => ({\n src: trimToUndefined(attachment.asset_url) ?? '',\n mimeType: trimToUndefined(attachment.mime_type) ?? 'audio/mpeg',\n filename: trimToUndefined((attachment as { title?: string }).title),\n })),\n }\n case 'pdf':\n return {\n items: attachments.map((attachment) => ({\n src: trimToUndefined(attachment.asset_url) ?? '',\n filename: trimToUndefined((attachment as { title?: string }).title),\n fileSize: (attachment as { file_size?: number }).file_size,\n })),\n }\n case 'file':\n return {\n items: attachments.map((attachment) => ({\n src: trimToUndefined(attachment.asset_url) ?? '',\n filename: trimToUndefined((attachment as { title?: string }).title),\n fileSize: (attachment as { file_size?: number }).file_size,\n mimeType:\n trimToUndefined(attachment.mime_type) ??\n 'application/octet-stream',\n })),\n }\n }\n }\n\n const attachment = attachments[0]\n if (!attachment) return {}\n\n switch (kind) {\n case 'image':\n return {\n src: imageSrcFromAttachment(attachment),\n alt: trimToUndefined((attachment as { title?: string }).title),\n }\n case 'video':\n return {\n src: trimToUndefined(attachment.asset_url) ?? '',\n poster: trimToUndefined(\n (attachment as { thumb_url?: string }).thumb_url\n ),\n mimeType: trimToUndefined(attachment.mime_type),\n }\n case 'audio':\n return {\n src: trimToUndefined(attachment.asset_url) ?? '',\n mimeType: trimToUndefined(attachment.mime_type) ?? 'audio/mpeg',\n filename: trimToUndefined((attachment as { title?: string }).title),\n }\n case 'pdf':\n return {\n src: trimToUndefined(attachment.asset_url) ?? '',\n filename: trimToUndefined((attachment as { title?: string }).title),\n fileSize: (attachment as { file_size?: number }).file_size,\n }\n case 'file':\n return {\n src: trimToUndefined(attachment.asset_url) ?? '',\n filename: trimToUndefined((attachment as { title?: string }).title),\n fileSize: (attachment as { file_size?: number }).file_size,\n mimeType:\n trimToUndefined(attachment.mime_type) ?? 'application/octet-stream',\n }\n }\n}\n\nfunction MediaClusterBubble({\n groupPosition,\n isMyMessage,\n segment,\n}: {\n groupPosition: BubbleGroupPosition\n isMyMessage: boolean\n segment: Extract<AttachmentSegment, { type: 'media' }>\n}) {\n const TypeNamespace = messageAttachmentNamespaceForKind(segment.kind)\n const props = {\n ...buildMediaClusterRenderProps(segment.kind, segment.attachments),\n groupPosition,\n }\n\n if (isMyMessage) {\n return <TypeNamespace.Sent {...props} />\n }\n\n return <TypeNamespace.Received {...props} />\n}\n\nexport interface StreamAttachmentMessageProps {\n groupPosition: BubbleGroupPosition\n isMyMessage: boolean\n message: LocalMessage\n renderText?: MessageContextValue['renderText']\n}\n\nconst StreamAttachmentMessage: React.FC<StreamAttachmentMessageProps> = ({\n groupPosition,\n isMyMessage,\n message,\n renderText,\n}) => {\n const segments = buildOrderedAttachmentSegments(message.attachments)\n if (segments.length === 0) return null\n\n const totalMediaBubbles = countMediaSegmentBubbles(segments)\n const rawCaption = message.text?.trim()\n const linkSegment = segments.find((segment) => segment.type === 'link')\n const primaryLinkUrl =\n linkSegment?.type === 'link'\n ? linkCardPropsFromStreamAttachment(linkSegment.attachments[0] ?? {}).url\n : undefined\n const caption =\n rawCaption && linkCaptionDuplicatesAttachmentUrl(rawCaption, primaryLinkUrl)\n ? undefined\n : rawCaption\n\n let mediaBubbleIndex = 0\n const rows: React.ReactNode[] = []\n\n // A link card paints its own accent-coloured tail only when it is the very\n // last thing this message renders. A caption bubble follows when there is\n // one, and that bubble already owns the tail via `styles.css`; and a message\n // mid-run has its tail on a later message. Anything else is a mid-run card,\n // which must stay tail-less.\n const linkTailPosition: BubbleGroupPosition = caption\n ? 'middle'\n : groupPosition\n\n const pushLinkRow = (\n attachment: Attachment,\n key: string,\n isFinalRow: boolean\n ) => {\n const Card = isMyMessage ? LinkAttachment.Sent : LinkAttachment.Received\n\n rows.push(\n <Card\n key={key}\n {...linkCardPropsFromStreamAttachment(attachment)}\n groupPosition={isFinalRow ? linkTailPosition : 'middle'}\n />\n )\n }\n\n const pushMediaCluster = (\n segment: Extract<AttachmentSegment, { type: 'media' }>,\n key: string\n ) => {\n const position = bubblePositionInRun(\n mediaBubbleIndex,\n totalMediaBubbles,\n groupPosition\n )\n\n mediaBubbleIndex += 1\n\n rows.push(\n <MediaClusterBubble\n key={key}\n groupPosition={position}\n isMyMessage={isMyMessage}\n segment={segment}\n />\n )\n }\n\n segments.forEach((segment, segmentIndex) => {\n const isFinalSegment = segmentIndex === segments.length - 1\n\n if (segment.type === 'link') {\n segment.attachments.forEach((attachment, attachmentIndex) => {\n pushLinkRow(\n attachment,\n `link-${segmentIndex}-${attachmentIndex}`,\n isFinalSegment && attachmentIndex === segment.attachments.length - 1\n )\n })\n return\n }\n\n pushMediaCluster(segment, `media-${segmentIndex}`)\n })\n\n return (\n <div className=\"str-chat__message-bubble-wrapper\">\n <div\n className=\"str-chat__message-bubble\"\n data-attachment-bubble=\"true\"\n style={{\n background: 'transparent',\n borderRadius: 0,\n overflow: 'visible',\n padding: 0,\n }}\n >\n {rows}\n {!caption && <MessageErrorIcon />}\n </div>\n {caption ? (\n <div className=\"str-chat__message-bubble\">\n <MessageText message={message} renderText={renderText} />\n <MessageErrorIcon />\n </div>\n ) : null}\n </div>\n )\n}\n\nexport default StreamAttachmentMessage\n","import classNames from 'classnames'\nimport React, { useContext, useMemo, useState } from 'react'\nimport {\n Attachment as DefaultAttachment,\n EditMessageModal as DefaultEditMessageModal,\n MessageBounceModal,\n MessageBouncePrompt as DefaultMessageBouncePrompt,\n MessageBlocked as DefaultMessageBlocked,\n MessageDeleted as DefaultMessageDeleted,\n MessageErrorIcon,\n MessageIsThreadReplyInChannelButtonIndicator as DefaultMessageIsThreadReplyInChannelButtonIndicator,\n MessageRepliesCountButton as DefaultMessageRepliesCountButton,\n MessageText,\n Poll,\n ReminderNotification as DefaultReminderNotification,\n StreamedMessageText as DefaultStreamedMessageText,\n areMessageUIPropsEqual,\n isDateSeparatorMessage,\n isMessageBlocked,\n isMessageBounced,\n messageHasAttachments,\n messageHasReactions,\n useChannelStateContext,\n useComponentContext,\n useChatContext,\n useMessageContext,\n useMessageReminder,\n type MessageContextValue,\n type MessageUIComponentProps,\n} from 'stream-chat-react'\n\nimport { useMessageVote } from '../../hooks/useMessageVote'\nimport { getMessageDisplayText } from '../../utils/getMessageDisplayText'\nimport { Avatar } from '../Avatar'\nimport { isLinkAttachment } from '../MediaMessage'\nimport { bubbleGroupPositionFromStream as messageAttachmentGroupPositionFromStream } from '../MessageAttachment'\n\nimport { BroadcastNameContext } from './BroadcastNameContext'\nimport { useCustomMessage } from './context'\nimport LockedAttachment from './LockedAttachment'\nimport {\n MessageTag,\n isAttachmentMessage,\n isChatbotMessage,\n isMediaAttachmentMessage,\n isTextAttachmentMessage,\n isTipOnlyMessage,\n} from './MessageTag'\nimport { MessageVoteButtons } from './MessageVoteButtons'\nimport { SentMessageDeliveryStatus } from './SentMessageDeliveryStatus'\nimport StreamAttachmentMessage, {\n buildOrderedAttachmentSegments,\n} from './StreamAttachmentMessage'\n\ntype CustomMessageUIComponentProps = MessageUIComponentProps & {\n chatbotVotingEnabled?: boolean\n viewerLanguage?: string\n onBroadcastClick?: (broadcast: { id: string; name?: string }) => void\n}\n\ntype CustomMessageWithContextProps = MessageContextValue & {\n chatbotVotingEnabled?: boolean\n viewerLanguage?: string\n onBroadcastClick?: (broadcast: { id: string; name?: string }) => void\n resolvedBroadcastName?: string\n}\n\nconst CustomMessageWithContext = (props: CustomMessageWithContextProps) => {\n const {\n additionalMessageInputProps,\n chatbotVotingEnabled,\n editing,\n endOfGroup,\n firstOfGroup,\n groupedByUser,\n handleAction,\n handleOpenThread,\n handleRetry,\n highlighted,\n isMessageAIGenerated,\n isMyMessage,\n message,\n renderText,\n threadList,\n viewerLanguage,\n onBroadcastClick,\n resolvedBroadcastName,\n } = props\n\n const { client } = useChatContext('CustomMessage')\n const { channel } = useChannelStateContext('CustomMessage')\n const { isUnlocking, onUnlockClick, onFetchSource, onDownloadClick } =\n useCustomMessage('LockedAttachment')\n const [isBounceDialogOpen, setIsBounceDialogOpen] = useState(false)\n const reminder = useMessageReminder(message.id)\n const { selected: voteState, voteUp, voteDown } = useMessageVote(message)\n\n const {\n Attachment = DefaultAttachment,\n EditMessageModal = DefaultEditMessageModal,\n MessageActions,\n MessageBlocked = DefaultMessageBlocked,\n MessageBouncePrompt = DefaultMessageBouncePrompt,\n MessageDeleted = DefaultMessageDeleted,\n MessageIsThreadReplyInChannelButtonIndicator = DefaultMessageIsThreadReplyInChannelButtonIndicator,\n MessageRepliesCountButton = DefaultMessageRepliesCountButton,\n ReminderNotification = DefaultReminderNotification,\n StreamedMessageText = DefaultStreamedMessageText,\n PinIndicator,\n } = useComponentContext('CustomMessage')\n\n const hasAttachment = messageHasAttachments(message)\n const hasReactions = messageHasReactions(message)\n const isAIGenerated = useMemo(\n () => isMessageAIGenerated?.(message),\n [isMessageAIGenerated, message]\n )\n const finalAttachments = useMemo(() => {\n const attachments = message.attachments ?? []\n const raw = message.shared_location\n ? [message.shared_location, ...attachments]\n : attachments\n\n if (!isChatbotMessage(message)) return raw\n\n const filtered = raw.filter((a) => !('type' in a) || !isLinkAttachment(a))\n return filtered.length === raw.length ? raw : filtered\n }, [message])\n const attachmentSegments = useMemo(\n () => buildOrderedAttachmentSegments(finalAttachments),\n [finalAttachments]\n )\n const displayMessage = useMemo(() => {\n const displayText = getMessageDisplayText({ message, viewerLanguage })\n return displayText === message.text\n ? message\n : { ...message, text: displayText }\n }, [message, viewerLanguage])\n // Route every generic Stream-attachment message (link OG previews and\n // image/video/audio/pdf/file media) through the toolkit renderer, so\n // messaging-react owns all shared attachment rendering rather than leaving\n // media on stream-chat-react's default Attachment. App-specific types\n // (locked/paid, tips, chatbot) are handled by the branches above.\n const hasAttachmentSegments = attachmentSegments.length > 0\n // Only own the message when every attachment maps to a representable segment.\n // Otherwise a mixed message (e.g. an unsupported shared_location alongside a\n // photo) would silently drop the unrepresented attachment — those fall\n // through to the default `Attachment` renderer, which handles all of them.\n const allAttachmentsRepresented =\n attachmentSegments.reduce(\n (total, segment) => total + segment.attachments.length,\n 0\n ) === (finalAttachments?.length ?? 0)\n const streamAttachmentGroupPosition =\n messageAttachmentGroupPositionFromStream({\n endOfGroup,\n firstOfGroup,\n groupedByUser,\n })\n\n if (isDateSeparatorMessage(message)) {\n return null\n }\n\n if (message.deleted_at || message.type === 'deleted') {\n return <MessageDeleted message={message} />\n }\n\n if (isMessageBlocked(message)) {\n return <MessageBlocked />\n }\n\n const showReplyCountButton = !threadList && !!message.reply_count\n const showIsReplyInChannel =\n !threadList && message.show_in_channel && message.parent_id\n const allowRetry =\n message.status === 'failed' && message.error?.status !== 403\n const isBounced = isMessageBounced(message)\n let handleClick: (() => void) | undefined = undefined\n\n if (allowRetry) {\n handleClick = () => handleRetry(message)\n } else if (isBounced) {\n handleClick = () => setIsBounceDialogOpen(true)\n }\n\n const isMine = isMyMessage()\n const rootClassName = classNames(\n 'str-chat__message str-chat__message-simple',\n `str-chat__message--${message.type}`,\n `str-chat__message--${message.status}`,\n isMine\n ? 'str-chat__message--me str-chat__message-simple--me'\n : 'str-chat__message--other',\n message.text ? 'str-chat__message--has-text' : 'has-no-text',\n {\n 'str-chat__message--has-attachment': hasAttachment,\n 'str-chat__message--highlighted': highlighted,\n 'str-chat__message--pinned pinned-message': message.pinned,\n 'str-chat__message--with-reactions': hasReactions,\n 'str-chat__message-send-can-be-retried':\n message?.status === 'failed' && message?.error?.status !== 403,\n 'str-chat__message-with-thread-link':\n showReplyCountButton || showIsReplyInChannel,\n 'str-chat__virtual-message__wrapper--end': endOfGroup,\n 'str-chat__virtual-message__wrapper--first': firstOfGroup,\n 'str-chat__virtual-message__wrapper--group': groupedByUser,\n }\n )\n\n const poll = message.poll_id && client.polls.fromState(message.poll_id)\n const isTipOnly = isTipOnlyMessage(message)\n const isChatbot = isChatbotMessage(message)\n const isAttachment = isAttachmentMessage(message)\n const hasRenderableAttachments = !!(\n finalAttachments?.length && !message.quoted_message\n )\n const useAttachmentFooterChatbotTag =\n isChatbot && isMine && hasRenderableAttachments\n // Route generic Stream attachments through the toolkit renderer only when it\n // can faithfully own the whole message. Quoted replies (attachments are\n // suppressed there), polls, AI-streamed, and chatbot messages fall through to\n // the default branch so their Poll / StreamedMessageText / message-text and\n // chatbot attribution (MessageTag) handling is preserved — the accompanying\n // message text and attribution must never be dropped.\n const canRenderAttachmentsInToolkit =\n hasAttachmentSegments &&\n allAttachmentsRepresented &&\n !message.quoted_message &&\n !poll &&\n !isAIGenerated &&\n !isChatbot\n\n const sharedLockedTextProps = {\n contentType: 'text' as const,\n amountText: message.metadata?.amount_text,\n paymentStatus: message.metadata?.payment_status,\n renderedText: message.text && (\n <MessageText message={displayMessage} renderText={renderText} />\n ),\n }\n const sharedLockedMediaProps = {\n contentType: 'media' as const,\n title: message.metadata?.attachment_title,\n mimeType: message.metadata?.attachment_mime_type,\n thumbnailUrl: message.metadata?.attachment_thumbnail,\n amountText: message.metadata?.amount_text,\n detail: message.metadata?.attachment_detail,\n paymentStatus: message.metadata?.payment_status,\n onFetchSource: onFetchSource\n ? () => onFetchSource(message, channel)\n : undefined,\n }\n return (\n <>\n {editing && (\n <EditMessageModal\n additionalMessageInputProps={additionalMessageInputProps}\n />\n )}\n {isBounceDialogOpen && (\n <MessageBounceModal\n MessageBouncePrompt={MessageBouncePrompt}\n onClose={() => setIsBounceDialogOpen(false)}\n open={isBounceDialogOpen}\n />\n )}\n <div\n className={rootClassName}\n key={message.id}\n data-message-id={message.id}\n data-dd-privacy=\"mask\"\n >\n {PinIndicator && <PinIndicator />}\n {!!reminder && <ReminderNotification reminder={reminder} />}\n {message.user && (\n <Avatar\n className=\"str-chat__avatar str-chat__message-sender-avatar\"\n id={message.user.id}\n image={message.user.image}\n name={message.user.name || message.user.id}\n size={24}\n shape=\"circle\"\n dmAgentEnabled={isChatbot}\n />\n )}\n <div\n className={classNames('str-chat__message-inner', {\n 'str-chat__simple-message--error-failed': allowRetry || isBounced,\n })}\n data-testid=\"message-inner\"\n onClick={handleClick}\n onKeyDown={handleClick}\n role={handleClick ? 'button' : undefined}\n tabIndex={handleClick ? 0 : undefined}\n style={{\n // Force margins to 0 to prevent hover layout shift\n // Stream Chat CSS sets margin-inline-end/start to 78px, then 0 on hover\n marginInlineEnd: 0,\n marginInlineStart: 0,\n }}\n >\n {isTipOnly ? (\n <MessageTag message={message} standalone />\n ) : isTextAttachmentMessage(message) ? (\n <div className=\"str-chat__message-bubble-wrapper\">\n <div className=\"flex items-center gap-2\">\n {isMine && MessageActions && <MessageActions />}\n {isMine ? (\n <LockedAttachment\n {...sharedLockedTextProps}\n isMine={true}\n />\n ) : (\n <LockedAttachment\n {...sharedLockedTextProps}\n isMine={false}\n isUnlocking={isUnlocking(message.id)}\n onUnlockClick={() => onUnlockClick?.(message, channel)}\n />\n )}\n {!isMine && MessageActions && <MessageActions />}\n </div>\n </div>\n ) : isMediaAttachmentMessage(message) ? (\n <div className=\"str-chat__message-bubble-wrapper\">\n <div className=\"flex items-center gap-2\">\n {isMine && MessageActions && <MessageActions />}\n {isMine ? (\n <LockedAttachment\n {...sharedLockedMediaProps}\n isMine={true}\n onPreviewClick={() =>\n onUnlockClick\n ? onUnlockClick(message, channel)\n : undefined\n }\n />\n ) : (\n <LockedAttachment\n {...sharedLockedMediaProps}\n isMine={false}\n isUnlocking={isUnlocking(message.id)}\n onUnlockClick={() =>\n onUnlockClick\n ? onUnlockClick(message, channel)\n : undefined\n }\n onDownloadClick={() =>\n onDownloadClick\n ? onDownloadClick(message, channel)\n : undefined\n }\n />\n )}\n {!isMine && MessageActions && <MessageActions />}\n </div>\n {message.text && (\n <div className=\"str-chat__message-bubble\">\n <MessageText\n message={displayMessage}\n renderText={renderText}\n />\n </div>\n )}\n </div>\n ) : canRenderAttachmentsInToolkit ? (\n <StreamAttachmentMessage\n groupPosition={streamAttachmentGroupPosition}\n isMyMessage={isMine}\n message={{\n ...displayMessage,\n attachments: finalAttachments,\n // MessageText prefers message.i18n[userLanguage_text] from\n // Stream's TranslationContext over message.text. Drop i18n so\n // the caption uses displayMessage.text from viewerLanguage.\n i18n: undefined,\n }}\n renderText={renderText}\n />\n ) : (\n <div className=\"str-chat__message-bubble-wrapper\">\n <div className=\"str-chat__message-bubble\">\n {isChatbot && !useAttachmentFooterChatbotTag && (\n <MessageTag\n message={message}\n hasAttachment={hasRenderableAttachments}\n isMyMessage={isMine}\n />\n )}\n {poll && <Poll poll={poll} />}\n {finalAttachments?.length && !message.quoted_message ? (\n <Attachment\n actionHandler={handleAction}\n attachments={finalAttachments}\n />\n ) : null}\n {isAIGenerated ? (\n <StreamedMessageText\n message={displayMessage}\n renderText={renderText}\n />\n ) : (\n <MessageText\n message={displayMessage}\n renderText={renderText}\n />\n )}\n <MessageErrorIcon />\n </div>\n </div>\n )}\n </div>\n {!isAttachment && !isTipOnly && (\n <div className=\"str-chat__message-footer\">\n {(!isChatbot || useAttachmentFooterChatbotTag) && (\n <MessageTag\n message={message}\n hasAttachment={hasRenderableAttachments}\n isMyMessage={isMine}\n />\n )}\n {chatbotVotingEnabled && isChatbot && (\n <MessageVoteButtons\n selected={voteState}\n onVoteUp={voteUp}\n onVoteDown={voteDown}\n />\n )}\n </div>\n )}\n <SentMessageDeliveryStatus\n onBroadcastClick={onBroadcastClick}\n resolvedBroadcastName={resolvedBroadcastName}\n />\n {showReplyCountButton && (\n <MessageRepliesCountButton\n onClick={handleOpenThread}\n reply_count={message.reply_count}\n />\n )}\n {showIsReplyInChannel && (\n <MessageIsThreadReplyInChannelButtonIndicator />\n )}\n </div>\n </>\n )\n}\n\nconst MemoizedCustomMessage = React.memo(\n CustomMessageWithContext,\n (prev, next) => {\n if (prev.chatbotVotingEnabled !== next.chatbotVotingEnabled) return false\n if (prev.viewerLanguage !== next.viewerLanguage) return false\n if (prev.onBroadcastClick !== next.onBroadcastClick) return false\n if (prev.resolvedBroadcastName !== next.resolvedBroadcastName) return false\n return areMessageUIPropsEqual(prev, next)\n }\n) as typeof CustomMessageWithContext\n\nexport const CustomMessage = (props: CustomMessageUIComponentProps) => {\n const messageContext = useMessageContext('CustomMessage')\n const broadcastNamesById = useContext(BroadcastNameContext)\n const broadcastId = messageContext.message.metadata?.broadcast_id\n const resolvedBroadcastName =\n typeof broadcastId === 'string'\n ? broadcastNamesById?.[broadcastId]\n : undefined\n\n return (\n <MemoizedCustomMessage\n {...messageContext}\n {...props}\n resolvedBroadcastName={resolvedBroadcastName}\n />\n )\n}\n","import { MESSAGE_CUSTOM_TYPE } from '@linktr.ee/messaging-taxonomy'\nimport { FlagIcon, TrashSimpleIcon } from '@phosphor-icons/react'\nimport React from 'react'\nimport { useMessageContext } from 'stream-chat-react'\nimport {\n DefaultDropdownActionButton,\n MessageActions,\n} from 'stream-chat-react/experimental'\n\nconst DeleteAction = () => {\n const { handleDelete, message } = useMessageContext('CustomMessageActions')\n if (message.metadata?.payment_status === 'paid') return null\n return (\n <DefaultDropdownActionButton\n onClick={handleDelete}\n aria-label=\"Delete\"\n title=\"Delete\"\n className=\"bg-marble rounded-full p-2 hover:bg-sand transition-all\"\n >\n <TrashSimpleIcon size={16} weight=\"light\" aria-hidden />\n </DefaultDropdownActionButton>\n )\n}\n\nconst ReportAction = () => {\n const { handleFlag } = useMessageContext('CustomMessageActions')\n return (\n <DefaultDropdownActionButton\n onClick={handleFlag}\n aria-label=\"Report\"\n title=\"Report\"\n className=\"bg-marble rounded-full p-2 hover:bg-sand transition-all\"\n >\n <FlagIcon size={16} weight=\"light\" aria-hidden />\n </DefaultDropdownActionButton>\n )\n}\n\nexport const CustomMessageActions = () => {\n const { message } = useMessageContext('CustomMessageActions')\n if (message.metadata?.custom_type !== MESSAGE_CUSTOM_TYPE.ATTACHMENT)\n return null\n return (\n <MessageActions\n messageActionSet={[\n { Component: DeleteAction, placement: 'quick', type: 'delete' },\n { Component: ReportAction, placement: 'quick', type: 'flag' },\n ]}\n />\n )\n}\n","import React from 'react'\nimport { LinkPreviewsManager, LinkPreviewsManagerState } from 'stream-chat'\nimport { useMessageComposer, useStateStore } from 'stream-chat-react'\n\nimport LinkAttachment from '../LinkAttachment'\n\nconst linkPreviewsManagerStateSelector = (state: LinkPreviewsManagerState) => ({\n linkPreviews: Array.from(state.previews.values()).filter(\n (preview) =>\n LinkPreviewsManager.previewIsLoaded(preview) ||\n LinkPreviewsManager.previewIsLoading(preview)\n ),\n})\n\n/**\n * The composer's staged link previews, rendered as `LinkAttachment.Composer`\n * cards.\n *\n * **The cards are deliberately dismiss-only — they do not navigate.**\n * `LinkAttachment.Composer` is the one card variant whose shell is never an\n * anchor or a button, and the hand-rolled card this replaced wrapped its whole\n * body in `<a href={og_scrape_url} target=\"_blank\">` with the dismiss button\n * calling `preventDefault()` inside it. That shape is a touch hazard —\n * MES-1358 §7 Q7 raised it and deferred the call to MES-1349 — because a\n * mis-tap while composing opens a new tab mid-draft, and the dismiss button's\n * 44px hit halo (`Composer/Card.tsx`, `before:-inset-[10px]`) sits *inside*\n * that anchor, so enlarging the target for touch enlarges the navigation\n * trigger with it. A staged preview is a draft affordance rather than\n * content — its URL is still in the textarea the author just typed it into,\n * one tap away without leaving the thread.\n *\n * Nothing depended on the old behaviour: no test, story or analytics asserted\n * it here or in frontyard's parallel `ComposerLinkPreviewList`, whose own\n * tests cover text, dismiss and layout only. If a surface ever genuinely needs\n * activation, add an explicit prop to `ComposerCardProps` — do not re-wrap the\n * card in an anchor. (MES-1349)\n */\nexport const CustomLinkPreviewList = () => {\n const { linkPreviewsManager } = useMessageComposer()\n\n const { linkPreviews: stateLinkPreviews } = useStateStore(\n linkPreviewsManager.state,\n linkPreviewsManagerStateSelector\n )\n\n const handleDismiss = (url: string) => {\n linkPreviewsManager.dismissPreview(url)\n }\n\n const showLinkPreviews = stateLinkPreviews.length > 0\n\n if (!showLinkPreviews) return null\n\n return (\n // Layout contract: this list is the composer's *shrinkable* region. The\n // mobile visitor surface sizes itself to the keyboard-shrunk\n // visualViewport, so when vertical space runs out this container gives\n // way (min-h-0) and scrolls, while the textarea + send row stays visible\n // (shrink-0 in CustomMessageInput). Each card is wrapped in a shrink-0\n // block so it keeps its intrinsic height and the container scrolls — a\n // bare flex-column child would be shrunk on the column axis and its\n // fixed-height hero would spill out of the collapsed card box.\n //\n // Horizontally the card does NOT shrink, deliberately. `CardShell` bakes\n // Figma's `w-[290px]` and there is exactly one width, in the toolkit\n // (MES-1349 and MES-1358 agreed consumers add no competing cap). Do not\n // \"fix\" a narrow viewport with `max-w-full` here or on the shell: the box is\n // `flex h-[250px] flex-col` with a `flex-1` hero and a title clamped to two\n // lines against a known width, so capping deforms it on every narrow\n // surface, in-thread Sent/Received included.\n //\n // Measured against the real class chain in headless Chromium:\n //\n // chrome = 32px (`CustomMessageInput`'s outer `p-4`)\n // + 16px (this region's `px-2`) = 48px\n // card = 290px -> floor = 290 + 48 = 338px viewport\n //\n // viewport 320 360 375 393 430\n // available 272 312 327 345 382\n // delta -18 +22 +37 +55 +92\n //\n // 393px is the design frame, and its 345px reproduces the frame's measured\n // `attachment-area` width, so the chrome arithmetic is corroborated. The\n // lowest named breakpoint is `xs: 359px`\n // (`@repo/tailwind-config/transitional-tokens.js:29-36`), which is *above*\n // the 338px floor — the card fits at every width the scale names. MES-1358's\n // `max-md:p-3` trims chrome 48px -> 40px and moves the floor to 330px, still\n // above 320px, so capping `CardShell` would be the only way to reach a 320px\n // viewport. That is the whole trade: deform every narrow surface, or leave\n // one sub-floor device class awkward.\n //\n // It is awkward, not broken. Setting only `overflow-y` promotes the other\n // axis, so `overflow-x` computes to `auto` and the region scrolls sideways\n // instead of spilling; at 320px the dismiss button's right edge lands ~6px\n // past the fold, reachable by scrolling. That residue belongs to whoever\n // owns the mobile layout contract, not to this component.\n <div className=\"messaging-link-preview-list flex min-h-0 flex-col items-stretch w-full gap-2 overflow-y-auto overscroll-contain\">\n {stateLinkPreviews.map((linkPreview) => {\n // A LOADING preview has no `image_url` yet, so keying the layout off\n // the image alone rendered the skeleton as two bare text bars and then\n // snapped it open to the 250px featured box the instant the scrape\n // returned. Hold the hero's space for the duration instead — reserving\n // that space is what the skeleton is for.\n const isLoading = LinkPreviewsManager.previewIsLoading(linkPreview)\n\n return (\n <div key={linkPreview.og_scrape_url} className=\"w-full shrink-0\">\n <LinkAttachment.Composer\n title={linkPreview.title}\n url={linkPreview.og_scrape_url}\n thumbnailUrl={linkPreview.image_url}\n layout={\n isLoading || linkPreview.image_url ? 'featured' : 'classic'\n }\n status={isLoading ? 'loading' : 'ready'}\n onDismiss={() => handleDismiss(linkPreview.og_scrape_url)}\n />\n </div>\n )\n })}\n </div>\n )\n}\n","import { ArrowUpIcon } from '@phosphor-icons/react'\nimport React, { useContext } from 'react'\nimport {\n AttachmentPreviewList as DefaultAttachmentPreviewList,\n MessageInput,\n QuotedMessagePreview,\n TextareaComposer,\n useChannelStateContext,\n useComponentContext,\n useMessageComposerHasSendableData,\n useMessageInputContext,\n} from 'stream-chat-react'\n\nimport { CustomLinkPreviewList } from '../CustomLinkPreviewList'\n\n/**\n * Carries the channel's `frozen` state down to CustomMessageInputInner, which\n * renders the composer as a read-only/disabled input. Using a context — rather\n * than closing the value into the `Input` component passed to Stream's\n * <MessageInput> — keeps CustomMessageInputInner a stable reference, so the\n * value toggling re-renders the composer instead of unmounting and remounting\n * it (which would drop textarea focus and interrupt IME composition).\n */\nconst ComposerLockedContext = React.createContext(false)\n\n/**\n * Distance from the bottom (px) still treated as \"at the latest message\", used\n * to decide whether a growing composer should re-pin the thread to the bottom\n * (MES-1303). Matches stream-chat-react's own `scrolledUpThreshold` default\n * (200) so composer growth keeps the thread pinned under the same condition\n * Stream already auto-scrolls a new message — anything closer than one message\n * would let a user resting just off the bottom fall through and get covered.\n */\nconst NEAR_BOTTOM_THRESHOLD_PX = 200\n\n/**\n * Read the composer's locked (frozen-channel) state from inside a custom\n * composer supplied via `composerInput`. Returns true when the channel is\n * frozen; mirror the default composer by rendering the textarea read-only and\n * disabling the send control.\n */\nexport const useComposerLocked = (): boolean =>\n useContext(ComposerLockedContext)\n\nconst DefaultSendButton: React.FC<{\n sendMessage: () => void\n disabled?: boolean\n [key: string]: unknown\n}> = ({ sendMessage, disabled, ...rest }) => (\n <button\n {...rest}\n type=\"button\"\n aria-label=\"Send\"\n disabled={disabled}\n // Keep the soft keyboard open after tapping send (MES-1320). Pressing a\n // button moves focus to it, blurring the textarea — on mobile that\n // dismisses the on-screen keyboard, forcing the visitor to re-tap the\n // composer for every message. preventDefault on pointerdown suppresses that\n // focus shift so the textarea stays focused; the click still fires (click is\n // derived from pointerup, not pointerdown), so `sendMessage` runs as normal.\n // pointerdown covers both touch and mouse, and keyboard activation (Enter/\n // Space → click) is unaffected.\n onPointerDown={(e) => e.preventDefault()}\n onClick={sendMessage}\n >\n <ArrowUpIcon weight=\"bold\" className=\"size-4\" />\n </button>\n)\n\nconst CustomMessageInputInner: React.FC = () => {\n const disabled = useContext(ComposerLockedContext)\n const { handleSubmit } = useMessageInputContext()\n\n const hasSendableData = useMessageComposerHasSendableData()\n const isSendDisabled = disabled || !hasSendableData\n\n const {\n SendButton = DefaultSendButton,\n AttachmentPreviewList = DefaultAttachmentPreviewList,\n } = useComponentContext('CustomMessageInput')\n\n return (\n // min-h-0 lets the composer shrink under keyboard squeeze (the link\n // preview list inside is the scrollable region); the textarea + send row\n // is shrink-0 so it can never be pushed out of view. self-stretch matters\n // because the parent `.message-input` row uses items-end, which suppresses\n // the default cross-axis stretch — without it this container keeps its\n // content height and the squeeze never reaches the preview list. Stream's\n // <MessageInput> renders its Input directly (context providers only, no\n // wrapper element), so this is a direct flex item of that row.\n //\n // The container itself carries no padding of its own: it used to (p-2),\n // but that inset now lives on the textarea as padding instead, so the\n // textarea's actual (clickable) box is as large as the container — save\n // for the small margin and the send button on the right (MES-1325).\n // Visually nothing moves; the container ends up exactly the size of the\n // textarea + send button row it contains.\n //\n // Some hosts portal staged-media thumbnails (e.g. ComposerPendingMediaPortal,\n // see this component's stories) straight into `.central-container` rather\n // than through this React tree, bypassing the two wrappers below. The\n // `[&>:not(...)]:p-2` variant restores the container's old inset for any\n // such foreign direct child, without re-adding it to our own wrappers.\n <div\n className=\"central-container flex min-h-0 flex-col min-w-0 w-full self-stretch bg-white rounded-[1.5rem] shadow-[0_4px_16px_0_rgba(0,0,0,0.08),0_1px_2px_0_rgba(0,0,0,0.04),0_0_0_1px_rgba(0,0,0,0.04)] [&>:not(.messaging-composer-previews):not(.messaging-composer-row)]:p-2\"\n data-dd-privacy=\"mask\"\n >\n {/* empty:hidden collapses this row (padding, gap, and all) when none of\n the previews below have anything to render, so an idle composer has\n no leftover top inset before the textarea row. */}\n <div className=\"messaging-composer-previews empty:hidden flex min-h-0 flex-col gap-2 px-2 pt-2\">\n <QuotedMessagePreview />\n <CustomLinkPreviewList />\n <AttachmentPreviewList />\n </div>\n <div className=\"messaging-composer-row flex shrink-0 items-start\">\n <TextareaComposer\n aria-disabled={disabled || undefined}\n // TextareaComposer wraps the real <textarea> in its own div, so\n // `containerClassName` (not `className`) is what joins the row's\n // flex layout; `leading-[0]` drops the line-height space an\n // inline-level parent otherwise reserves, keeping that wrapper\n // exactly the textarea's height rather than stretched by the row\n // (items-start above is a second guard against that same stretch).\n containerClassName=\"min-w-0 flex-1 leading-[0]\"\n // bg-transparent: the container has no padding to inset it behind\n // anymore, so an opaque textarea would paint over its rounded corners.\n className=\"w-full resize-none bg-transparent py-3.5 pl-4 pr-4 outline-none leading-5 placeholder:text-black/30 text-sm\"\n // While this might usually be considered an anti-pattern, in most\n // cases, when a message thread is rendered, we want the input to\n // gain focus automatically.\n // eslint-disable-next-line jsx-a11y/no-autofocus\n autoFocus={!disabled}\n // Enter sends (Shift+Enter inserts a newline), so label the\n // on-screen keyboard's return key accordingly.\n enterKeyHint=\"send\"\n maxRows={4}\n readOnly={disabled}\n tabIndex={disabled ? -1 : undefined}\n />\n {/* The container no longer has its own p-2, so this inset — and the\n mt-auto that anchors the button to the bottom as the textarea\n grows — lives on a wrapper instead of the button's own\n className: a host-supplied SendButton can (and, per our own\n stories, does) spread its own className over the one we pass in,\n which would otherwise silently drop this spacing. */}\n <div className=\"mt-auto mb-2 mr-2 shrink-0\">\n <SendButton\n sendMessage={handleSubmit}\n aria-label=\"Send\"\n // before:-inset-2 extends the button's clickable area to 48x48\n // (MES-1325) via an invisible pseudo-element — clicks on it still\n // land on the button itself — without growing the 32x32 circle\n // `size-8`/`rounded-full`/`bg-[#121110]` visually describe.\n className=\"str-chat__send-button relative flex justify-center items-center rounded-full size-8 bg-[#121110] disabled:bg-[#F1F0EE] disabled:text-black/20 text-white focus-ring before:absolute before:-inset-2 before:content-['']\"\n data-testid=\"send-button\"\n disabled={isSendDisabled}\n type=\"button\"\n />\n </div>\n </div>\n </div>\n )\n}\n\nexport interface CustomMessageInputProps {\n renderActions?: () => React.ReactNode\n /**\n * Content rendered above the composer controls (and above the locked panel\n * when `disabled`). Used by the floating layout to keep conversation footer\n * content inside the absolutely positioned chrome so it is not covered.\n */\n renderHeader?: () => React.ReactNode\n renderFooter?: () => React.ReactNode\n /**\n * Replace the composer entirely with a non-interactive locked panel that\n * shows `disabledReason`. Used by the Linktree official channel, where the\n * linker cannot message Linktree from the inbox. Defaults to false.\n *\n * Distinct from the channel's `frozen` flag, which keeps the composer\n * rendered but read-only/dimmed.\n */\n disabled?: boolean\n /**\n * Explanatory text shown inside the locked panel. Only rendered when\n * `disabled` is true.\n */\n disabledReason?: string\n /**\n * Replace the inner composer — the textarea + send arrangement rendered\n * inside Stream's `<MessageInput>` — with a host-owned component. When\n * provided it is passed to Stream as the `Input` component, so it runs inside\n * the message-input context and can drive sending, attachments, and previews\n * via the Stream hooks (`useMessageInputContext`,\n * `useMessageComposerHasSendableData`, `TextareaComposer`, …). The outer\n * frozen/`renderActions`/`renderFooter` wrapper is unchanged; read\n * `useComposerLocked()` to honour the frozen state. Defaults to the built-in\n * composer.\n */\n composerInput?: React.ComponentType\n}\n\nexport const CustomMessageInput: React.FC<CustomMessageInputProps> = ({\n renderActions,\n renderHeader,\n renderFooter,\n disabled = false,\n disabledReason,\n composerInput,\n}) => {\n const { channel } = useChannelStateContext()\n const isFrozen = channel?.data?.frozen === true\n const isFloating = Boolean(composerInput)\n const composerRef = React.useRef<HTMLDivElement>(null)\n\n React.useEffect(() => {\n if (!isFloating) {\n return\n }\n\n const composer = composerRef.current\n const layout = composer?.parentElement\n\n if (!composer || !layout) {\n return\n }\n\n // Track the composer height across resizes so we can re-pin only when it\n // actually grows (see below).\n let previousComposerHeight = composer.offsetHeight\n\n const updateComposerHeight = () => {\n // The floating composer overlays the message list; growing it only\n // reserves space via padding-bottom, which never moves the viewport, so\n // a taller composer creeps up over the last message (MES-1303). Capture\n // whether the thread is pinned to the latest message *before* the padding\n // grows, then re-pin afterwards.\n const nextComposerHeight = composer.offsetHeight\n // Only growth can cover the latest message: shrinks free up space and\n // width-only resizes (window/layout changes) cover nothing, so re-pinning\n // then would needlessly yank a user resting just off the bottom.\n const grew = nextComposerHeight > previousComposerHeight\n previousComposerHeight = nextComposerHeight\n\n // The scroll viewport is Stream's `.str-chat__list` (overflow-y: auto);\n // its child `.str-chat__message-list-scroll` holds the padding but has\n // overflow: visible and never scrolls. The redesigned empty state also\n // renders a placeholder `.str-chat__list`, so select the one that is\n // actually scrollable rather than the first match — that is also the only\n // one where re-pinning can do anything.\n const scroller =\n Array.from(\n layout.querySelectorAll<HTMLElement>('.str-chat__list')\n ).find((el) => el.scrollHeight > el.clientHeight) ?? null\n // Guarded on `wasAtBottom` so we never yank a user reading history.\n const wasAtBottom = scroller\n ? scroller.scrollHeight - scroller.scrollTop - scroller.clientHeight <\n NEAR_BOTTOM_THRESHOLD_PX\n : false\n\n layout.style.setProperty(\n '--messaging-composer-height',\n `${nextComposerHeight}px`\n )\n\n // Reading scrollHeight forces a synchronous reflow, so it reflects the\n // padding-bottom we just set; scrolling to it pins the true bottom.\n if (grew && wasAtBottom && scroller) {\n scroller.scrollTop = scroller.scrollHeight\n }\n }\n\n updateComposerHeight()\n\n if (typeof ResizeObserver === 'undefined') {\n return\n }\n\n const resizeObserver = new ResizeObserver(updateComposerHeight)\n resizeObserver.observe(composer)\n\n return () => {\n resizeObserver.disconnect()\n layout.style.removeProperty('--messaging-composer-height')\n }\n }, [isFloating])\n\n // Linktree official channel: the composer is replaced by an info panel\n // explaining the linker cannot send messages on this thread.\n if (disabled) {\n if (!isFloating) {\n return (\n <>\n {renderHeader?.()}\n <div className=\"messaging-composer-locked-panel flex w-full flex-col items-center justify-center gap-3 px-6 py-4\">\n {disabledReason ? (\n <p className=\"max-w-[345px] text-center text-xs font-normal leading-[1.3] tracking-[0.12px] text-black/40\">\n {disabledReason}\n </p>\n ) : null}\n </div>\n {renderFooter?.()}\n </>\n )\n }\n\n return (\n <div\n ref={composerRef}\n className=\"messaging-composer-chrome messaging-composer-chrome--floating\"\n >\n <div className=\"messaging-composer-backdrop\" aria-hidden=\"true\">\n <div className=\"messaging-composer-backdrop-blur\" />\n <div className=\"messaging-composer-backdrop-blur\" />\n <div className=\"messaging-composer-backdrop-blur\" />\n <div className=\"messaging-composer-backdrop-blur\" />\n <div className=\"messaging-composer-backdrop-blur\" />\n <div className=\"messaging-composer-backdrop-gradient\" />\n </div>\n <div className=\"relative z-10 flex flex-col\">\n {renderHeader?.()}\n <div className=\"messaging-composer-locked-panel flex w-full flex-col items-center justify-center gap-3 px-6 py-4\">\n {disabledReason ? (\n <p className=\"max-w-[345px] text-center text-xs font-normal leading-[1.3] tracking-[0.12px] text-black/40\">\n {disabledReason}\n </p>\n ) : null}\n </div>\n {renderFooter?.()}\n </div>\n </div>\n )\n }\n\n if (!isFloating) {\n return (\n <div className=\"flex min-h-0 flex-col gap-4 p-4\">\n {renderHeader?.()}\n <div\n // @ts-expect-error Only React 19 onwards has `inert` in its types.\n inert={isFrozen ? '' : undefined}\n aria-disabled={isFrozen || undefined}\n className=\"message-input flex min-h-0 items-end gap-4 aria-disabled:opacity-40\"\n >\n {renderActions && (\n <div className=\"flex h-12 shrink-0 items-center justify-center\">\n {renderActions()}\n </div>\n )}\n <ComposerLockedContext.Provider value={isFrozen}>\n <MessageInput Input={CustomMessageInputInner} />\n </ComposerLockedContext.Provider>\n </div>\n {renderFooter?.()}\n </div>\n )\n }\n\n return (\n <div\n ref={composerRef}\n className=\"messaging-composer-chrome messaging-composer-chrome--floating\"\n >\n <div className=\"messaging-composer-backdrop\" aria-hidden=\"true\">\n <div className=\"messaging-composer-backdrop-blur\" />\n <div className=\"messaging-composer-backdrop-blur\" />\n <div className=\"messaging-composer-backdrop-blur\" />\n <div className=\"messaging-composer-backdrop-blur\" />\n <div className=\"messaging-composer-backdrop-blur\" />\n <div className=\"messaging-composer-backdrop-gradient\" />\n </div>\n\n <div className=\"relative z-10 flex min-h-0 flex-col\">\n {renderHeader?.()}\n <div className=\"flex min-h-0 flex-col gap-4 p-4\">\n <div\n // @ts-expect-error Only React 19 onwards has `inert` in its types.\n inert={isFrozen ? '' : undefined}\n aria-disabled={isFrozen || undefined}\n className=\"message-input flex min-h-0 items-end gap-4 aria-disabled:opacity-40\"\n >\n {renderActions && (\n <div className=\"flex h-12 shrink-0 items-center justify-center\">\n {renderActions()}\n </div>\n )}\n <ComposerLockedContext.Provider value={isFrozen}>\n <MessageInput Input={composerInput ?? CustomMessageInputInner} />\n </ComposerLockedContext.Provider>\n </div>\n {renderFooter?.()}\n </div>\n </div>\n </div>\n )\n}\n","import {\n isAgeSafetySystemType,\n isDmAgentSystemType,\n type AgeSafetySystemType,\n type DmAgentSystemType,\n} from '@linktr.ee/messaging-taxonomy'\nimport { ProhibitIcon, SparkleIcon } from '@phosphor-icons/react'\nimport { MessageTimestamp, type EventComponentProps } from 'stream-chat-react'\n\nconst DM_AGENT_SYSTEM_MESSAGE_FALLBACK_TEXT: Record<DmAgentSystemType, string> =\n {\n SYSTEM_DM_AGENT_PAUSED: 'DM Agent has left the conversation',\n SYSTEM_DM_AGENT_RESUMED: 'DM Agent has rejoined the conversation',\n }\n\n/**\n * System-message timestamps are hidden by default. A semantic type must opt in\n * here to render one, so new/unknown system types stay timestamp-less until\n * explicitly added. Keep in sync with the mobile client (cerberus\n * `CustomMessageSystem`); there is no shared package between the two surfaces.\n */\nexport const SHOW_SYSTEM_MESSAGE_TIMESTAMP_TYPES: readonly AgeSafetySystemType[] =\n ['SYSTEM_AGE_SAFETY_BLOCKED']\n\nconst AGE_SAFETY_SYSTEM_MESSAGE_FALLBACK_TEXT: Record<\n AgeSafetySystemType,\n string\n> = {\n SYSTEM_AGE_SAFETY_BLOCKED:\n 'This user isn’t able to reply because they don’t meet our age safety guidelines.',\n}\n\nconst AGE_SAFETY_SYSTEM_MESSAGE_EMPHASIS = 'age safety guidelines.'\nconst AGE_SAFETY_SYSTEM_MESSAGE_URL = 'https://linktr.ee/s/about/contact'\n\nconst isShowTimestampSystemType = (\n value: string | undefined\n): value is (typeof SHOW_SYSTEM_MESSAGE_TIMESTAMP_TYPES)[number] => {\n return SHOW_SYSTEM_MESSAGE_TIMESTAMP_TYPES.includes(\n value as (typeof SHOW_SYSTEM_MESSAGE_TIMESTAMP_TYPES)[number]\n )\n}\n\nconst shouldShowSystemMessageTimestamp = (\n message: EventComponentProps['message']\n): boolean => {\n return isShowTimestampSystemType(message.metadata?.custom_type)\n}\n\ntype CustomSystemMessageVariant =\n | {\n kind: 'dm-agent'\n type: DmAgentSystemType\n }\n | {\n kind: 'age-safety'\n type: AgeSafetySystemType\n }\n\nconst getCustomSystemMessageVariant = (\n message: EventComponentProps['message']\n): CustomSystemMessageVariant | undefined => {\n const metadataCustomType = message.metadata?.custom_type\n if (isDmAgentSystemType(metadataCustomType)) {\n return {\n kind: 'dm-agent',\n type: metadataCustomType,\n }\n }\n\n if (isAgeSafetySystemType(metadataCustomType)) {\n return {\n kind: 'age-safety',\n type: metadataCustomType,\n }\n }\n\n const fallbackType = message.dm_agent_system_type\n if (isDmAgentSystemType(fallbackType)) {\n return {\n kind: 'dm-agent',\n type: fallbackType,\n }\n }\n\n return undefined\n}\n\nconst renderAgeSafetyMessageText = (messageText: string): React.ReactNode => {\n const emphasisIndex = messageText.indexOf(AGE_SAFETY_SYSTEM_MESSAGE_EMPHASIS)\n if (emphasisIndex === -1) {\n return messageText\n }\n\n const emphasisEndIndex =\n emphasisIndex + AGE_SAFETY_SYSTEM_MESSAGE_EMPHASIS.length\n\n return (\n <>\n {messageText.slice(0, emphasisIndex)}\n <a\n href={AGE_SAFETY_SYSTEM_MESSAGE_URL}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"mes-age-safety-system-message__emphasis font-medium text-inherit underline\"\n >\n {AGE_SAFETY_SYSTEM_MESSAGE_EMPHASIS}\n </a>\n {messageText.slice(emphasisEndIndex)}\n </>\n )\n}\n\nexport const CustomSystemMessage: React.FC<EventComponentProps> = (props) => {\n const isDateHidden = !shouldShowSystemMessageTimestamp(props.message)\n const customSystemMessageVariant = getCustomSystemMessageVariant(\n props.message\n )\n\n if (customSystemMessageVariant?.kind === 'dm-agent') {\n const messageText =\n props.message.text?.trim() ||\n DM_AGENT_SYSTEM_MESSAGE_FALLBACK_TEXT[customSystemMessageVariant.type]\n\n return (\n <div className=\"str-chat__message--system\" data-testid=\"message-system\">\n <div\n className=\"mes-dm-agent-system-message mx-auto mb-2 inline-flex w-fit max-w-[min(100%,480px)] items-center justify-center gap-[10px] rounded-[12px] border border-[rgba(0,0,0,0.08)] p-3 text-[rgba(0,0,0,0.55)]\"\n data-testid=\"dm-agent-system-message\"\n data-dm-agent-system-type={customSystemMessageVariant.type}\n >\n <SparkleIcon\n size={16}\n weight=\"regular\"\n aria-hidden\n className=\"mes-dm-agent-system-message__sparkle shrink-0\"\n />\n <p className=\"mes-dm-agent-system-message__text m-0 text-center text-[14px] font-normal leading-5 tracking-[0.21px]\">\n {messageText}\n </p>\n </div>\n {!isDateHidden && <MessageTimestamp message={props.message} />}\n </div>\n )\n }\n\n if (customSystemMessageVariant?.kind === 'age-safety') {\n const messageText =\n props.message.text?.trim() ||\n AGE_SAFETY_SYSTEM_MESSAGE_FALLBACK_TEXT[customSystemMessageVariant.type]\n\n return (\n <div className=\"str-chat__message--system\" data-testid=\"message-system\">\n <div\n className=\"mes-age-safety-system-message box-border mx-auto mb-2 flex w-full max-w-[329px] items-start justify-center gap-3 rounded-[12px] border border-[var(--border-secondary,rgba(0,0,0,0.08))] bg-[var(--bg-warning-subtle,#fef3c6)] px-2 py-4 pl-5 text-[color:var(--text-warning-on-warning,#894b00)]\"\n data-testid=\"age-safety-system-message\"\n data-age-safety-system-type={customSystemMessageVariant.type}\n >\n <ProhibitIcon\n size={24}\n weight=\"duotone\"\n aria-hidden\n className=\"mes-age-safety-system-message__icon shrink-0 text-[color:var(--text-warning-on-warning,#894b00)]\"\n data-testid=\"age-safety-system-message-icon\"\n />\n <div className=\"mes-age-safety-system-message__content min-w-0 flex-[1_0_0]\">\n <p className=\"m-0 text-balance text-left text-[12px] font-normal leading-4 tracking-[0.21px] text-[color:var(--text-warning-on-warning,#894b00)]\">\n {renderAgeSafetyMessageText(messageText)}\n </p>\n </div>\n </div>\n {!isDateHidden && <MessageTimestamp message={props.message} />}\n </div>\n )\n }\n\n return (\n <div className=\"str-chat__message--system\" data-testid=\"message-system\">\n <div className=\"str-chat__message--system__text\">\n <div className=\"str-chat__message--system__line\"></div>\n <p>{props.message.text}</p>\n <div className=\"str-chat__message--system__line\"></div>\n </div>\n {!isDateHidden && <MessageTimestamp message={props.message} />}\n </div>\n )\n}\n","import { createContext } from 'react'\n\nexport const DmAgentEnabledContext = createContext<boolean>(false)\n","import React, { useContext } from 'react'\nimport type { Event, UserResponse } from 'stream-chat'\nimport {\n AIStates,\n useAIState,\n useChannelStateContext,\n useChatContext,\n useTypingContext,\n} from 'stream-chat-react'\n\nimport { Avatar } from '../Avatar'\n\nimport { DmAgentEnabledContext } from './DmAgentContext'\n\ninterface CustomTypingIndicatorProps {\n threadList?: boolean\n}\n\nconst Circle = ({ cx, index }: { cx: string; index: number }) => (\n <circle cx={cx} cy=\"6.15\" r=\"3.9\" fill=\"#A0A0A0\">\n <animateTransform\n attributeName=\"transform\"\n type=\"translate\"\n values=\"0 0; 0 -2.25; 0 0;\"\n dur=\"900ms\"\n begin={`${120 * index}ms`} // 0ms, 120ms, 240ms\n repeatCount=\"indefinite\"\n />\n </circle>\n)\n\nconst AI_ACTIVE_STATES = new Set<string>([\n AIStates.Thinking,\n AIStates.Generating,\n AIStates.ExternalSources,\n])\n\nconst CustomTypingIndicator = ({ threadList }: CustomTypingIndicatorProps) => {\n const { channel, channelConfig, thread } = useChannelStateContext()\n const { client } = useChatContext()\n const { typing = {} } = useTypingContext()\n const { aiState } = useAIState(channel)\n const dmAgentEnabled = useContext(DmAgentEnabledContext)\n\n // Show the AI indicator whenever the consumer agent is producing a reply.\n // This event stream is independent of `typing.start`/`typing.stop`, so it is\n // intentionally NOT gated by `channelConfig.typing_events`. Gate strictly on\n // `dmAgentEnabled` so stale or off-surface ai_indicator events never surface\n // the bubble on channels where the agent is not active.\n const isAiActive =\n !threadList && dmAgentEnabled && AI_ACTIVE_STATES.has(aiState)\n\n if (isAiActive) {\n const agentUser = findOtherChannelUser(channel, client.user?.id)\n return (\n <TypingBubble\n avatarId={agentUser?.id ?? 'ai-agent'}\n avatarName={agentUser?.name ?? agentUser?.id ?? 'Agent'}\n avatarImage={agentUser?.image}\n testId=\"typing-indicator-ai\"\n />\n )\n }\n\n if (channelConfig?.typing_events === false) {\n return null\n }\n\n const typingInChannel = !threadList\n ? Object.values(typing).filter(\n ({ parent_id, user }: Event) =>\n user?.id !== client.user?.id && !parent_id\n )\n : []\n\n const typingInThread = threadList\n ? Object.values(typing).filter(\n ({ parent_id, user }: Event) =>\n user?.id !== client.user?.id && parent_id === thread?.id\n )\n : []\n\n const typingUsers = threadList ? typingInThread : typingInChannel\n if (!typingUsers.length) {\n return null\n }\n\n const typingUser = typingUsers[0]?.user\n const memberUser =\n typingUser?.id && channel.state.members[typingUser.id]\n ? channel.state.members[typingUser.id].user\n : undefined\n\n return (\n <TypingBubble\n avatarId={typingUser?.id ?? memberUser?.id ?? 'typing-user'}\n avatarName={\n typingUser?.name ?? memberUser?.name ?? typingUser?.id ?? 'Typing user'\n }\n avatarImage={typingUser?.image ?? memberUser?.image}\n testId=\"typing-indicator\"\n />\n )\n}\n\nconst TypingBubble = ({\n avatarId,\n avatarName,\n avatarImage,\n testId,\n}: {\n avatarId: string\n avatarName: string\n avatarImage?: string | null\n testId: string\n}) => (\n <div\n className=\"str-chat__li str-chat__li--single str-chat__typing-indicator !static\"\n data-testid={testId}\n style={{\n marginBottom: 'var(--messaging-channel-input-spacer-height, 80px)',\n }}\n >\n <div className=\"str-chat__message str-chat__message-simple str-chat__message--regular str-chat__message--received str-chat__message--other str-chat__message--has-text\">\n <Avatar\n className=\"str-chat__avatar str-chat__message-sender-avatar\"\n id={avatarId}\n name={avatarName}\n image={avatarImage ?? undefined}\n size={24}\n shape=\"circle\"\n />\n <div className=\"str-chat__message-inner mx-0\">\n <div className=\"str-chat__message-bubble-wrapper\">\n <div className=\"str-chat__message-bubble\">\n <div className=\"str-chat__message-text min-h-11 flex items-center\">\n <div className=\"str-chat__message-text-inner str-chat__message-simple-text-inner\">\n <svg\n aria-hidden=\"true\"\n className=\"block overflow-visible\"\n viewBox=\"0 0 32 12.3\"\n width=\"32\"\n height=\"13\"\n overflow=\"visible\"\n >\n <Circle cx=\"4\" index={0} />\n <Circle cx=\"16\" index={1} />\n <Circle cx=\"28\" index={2} />\n </svg>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n)\n\ntype ChannelLike = ReturnType<typeof useChannelStateContext>['channel']\n\nfunction findOtherChannelUser(\n channel: ChannelLike,\n selfId: string | undefined\n): UserResponse | undefined {\n const members = channel?.state?.members ?? {}\n for (const member of Object.values(members)) {\n const memberUser = member?.user\n if (memberUser && memberUser.id !== selfId) {\n return memberUser\n }\n }\n return undefined\n}\n\nexport default CustomTypingIndicator\n","import React from 'react'\n\n/**\n * Empty state component shown when a channel has no messages\n * Returns null to show nothing - the LoadingIndicator handles the loading state\n */\nexport const ChannelEmptyState: React.FC = () => null\n","import classNames from 'classnames'\n\ntype LoadingProps = {\n className?: string\n message?: string\n}\n\nconst Loading = ({ className, message }: LoadingProps) => (\n <div\n className={classNames('flex items-center justify-center h-full', className)}\n >\n <svg viewBox=\"0 0 100 100\" className=\"size-8 fill-pebble\" stroke=\"none\">\n <circle cx=\"6\" cy=\"50\" r=\"6\">\n <animateTransform\n attributeName=\"transform\"\n dur=\"1s\"\n type=\"translate\"\n values=\"0 15 ; 0 -15; 0 15\"\n repeatCount=\"indefinite\"\n begin=\"0.1\"\n />\n </circle>\n <circle cx=\"30\" cy=\"50\" r=\"6\">\n <animateTransform\n attributeName=\"transform\"\n dur=\"1s\"\n type=\"translate\"\n values=\"0 10 ; 0 -10; 0 10\"\n repeatCount=\"indefinite\"\n begin=\"0.2\"\n />\n </circle>\n <circle cx=\"54\" cy=\"50\" r=\"6\">\n <animateTransform\n attributeName=\"transform\"\n dur=\"1s\"\n type=\"translate\"\n values=\"0 5 ; 0 -5; 0 5\"\n repeatCount=\"indefinite\"\n begin=\"0.3\"\n />\n </circle>\n </svg>\n {message && <span className=\"text-stone\">{message}</span>}\n </div>\n)\n\nexport default Loading\n","import React from 'react'\n\nimport Loading from '../Loading'\n\n/**\n * Loading state component\n */\nexport const LoadingState = React.memo(() => (\n <div className=\"messaging-loading-state flex items-center justify-center h-full\">\n <div className=\"flex items-center\">\n <Loading className=\"w-6 h-6\" />\n <span className=\"text-sm text-stone\">Loading messages</span>\n </div>\n </div>\n))\nLoadingState.displayName = 'LoadingState'\n","import classNames from 'classnames'\nimport React, { useCallback, useEffect, useRef } from 'react'\nimport { Channel as ChannelType } from 'stream-chat'\nimport {\n Channel,\n Window,\n MessageList,\n useMessageContext,\n useChannelStateContext,\n WithComponents,\n MessageUIComponentProps,\n} from 'stream-chat-react'\n\nimport type { ChannelViewProps } from '../types'\n\nimport { ChannelHeaderRedesign } from './ChannelHeaderRedesign'\nimport { CustomDateSeparator } from './CustomDateSeparator'\nimport { CustomMessage } from './CustomMessage'\nimport {\n BroadcastNameContext,\n useBroadcastNamesById,\n} from './CustomMessage/BroadcastNameContext'\nimport { CustomMessageActions } from './CustomMessage/CustomMessageActions'\nimport { CustomMessageInput } from './CustomMessageInput'\nimport { CustomSystemMessage } from './CustomSystemMessage'\nimport CustomTypingIndicator from './CustomTypingIndicator'\nimport { DmAgentEnabledContext } from './CustomTypingIndicator/DmAgentContext'\nimport { ChannelEmptyState } from './MessagingShell/ChannelEmptyState'\nimport { LoadingState } from './MessagingShell/LoadingState'\n\n/**\n * Inner component that has access to channel context\n */\nconst ChannelViewInner: React.FC<{\n onBack?: () => void\n showBackButton: boolean\n renderMessageInputActions?: (channel: ChannelType) => React.ReactNode\n renderMessageInputFooter?: (channel: ChannelType) => React.ReactNode\n renderConversationFooter?: (channel: ChannelType) => React.ReactNode\n onLeaveConversation?: (channel: ChannelType) => void\n onBlockParticipant?: (participantId?: string) => void\n CustomChannelEmptyState?: React.ComponentType\n showDeleteConversation?: boolean\n onDeleteConversationClick?: () => void\n onBlockParticipantClick?: () => void\n onReportParticipantClick?: () => void\n showBlockParticipant?: boolean\n showReportParticipant?: boolean\n composerDisabled?: boolean\n composerDisabledReason?: string\n showStarButton?: boolean\n chatbotVotingEnabled?: boolean\n renderChannelBanner?: () => React.ReactNode\n customChannelActions?: React.ReactNode\n renderChannelActions?: React.ReactNode\n renderMessage?: (\n messageNode: React.ReactElement,\n message: NonNullable<MessageUIComponentProps['message']>\n ) => React.ReactNode\n viewerLanguage?: string\n showChannelInfo?: boolean\n onParticipantNameClick?: () => void\n onBroadcastClick?: ChannelViewProps['onBroadcastClick']\n resolveBroadcastName?: ChannelViewProps['resolveBroadcastName']\n composerInput?: ChannelViewProps['composerInput']\n}> = ({\n onBack,\n showBackButton,\n renderMessageInputActions,\n renderMessageInputFooter,\n renderConversationFooter,\n onLeaveConversation,\n onBlockParticipant,\n showDeleteConversation = true,\n onDeleteConversationClick,\n onBlockParticipantClick,\n onReportParticipantClick,\n showBlockParticipant = true,\n showReportParticipant = true,\n composerDisabled = false,\n composerDisabledReason,\n showStarButton = false,\n chatbotVotingEnabled = false,\n renderChannelBanner,\n customChannelActions,\n renderChannelActions,\n renderMessage,\n viewerLanguage,\n showChannelInfo = true,\n onParticipantNameClick,\n onBroadcastClick,\n resolveBroadcastName,\n composerInput,\n}) => {\n const { channel, messages } = useChannelStateContext()\n const onBroadcastClickRef = useRef(onBroadcastClick)\n useEffect(() => {\n onBroadcastClickRef.current = onBroadcastClick\n }, [onBroadcastClick])\n const stableOnBroadcastClick = useCallback<\n NonNullable<ChannelViewProps['onBroadcastClick']>\n >((broadcast) => {\n onBroadcastClickRef.current?.(broadcast)\n }, [])\n const messageBroadcastClick = onBroadcastClick\n ? stableOnBroadcastClick\n : undefined\n // Resolve outside memoized Stream rows so new campaign names publish without\n // remounting the rows.\n const broadcastNamesById = useBroadcastNamesById(\n messages,\n resolveBroadcastName\n )\n\n const hasVisibleMessages = channel.state.messages.some(\n (message) => message.type !== 'deleted'\n )\n const channelBanner = renderChannelBanner ? (\n <React.Fragment key=\"lt-channel-banner\">\n {renderChannelBanner()}\n </React.Fragment>\n ) : null\n const channelHeader = (\n <ChannelHeaderRedesign\n className=\"-mx-[var(--str-chat\\_\\_spacing-2)] px-[var(--str-chat\\_\\_spacing-2)] md:-mx-[min(var(--str-chat\\_\\_spacing-10),4%)] md:px-[min(var(--str-chat\\_\\_spacing-10),4%)]\"\n onBack={onBack}\n showBackButton={showBackButton}\n showChannelInfo={showChannelInfo}\n showStarButton={showStarButton}\n onLeaveConversation={onLeaveConversation}\n onBlockParticipant={onBlockParticipant}\n showDeleteConversation={showDeleteConversation}\n showBlockParticipant={showBlockParticipant}\n showReportParticipant={showReportParticipant}\n onDeleteConversationClick={onDeleteConversationClick}\n onBlockParticipantClick={onBlockParticipantClick}\n onReportParticipantClick={onReportParticipantClick}\n customChannelActions={customChannelActions}\n renderChannelActions={renderChannelActions}\n onParticipantNameClick={onParticipantNameClick}\n />\n )\n\n // Prevents all message instances from unmounting when ChannelViewInner re-renders\n const MessageOverride = useCallback(\n (props: MessageUIComponentProps) => {\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const { message } = useMessageContext('ChannelView')\n const messageNode = (\n <CustomMessage\n {...props}\n chatbotVotingEnabled={chatbotVotingEnabled}\n viewerLanguage={viewerLanguage}\n onBroadcastClick={messageBroadcastClick}\n />\n )\n\n if (!renderMessage || !message) {\n return messageNode\n }\n\n return renderMessage(messageNode, message)\n },\n [chatbotVotingEnabled, messageBroadcastClick, renderMessage, viewerLanguage]\n )\n\n return (\n <BroadcastNameContext.Provider value={broadcastNamesById}>\n <WithComponents\n overrides={{\n Message: MessageOverride,\n MessageActions: CustomMessageActions,\n UnreadMessagesNotification: () => null,\n UnreadMessagesSeparator: () => null,\n }}\n >\n <Window>\n {composerInput ? (\n <div className=\"messaging-channel-layout relative flex min-h-0 flex-1 flex-col\">\n {/* Message List */}\n <div\n key=\"lt-channel-message-list\"\n className=\"messaging-channel-message-list messaging-channel-message-list--floating relative min-h-0 flex-1 overflow-hidden\"\n >\n {/* Stream only renders MessageList.head when there are messages, so\n empty channels need the header and banner in normal flow. */}\n {!hasVisibleMessages && (\n <div className=\"str-chat__list\">\n <div className=\"str-chat__message-list-scroll\">\n {channelHeader}\n {channelBanner}\n </div>\n </div>\n )}\n\n <MessageList\n head={\n hasVisibleMessages ? (\n <div className=\"sticky top-0 z-10\">\n {channelHeader}\n {channelBanner}\n </div>\n ) : undefined\n }\n hideDeletedMessages\n hideNewMessageSeparator={false}\n />\n </div>\n\n {/* Message Input — conversation footer is rendered inside the\n floating chrome (via renderHeader) so it stays above the absolute\n composer and remains interactive. */}\n <CustomMessageInput\n key=\"lt-channel-message-input\"\n {...(renderMessageInputActions && {\n renderActions: () => renderMessageInputActions?.(channel),\n })}\n {...(renderConversationFooter && {\n renderHeader: () => renderConversationFooter(channel),\n })}\n renderFooter={() => renderMessageInputFooter?.(channel)}\n disabled={composerDisabled}\n disabledReason={composerDisabledReason}\n composerInput={composerInput}\n />\n </div>\n ) : (\n <>\n {/* Message List */}\n <div\n key=\"lt-channel-message-list\"\n className=\"flex-1 overflow-hidden relative\"\n >\n {/* Stream only renders MessageList.head when there are messages, so\n empty channels need the header and banner in normal flow. */}\n {!hasVisibleMessages && (\n <div className=\"str-chat__list\">\n <div className=\"str-chat__message-list-scroll\">\n {channelHeader}\n {channelBanner}\n </div>\n </div>\n )}\n\n <MessageList\n head={\n hasVisibleMessages ? (\n <div className=\"sticky top-0 z-10\">\n {channelHeader}\n {channelBanner}\n </div>\n ) : undefined\n }\n hideDeletedMessages\n hideNewMessageSeparator={false}\n />\n </div>\n\n {renderConversationFooter ? (\n <React.Fragment key=\"lt-channel-conversation-footer\">\n {renderConversationFooter(channel)}\n </React.Fragment>\n ) : null}\n\n {/* Message Input */}\n <CustomMessageInput\n key=\"lt-channel-message-input\"\n {...(renderMessageInputActions && {\n renderActions: () => renderMessageInputActions?.(channel),\n })}\n renderFooter={() => renderMessageInputFooter?.(channel)}\n disabled={composerDisabled}\n disabledReason={composerDisabledReason}\n composerInput={composerInput}\n />\n </>\n )}\n </Window>\n </WithComponents>\n </BroadcastNameContext.Provider>\n )\n}\n\n/**\n * Channel view component with message list and input\n */\nexport const ChannelView = React.memo<ChannelViewProps>(\n ({\n channel,\n onBack,\n showBackButton = false,\n renderMessageInputActions,\n renderMessageInputFooter,\n renderConversationFooter,\n onLeaveConversation,\n onBlockParticipant,\n className,\n CustomChannelEmptyState = ChannelEmptyState,\n showDeleteConversation = true,\n onDeleteConversationClick,\n onBlockParticipantClick,\n onReportParticipantClick,\n showBlockParticipant = true,\n showReportParticipant = true,\n composerDisabled = false,\n composerDisabledReason,\n dmAgentEnabled,\n messageMetadata,\n onMessageSent,\n showStarButton = false,\n chatbotVotingEnabled = false,\n renderChannelBanner,\n customChannelActions,\n renderChannelActions,\n renderMessage,\n onMessageLinkClick,\n sendButton,\n attachmentPreviewList,\n viewerLanguage,\n showChannelInfo = true,\n onParticipantNameClick,\n onBroadcastClick,\n resolveBroadcastName,\n composerInput,\n }) => {\n // Custom send message handler that:\n // 1. Applies messageMetadata if provided\n // 2. Adds skip_push and silent when DM agent is active\n // 3. Calls onMessageSent callback with full response\n // Read chatbot_paused inside callback to get current value at send time (not stale closure)\n const doSendMessageRequest = useCallback(\n async (\n _channel: ChannelType,\n message: Parameters<ChannelType['sendMessage']>[0],\n options?: Parameters<ChannelType['sendMessage']>[1]\n ) => {\n const agentPaused = channel.data?.chatbot_paused === true\n const shouldSuppressNotifications = dmAgentEnabled && !agentPaused\n\n // Build final message with nested metadata\n const finalMessage = {\n ...message,\n ...(shouldSuppressNotifications && { silent: true }),\n ...(messageMetadata && {\n metadata: {\n ...(message.metadata ?? {}),\n ...messageMetadata,\n },\n }),\n }\n\n // Build final options\n const finalOptions = {\n ...options,\n ...(shouldSuppressNotifications && { skip_push: true }),\n }\n\n const response = await channel.sendMessage(finalMessage, finalOptions)\n\n // Fire callback with full response (includes message.id)\n onMessageSent?.(response)\n\n return response\n },\n [channel, dmAgentEnabled, messageMetadata, onMessageSent]\n )\n\n const containerRef = useRef<HTMLDivElement>(null)\n useEffect(() => {\n if (!onMessageLinkClick) return\n const container = containerRef.current\n if (!container) return\n const handler = (event: MouseEvent) => {\n const target = event.target as HTMLElement | null\n const anchor = target?.closest('a[href]')\n const href = anchor?.getAttribute('href')\n if (!href) return\n const messageWrapper = anchor?.closest<HTMLElement>('[data-message-id]')\n const messageId = messageWrapper?.getAttribute('data-message-id')\n const message = messageId\n ? channel.state.messages.find((m) => m.id === messageId)\n : undefined\n onMessageLinkClick(href, message)\n }\n container.addEventListener('click', handler)\n return () => container.removeEventListener('click', handler)\n }, [onMessageLinkClick, channel])\n\n return (\n <div\n ref={containerRef}\n className={classNames(\n 'messaging-channel-view h-full flex flex-col',\n className\n )}\n >\n <DmAgentEnabledContext.Provider value={dmAgentEnabled ?? false}>\n <Channel\n channel={channel}\n MessageSystem={CustomSystemMessage}\n EmptyStateIndicator={CustomChannelEmptyState}\n LoadingIndicator={LoadingState}\n DateSeparator={CustomDateSeparator}\n TypingIndicator={CustomTypingIndicator}\n doSendMessageRequest={doSendMessageRequest}\n {...(sendButton ? { SendButton: sendButton } : {})}\n {...(attachmentPreviewList\n ? { AttachmentPreviewList: attachmentPreviewList }\n : {})}\n >\n <ChannelViewInner\n onBack={onBack}\n showBackButton={showBackButton}\n renderMessageInputActions={renderMessageInputActions}\n renderMessageInputFooter={renderMessageInputFooter}\n renderConversationFooter={renderConversationFooter}\n onLeaveConversation={onLeaveConversation}\n onBlockParticipant={onBlockParticipant}\n CustomChannelEmptyState={CustomChannelEmptyState}\n showDeleteConversation={showDeleteConversation}\n onDeleteConversationClick={onDeleteConversationClick}\n onBlockParticipantClick={onBlockParticipantClick}\n onReportParticipantClick={onReportParticipantClick}\n showBlockParticipant={showBlockParticipant}\n showReportParticipant={showReportParticipant}\n composerDisabled={composerDisabled}\n composerDisabledReason={composerDisabledReason}\n showStarButton={showStarButton}\n chatbotVotingEnabled={chatbotVotingEnabled}\n renderChannelBanner={renderChannelBanner}\n customChannelActions={customChannelActions}\n renderChannelActions={renderChannelActions}\n renderMessage={renderMessage}\n viewerLanguage={viewerLanguage}\n showChannelInfo={showChannelInfo}\n onParticipantNameClick={onParticipantNameClick}\n onBroadcastClick={onBroadcastClick}\n resolveBroadcastName={resolveBroadcastName}\n composerInput={composerInput}\n />\n </Channel>\n </DmAgentEnabledContext.Provider>\n </div>\n )\n }\n)\nChannelView.displayName = 'ChannelView'\n","import React from 'react'\n\ntype ErrorStateProps = {\n message: string\n onBack?: () => void\n}\n\n/**\n * Error state component shown when something goes wrong\n */\nexport const ErrorState = React.memo<ErrorStateProps>(({ message, onBack }) => (\n <div className=\"messaging-error-state flex items-center justify-center h-full p-8\">\n <div className=\"text-center max-w-sm\">\n <div className=\"w-24 h-24 bg-danger-alt/20 rounded-full flex items-center justify-center mx-auto mb-6\">\n <span className=\"text-4xl\">⚠️</span>\n </div>\n\n <h2 className=\"font-semibold text-charcoal mb-2\">Oops!</h2>\n\n <p className=\"text-stone text-sm mb-6\">{message}</p>\n\n {onBack && (\n <button\n type=\"button\"\n onClick={onBack}\n className=\"inline-flex items-center gap-2 px-4 py-2 text-sm font-medium text-white bg-[#7f22fe] hover:bg-primary-alt rounded-lg transition-colors focus-ring\"\n >\n Go Back\n </button>\n )}\n </div>\n </div>\n))\nErrorState.displayName = 'ErrorState'\n","/* eslint-disable react-hooks/refs -- pre-existing pattern flagged by the React\n Compiler rules added in eslint-plugin-react-hooks v7; refactoring it is\n out of scope for the lint toolchain upgrade. */\nimport React, { useCallback, useEffect, useRef, useState } from 'react'\nimport type { Channel } from 'stream-chat'\n\nimport { useMessaging } from '../../hooks/useMessaging'\nimport type { MessagingShellProps } from '../../types'\nimport { ChannelView } from '../ChannelView'\n\nimport { ErrorState } from './ErrorState'\nimport { LoadingState } from './LoadingState'\n\n/**\n * Direct-conversation surface for one specific participant.\n *\n * Renders a single ChannelView for the channel between the connected user and\n * `initialParticipantFilter`. If no channel exists yet and\n * `initialParticipantData` is supplied, the configured StreamChatService\n * channel creator is invoked to create one.\n */\nexport const MessagingShell: React.FC<MessagingShellProps> = ({\n capabilities = {},\n renderMessageInputActions,\n renderConversationFooter,\n onChannelSelect,\n onExitConversation,\n initialParticipantFilter,\n initialParticipantData,\n CustomChannelEmptyState,\n onBlockParticipantClick,\n onReportParticipantClick,\n dmAgentEnabled,\n onMessageSent,\n chatbotVotingEnabled = false,\n viewerLanguage,\n renderChannelBanner,\n customChannelActions,\n renderChannelActions,\n onParticipantNameClick,\n onBroadcastClick,\n resolveBroadcastName,\n renderMessage,\n onMessageLinkClick,\n showChannelInfo,\n composerInput,\n}) => {\n const {\n client,\n isConnected,\n isLoading,\n error,\n refreshConnection,\n service,\n debug,\n } = useMessaging()\n\n const [selectedChannel, setSelectedChannel] = useState<Channel | null>(null)\n const [directConversationError, setDirectConversationError] = useState<\n string | null\n >(null)\n const [didExit, setDidExit] = useState(false)\n\n const { showDeleteConversation = true } = capabilities\n\n // Stash consumer props that are unstable when passed inline (object\n // literals, arrow-function callbacks) so the load effect's deps stay\n // identity-stable. Without this, the documented usage pattern in the\n // README — passing `initialParticipantData={{ ... }}` and\n // `onChannelSelect={(ch) => ...}` — re-fires the effect on every render\n // and triggers a queryChannels call each time.\n const initialParticipantDataRef = useRef(initialParticipantData)\n initialParticipantDataRef.current = initialParticipantData\n const onChannelSelectRef = useRef(onChannelSelect)\n onChannelSelectRef.current = onChannelSelect\n\n // Track the direct-conversation load to prevent repeated/concurrent loads.\n // Identity-stable deps (above) stop the common re-fire, but legitimate dep\n // changes (e.g. `service`/`client` settling during connect) can still re-run\n // this effect before the just-created channel is indexed, each firing another\n // startChannelWithParticipant call and creating duplicate welcome messages.\n const directConversationLoadRef = useRef<string | null>(null)\n\n // Mirror the currently-selected channel into a ref so the async load can read\n // the latest value rather than the (possibly stale) effect-closure value.\n const selectedChannelRef = useRef<Channel | null>(null)\n useEffect(() => {\n selectedChannelRef.current = selectedChannel\n }, [selectedChannel])\n\n useEffect(() => {\n if (!client || !isConnected) return\n\n const userId = client.userID\n if (!userId) return\n\n // Only load once per viewer ↔ participant pair. Set synchronously (before\n // the async work) so re-runs triggered by changing dependency identities\n // bail out instead of issuing another channel-create request.\n const loadKey = `${userId}::${initialParticipantFilter}`\n if (directConversationLoadRef.current === loadKey) return\n directConversationLoadRef.current = loadKey\n\n // Release the guard only if it still belongs to this load. A newer load for\n // a different pair may have taken ownership while this one was in flight, so\n // clearing unconditionally could wipe the newer guard and let a duplicate\n // load/create slip through.\n const releaseLoadGuard = () => {\n if (directConversationLoadRef.current === loadKey) {\n directConversationLoadRef.current = null\n }\n }\n\n const loadInitialChannel = async () => {\n try {\n if (debug) {\n console.log(\n '[MessagingShell] Loading initial conversation with:',\n initialParticipantFilter\n )\n }\n\n const channels = await client.queryChannels(\n {\n type: 'messaging',\n members: { $eq: [userId, initialParticipantFilter] },\n },\n {},\n { limit: 1 }\n )\n\n if (channels.length > 0) {\n setSelectedChannel(channels[0])\n setDirectConversationError(null)\n onChannelSelectRef.current?.(channels[0])\n\n if (debug) {\n console.log(\n '[MessagingShell] Initial conversation loaded:',\n channels[0].id\n )\n }\n return\n }\n\n const participantData = initialParticipantDataRef.current\n if (!participantData || !service) {\n // Allow a retry once participant data / service become available.\n releaseLoadGuard()\n setDirectConversationError('No conversation found with this account')\n if (debug) {\n console.log(\n '[MessagingShell] No conversation found for:',\n initialParticipantFilter\n )\n }\n return\n }\n\n try {\n const channel = await service.startChannelWithParticipant({\n id: participantData.id,\n name: participantData.name,\n phone: participantData.phone,\n })\n setSelectedChannel(channel)\n setDirectConversationError(null)\n onChannelSelectRef.current?.(channel)\n\n if (debug) {\n console.log(\n '[MessagingShell] Channel created and loaded:',\n channel.id\n )\n }\n } catch (createErr) {\n console.error(\n '[MessagingShell] Failed to create conversation:',\n createErr\n )\n // Allow a retry for this pair after a transient failure.\n releaseLoadGuard()\n setDirectConversationError('Failed to create conversation')\n }\n } catch (err) {\n console.error(\n '[MessagingShell] Failed to load initial conversation:',\n err\n )\n // Allow a retry for this pair after a transient failure.\n releaseLoadGuard()\n // Don't replace an already-loaded conversation with an error screen.\n // Read the latest selected channel via ref to avoid acting on a stale\n // closure value when the channel was selected mid-flight.\n if (!selectedChannelRef.current) {\n setDirectConversationError('Failed to load conversation')\n }\n }\n }\n\n void loadInitialChannel()\n }, [initialParticipantFilter, client, isConnected, service, debug])\n\n // Leave / block clears the selected channel and notifies the consumer.\n // The consumer owns what happens next — typically unmounting MessagingShell\n // or re-rendering with new participant data. When no callback is provided,\n // the shell renders an \"ended\" state rather than an indefinite spinner so\n // the surface remains honest about why no conversation is shown.\n const onExitConversationRef = useRef(onExitConversation)\n onExitConversationRef.current = onExitConversation\n const handleExitConversation = useCallback(() => {\n setSelectedChannel(null)\n setDidExit(true)\n onExitConversationRef.current?.()\n }, [])\n\n if (isLoading) {\n return <LoadingState />\n }\n\n if (error) {\n return <ErrorState message={error} onBack={refreshConnection} />\n }\n\n if (!isConnected || !client) {\n return (\n <ErrorState\n message=\"Not connected to messaging service\"\n onBack={refreshConnection}\n />\n )\n }\n\n if (directConversationError) {\n return <ErrorState message={directConversationError} />\n }\n\n if (didExit && !selectedChannel) {\n return <ErrorState message=\"Conversation ended\" />\n }\n\n if (!selectedChannel) {\n return <LoadingState />\n }\n\n return (\n <div className=\"messaging-shell h-full bg-background-primary overflow-hidden\">\n <div className=\"flex h-full min-h-0 flex-col\">\n <ChannelView\n channel={selectedChannel}\n key={selectedChannel.id}\n renderMessageInputActions={renderMessageInputActions}\n renderConversationFooter={renderConversationFooter}\n renderChannelBanner={renderChannelBanner}\n onLeaveConversation={handleExitConversation}\n onBlockParticipant={handleExitConversation}\n CustomChannelEmptyState={CustomChannelEmptyState}\n showDeleteConversation={showDeleteConversation}\n onBlockParticipantClick={onBlockParticipantClick}\n onReportParticipantClick={onReportParticipantClick}\n dmAgentEnabled={dmAgentEnabled}\n onMessageSent={onMessageSent}\n chatbotVotingEnabled={chatbotVotingEnabled}\n viewerLanguage={viewerLanguage}\n customChannelActions={customChannelActions}\n renderChannelActions={renderChannelActions}\n onParticipantNameClick={onParticipantNameClick}\n onBroadcastClick={onBroadcastClick}\n resolveBroadcastName={resolveBroadcastName}\n renderMessage={renderMessage}\n onMessageLinkClick={onMessageLinkClick}\n showChannelInfo={showChannelInfo}\n composerInput={composerInput}\n />\n </div>\n </div>\n )\n}\n","import type { Channel } from 'stream-chat'\n\n/**\n * Restores pending messages into the channel's visible message list so they\n * appear as if they were already sent.\n *\n * Stream's pending-messages feature removes messages from the channel view\n * once client state is lost (e.g. page refresh). This function works around\n * that limitation by reading `channel.state.pending_messages` and\n * re-inserting them via `channel.state.addMessageSorted`.\n */\nexport function restorePendingMessages(channel: Channel) {\n const pendingMessages = channel.state.pending_messages\n if (!pendingMessages?.length) return\n\n for (const pending of pendingMessages) {\n channel.state.addMessageSorted(pending.message)\n }\n}\n","import React from 'react'\nimport type { Channel, LocalMessage } from 'stream-chat'\n\nimport type { ChannelListProps } from '../../types'\n\ntype ChannelListContextValue = {\n selectedChannel?: Channel | null\n onChannelSelect: (channel: Channel) => void\n debug: boolean\n renderMessagePreview?: (\n message: LocalMessage | undefined,\n defaultPreview?: string\n ) => React.ReactNode\n channelPreview?: ChannelListProps['channelPreview']\n viewerLanguage?: string\n}\n\nconst ChannelListContext = React.createContext<ChannelListContextValue>({\n selectedChannel: undefined,\n onChannelSelect: () => {},\n debug: false,\n renderMessagePreview: undefined,\n channelPreview: undefined,\n viewerLanguage: undefined,\n})\n\nexport const ChannelListProvider = ChannelListContext.Provider\n\nexport const useChannelListContext = () => React.useContext(ChannelListContext)\n","/**\n * Get the number of days between two dates (calendar days in UTC, not 24-hour periods)\n * Uses UTC to ensure consistent day calculations globally since messages are stored in UTC\n */\nconst getDaysDifference = (date1: Date, date2: Date): number => {\n const d1 = new Date(\n Date.UTC(date1.getUTCFullYear(), date1.getUTCMonth(), date1.getUTCDate())\n )\n const d2 = new Date(\n Date.UTC(date2.getUTCFullYear(), date2.getUTCMonth(), date2.getUTCDate())\n )\n const diffTime = d2.getTime() - d1.getTime()\n return Math.floor(diffTime / (1000 * 60 * 60 * 24))\n}\n\n/**\n * Format a date - shows time for today, relative time for older messages\n * (e.g., \"Just now\", \"2:08 PM\" for today, \"Yesterday\" for yesterday, \"2d\" for 2 days ago)\n */\nexport const formatRelativeTime = (date: Date): string => {\n const now = new Date()\n const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000)\n\n // Less than 1 minute\n if (diffInSeconds < 60) {\n return 'Just now'\n }\n\n // Check if it's today (same calendar day)\n const daysDiff = getDaysDifference(date, now)\n\n // If today, show time in 12-hour format (e.g., \"8:40 PM\")\n if (daysDiff === 0) {\n return date.toLocaleTimeString([], {\n hour: 'numeric',\n minute: '2-digit',\n hour12: true,\n })\n }\n\n // Yesterday\n if (daysDiff === 1) {\n return 'Yesterday'\n }\n\n // Less than 7 days - show days\n if (daysDiff < 7) {\n return `${daysDiff}d`\n }\n\n // Less than 4 weeks - show weeks\n if (daysDiff < 28) {\n const weeks = Math.floor(daysDiff / 7)\n return `${weeks}w`\n }\n\n // More than 4 weeks - show locale-aware date with spelled-out month\n return date.toLocaleDateString(undefined, {\n day: 'numeric',\n month: 'short',\n year: '2-digit',\n })\n}\n","import { MESSAGE_CUSTOM_TYPE } from '@linktr.ee/messaging-taxonomy'\nimport classNames from 'classnames'\nimport React from 'react'\nimport {\n ChannelPreviewUIComponentProps,\n useChatContext,\n} from 'stream-chat-react'\n\nimport { useChannelStar } from '../../hooks/useChannelStar'\nimport { formatRelativeTime } from '../../utils/formatRelativeTime'\nimport { getMessageDisplayText } from '../../utils/getMessageDisplayText'\nimport { resolveConversationParticipant } from '../../utils/resolveConversationParticipant'\nimport { resolveParticipantDisplayName } from '../../utils/resolveParticipantDisplayName'\nimport { Avatar } from '../Avatar'\nimport { isChatbotMessage } from '../CustomMessage/MessageTag'\n\nimport { useChannelListContext } from './ChannelListContext'\n\n/**\n * Custom channel preview that handles selection\n */\nconst CustomChannelPreview = React.memo<ChannelPreviewUIComponentProps>(\n (props) => {\n const { channel, unread } = props\n const {\n selectedChannel,\n onChannelSelect,\n debug,\n channelPreview,\n renderMessagePreview,\n viewerLanguage,\n } = useChannelListContext()\n const { client } = useChatContext()\n\n const isSelected = selectedChannel?.id === channel?.id\n const isChannelStarred = useChannelStar(channel)\n\n if (channelPreview) {\n const ChannelPreview = channelPreview\n\n return (\n <ChannelPreview\n {...props}\n active={isSelected}\n selectedChannel={selectedChannel}\n onChannelSelect={onChannelSelect}\n viewerLanguage={viewerLanguage}\n />\n )\n }\n\n const handleClick = () => {\n if (channel) {\n onChannelSelect(channel)\n }\n }\n const handleKeyDown = (event: React.KeyboardEvent<HTMLDivElement>) => {\n const isActivationKey = event.key === 'Enter' || event.key === ' '\n const isRepeatedKeydown = event.repeat\n\n if (!isActivationKey || isRepeatedKeydown) return\n\n event.preventDefault()\n handleClick()\n }\n\n // Get participant info\n const participant = resolveConversationParticipant(\n channel?.state?.members,\n client?.userID,\n channel?.type\n )\n const participantName = resolveParticipantDisplayName(participant?.user)\n const participantImage = participant?.user?.image\n\n // Get last non-system message for preview\n const lastMessage = (() => {\n const messages = channel?.state?.messages\n if (!messages?.length) return undefined\n for (let i = messages.length - 1; i >= 0; i--) {\n if (messages[i].type !== 'system') return messages[i]\n }\n return undefined\n })()\n\n const getLastMessageText = () => {\n const displayText = getMessageDisplayText({\n message: lastMessage,\n viewerLanguage,\n })\n\n const { custom_type, attachment_content_type } =\n lastMessage?.metadata || {}\n\n if (custom_type === MESSAGE_CUSTOM_TYPE.TIP) {\n return displayText ? displayText : 'Sent a tip'\n }\n if (custom_type === MESSAGE_CUSTOM_TYPE.PAID) {\n return displayText ? displayText : 'Sent a message'\n }\n if (custom_type === MESSAGE_CUSTOM_TYPE.ATTACHMENT) {\n if (attachment_content_type === 'text') {\n return '🔒 Sent a locked message'\n }\n if (attachment_content_type === 'media') {\n return '🔒 Sent a locked attachment'\n }\n }\n\n if (displayText) return displayText\n\n const attachment = lastMessage?.attachments?.[0]\n if (attachment) {\n // Link previews - show the actual URL\n if (attachment.og_scrape_url) return attachment.og_scrape_url\n\n // Type-based detection\n if (attachment.type === 'image') return '📷 Sent an image'\n if (attachment.type === 'video') return '🎥 Sent a video'\n if (attachment.type === 'audio') return '🎵 Sent audio'\n if (attachment.type === 'file') return '📎 Sent a file'\n\n // Fallback\n return '📎 Sent an attachment'\n }\n\n return 'No messages yet'\n }\n\n const lastMessageText = getLastMessageText()\n const lastMessageTime = lastMessage?.created_at\n ? formatRelativeTime(new Date(lastMessage.created_at))\n : ''\n const isLastMessageFromChatbot = lastMessage\n ? isChatbotMessage(lastMessage)\n : false\n\n const messagePreview = renderMessagePreview\n ? renderMessagePreview(lastMessage, lastMessageText)\n : `${isLastMessageFromChatbot ? '✨ ' : ''}${lastMessageText}`\n\n // Use the unread prop passed by Stream Chat (reactive and updates automatically)\n const unreadCount = unread ?? 0\n\n if (debug) {\n console.log('📺 [ChannelList] 📋 CHANNEL PREVIEW RENDER', {\n channelId: channel?.id,\n isSelected,\n participantName,\n unreadCount,\n hasTimestamp: !!lastMessageTime,\n })\n }\n\n return (\n <div\n role=\"button\"\n tabIndex={0}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n className={classNames(\n 'group w-full px-4 py-3 transition-colors text-left max-w-full overflow-hidden focus-ring rounded-[12px] [&+&]:mt-2',\n {\n 'bg-black/[0.04]': isSelected,\n 'hover:bg-black/[0.02]': !isSelected,\n }\n )}\n data-dd-privacy=\"mask\"\n >\n <div className=\"flex items-start gap-4\">\n {/* Avatar */}\n <Avatar\n id={participant?.user?.id || channel.id || 'unknown'}\n name={participantName}\n image={participantImage}\n size={48}\n starred={isChannelStarred}\n />\n\n {/* Content column */}\n <div className=\"flex-1 min-w-0 flex flex-col gap-1\">\n {/* Name and timestamp row */}\n <div className=\"flex items-center justify-between gap-2\">\n <h3\n className={classNames(\n 'text-sm font-medium truncate text-[#191918]'\n )}\n >\n {isChannelStarred && (\n <span className=\"sr-only\">Starred conversation. </span>\n )}\n {participantName}\n </h3>\n {lastMessageTime && (\n <span className=\"text-xs text-[#717070] flex-shrink-0\">\n {lastMessageTime}\n </span>\n )}\n </div>\n\n {/* Message and unread badge row */}\n <div className=\"flex items-center justify-between gap-2 min-w-0\">\n <p className=\"text-sm text-[#717070] flex-1 line-clamp-1\">\n {messagePreview}\n </p>\n {unreadCount > 0 && (\n <span className=\"bg-[#7f22fe] text-white text-[10px] rounded-full h-4 flex items-center justify-center p-1 min-w-4 text-center flex-shrink-0\">\n {unreadCount > 99 ? '99+' : unreadCount}\n </span>\n )}\n </div>\n </div>\n </div>\n </div>\n )\n }\n)\n\nexport default CustomChannelPreview\nCustomChannelPreview.displayName = 'CustomChannelPreview'\n","import classNames from 'classnames'\nimport React from 'react'\nimport type { Channel } from 'stream-chat'\nimport {\n ChannelList as StreamChannelList,\n InfiniteScroll,\n} from 'stream-chat-react'\n\nimport { restorePendingMessages } from '../../hooks/useRestorePendingMessages'\nimport { useMessagingContext } from '../../providers/MessagingProvider'\nimport type { ChannelListProps } from '../../types'\n\nimport { ChannelListProvider } from './ChannelListContext'\nimport CustomChannelPreview from './CustomChannelPreview'\n\nconst DEFAULT_SORT = { last_message_at: -1 } as const\n\n/**\n * Channel list component with customizable header and actions\n */\nexport const ChannelList = React.memo<ChannelListProps>(\n ({\n onChannelSelect,\n selectedChannel,\n filters,\n allowNewMessagesFromUnfilteredChannels = false,\n channelRenderFilterFn,\n sort = DEFAULT_SORT,\n className,\n customEmptyStateIndicator,\n channelListPaginator: Paginator = InfiniteScroll,\n channelPreview,\n renderMessagePreview,\n viewerLanguage,\n lockChannelOrder,\n onMessageNewHandler,\n onMessageNew,\n onChannelVisible,\n onAddedToChannel,\n onChannelUpdated,\n }) => {\n // Track renders\n const renderCountRef = React.useRef(0)\n renderCountRef.current++\n\n // Get debug flag from context\n const { debug = false } = useMessagingContext()\n\n // Wrap channelRenderFilterFn to restore pending messages for all channels\n // as soon as they are loaded, without waiting for the user to click into each one.\n const wrappedChannelRenderFilterFn = React.useCallback(\n (channels: Channel[]) => {\n for (const channel of channels) {\n restorePendingMessages(channel)\n }\n return channelRenderFilterFn\n ? channelRenderFilterFn(channels)\n : channels\n },\n [channelRenderFilterFn]\n )\n\n if (debug) {\n console.log('📺 [ChannelList] 🔄 RENDER START', {\n renderCount: renderCountRef.current,\n selectedChannelId: selectedChannel?.id,\n filters,\n })\n }\n\n const contextValue = React.useMemo(\n () => ({\n selectedChannel,\n onChannelSelect,\n debug,\n channelPreview,\n renderMessagePreview,\n viewerLanguage,\n }),\n [\n selectedChannel,\n onChannelSelect,\n debug,\n channelPreview,\n renderMessagePreview,\n viewerLanguage,\n ]\n )\n\n return (\n <div\n className={classNames(\n 'messaging-channel-list h-full flex flex-col min-w-0 overflow-hidden',\n className\n )}\n >\n {/* Channel List */}\n <div className=\"flex-1 overflow-hidden min-w-0\">\n <ChannelListProvider value={contextValue}>\n <StreamChannelList\n key={`${JSON.stringify(filters)}:${JSON.stringify(sort)}`}\n filters={filters}\n sort={sort}\n options={{ limit: 30 }}\n allowNewMessagesFromUnfilteredChannels={\n allowNewMessagesFromUnfilteredChannels\n }\n channelRenderFilterFn={wrappedChannelRenderFilterFn}\n lockChannelOrder={lockChannelOrder}\n onMessageNewHandler={onMessageNewHandler}\n onMessageNew={onMessageNew}\n onChannelVisible={onChannelVisible}\n onAddedToChannel={onAddedToChannel}\n onChannelUpdated={onChannelUpdated}\n Paginator={Paginator}\n Preview={CustomChannelPreview}\n EmptyStateIndicator={customEmptyStateIndicator}\n />\n </ChannelListProvider>\n </div>\n </div>\n )\n }\n)\nChannelList.displayName = 'ChannelList'\n","import React from 'react'\n\nimport type { MessageBubbleVariant } from '../../types'\n\n/**\n * Canonical chat-bubble tail (20×23). Kept identical to the in-channel tail\n * drawn by `CustomMessage` in `styles.css` so standalone previews and real\n * messages share one silhouette — the single source of truth for the shape.\n *\n * The path points to the bottom-*right*; the `received` variant mirrors it\n * with `scaleX(-1)`, matching the in-channel convention.\n */\nconst TAIL_MASK =\n \"url(\\\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='23' fill='none'%3E%3Cpath fill='black' d='M0 0H15C15 10.1934 15.859 15.2345 19.168 21.4893C19.527 22.168 19.039 22.9917 18.274 22.9178C5.176 21.6506 0.32 6.0737 0 0Z'/%3E%3C/svg%3E\\\") no-repeat center / 100% 100%\"\n\n/**\n * Bubble surface colours, reused from the toolkit's Stream theme vars so the\n * tail is always tinted the same colour as its bubble. Those vars are declared\n * on `.str-chat`, so we supply the canonical values as `var()` fallbacks —\n * that keeps the tail correct when rendered *outside* a channel (e.g. a\n * standalone preview) while still honouring the var (or a consumer override)\n * wherever it's defined.\n */\nconst BG_VAR_BY_VARIANT: Record<MessageBubbleVariant, string> = {\n sent: 'var(--str-chat__own-message-bubble-background-color, #1e2330)',\n received: 'var(--str-chat__message-bubble-background-color, #f1f0ee)',\n}\n\n/**\n * The tail element. Absolutely positioned at the bubble's bottom corner and\n * painted behind the bubble body (`z-index: -1`), so the parent bubble must be\n * `position: relative` with `isolation: isolate` (see {@link BubbleShell}).\n */\nexport const BubbleTail = ({ variant }: { variant: MessageBubbleVariant }) => (\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute bottom-0 z-[-1] h-[1.4375rem] w-5\"\n style={{\n insetInlineEnd: variant === 'sent' ? 'calc(-1 * 0.25rem)' : undefined,\n insetInlineStart: variant === 'received' ? 'calc(-1 * 0.25rem)' : undefined,\n transform: variant === 'received' ? 'scaleX(-1)' : undefined,\n transformOrigin: 'center',\n backgroundColor: BG_VAR_BY_VARIANT[variant],\n WebkitMask: TAIL_MASK,\n mask: TAIL_MASK,\n }}\n />\n)\n","import classNames from 'classnames'\nimport React from 'react'\n\nimport type { MessageBubbleVariant } from '../../types'\n\nimport { BubbleTail } from './bubbleTail'\n\nexport interface BubbleShellProps {\n variant: MessageBubbleVariant\n text: string\n /** Draw the bubble tail. Defaults to `true`. */\n tail?: boolean\n /** Optional header rendered above the text (e.g. sender name). */\n header?: React.ReactNode\n /**\n * Width is caller-controlled — pass a width class in `className`\n * (`w-fit` to hug the text for chat/preview bubbles, `w-full` to fill the\n * container for card-like list rows). With no width class the bubble is a\n * block element and fills its container.\n */\n className?: string\n}\n\n/**\n * Surface colours and metrics are pulled from the toolkit's Stream theme vars\n * (see `styles.css`) so a standalone bubble is pixel-identical to the\n * in-channel one and re-themes from the same single source of truth.\n */\nconst SURFACE_STYLE_BY_VARIANT: Record<\n MessageBubbleVariant,\n React.CSSProperties\n> = {\n sent: {\n backgroundColor:\n 'var(--str-chat__own-message-bubble-background-color, #1e2330)',\n color: 'var(--str-chat__own-message-bubble-color, #fff)',\n },\n received: {\n backgroundColor:\n 'var(--str-chat__message-bubble-background-color, #f1f0ee)',\n color: 'var(--str-chat__message-bubble-color, #000000)',\n },\n}\n\n/**\n * The rounded bubble box: theme-driven surface, channel-matched typography\n * (`0.875rem / 1.3125rem`, `0.14px` tracking, `0.75rem 1rem` padding), an\n * optional header slot, and an optional tail.\n *\n * `isolation: isolate` forms a stacking context so the `z-index: -1` tail\n * paints behind the bubble's own opaque, same-colour background but in front\n * of the surrounding page — matching the in-channel `::after` tail.\n *\n * `data-dd-privacy=\"mask\"` masks the message text (and header) from Datadog\n * session replay by default, matching the in-channel renderers\n * (`CustomMessage`, `MediaMessage`). Since this bubble is used for standalone\n * previews of real user content outside `ChannelView`, masking must live on\n * the component rather than relying on every consumer to wrap it.\n */\nconst BubbleShell: React.FC<BubbleShellProps> = ({\n variant,\n text,\n tail = true,\n header,\n className,\n}) => (\n <div\n data-dd-privacy=\"mask\"\n className={classNames(\n 'relative px-4 py-3',\n 'text-[0.875rem] leading-[1.3125rem] tracking-[0.14px]',\n className\n )}\n style={{\n ...SURFACE_STYLE_BY_VARIANT[variant],\n borderRadius: 'var(--str-chat__message-bubble-border-radius, 1.5rem)',\n isolation: 'isolate',\n }}\n >\n {header != null && (\n <div className=\"mb-1 font-medium\" data-testid=\"message-bubble-header\">\n {header}\n </div>\n )}\n <p className=\"m-0 whitespace-pre-wrap break-words\">{text}</p>\n {tail && <BubbleTail variant={variant} />}\n </div>\n)\n\nexport default BubbleShell\n","import React from 'react'\n\nimport type { ReceivedBubbleProps } from '../../types'\nimport BubbleShell from '../_shared/BubbleShell'\n\n/**\n * A message bubble in the recipient's treatment — light surface, left-side\n * tail, with an optional header (e.g. sender name). Use to preview how a\n * message looks *to the visitor* — including a preview of your own outgoing\n * message as the recipient will receive it (e.g. a bulk-reply confirmation).\n */\nconst ReceivedCard: React.FC<ReceivedBubbleProps> = ({\n text,\n tail,\n header,\n className,\n}) => (\n <BubbleShell\n variant=\"received\"\n text={text}\n tail={tail}\n header={header}\n className={className}\n />\n)\n\nexport default ReceivedCard\n","import React from 'react'\n\nimport type { SentBubbleProps } from '../../types'\nimport BubbleShell from '../_shared/BubbleShell'\n\n/**\n * A message bubble in the sender's own treatment — dark surface, right-side\n * tail. Use to preview how a message looks *to you in the channel*.\n *\n * Note: the variant is a visual treatment, not an authorship claim. To preview\n * an outgoing message as the *recipient* will see it, use\n * `MessageBubble.Received` instead.\n */\nconst SentCard: React.FC<SentBubbleProps> = ({ text, tail, className }) => (\n <BubbleShell variant=\"sent\" text={text} tail={tail} className={className} />\n)\n\nexport default SentCard\n","import ReceivedCard from './components/Received/Card'\nimport SentCard from './components/Sent/Card'\n\n/**\n * A dumb, context-free chat message bubble for rendering a single message row\n * *outside* a live channel — previews, digests, confirmation dialogs, the\n * Stacks \"responded\" summary, etc. Unlike `ChannelView`, it needs no Stream\n * client or provider.\n *\n * Render `MessageBubble.Sent` for the sender's own treatment (dark, right\n * tail) and `MessageBubble.Received` for the recipient's (light, left tail,\n * optional header). Surface colours, radius, typography, and the tail\n * silhouette are shared with the in-channel bubble drawn by `CustomMessage`,\n * so previews stay pixel-identical and re-theme from one source of truth.\n *\n * The variant is a **visual treatment, not an authorship claim**: to preview\n * an outgoing message as the recipient will see it, render\n * `MessageBubble.Received` with your own text.\n */\nconst MessageBubble = {\n Sent: SentCard,\n Received: ReceivedCard,\n}\n\nexport default MessageBubble\nexport type {\n MessageBubbleBaseProps,\n MessageBubbleVariant,\n SentBubbleProps,\n ReceivedBubbleProps,\n} from './types'\n","import classNames from 'classnames'\nimport React from 'react'\nexport interface FaqListItemProps {\n question: string\n onClick: () => void\n loading?: boolean\n className?: string\n}\n\nexport const FaqListItem: React.FC<FaqListItemProps> = ({\n question,\n onClick,\n loading = false,\n className,\n}) => {\n return (\n <button\n type=\"button\"\n onClick={onClick}\n disabled={loading}\n style={{ backgroundColor: '#E6E5E3' }}\n className={classNames(\n 'w-full text-center p-4 rounded-xl text-charcoal font-medium transition-colors focus-ring',\n {\n 'hover:brightness-95 active:brightness-90': !loading,\n 'opacity-50 cursor-not-allowed': loading,\n },\n className\n )}\n >\n {question}\n </button>\n )\n}\n","import { selectEnabledFaqs } from '@linktr.ee/messaging-taxonomy'\nimport React from 'react'\n\nimport { Avatar } from '../Avatar'\n\nimport { FaqListItem } from './FaqListItem'\n\nexport interface Faq {\n id: string\n question: string\n answer: string\n enabled: boolean\n order?: number | null\n}\n\nexport interface FaqListProps {\n faqs: Faq[]\n onFaqClick: (faqId: string) => void\n loadingFaqId?: string | null\n headerText?: string\n className?: string\n avatarImage?: string\n avatarName?: string\n}\n\nexport const FaqList: React.FC<FaqListProps> = ({\n faqs,\n onFaqClick,\n loadingFaqId,\n headerText,\n className,\n avatarImage,\n avatarName,\n}) => {\n const enabledFaqs = selectEnabledFaqs(faqs)\n\n if (enabledFaqs.length === 0) {\n return null\n }\n\n return (\n <div className={className}>\n <div className=\"flex gap-3 items-end\">\n {/* Avatar at bottom-left, outside grey background */}\n {(avatarImage || avatarName) && (\n <div className=\"flex-none\">\n <Avatar\n id={avatarName || 'account'}\n name={avatarName || 'Account'}\n image={avatarImage}\n size={24}\n shape=\"circle\"\n />\n </div>\n )}\n\n {/* FAQs with grey background */}\n <div\n className=\"flex-1 flex flex-col gap-3 rounded-lg p-4\"\n style={{ backgroundColor: '#F1F0EE' }}\n >\n {headerText && (\n <p className=\"text-md text-charcoal mb-4\">{headerText}</p>\n )}\n {enabledFaqs.map((faq) => (\n <FaqListItem\n key={faq.id}\n question={faq.question}\n onClick={() => onFaqClick(faq.id)}\n loading={loadingFaqId === faq.id}\n />\n ))}\n </div>\n </div>\n </div>\n )\n}\n"],"names":["MessagingContext","createContext","useMessagingContext","useContext","MessagingProvider","children","user","serviceConfig","apiKey","capabilities","debug","injectedClient","debugLog","useCallback","message","args","service","setService","useState","client","setClient","isConnected","setIsConnected","isLoading","setIsLoading","error","setError","connectingRef","useRef","serviceRef","serviceConfigRef","debugRef","prevPropsRef","renderCountRef","clientRef","_a","StreamChat","chatClient","_b","useEffect","currentRender","currentConfig","newService","StreamChatService","connectedUserRef","streamClient","err","errorMessage","refreshConnection","contextValue","React","jsx","Chat","useMessaging","useChannelStar","channel","isChannelStarred","setIsChannelStarred","handleMemberUpdate","event","resolveConversationParticipant","members","currentUserId","channelType","memberList","isOfficialChannel","officialSender","member","OFFICIAL_SENDER_USER_ID","UUID_REGEX","isUuidLike","value","isUsableDisplayValue","userId","trimmed","resolveParticipantDisplayName","FRUITS","hashString","str","hash","i","char","getFruit","id","getAvatarEmoji","getAvatarBgColor","Avatar","image","size","className","starred","shape","dmAgentEnabled","emoji","bgColor","SMALL_EMOJI_RATIO","fontSize","aiBorderWidth","borderStyle","avatarInner","classNames","jsxs","StarIcon","REPORT_URL","useChannelModerationActions","participant","showBlockParticipant","enabled","onLeaveConversation","onBlockParticipant","onDeleteConversationClick","onBlockParticipantClick","onReportParticipantClick","onActionComplete","logLabel","participantId","willLookup","isParticipantBlocked","setIsParticipantBlocked","resolvedFor","setResolvedFor","isLeaving","setIsLeaving","isUpdatingBlockStatus","setIsUpdatingBlockStatus","isCheckingBlockedStatus","cancelled","blockedUsers","actingUserId","_c","ActionButton","variant","rest","ChannelActionsMenu","showDeleteConversation","showReportParticipant","customChannelActions","triggerClassName","isOpen","setIsOpen","containerRef","menuId","useId","close","handleLeaveConversation","handleBlockUser","handleUnblockUser","handleReportUser","handlePointerDown","handleKeyDown","open","DotsThreeIcon","SpinnerGapIcon","SignOutIcon","ProhibitInsetIcon","FlagIcon","ICON_BTN_CLASS","CUSTOMER_PAID_TAG","isCustomerPaidTag","ChannelHeaderRedesign","onBack","showBackButton","showStarButton","renderChannelActions","showChannelInfo","onParticipantNameClick","useChannelStateContext","useChatContext","participantName","participantImage","isStarred","isPaidCustomer","showStarBadge","hasNameAdornment","handleStarClick","identityContent","Fragment","_d","CurrencyDollarIcon","CaretRightIcon","ArrowLeftIcon","CustomDateSeparator","props","DateSeparator","VOTE_UP","VOTE_DOWN","getVoteFromReactions","ownReactions","r","useMessageVote","selected","useMemo","voteUp","voteDown","normalizeLanguageCode","language","getMessageDisplayText","viewerLanguage","fallbackText","normalizedLanguage","LINKTREE_CDN_HOSTS","ATTACHMENT_IMAGE_SIZE_PRESET","hostnameFromUrl","url","isLinktreeCdnHost","hostname","host","optimizeMessagingAttachmentUrl","parsedUrl","DOCUMENT_ICON_PATTERNS","getSourceType","mimeType","getDocumentIconType","match","pattern","MEDIA_TYPE_ICON","VideoCameraIcon","SpeakerHighIcon","ImageIcon","FileIcon","DOCUMENT_ICON_COMPONENT","FilePdfIcon","FileDocIcon","FileXlsIcon","FileCsvIcon","FilePptIcon","FileZipIcon","FileTextIcon","FileMdIcon","getTypeIcon","sourceType","renderTypeIcon","getClientXFromEvent","MediaPlayer","source","poster","autoPlay","playingProp","loop","controls","showProgress","muted","onContainerClick","playerRef","trackRef","rafRef","prevPlayingPropRef","playing","setPlaying","played","setPlayed","seeking","setSeeking","scrubberHovered","setScrubberHovered","manualPlayRequired","setManualPlayRequired","buffering","setBuffering","initialLoad","setInitialLoad","videoAspect","setVideoAspect","startPlaybackFromGesture","getFraction","e","track","rect","seekTo","fraction","el","handleTrackPointerDown","tick","onMove","onUp","aspectStyle","aspectClass","scrubberPercent","p","CircleNotchIcon","PlayIcon","PauseIcon","placeholderIconClass","posterShellClass","AttachmentThumbnail","sourceUrl","thumbnailUrl","title","mediaPlayerProps","containedImage","sourceReady","setSourceReady","optimizedSourceUrl","optimizedThumbnailUrl","AttachmentCard","thumbnail","placeholderTitle","detail","statusBadge","action","topLeft","topRight","rootRef","dataTestId","isDark","displayTitle","titleDimmed","formatBytes","bytes","linkCardShellClass","isMyMessage","linkThumbnailBg","linkPrimaryText","linkSecondaryText","linkTertiaryText","linkIconColor","LinkCard","attachment","text","image_url","og_scrape_url","title_link","rawUrl","body","LinkIcon","isLinkAttachment","a","resolveLinkAttachment","triggerDownload","filename","name","res","blob","objectUrl","DownloadAction","busy","setBusy","fallback","DownloadSimpleIcon","resolveMediaFromMessage","videoAttachment","imageAttachment","audioAttachment","fileAttachment","activeAttachment","resolvedUrl","resolvedType","fileSize","Creator","Visitor","MediaMessageRoot","linkAttachment","resolved","MediaMessageCreatorEntry","MediaMessageVisitorEntry","MediaMessage","BUBBLE_BG_BY_VARIANT","BUBBLE_TEXT_BY_VARIANT","BUBBLE_BORDER_BY_VARIANT","sideForVariant","CORNER_CLASSES_BY_SIDE_AND_POSITION","Bubble","bordered","groupPosition","widthClassName","paddingClassName","radiusClassName","hasText","cornerClasses","DismissButton","onClick","ariaLabel","XIcon","bubbleVariantForState","state","bubbleGroupPositionFromStream","firstOfGroup","endOfGroup","groupedByUser","resolveItems","src","items","NativeAudioPlayer","item","preload","trailingAction","AudioAttachmentRow","onDismiss","showDismiss","resolvedItems","resolvedPreload","index","AudioComposer","AudioSent","AudioReceived","AudioAttachment","formatFileSize","EXTENSION_LABEL_BY_DOCUMENT_TYPE","getFileExtensionLabel","lastDot","ext","docType","docLabel","subtype","buildCompactMetaLabel","filenameFromUrl","last","META_CLASS_BY_VARIANT","ICON_BG_BY_VARIANT","ICON_COLOR_BY_VARIANT","CompactDocumentRow","onActivate","activateLabel","resolvedTitle","metaLabel","iconTile","textBlock","FileRowButton","resolvedFilename","FileAttachmentRow","handleActivate","downloadIcon","FileComposer","FileSent","FileReceived","FileAttachment","CarouselNav","onPrev","onNext","prevLabel","nextLabel","CaretLeftIcon","label","iconOnly","tone","onTriggered","handleClick","showIconOnly","iconProps","clamp","min","max","useCarousel","length","initialIndex","safeInitial","setIndex","prev","next","onKey","active","ViewerShell","onClose","counter","actions","dialogRef","closeButtonRef","dialog","previouslyFocused","ImageViewer","TILE_SHELL","OUTER_CORNER_CLASSES","SINGLE_WIDTH_CAP_PROPERTY","SINGLE_WIDTH_CAPS","SINGLE_HEIGHT_CAP_PX","MediaStackGrid","tiles","onTileActivate","maxVisible","singleAspectRatio","total","visible","overflow","renderTile","tile","extra","sharedClass","singleTileStyle","isLastWithOverflow","useViewer","viewerOpen","setViewerOpen","viewerIndex","setViewerIndex","closeViewer","tileFromItem","totalCount","fallbackLoading","imgRef","onLoad","alt","buildViewerItems","ImageComposerInner","loading","RESERVED_SINGLE_ASPECT_RATIO","useSingleImageRatio","measured","setMeasured","measure","img","ratio","handleLoad","supplied","measuredRatio","ImageBubbleRow","isSingle","single","ImageComposer","ImageSent","ImageReceived","ImageAttachment","PdfViewer","iframeSrc","withPdfViewerParams","hashIndex","base","existing","params","PdfRowButton","PdfAttachmentRow","viewerItems","itemFilename","PdfComposer","PdfSent","PdfReceived","PdfAttachment","VideoViewer","PlayBadge","PosterTile","it","VideoComposerInner","VideoBubbleRow","VideoComposer","VideoSent","VideoReceived","VideoAttachment","MessageAttachment","BroadcastNameContext","broadcastIdFromMessage","broadcastId","buildBroadcastNamesById","messages","resolveBroadcastName","seen","names","areBroadcastNamesEqual","previous","previousIds","nextIds","useBroadcastNamesById","publishedNames","setPublishedNames","defaultLockedAttachmentContextValue","customMessageDefaults","CustomMessageContext","CustomMessageProvider","useCustomMessage","key","TextCardLazy","MediaCardLazy","LockedAttachmentFallback","LockedAttachment","Suspense","SparkleIcon","isTipMessage","MESSAGE_CUSTOM_TYPE","isPaidMessage","isChatbotMessage","isAttachmentMessage","isTextAttachmentMessage","isMediaAttachmentMessage","isTipOrPaidMessage","isTipOnlyMessage","MessageTag","standalone","hasAttachment","isTipOrPaid","isChatbot","amountText","amountLabel","GiftIcon","isSenderAttachmentVariant","chatbotLabel","chatbotClassName","icon","MessageVoteButtons","onVoteUp","onVoteDown","ThumbsUpIcon","ThumbsDownIcon","useIsLatestRealMessage","useMessageContext","lastMessageId","lastMessage","DeliveredStatus","ChecksIcon","SendingStatus","BroadcastStatus","broadcastName","resolvedBroadcastName","onBroadcastClick","campaignName","content","MegaphoneIcon","FailedStatus","WarningCircleIcon","SentMessageDeliveryStatus","threadList","isOwnMessage","isLatestRealMessage","broadcastStatus","messageStatus","MessageStatus","SCHEME_PATTERN","SAFE_SCHEMES","normalizeExternalHref","schemeMatch","scheme","BUTTON_CLASS_BY_VARIANT","CardCta","cta","normalizedHref","TITLE_CLASS_BY_VARIANT","TITLE_DIMMED_CLASS","SECONDARY_CLASS_BY_VARIANT","SKELETON_BAR_CLASS_BY_VARIANT","CardBody","chinTextColor","description","appIcon","hasTitle","hasDescription","trimmedUrl","hasUrl","hasCta","titleClass","secondaryClass","barClass","chinTextStyle","LOADING_LABEL","SHELL_CLASS","FIXED_HEIGHT_CLASS","CardShell","href","bgClassName","accentStyle","fixedHeight","isInteractive","busyProps","corner","PLACEHOLDER_BG","PLACEHOLDER_ICON","isPlayableAudio","isPlayableMedia","AUDIO_BG","AUDIO_BG_CLASS","CardThumbnail","onImageError","isPlayableVideo","parseNumber","color","len","named","parseNamed","hex","parseHex","num","per","num_per","hue","c","rgb_num_old","rgb_per_old","parseRgbLegacy","prepare","mode","parse","converter","target_mode","converters","modes","parsers","colorProfiles","identity","v","useMode","definition","k","parser","useParser","getMode","IdentStartCodePoint","IdentCodePoint","Tok","_i","is_num","chars","ch","ch1","is_ident","huenits","digits","ident","identlike","tokenize","tokens","alpha","parseColorSyntax","token","coords","consumeCoords","channels","ii","includeHue","parseModernSyntax","parsed","result","parseRgb","g","b","parseTransparent","lerp","t","get_classes","arr","classes","interpolatorPiecewise","interpolator","cls","idx","pair","interpolatorLinear","fixupAlpha","some_defined","linearize","convertA98ToXyz65","a98","gamma","convertXyz65ToA98","x","y","z","fn","abs","convertRgbToLrgb","convertRgbToXyz65","rgb","convertLrgbToRgb","convertXyz65ToRgb","normalizeHue","hues","normalized","acc","curr","fixupHueShorter","d","M","degToRad","radToDeg","DE","BE","BCAD","convertRgbToCubehelix","l","convertCubehelixToRgb","h","s","amp","cosh","sinh","differenceHueSaturation","std","smp","std_h","smp_h","dH","differenceHueNaive","differenceHueChroma","averageAngle","val","sum","rad","angle","convertLabToLch","convertLchToLab","D50","D65","convertLab65ToXyz65","fy","fx","fz","convertLab65ToRgb","lab","f","convertXyz65ToLab65","f0","f1","f2","convertRgbToLab65","kE","kCH","θ","cosθ","sinθ","factor","convertDlchToLab65","G","convertLab65ToDlch","convertDlabToLab65","convertLab65ToDlab","convertHsiToRgb","convertRgbToHsi","m","convertHslToRgb","m1","m2","convertRgbToHsl","hueToDeg","unit","hsl_old","parseHslLegacy","parseHsl","convertHsvToRgb","convertRgbToHsv","convertHwbToRgb","w","convertRgbToHwb","rgba","hsv","ParseHwb","parseHwb","YW","M1","M2","C1","C2","C3","transferPqDecode","transferPqEncode","toRel","convertItpToXyz65","toAbs","convertXyz65ToItp","absX","absY","absZ","d0","jabPqEncode","vn","n","convertXyz65ToJab","xp","yp","jabPqDecode","vp","rel","convertJabToXyz65","j","convertRgbToJab","convertJabToRgb","convertJabToJch","convertJchToJab","convertLabToXyz50","convertXyz50ToRgb","convertLabToRgb","convertRgbToXyz50","convertXyz50ToLab","convertRgbToLab","parseLab","parseLch","lch","convertLuvToLchuv","u","convertLchuvToLuv","u_fn","v_fn","un","l_fn","convertXyz50ToLuv","convertLuvToXyz50","up","convertRgbToLchuv","convertLchuvToRgb","lchuv","luv","convertLrgbToOklab","L","S","convertRgbToOklab","convertOklabToLrgb","convertOklabToRgb","toe","k_3","toe_inv","compute_max_saturation","k0","k1","k2","k3","k4","wl","wm","ws","k_l","k_m","k_s","l_","m_","s_","l_dS","m_dS","s_dS","l_dS2","m_dS2","s_dS2","find_cusp","S_cusp","L_cusp","C_cusp","find_gamut_intersection","L1","L0","cusp","dL","dC","l_dt","m_dt","s_dt","C","ldt","mdt","sdt","ldt2","mdt2","sdt2","r1","r2","u_r","t_r","g1","g2","u_g","t_g","b1","b2","u_b","t_b","get_ST_max","a_","b_","get_Cs","C_max","ST_max","S_mid","T_mid","C_a","C_b","C_mid","convertOklabToOkhsl","ret","C_0","k_0","k_1","k_2","convertOkhslToOklab","hsl","modeOkhsl","modeHsl","convertOklabToOkhsv","S_max","T","S_0","L_v","C_v","L_vt","C_vt","rgb_scale","scale_L","convertOkhsvToOklab","L_new","modeOkhsv","modeHsv","parseOklab","parseOklch","convertP3ToXyz65","convertXyz65ToP3","convertXyz50ToProphoto","convertProphotoToXyz50","prophoto","α","β","convertXyz65ToRec2020","convertRec2020ToXyz65","rec2020","bias","bias_cbrt","transfer","convertRgbToXyb","convertXybToRgb","convertXyz65ToXyz50","xyz65","convertXyz50ToXyz65","xyz50","convertRgbToYiq","convertYiqToRgb","q","fixup","serializeHex","formatHex","fixup_rgb","to_displayable_srgb","inrange_rgb","displayable","inGamut","gamut","conv","clampGamut","destMode","destConv","inDestGamut","original","converted","clamped","clampChroma","rgbGamut","inDestinationGamut","clipToGamut","start","end","range","resolution","_last_good_c","luminance","contrast","L2","modeA98","modeCubehelix","modeDlab","modeDlch","modeHsi","modeHwb","modeItp","modeJab","modeJch","modeLab","modeLab65","modeLch","modeLch65","modeLchuv","modeLrgb","modeLuv","modeOklab","modeOklch","modeP3","modeProphoto","modeRec2020","modeRgb","modeXyb","modeXyz50","modeXyz65","modeYiq","HEX_PATTERN","toCssHex","WCAG_AA_NORMAL_TEXT","INK_ON_DARK","INK_ON_LIGHT","contrastRatio","wcagContrast","inkFor","background","againstDarkInk","SURFACE_LIGHTNESS","INK_BY_VARIANT","toOklch","accentSurface","accentColor","surface","useChinPalette","status","layout","heroFailed","setHeroFailed","isAudio","painted","DISMISS_CLASS","DISMISS_TOUCH_TARGET_CLASS","ComposerCard","onEditClick","dismissLabel","isClassic","chin","dismissButton","editButton","PencilSimpleIcon","BubbleTail","side","ReceivedCard","isPlayingMedia","normalizedUrl","shellHref","shellOnClick","audioBg","wrappedCta","SentCard","LinkAttachment","trimToUndefined","normalizeLinkUrl","linkCaptionDuplicatesAttachmentUrl","caption","attachmentUrl","normalizedCaption","remainder","linkCardPropsFromStreamAttachment","getAttachmentMediaKind","ogScrapeUrl","buildOrderedAttachmentSegments","attachments","segments","pushOrMergeMedia","kind","pushOrMergeLink","countMediaSegmentBubbles","segment","bubblePositionInRun","streamPosition","imageSrcFromAttachment","messageAttachmentNamespaceForKind","buildMediaClusterRenderProps","MediaClusterBubble","TypeNamespace","StreamAttachmentMessage","renderText","totalMediaBubbles","rawCaption","linkSegment","primaryLinkUrl","mediaBubbleIndex","rows","linkTailPosition","pushLinkRow","isFinalRow","Card","pushMediaCluster","position","segmentIndex","isFinalSegment","attachmentIndex","MessageErrorIcon","MessageText","CustomMessageWithContext","additionalMessageInputProps","chatbotVotingEnabled","editing","handleAction","handleOpenThread","handleRetry","highlighted","isMessageAIGenerated","isUnlocking","onUnlockClick","onFetchSource","onDownloadClick","isBounceDialogOpen","setIsBounceDialogOpen","reminder","useMessageReminder","voteState","Attachment","DefaultAttachment","EditMessageModal","DefaultEditMessageModal","MessageActions","MessageBlocked","DefaultMessageBlocked","MessageBouncePrompt","DefaultMessageBouncePrompt","MessageDeleted","DefaultMessageDeleted","MessageIsThreadReplyInChannelButtonIndicator","DefaultMessageIsThreadReplyInChannelButtonIndicator","MessageRepliesCountButton","DefaultMessageRepliesCountButton","ReminderNotification","DefaultReminderNotification","StreamedMessageText","DefaultStreamedMessageText","PinIndicator","useComponentContext","messageHasAttachments","hasReactions","messageHasReactions","isAIGenerated","finalAttachments","raw","filtered","attachmentSegments","displayMessage","displayText","hasAttachmentSegments","allAttachmentsRepresented","streamAttachmentGroupPosition","messageAttachmentGroupPositionFromStream","isDateSeparatorMessage","isMessageBlocked","showReplyCountButton","showIsReplyInChannel","allowRetry","isBounced","isMessageBounced","isMine","rootClassName","poll","isTipOnly","isAttachment","hasRenderableAttachments","useAttachmentFooterChatbotTag","canRenderAttachmentsInToolkit","sharedLockedTextProps","sharedLockedMediaProps","_e","_f","_g","_h","_j","MessageBounceModal","Poll","MemoizedCustomMessage","areMessageUIPropsEqual","CustomMessage","messageContext","broadcastNamesById","DeleteAction","handleDelete","DefaultDropdownActionButton","TrashSimpleIcon","ReportAction","handleFlag","CustomMessageActions","linkPreviewsManagerStateSelector","preview","LinkPreviewsManager","CustomLinkPreviewList","linkPreviewsManager","useMessageComposer","stateLinkPreviews","useStateStore","handleDismiss","linkPreview","ComposerLockedContext","NEAR_BOTTOM_THRESHOLD_PX","useComposerLocked","DefaultSendButton","sendMessage","disabled","ArrowUpIcon","CustomMessageInputInner","handleSubmit","useMessageInputContext","hasSendableData","useMessageComposerHasSendableData","isSendDisabled","SendButton","AttachmentPreviewList","DefaultAttachmentPreviewList","QuotedMessagePreview","TextareaComposer","CustomMessageInput","renderActions","renderHeader","renderFooter","disabledReason","composerInput","isFrozen","isFloating","composerRef","composer","previousComposerHeight","updateComposerHeight","nextComposerHeight","grew","scroller","wasAtBottom","resizeObserver","MessageInput","DM_AGENT_SYSTEM_MESSAGE_FALLBACK_TEXT","SHOW_SYSTEM_MESSAGE_TIMESTAMP_TYPES","AGE_SAFETY_SYSTEM_MESSAGE_FALLBACK_TEXT","AGE_SAFETY_SYSTEM_MESSAGE_EMPHASIS","AGE_SAFETY_SYSTEM_MESSAGE_URL","isShowTimestampSystemType","shouldShowSystemMessageTimestamp","getCustomSystemMessageVariant","metadataCustomType","isDmAgentSystemType","isAgeSafetySystemType","fallbackType","renderAgeSafetyMessageText","messageText","emphasisIndex","emphasisEndIndex","CustomSystemMessage","isDateHidden","customSystemMessageVariant","MessageTimestamp","ProhibitIcon","DmAgentEnabledContext","Circle","cx","AI_ACTIVE_STATES","AIStates","CustomTypingIndicator","channelConfig","thread","typing","useTypingContext","aiState","useAIState","agentUser","findOtherChannelUser","TypingBubble","typingInChannel","parent_id","typingInThread","typingUsers","typingUser","memberUser","avatarId","avatarName","avatarImage","testId","selfId","ChannelEmptyState","Loading","LoadingState","ChannelViewInner","renderMessageInputActions","renderMessageInputFooter","renderConversationFooter","composerDisabled","composerDisabledReason","renderChannelBanner","renderMessage","onBroadcastClickRef","stableOnBroadcastClick","broadcast","messageBroadcastClick","hasVisibleMessages","channelBanner","channelHeader","MessageOverride","messageNode","WithComponents","Window","MessageList","ChannelView","CustomChannelEmptyState","messageMetadata","onMessageSent","onMessageLinkClick","sendButton","attachmentPreviewList","doSendMessageRequest","_channel","options","agentPaused","shouldSuppressNotifications","finalMessage","finalOptions","response","container","handler","target","anchor","messageWrapper","messageId","Channel","ErrorState","MessagingShell","onChannelSelect","onExitConversation","initialParticipantFilter","initialParticipantData","selectedChannel","setSelectedChannel","directConversationError","setDirectConversationError","didExit","setDidExit","initialParticipantDataRef","onChannelSelectRef","directConversationLoadRef","selectedChannelRef","loadKey","releaseLoadGuard","participantData","createErr","onExitConversationRef","handleExitConversation","restorePendingMessages","pendingMessages","pending","ChannelListContext","ChannelListProvider","useChannelListContext","getDaysDifference","date1","date2","d1","diffTime","formatRelativeTime","date","now","daysDiff","CustomChannelPreview","unread","channelPreview","renderMessagePreview","isSelected","isActivationKey","isRepeatedKeydown","lastMessageText","custom_type","attachment_content_type","lastMessageTime","isLastMessageFromChatbot","messagePreview","unreadCount","DEFAULT_SORT","ChannelList","filters","allowNewMessagesFromUnfilteredChannels","channelRenderFilterFn","sort","customEmptyStateIndicator","Paginator","InfiniteScroll","lockChannelOrder","onMessageNewHandler","onMessageNew","onChannelVisible","onAddedToChannel","onChannelUpdated","wrappedChannelRenderFilterFn","StreamChannelList","TAIL_MASK","BG_VAR_BY_VARIANT","SURFACE_STYLE_BY_VARIANT","BubbleShell","tail","header","MessageBubble","FaqListItem","question","FaqList","faqs","onFaqClick","loadingFaqId","headerText","enabledFaqs","selectEnabledFaqs","faq"],"mappings":"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","x_google_ignoreList":[54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,181,182,183,184,185,186]}
|