@assistant-ui/react 0.15.10 → 0.15.11
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/client/ExternalThread.d.ts.map +1 -1
- package/dist/client/ExternalThread.js +330 -338
- package/dist/client/ExternalThread.js.map +1 -1
- package/dist/client/InMemoryThreadList.d.ts.map +1 -1
- package/dist/client/InMemoryThreadList.js +82 -86
- package/dist/client/InMemoryThreadList.js.map +1 -1
- package/dist/context/react/ThreadViewportContext.js +2 -1
- package/dist/context/react/ThreadViewportContext.js.map +1 -1
- package/dist/primitives/composer/ComposerInput.js +2 -1
- package/dist/primitives/composer/ComposerInput.js.map +1 -1
- package/dist/primitives/message/MessagePartsGrouped.js +2 -1
- package/dist/primitives/message/MessagePartsGrouped.js.map +1 -1
- package/dist/primitives/thread/ThreadViewport.js +4 -2
- package/dist/primitives/thread/ThreadViewport.js.map +1 -1
- package/dist/primitives/thread/ThreadViewportFooter.js +3 -1
- package/dist/primitives/thread/ThreadViewportFooter.js.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemRoot.js.map +1 -1
- package/dist/primitives/threadListItem/ThreadListItemTrigger.js +2 -1
- package/dist/primitives/threadListItem/ThreadListItemTrigger.js.map +1 -1
- package/dist/utils/useToolArgsFieldStatus.d.ts +2 -2
- package/package.json +14 -14
- package/src/client/ExternalThread.ts +26 -43
- package/src/client/InMemoryThreadList.ts +5 -4
- package/src/tests/external-thread-parity.test.tsx +95 -0
- package/src/tests/in-memory-thread-list.test.tsx +55 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessagePartsGrouped.js","names":["c","_c","ComponentType","FC","memo","PropsWithChildren","useMemo","useAuiState","useAui","PartByIndexProvider","TextMessagePartProvider","MessagePartPrimitiveText","MessagePartPrimitiveImage","Unstable_AudioMessagePartComponent","DataMessagePartComponent","DataMessagePartProps","EmptyMessagePartComponent","TextMessagePartComponent","ImageMessagePartComponent","SourceMessagePartComponent","ToolCallMessagePartComponent","ToolCallMessagePartProps","FileMessagePartComponent","ReasoningMessagePartComponent","MessagePartPrimitiveInProgress","MessagePartStatus","MessagePartGroup","groupKey","indices","GroupingFunction","parts","groupMessagePartsByParentId","groupMap","Map","i","length","part","parentId","groupId","get","push","set","groups","startsWith","undefined","useMessagePartsGrouped","groupingFunction","$","_temp","t0","bb0","t1","Symbol","for","MessagePrimitiveUnstable_PartsGrouped","Props","components","Empty","Text","Reasoning","Source","Image","File","Unstable_Audio","data","by_name","Record","Fallback","tools","Override","Group","ToolUIDisplay","props","toolName","s","toolUIs","render","Render","t2","DataUIDisplay","name","dataRenderers","renderers","Array","isArray","Render_0","defaultComponents","whiteSpace","fontFamily","children","MessagePartComponentProps","MessagePartComponent","t3","t4","t5","t6","t7","t8","t9","Audio","t10","aui","_temp2","type","addResult","addToolResult","resume","resumeToolCall","respondToApproval","respondToToolApproval","t11","Tool","status","Error","Data","console","warn","MessagePartProps","partIndex","MessagePartImpl","MessagePart","prev","next","EmptyPartFallback","component","Component","COMPLETE_STATUS","Object","freeze","EmptyPartsImpl","_temp3","EmptyParts","contentLength","_temp4","messageGroups","group","groupIndex","GroupComponent","map","partsElements","displayName","MessagePrimitiveUnstable_PartsGroupedByParentId","Omit","message"],"sources":["../../../src/primitives/message/MessagePartsGrouped.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n type ComponentType,\n type FC,\n memo,\n type PropsWithChildren,\n useMemo,\n} from \"react\";\nimport { useAuiState, useAui } from \"@assistant-ui/store\";\nimport { PartByIndexProvider } from \"../../context/providers/PartByIndexProvider\";\nimport { TextMessagePartProvider } from \"../../context/providers/TextMessagePartProvider\";\nimport { MessagePartPrimitiveText } from \"../messagePart/MessagePartText\";\nimport { MessagePartPrimitiveImage } from \"../messagePart/MessagePartImage\";\nimport type {\n Unstable_AudioMessagePartComponent,\n DataMessagePartComponent,\n DataMessagePartProps,\n EmptyMessagePartComponent,\n TextMessagePartComponent,\n ImageMessagePartComponent,\n SourceMessagePartComponent,\n ToolCallMessagePartComponent,\n ToolCallMessagePartProps,\n FileMessagePartComponent,\n ReasoningMessagePartComponent,\n} from \"@assistant-ui/core/react\";\nimport { MessagePartPrimitiveInProgress } from \"../messagePart/MessagePartInProgress\";\nimport type { MessagePartStatus } from \"@assistant-ui/core\";\n\ntype MessagePartGroup = {\n groupKey: string | undefined;\n indices: number[];\n};\n\nexport type GroupingFunction = (parts: readonly any[]) => MessagePartGroup[];\n\n/**\n * Groups message parts by their parent ID.\n * Parts without a parent ID appear in their chronological position as individual groups.\n * Parts with the same parent ID are grouped together at the position of their first occurrence.\n */\nconst groupMessagePartsByParentId: GroupingFunction = (\n parts: readonly any[],\n): MessagePartGroup[] => {\n // Map maintains insertion order, so groups appear in order of first occurrence\n const groupMap = new Map<string, number[]>();\n\n // Process each part in order\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n const parentId = part?.parentId as string | undefined;\n\n // For parts without parentId, assign a unique group ID to maintain their position\n const groupId = parentId ?? `__ungrouped_${i}`;\n\n // Get or create the indices array for this group\n const indices = groupMap.get(groupId) ?? [];\n indices.push(i);\n groupMap.set(groupId, indices);\n }\n\n // Convert map to array of groups\n const groups: MessagePartGroup[] = [];\n for (const [groupId, indices] of groupMap) {\n // Extract parentId (undefined for ungrouped parts)\n const groupKey = groupId.startsWith(\"__ungrouped_\") ? undefined : groupId;\n groups.push({ groupKey, indices });\n }\n\n return groups;\n};\n\nconst useMessagePartsGrouped = (\n groupingFunction: GroupingFunction,\n): MessagePartGroup[] => {\n const parts = useAuiState((s) => s.message.parts);\n\n return useMemo(() => {\n if (parts.length === 0) {\n return [];\n }\n return groupingFunction(parts);\n }, [parts, groupingFunction]);\n};\n\nexport namespace MessagePrimitiveUnstable_PartsGrouped {\n export type Props = {\n /**\n * Function that takes an array of message parts and returns an array of groups.\n * Each group contains a key (for identification) and an array of indices.\n *\n * @example\n * ```tsx\n * // Group by parent ID (default behavior)\n * groupingFunction={(parts) => {\n * const groups = new Map<string, number[]>();\n * parts.forEach((part, i) => {\n * const key = part.parentId ?? `__ungrouped_${i}`;\n * const indices = groups.get(key) ?? [];\n * indices.push(i);\n * groups.set(key, indices);\n * });\n * return Array.from(groups.entries()).map(([key, indices]) => ({\n * key: key.startsWith(\"__ungrouped_\") ? undefined : key,\n * indices\n * }));\n * }}\n * ```\n *\n * @example\n * ```tsx\n * // Group by tool name\n * import { groupMessagePartsByToolName } from \"@assistant-ui/react\";\n *\n * <MessagePrimitive.Unstable_PartsGrouped\n * groupingFunction={groupMessagePartsByToolName}\n * components={{\n * Group: ({ key, indices, children }) => {\n * if (!key) return <>{children}</>;\n * return (\n * <div className=\"tool-group\">\n * <h4>Tool: {key}</h4>\n * {children}\n * </div>\n * );\n * }\n * }}\n * />\n * ```\n */\n groupingFunction: GroupingFunction;\n\n /**\n * Component configuration for rendering different types of message content.\n *\n * You can provide custom components for each content type (text, image, file, etc.)\n * and configure tool rendering behavior. If not provided, default components will be used.\n */\n components:\n | {\n /** Component for rendering empty messages */\n Empty?: EmptyMessagePartComponent | undefined;\n /** Component for rendering text content */\n Text?: TextMessagePartComponent | undefined;\n /** Component for rendering reasoning content (typically hidden) */\n Reasoning?: ReasoningMessagePartComponent | undefined;\n /** Component for rendering source content */\n Source?: SourceMessagePartComponent | undefined;\n /** Component for rendering image content */\n Image?: ImageMessagePartComponent | undefined;\n /** Component for rendering file content */\n File?: FileMessagePartComponent | undefined;\n /**\n * Component for rendering audio content.\n *\n * @deprecated Render audio through the `File` slot instead, branching\n * on an `audio/*` mime type.\n */\n Unstable_Audio?: Unstable_AudioMessagePartComponent | undefined;\n /** Configuration for data part rendering */\n data?:\n | {\n /** Map data event names to specific components */\n by_name?:\n | Record<string, DataMessagePartComponent | undefined>\n | undefined;\n /** Fallback component for unmatched data events */\n Fallback?: DataMessagePartComponent | undefined;\n }\n | undefined;\n /** Configuration for tool call rendering */\n tools?:\n | {\n /** Map of tool names to their specific components */\n by_name?:\n | Record<string, ToolCallMessagePartComponent | undefined>\n | undefined;\n /** Fallback component for unregistered tools */\n Fallback?: ComponentType<ToolCallMessagePartProps> | undefined;\n }\n | {\n /** Override component that handles all tool calls */\n Override: ComponentType<ToolCallMessagePartProps>;\n }\n | undefined;\n\n /**\n * Component for rendering grouped message parts.\n *\n * When provided, this component will automatically wrap message parts that share\n * the same group key as determined by the groupingFunction.\n *\n * The component receives:\n * - `groupKey`: The group key (or undefined for ungrouped parts)\n * - `indices`: Array of indices for the parts in this group\n * - `children`: The rendered message part components\n *\n * @example\n * ```tsx\n * // Collapsible group\n * Group: ({ groupKey, indices, children }) => {\n * if (!groupKey) return <>{children}</>;\n * return (\n * <details className=\"message-group\">\n * <summary>\n * Group {groupKey} ({indices.length} parts)\n * </summary>\n * <div className=\"group-content\">\n * {children}\n * </div>\n * </details>\n * );\n * }\n * ```\n *\n * @param groupKey - The group key (undefined for ungrouped parts)\n * @param indices - Array of indices for the parts in this group\n * @param children - Rendered message part components to display within the group\n */\n Group?: ComponentType<\n PropsWithChildren<{\n groupKey: string | undefined;\n indices: number[];\n }>\n >;\n }\n | undefined;\n };\n}\n\nconst ToolUIDisplay = ({\n Fallback,\n ...props\n}: {\n Fallback: ToolCallMessagePartComponent | undefined;\n} & ToolCallMessagePartProps) => {\n const Render = useAuiState(\n (s) => s.tools.toolUIs[props.toolName]?.[0]?.render ?? Fallback,\n );\n if (!Render) return null;\n return <Render {...props} />;\n};\n\nconst DataUIDisplay = ({\n Fallback,\n ...props\n}: {\n Fallback: DataMessagePartComponent | undefined;\n} & DataMessagePartProps) => {\n const Render = useAuiState((s) => {\n const Render = s.dataRenderers.renderers[props.name] ?? Fallback;\n if (Array.isArray(Render)) return Render[0] ?? Fallback;\n return Render;\n });\n if (!Render) return null;\n return <Render {...props} />;\n};\n\nconst defaultComponents = {\n Text: () => (\n <p style={{ whiteSpace: \"pre-line\" }}>\n <MessagePartPrimitiveText />\n <MessagePartPrimitiveInProgress>\n <span style={{ fontFamily: \"revert\" }}>{\" \\u25CF\"}</span>\n </MessagePartPrimitiveInProgress>\n </p>\n ),\n Reasoning: () => null,\n Source: () => null,\n Image: () => <MessagePartPrimitiveImage />,\n File: () => null,\n Unstable_Audio: () => null,\n Group: ({ children }) => children,\n} satisfies MessagePrimitiveUnstable_PartsGrouped.Props[\"components\"];\n\ntype MessagePartComponentProps = {\n components: MessagePrimitiveUnstable_PartsGrouped.Props[\"components\"];\n};\n\nconst MessagePartComponent: FC<MessagePartComponentProps> = ({\n components: {\n Text = defaultComponents.Text,\n Reasoning = defaultComponents.Reasoning,\n Image = defaultComponents.Image,\n Source = defaultComponents.Source,\n File = defaultComponents.File,\n Unstable_Audio: Audio = defaultComponents.Unstable_Audio,\n tools = {},\n data,\n } = {},\n}) => {\n const aui = useAui();\n const part = useAuiState((s) => s.part);\n\n const type = part.type;\n if (type === \"tool-call\") {\n const addResult = aui.part.addToolResult;\n const resume = aui.part.resumeToolCall;\n const respondToApproval = aui.part.respondToToolApproval;\n if (\"Override\" in tools)\n return (\n <tools.Override\n {...part}\n addResult={addResult}\n resume={resume}\n respondToApproval={respondToApproval}\n />\n );\n const Tool = tools.by_name?.[part.toolName] ?? tools.Fallback;\n return (\n <ToolUIDisplay\n {...part}\n Fallback={Tool}\n addResult={addResult}\n resume={resume}\n respondToApproval={respondToApproval}\n />\n );\n }\n\n if (part.status?.type === \"requires-action\")\n throw new Error(\"Encountered unexpected requires-action status\");\n\n switch (type) {\n case \"text\":\n return <Text {...part} />;\n\n case \"reasoning\":\n return <Reasoning {...part} />;\n\n case \"source\":\n return <Source {...part} />;\n\n case \"image\":\n return <Image {...part} />;\n\n case \"file\":\n return <File {...part} />;\n\n case \"audio\":\n return <Audio {...part} />;\n\n case \"data\": {\n const Data = data?.by_name?.[part.name] ?? data?.Fallback;\n return <DataUIDisplay {...part} Fallback={Data} />;\n }\n\n default:\n console.warn(`Unknown message part type: ${type}`);\n return null;\n }\n};\n\ntype MessagePartProps = {\n partIndex: number;\n components: MessagePrimitiveUnstable_PartsGrouped.Props[\"components\"];\n};\n\nconst MessagePartImpl: FC<MessagePartProps> = ({ partIndex, components }) => {\n return (\n <PartByIndexProvider index={partIndex}>\n <MessagePartComponent components={components} />\n </PartByIndexProvider>\n );\n};\n\nconst MessagePart = memo(\n MessagePartImpl,\n (prev, next) =>\n prev.partIndex === next.partIndex &&\n prev.components?.Text === next.components?.Text &&\n prev.components?.Reasoning === next.components?.Reasoning &&\n prev.components?.Source === next.components?.Source &&\n prev.components?.Image === next.components?.Image &&\n prev.components?.File === next.components?.File &&\n prev.components?.Unstable_Audio === next.components?.Unstable_Audio &&\n prev.components?.tools === next.components?.tools &&\n prev.components?.data === next.components?.data &&\n prev.components?.Group === next.components?.Group,\n);\n\nconst EmptyPartFallback: FC<{\n status: MessagePartStatus;\n component: TextMessagePartComponent;\n}> = ({ status, component: Component }) => {\n return (\n <TextMessagePartProvider text=\"\" isRunning={status.type === \"running\"}>\n <Component type=\"text\" text=\"\" status={status} />\n </TextMessagePartProvider>\n );\n};\n\nconst COMPLETE_STATUS: MessagePartStatus = Object.freeze({\n type: \"complete\",\n});\n\nconst EmptyPartsImpl: FC<MessagePartComponentProps> = ({ components }) => {\n const status = useAuiState(\n (s) => (s.message.status ?? COMPLETE_STATUS) as MessagePartStatus,\n );\n\n if (components?.Empty) return <components.Empty status={status} />;\n\n return (\n <EmptyPartFallback\n status={status}\n component={components?.Text ?? defaultComponents.Text}\n />\n );\n};\n\nconst EmptyParts = memo(\n EmptyPartsImpl,\n (prev, next) =>\n prev.components?.Empty === next.components?.Empty &&\n prev.components?.Text === next.components?.Text,\n);\n\n/**\n * Renders the parts of a message grouped by a custom grouping function.\n *\n * This component allows you to group message parts based on any criteria you define.\n * The grouping function receives all message parts and returns an array of groups,\n * where each group has a key and an array of part indices.\n *\n * @deprecated Prefer `<MessagePrimitive.GroupedParts>` for adjacent\n * grouping — it dispatches all rendering through one `switch (part.type)`\n * and supports nested group paths. Keep this primitive only for\n * non-adjacent clustering (e.g., gathering parts with the same parent-id\n * across the message).\n *\n * @example\n * ```tsx\n * // Group by parent ID (default behavior)\n * <MessagePrimitive.Unstable_PartsGrouped\n * components={{\n * Text: ({ text }) => <p className=\"message-text\">{text}</p>,\n * Image: ({ image }) => <img src={image} alt=\"Message image\" />,\n * Group: ({ groupKey, indices, children }) => {\n * if (!groupKey) return <>{children}</>;\n * return (\n * <div className=\"parent-group border rounded p-4\">\n * <h4>Parent ID: {groupKey}</h4>\n * {children}\n * </div>\n * );\n * }\n * }}\n * />\n * ```\n */\nexport const MessagePrimitiveUnstable_PartsGrouped: FC<\n MessagePrimitiveUnstable_PartsGrouped.Props\n> = ({ groupingFunction, components }) => {\n const contentLength = useAuiState((s) => s.message.parts.length);\n const messageGroups = useMessagePartsGrouped(groupingFunction);\n\n const partsElements = useMemo(() => {\n if (contentLength === 0) {\n return <EmptyParts components={components} />;\n }\n\n return messageGroups.map((group, groupIndex) => {\n const GroupComponent = components?.Group ?? defaultComponents.Group;\n\n return (\n <GroupComponent\n key={`group-${groupIndex}-${group.groupKey ?? \"ungrouped\"}`}\n groupKey={group.groupKey}\n indices={group.indices}\n >\n {group.indices.map((partIndex) => (\n <MessagePart\n key={partIndex}\n partIndex={partIndex}\n components={components}\n />\n ))}\n </GroupComponent>\n );\n });\n }, [messageGroups, components, contentLength]);\n\n return <>{partsElements}</>;\n};\n\nMessagePrimitiveUnstable_PartsGrouped.displayName =\n \"MessagePrimitive.Unstable_PartsGrouped\";\n\n/**\n * Renders the parts of a message grouped by their parent ID.\n * This is a convenience wrapper around Unstable_PartsGrouped with parent ID grouping.\n *\n * @deprecated Use MessagePrimitive.Unstable_PartsGrouped instead for more flexibility\n */\nexport const MessagePrimitiveUnstable_PartsGroupedByParentId: FC<\n Omit<MessagePrimitiveUnstable_PartsGrouped.Props, \"groupingFunction\">\n> = ({ components, ...props }) => {\n return (\n <MessagePrimitiveUnstable_PartsGrouped\n {...props}\n components={components}\n groupingFunction={groupMessagePartsByParentId}\n />\n );\n};\n\nMessagePrimitiveUnstable_PartsGroupedByParentId.displayName =\n \"MessagePrimitive.Unstable_PartsGroupedByParentId\";\n"],"mappings":";;;;;;;;;;;;;;;;AA0CA,MAAM+B,+BACJD,UACuB;CAEvB,MAAME,2BAAW,IAAIC,IAAsB;CAG3C,KAAK,IAAIC,IAAI,GAAGA,IAAIJ,MAAMK,QAAQD,KAAK;EAKrC,MAAMI,UAJOR,MAAMI,EACE,EAAEG,YAGK,eAAeH;EAG3C,MAAMN,UAAUI,SAASO,IAAID,OAAO,KAAK,CAAA;EACzCV,QAAQY,KAAKN,CAAC;EACdF,SAASS,IAAIH,SAASV,OAAO;CAC/B;CAGA,MAAMc,SAA6B,CAAA;CACnC,KAAK,MAAM,CAACJ,SAASV,YAAYI,UAAU;EAEzC,MAAML,WAAWW,QAAQK,WAAW,cAAc,IAAIC,KAAAA,IAAYN;EAClEI,OAAOF,KAAK;GAAEb;GAAUC;EAAQ,CAAC;CACnC;CAEA,OAAOc;AACT;AAEA,MAAMG,0BAAyBC,qBAAA;CAAA,MAAAC,IAAA9C,EAAA,CAAA;CAG7B,MAAA6B,QAAcvB,YAAYyC,KAAsB;CAAE,IAAAC;CAAAC,KAAA;EAGhD,IAAIpB,MAAKK,WAAY,GAAC;GAAA,IAAAgB;GAAA,IAAAJ,EAAA,OAAAK,OAAAC,IAAA,2BAAA,GAAA;IACbF,KAAA,CAAA;IAAEJ,EAAA,KAAAI;GAAA,OAAAA,KAAAJ,EAAA;GAATE,KAAOE;GAAP,MAAAD;EAAU;EACX,IAAAC;EAAA,IAAAJ,EAAA,OAAAD,oBAAAC,EAAA,OAAAjB,OAAA;GACMqB,KAAAL,iBAAiBhB,KAAK;GAACiB,EAAA,KAAAD;GAAAC,EAAA,KAAAjB;GAAAiB,EAAA,KAAAI;EAAA,OAAAA,KAAAJ,EAAA;EAA9BE,KAAOE;CAAwB;CAAA,OAJ1BF;AAKsB;AAoJ/B,MAAMsB,iBAAgBtB,OAAA;CAAA,MAAAF,IAAA9C,EAAA,CAAA;CAAA,IAAAkE;CAAA,IAAAK;CAAA,IAAAzB,EAAA,OAAAE,IAAA;EAAC,CAAA,CAAAkB,aAAAK,SAAAvB;EAKKF,EAAA,KAAAE;EAAAF,EAAA,KAAAoB;EAAApB,EAAA,KAAAyB;CAAA,OAAA;EAAAL,WAAApB,EAAA;EAAAyB,QAAAzB,EAAA;CAAA;CAAA,IAAAI;CAAA,IAAAJ,EAAA,OAAAoB,YAAApB,EAAA,OAAAyB,MAAAC,UAAA;EAExBtB,MAAAuB,MAAOA,EAACN,MAAMO,QAASH,MAAKC,SAAe,GAAA,EAAQ,EAAAG,UAA5CT;EAAwDpB,EAAA,KAAAoB;EAAApB,EAAA,KAAAyB,MAAAC;EAAA1B,EAAA,KAAAI;CAAA,OAAAA,KAAAJ,EAAA;CADjE,MAAA8B,SAAetE,YACb4C,EACF;CACA,IAAI,CAAC0B,QAAM,OAAS;CAAK,IAAAC;CAAA,IAAA/B,EAAA,OAAA8B,UAAA9B,EAAA,OAAAyB,OAAA;EAClBM,KAAA,oBAAC,QAAD,EAAO,GAAKN,MAAK,CAAA;EAAIzB,EAAA,KAAA8B;EAAA9B,EAAA,KAAAyB;EAAAzB,EAAA,KAAA+B;CAAA,OAAAA,KAAA/B,EAAA;CAAA,OAArB+B;AAAqB;AAG9B,MAAMC,iBAAgB9B,OAAA;CAAA,MAAAF,IAAA9C,EAAA,CAAA;CAAA,IAAAkE;CAAA,IAAAK;CAAA,IAAAzB,EAAA,OAAAE,IAAA;EAAC,CAAA,CAAAkB,aAAAK,SAAAvB;EAKCF,EAAA,KAAAE;EAAAF,EAAA,KAAAoB;EAAApB,EAAA,KAAAyB;CAAA,OAAA;EAAAL,WAAApB,EAAA;EAAAyB,QAAAzB,EAAA;CAAA;CAAA,IAAAI;CAAA,IAAAJ,EAAA,OAAAoB,YAAApB,EAAA,OAAAyB,MAAAQ,MAAA;EACK7B,MAAAuB,MAAA;GACzB,MAAAG,SAAeH,EAACO,cAAcC,UAAWV,MAAKQ,SAA/Bb;GACf,IAAIgB,MAAKC,QAASP,MAAM,GAAC,OAASA,OAAM,MAANV;GAAsB,OACjDU;EAAM;EACd9B,EAAA,KAAAoB;EAAApB,EAAA,KAAAyB,MAAAQ;EAAAjC,EAAA,KAAAI;CAAA,OAAAA,KAAAJ,EAAA;CAJD,MAAAsC,WAAe9E,YAAY4C,EAI1B;CACD,IAAI,CAAC0B,UAAM,OAAS;CAAK,IAAAC;CAAA,IAAA/B,EAAA,OAAAsC,YAAAtC,EAAA,OAAAyB,OAAA;EAClBM,KAAA,oBAAC,UAAD,EAAO,GAAKN,MAAK,CAAA;EAAIzB,EAAA,KAAAsC;EAAAtC,EAAA,KAAAyB;EAAAzB,EAAA,KAAA+B;CAAA,OAAAA,KAAA/B,EAAA;CAAA,OAArB+B;AAAqB;AAG9B,MAAMQ,oBAAoB;CACxB5B,YACE,qBAAC,KAAD;EAAG,OAAO,EAAE6B,YAAY,WAAW;EAAnC,UAAA,CACE,oBAAC,0BAAD,CAAyB,CAAA,GACzB,oBAAC,gCAAD,EAAA,UACE,oBAAC,QAAD;GAAM,OAAO,EAAEC,YAAY,SAAS;GAAI,UAAA;EAAgB,CAAA,EAC1B,CAAA,CAC/B;;CAEL7B,iBAAiB;CACjBC,cAAc;CACdC,aAAa,oBAAC,2BAAD,CAA0B,CAAA;CACvCC,YAAY;CACZC,sBAAsB;CACtBO,QAAQ,EAAEmB,eAAeA;AAC3B;AAMA,MAAME,wBAAsD1C,OAAA;CAAA,MAAAF,IAAA9C,EAAA,EAAA;CAAC,MAAA,EAAAuD,YAAAL,OAAAF;CAW5D,IAAA6B;CAAA,IAAA/B,EAAA,OAAAI,IAAA;EAVa2B,KAAA3B,OAAAP,KAAAA,IAAA,CASP,IATOO;EASNJ,EAAA,KAAAI;EAAAJ,EAAA,KAAA+B;CAAA,OAAAA,KAAA/B,EAAA;CATM,MAAA,EAAAW,MAAAkC,IAAAjC,WAAAkC,IAAAhC,OAAAiC,IAAAlC,QAAAmC,IAAAjC,MAAAkC,IAAAjC,gBAAAkC,IAAA7B,OAAA8B,IAAAlC,SAAAc;CACV,MAAApB,OAAAkC,OAAAhD,KAAAA,IAAO0C,kBAAiB5B,OAAxBkC;CACA,MAAAjC,YAAAkC,OAAAjD,KAAAA,IAAY0C,kBAAiB3B,YAA7BkC;CACA,MAAAhC,QAAAiC,OAAAlD,KAAAA,IAAQ0C,kBAAiBzB,QAAzBiC;CACA,MAAAlC,SAAAmC,OAAAnD,KAAAA,IAAS0C,kBAAiB1B,SAA1BmC;CACA,MAAAjC,OAAAkC,OAAApD,KAAAA,IAAO0C,kBAAiBxB,OAAxBkC;CACgB,MAAAG,QAAAF,OAAArD,KAAAA,IAAQ0C,kBAAiBvB,iBAAzBkC;CAAwC,IAAAG;CAAA,IAAArD,EAAA,OAAAmD,IAAA;EACxDE,MAAAF,OAAAtD,KAAAA,IAAA,CAAS,IAATsD;EAAUnD,EAAA,KAAAmD;EAAAnD,EAAA,KAAAqD;CAAA,OAAAA,MAAArD,EAAA;CAAV,MAAAqB,QAAAgC;CAIF,MAAAC,MAAY7F,OAAO;CACnB,MAAA4B,OAAa7B,YAAY+F,MAAa;CAEtC,MAAAC,OAAanE,KAAImE;CACjB,IAAIA,SAAS,aAAW;EACtB,MAAAC,YAAkBH,IAAGjE,KAAKqE;EAC1B,MAAAC,SAAeL,IAAGjE,KAAKuE;EACvB,MAAAC,oBAA0BP,IAAGjE,KAAKyE;EAClC,IAAI,cAAczC,OAAK;GAAA,IAAA0C;GAAA,IAAA/D,EAAA,OAAAyD,aAAAzD,EAAA,OAAAX,QAAAW,EAAA,OAAA6D,qBAAA7D,EAAA,OAAA2D,UAAA3D,EAAA,OAAAqB,MAAAC,UAAA;IAEnByC,MAAA,oBAAA,MAAA,UAAA;KAAA,GACM1E;KACOoE;KACHE;KACWE;IAAiB,CAAA;IACpC7D,EAAA,KAAAyD;IAAAzD,EAAA,KAAAX;IAAAW,EAAA,KAAA6D;IAAA7D,EAAA,KAAA2D;IAAA3D,EAAA,KAAAqB,MAAAC;IAAAtB,EAAA,KAAA+D;GAAA,OAAAA,MAAA/D,EAAA;GAAA,OALF+D;EAKE;EAEN,MAAAC,OAAa3C,MAAKH,UAAW7B,KAAIqC,aAAcL,MAAKD;EAAU,IAAA2C;EAAA,IAAA/D,EAAA,QAAAgE,QAAAhE,EAAA,QAAAyD,aAAAzD,EAAA,QAAAX,QAAAW,EAAA,QAAA6D,qBAAA7D,EAAA,QAAA2D,QAAA;GAE5DI,MAAA,oBAAC,eAAD;IAAc,GACR1E;IACM2E,UAAAA;IACCP;IACHE;IACWE;GAAiB,CAAA;GACpC7D,EAAA,MAAAgE;GAAAhE,EAAA,MAAAyD;GAAAzD,EAAA,MAAAX;GAAAW,EAAA,MAAA6D;GAAA7D,EAAA,MAAA2D;GAAA3D,EAAA,MAAA+D;EAAA,OAAAA,MAAA/D,EAAA;EAAA,OANF+D;CAME;CAIN,IAAI1E,KAAI4E,QAAaT,SAAK,mBACxB,MAAM,IAAIU,MAAM,+CAA+C;CAEjE,QAAQV,MAAR;EAAY,KACL,QAAM;GAAA,IAAAO;GAAA,IAAA/D,EAAA,QAAAW,QAAAX,EAAA,QAAAX,MAAA;IACF0E,MAAA,oBAAC,MAAD,EAAK,GAAK1E,KAAI,CAAA;IAAIW,EAAA,MAAAW;IAAAX,EAAA,MAAAX;IAAAW,EAAA,MAAA+D;GAAA,OAAAA,MAAA/D,EAAA;GAAA,OAAlB+D;EAAkB;EAAA,KAEtB,aAAW;GAAA,IAAAA;GAAA,IAAA/D,EAAA,QAAAY,aAAAZ,EAAA,QAAAX,MAAA;IACP0E,MAAA,oBAAC,WAAD,EAAU,GAAK1E,KAAI,CAAA;IAAIW,EAAA,MAAAY;IAAAZ,EAAA,MAAAX;IAAAW,EAAA,MAAA+D;GAAA,OAAAA,MAAA/D,EAAA;GAAA,OAAvB+D;EAAuB;EAAA,KAE3B,UAAQ;GAAA,IAAAA;GAAA,IAAA/D,EAAA,QAAAa,UAAAb,EAAA,QAAAX,MAAA;IACJ0E,MAAA,oBAAC,QAAD,EAAO,GAAK1E,KAAI,CAAA;IAAIW,EAAA,MAAAa;IAAAb,EAAA,MAAAX;IAAAW,EAAA,MAAA+D;GAAA,OAAAA,MAAA/D,EAAA;GAAA,OAApB+D;EAAoB;EAAA,KAExB,SAAO;GAAA,IAAAA;GAAA,IAAA/D,EAAA,QAAAc,SAAAd,EAAA,QAAAX,MAAA;IACH0E,MAAA,oBAAC,OAAD,EAAM,GAAK1E,KAAI,CAAA;IAAIW,EAAA,MAAAc;IAAAd,EAAA,MAAAX;IAAAW,EAAA,MAAA+D;GAAA,OAAAA,MAAA/D,EAAA;GAAA,OAAnB+D;EAAmB;EAAA,KAEvB,QAAM;GAAA,IAAAA;GAAA,IAAA/D,EAAA,QAAAe,QAAAf,EAAA,QAAAX,MAAA;IACF0E,MAAA,oBAAC,MAAD,EAAK,GAAK1E,KAAI,CAAA;IAAIW,EAAA,MAAAe;IAAAf,EAAA,MAAAX;IAAAW,EAAA,MAAA+D;GAAA,OAAAA,MAAA/D,EAAA;GAAA,OAAlB+D;EAAkB;EAAA,KAEtB,SAAO;GAAA,IAAAA;GAAA,IAAA/D,EAAA,QAAAoD,SAAApD,EAAA,QAAAX,MAAA;IACH0E,MAAA,oBAAC,OAAD,EAAM,GAAK1E,KAAI,CAAA;IAAIW,EAAA,MAAAoD;IAAApD,EAAA,MAAAX;IAAAW,EAAA,MAAA+D;GAAA,OAAAA,MAAA/D,EAAA;GAAA,OAAnB+D;EAAmB;EAAA,KAEvB,QAAM;GACT,MAAAI,OAAalD,MAAIC,UAAY7B,KAAI4C,SAAUhB,MAAIG;GAAW,IAAA2C;GAAA,IAAA/D,EAAA,QAAAmE,QAAAnE,EAAA,QAAAX,MAAA;IACnD0E,MAAA,oBAAC,eAAD;KAAc,GAAK1E;KAAgB8E,UAAAA;IAAI,CAAA;IAAInE,EAAA,MAAAmE;IAAAnE,EAAA,MAAAX;IAAAW,EAAA,MAAA+D;GAAA,OAAAA,MAAA/D,EAAA;GAAA,OAA3C+D;EAA2C;EAAA;GAIlDK,QAAOC,KAAM,8BAA8Bb,MAAM;GAAC,OAC3C;CACX;AAAC;AAQH,MAAMgB,mBAAwCtE,OAAA;CAAA,MAAAF,IAAA9C,EAAA,CAAA;CAAC,MAAA,EAAAqH,WAAA9D,eAAAP;CAAyB,IAAAE;CAAA,IAAAJ,EAAA,OAAAS,YAAA;EAGlEL,KAAA,oBAAC,sBAAD,EAAkCK,WAAU,CAAA;EAAIT,EAAA,KAAAS;EAAAT,EAAA,KAAAI;CAAA,OAAAA,KAAAJ,EAAA;CAAA,IAAA+B;CAAA,IAAA/B,EAAA,OAAAuE,aAAAvE,EAAA,OAAAI,IAAA;EADlD2B,KAAA,oBAAC,qBAAD;GAA4BwC,OAAAA;GAC1BnE,UAAAA;EADkB,CAAA;EAEEJ,EAAA,KAAAuE;EAAAvE,EAAA,KAAAI;EAAAJ,EAAA,KAAA+B;CAAA,OAAAA,KAAA/B,EAAA;CAAA,OAFtB+B;AAEsB;AAI1B,MAAM0C,cAAcpH,KAClBmH,kBACCE,MAAMC,SACLD,KAAKH,cAAcI,KAAKJ,aACxBG,KAAKjE,YAAYE,SAASgE,KAAKlE,YAAYE,QAC3C+D,KAAKjE,YAAYG,cAAc+D,KAAKlE,YAAYG,aAChD8D,KAAKjE,YAAYI,WAAW8D,KAAKlE,YAAYI,UAC7C6D,KAAKjE,YAAYK,UAAU6D,KAAKlE,YAAYK,SAC5C4D,KAAKjE,YAAYM,SAAS4D,KAAKlE,YAAYM,QAC3C2D,KAAKjE,YAAYO,mBAAmB2D,KAAKlE,YAAYO,kBACrD0D,KAAKjE,YAAYY,UAAUsD,KAAKlE,YAAYY,SAC5CqD,KAAKjE,YAAYQ,SAAS0D,KAAKlE,YAAYQ,QAC3CyD,KAAKjE,YAAYc,UAAUoD,KAAKlE,YAAYc,KAChD;AAEA,MAAMqD,qBAGD1E,OAAA;CAAA,MAAAF,IAAA9C,EAAA,CAAA;CAAC,MAAA,EAAA+G,QAAAY,WAAAC,cAAA5E;CAE0C,MAAAE,KAAA6D,OAAMT,SAAU;CAAS,IAAAzB;CAAA,IAAA/B,EAAA,OAAA8E,aAAA9E,EAAA,OAAAiE,QAAA;EACnElC,KAAA,oBAAC,WAAD;GAAgB,MAAA;GAAY,MAAA;GAAWkC;EAAM,CAAA;EAAIjE,EAAA,KAAA8E;EAAA9E,EAAA,KAAAiE;EAAAjE,EAAA,KAAA+B;CAAA,OAAAA,KAAA/B,EAAA;CAAA,IAAA6C;CAAA,IAAA7C,EAAA,OAAAI,MAAAJ,EAAA,OAAA+B,IAAA;EADnDc,KAAA,oBAAC,yBAAD;GAA8B,MAAA;GAAc,WAAAzC;GAC1C2B,UAAAA;EADsB,CAAA;EAEE/B,EAAA,KAAAI;EAAAJ,EAAA,KAAA+B;EAAA/B,EAAA,KAAA6C;CAAA,OAAAA,KAAA7C,EAAA;CAAA,OAF1B6C;AAE0B;AAI9B,MAAMkC,kBAAqCC,OAAOC,OAAO,EACvDzB,MAAM,WACR,CAAC;AAED,MAAM0B,kBAAgDhF,OAAA;CAAA,MAAAF,IAAA9C,EAAA,CAAA;CAAC,MAAA,EAAAuD,eAAAP;CACrD,MAAA+D,SAAezG,YACb2H,MACF;CAEA,IAAI1E,YAAUC,OAAO;EAAA,IAAAN;EAAA,IAAAJ,EAAA,OAAAS,WAAAC,SAAAV,EAAA,OAAAiE,QAAA;GAAS7D,KAAA,oBAAA,WAAA,OAAA,EAA0B6D,OAAM,CAAA;GAAIjE,EAAA,KAAAS,WAAAC;GAAAV,EAAA,KAAAiE;GAAAjE,EAAA,KAAAI;EAAA,OAAAA,KAAAJ,EAAA;EAAA,OAApCI;CAAoC;CAKnD,MAAAA,KAAAK,YAAUE,QAAU4B,kBAAiB5B;CAAK,IAAAoB;CAAA,IAAA/B,EAAA,OAAAiE,UAAAjE,EAAA,OAAAI,IAAA;EAFvD2B,KAAA,oBAAC,mBAAD;GACUkC;GACG,WAAA7D;EAA0C,CAAA;EACrDJ,EAAA,KAAAiE;EAAAjE,EAAA,KAAAI;EAAAJ,EAAA,KAAA+B;CAAA,OAAAA,KAAA/B,EAAA;CAAA,OAHF+B;AAGE;AAIN,MAAMqD,aAAa/H,KACjB6H,iBACCR,MAAMC,SACLD,KAAKjE,YAAYC,UAAUiE,KAAKlE,YAAYC,SAC5CgE,KAAKjE,YAAYE,SAASgE,KAAKlE,YAAYE,IAC/C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmCA,MAAaJ,yCAETL,OAAA;CAAA,MAAAF,IAAA9C,EAAA,CAAA;CAAC,MAAA,EAAA6C,kBAAAU,eAAAP;CACH,MAAAmF,gBAAsB7H,YAAY8H,MAA6B;CAC/D,MAAAC,gBAAsBzF,uBAAuBC,gBAAgB;CAAE,IAAAK;CAAAD,KAAA;EAG7D,IAAIkF,kBAAkB,GAAC;GAAA,IAAAtD;GAAA,IAAA/B,EAAA,OAAAS,YAAA;IACdsB,KAAA,oBAAC,YAAD,EAAwBtB,WAAU,CAAA;IAAIT,EAAA,KAAAS;IAAAT,EAAA,KAAA+B;GAAA,OAAAA,KAAA/B,EAAA;GAA7CI,KAAO2B;GAAP,MAAA5B;EAA8C;EAC/C,IAAA4B;EAAA,IAAA/B,EAAA,OAAAS,cAAAT,EAAA,OAAAuF,eAAA;GAAA,IAAA1C;GAAA,IAAA7C,EAAA,OAAAS,YAAA;IAEwBoC,MAAA2C,OAAAC,eAAA;KAC6C,OAGlE,oBAHqBhF,YAAUc,SAAWgB,kBAAiBhB,OAG3D;MAEY,UAAAiE,MAAK5G;MACN,SAAA4G,MAAK3G;MAEb2G,UAAAA,MAAK3G,QAAQ8G,KAAKpB,cACjB,oBAAC,aAAD;OAEaA;OACC9D;MAAU,GAFjB8D,SAEiB,CAEzB;KAXY,GACR,SAASkB,WAAU,GAAID,MAAK5G,YAAL,aADf;IAYE;IAEpBoB,EAAA,KAAAS;IAAAT,EAAA,KAAA6C;GAAA,OAAAA,KAAA7C,EAAA;GAlBM+B,KAAAwD,cAAaI,IAAK9C,EAkBxB;GAAC7C,EAAA,KAAAS;GAAAT,EAAA,KAAAuF;GAAAvF,EAAA,KAAA+B;EAAA,OAAAA,KAAA/B,EAAA;EAlBFI,KAAO2B;CAkBJ;CAvBL,MAAA6D,gBAAsBxF;CAwByB,IAAA2B;CAAA,IAAA/B,EAAA,OAAA4F,eAAA;EAExC7D,KAAA,oBAAA,UAAA,EAAA,UAAG6D,cAAa,CAAA;EAAI5F,EAAA,KAAA4F;EAAA5F,EAAA,KAAA+B;CAAA,OAAAA,KAAA/B,EAAA;CAAA,OAApB+B;AAAoB;AAG7BxB,sCAAsCsF,cACpC;;;;;;;AAQF,MAAaC,mDAET5F,OAAA;CAAA,MAAAF,IAAA9C,EAAA,CAAA;CAAA,IAAAuD;CAAA,IAAAgB;CAAA,IAAAzB,EAAA,OAAAE,IAAA;EAAC,CAAA,CAAAO,eAAAgB,SAAAvB;EAAwBF,EAAA,KAAAE;EAAAF,EAAA,KAAAS;EAAAT,EAAA,KAAAyB;CAAA,OAAA;EAAAhB,aAAAT,EAAA;EAAAyB,QAAAzB,EAAA;CAAA;CAAA,IAAAI;CAAA,IAAAJ,EAAA,OAAAS,cAAAT,EAAA,OAAAyB,OAAA;EAEzBrB,KAAA,oBAAC,uCAAD;GAAsC,GAChCqB;GACQhB;GACMzB,kBAAAA;EAA2B,CAAA;EAC7CgB,EAAA,KAAAS;EAAAT,EAAA,KAAAyB;EAAAzB,EAAA,KAAAI;CAAA,OAAAA,KAAAJ,EAAA;CAAA,OAJFI;AAIE;AAIN0F,gDAAgDD,cAC9C;AApb6B,SAAA5F,MAAA0B,GAAA;CAAA,OAGIA,EAACqE,QAAQjH;AAAM;AA4MU,SAAAwE,OAAA5B,GAAA;CAAA,OAa1BA,EAACtC;AAAK;AAwGc,SAAA8F,OAAAxD,GAAA;CAAA,OAE1CA,EAACqE,QAAQ/B,UAATc;AAAyD;AAuDjE,SAAAO,OAAA3D,GAAA;CAAA,OACuCA,EAACqE,QAAQjH,MAAMK;AAAO"}
|
|
1
|
+
{"version":3,"file":"MessagePartsGrouped.js","names":["c","_c","ComponentType","FC","memo","PropsWithChildren","useMemo","useAuiState","useAui","PartByIndexProvider","TextMessagePartProvider","MessagePartPrimitiveText","MessagePartPrimitiveImage","Unstable_AudioMessagePartComponent","DataMessagePartComponent","DataMessagePartProps","EmptyMessagePartComponent","TextMessagePartComponent","ImageMessagePartComponent","SourceMessagePartComponent","ToolCallMessagePartComponent","ToolCallMessagePartProps","FileMessagePartComponent","ReasoningMessagePartComponent","MessagePartPrimitiveInProgress","MessagePartStatus","MessagePartGroup","groupKey","indices","GroupingFunction","parts","groupMessagePartsByParentId","groupMap","Map","i","length","part","parentId","groupId","get","push","set","groups","startsWith","undefined","useMessagePartsGrouped","groupingFunction","$","_temp","t0","bb0","t1","Symbol","for","MessagePrimitiveUnstable_PartsGrouped","Props","components","Empty","Text","Reasoning","Source","Image","File","Unstable_Audio","data","by_name","Record","Fallback","tools","Override","Group","ToolUIDisplay","props","toolName","s","toolUIs","render","Render","t2","DataUIDisplay","name","dataRenderers","renderers","Array","isArray","Render_0","defaultComponents","whiteSpace","fontFamily","children","MessagePartComponentProps","MessagePartComponent","t3","t4","t5","t6","t7","t8","t9","Audio","t10","aui","_temp2","type","addResult","addToolResult","resume","resumeToolCall","respondToApproval","respondToToolApproval","t11","Tool","status","Error","Data","console","warn","MessagePartProps","partIndex","MessagePartImpl","MessagePart","prev","next","EmptyPartFallback","component","Component","COMPLETE_STATUS","Object","freeze","EmptyPartsImpl","_temp3","EmptyParts","contentLength","_temp4","messageGroups","group","groupIndex","GroupComponent","map","partsElements","displayName","MessagePrimitiveUnstable_PartsGroupedByParentId","Omit","message"],"sources":["../../../src/primitives/message/MessagePartsGrouped.tsx"],"sourcesContent":["\"use client\";\n\nimport {\n type ComponentType,\n type FC,\n memo,\n type PropsWithChildren,\n useMemo,\n} from \"react\";\nimport { useAuiState, useAui } from \"@assistant-ui/store\";\nimport { PartByIndexProvider } from \"../../context/providers/PartByIndexProvider\";\nimport { TextMessagePartProvider } from \"../../context/providers/TextMessagePartProvider\";\nimport { MessagePartPrimitiveText } from \"../messagePart/MessagePartText\";\nimport { MessagePartPrimitiveImage } from \"../messagePart/MessagePartImage\";\nimport type {\n Unstable_AudioMessagePartComponent,\n DataMessagePartComponent,\n DataMessagePartProps,\n EmptyMessagePartComponent,\n TextMessagePartComponent,\n ImageMessagePartComponent,\n SourceMessagePartComponent,\n ToolCallMessagePartComponent,\n ToolCallMessagePartProps,\n FileMessagePartComponent,\n ReasoningMessagePartComponent,\n} from \"@assistant-ui/core/react\";\nimport { MessagePartPrimitiveInProgress } from \"../messagePart/MessagePartInProgress\";\nimport type { MessagePartStatus } from \"@assistant-ui/core\";\n\ntype MessagePartGroup = {\n groupKey: string | undefined;\n indices: number[];\n};\n\nexport type GroupingFunction = (parts: readonly any[]) => MessagePartGroup[];\n\n/**\n * Groups message parts by their parent ID.\n * Parts without a parent ID appear in their chronological position as individual groups.\n * Parts with the same parent ID are grouped together at the position of their first occurrence.\n */\nconst groupMessagePartsByParentId: GroupingFunction = (\n parts: readonly any[],\n): MessagePartGroup[] => {\n // Map maintains insertion order, so groups appear in order of first occurrence\n const groupMap = new Map<string, number[]>();\n\n // Process each part in order\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n const parentId = part?.parentId as string | undefined;\n\n // For parts without parentId, assign a unique group ID to maintain their position\n const groupId = parentId ?? `__ungrouped_${i}`;\n\n // Get or create the indices array for this group\n const indices = groupMap.get(groupId) ?? [];\n indices.push(i);\n groupMap.set(groupId, indices);\n }\n\n // Convert map to array of groups\n const groups: MessagePartGroup[] = [];\n for (const [groupId, indices] of groupMap) {\n // Extract parentId (undefined for ungrouped parts)\n const groupKey = groupId.startsWith(\"__ungrouped_\") ? undefined : groupId;\n groups.push({ groupKey, indices });\n }\n\n return groups;\n};\n\nconst useMessagePartsGrouped = (\n groupingFunction: GroupingFunction,\n): MessagePartGroup[] => {\n const parts = useAuiState((s) => s.message.parts);\n\n return useMemo(() => {\n if (parts.length === 0) {\n return [];\n }\n return groupingFunction(parts);\n }, [parts, groupingFunction]);\n};\n\nexport namespace MessagePrimitiveUnstable_PartsGrouped {\n export type Props = {\n /**\n * Function that takes an array of message parts and returns an array of groups.\n * Each group contains a key (for identification) and an array of indices.\n *\n * @example\n * ```tsx\n * // Group by parent ID (default behavior)\n * groupingFunction={(parts) => {\n * const groups = new Map<string, number[]>();\n * parts.forEach((part, i) => {\n * const key = part.parentId ?? `__ungrouped_${i}`;\n * const indices = groups.get(key) ?? [];\n * indices.push(i);\n * groups.set(key, indices);\n * });\n * return Array.from(groups.entries()).map(([key, indices]) => ({\n * key: key.startsWith(\"__ungrouped_\") ? undefined : key,\n * indices\n * }));\n * }}\n * ```\n *\n * @example\n * ```tsx\n * // Group by tool name\n * import { groupMessagePartsByToolName } from \"@assistant-ui/react\";\n *\n * <MessagePrimitive.Unstable_PartsGrouped\n * groupingFunction={groupMessagePartsByToolName}\n * components={{\n * Group: ({ key, indices, children }) => {\n * if (!key) return <>{children}</>;\n * return (\n * <div className=\"tool-group\">\n * <h4>Tool: {key}</h4>\n * {children}\n * </div>\n * );\n * }\n * }}\n * />\n * ```\n */\n groupingFunction: GroupingFunction;\n\n /**\n * Component configuration for rendering different types of message content.\n *\n * You can provide custom components for each content type (text, image, file, etc.)\n * and configure tool rendering behavior. If not provided, default components will be used.\n */\n components:\n | {\n /** Component for rendering empty messages */\n Empty?: EmptyMessagePartComponent | undefined;\n /** Component for rendering text content */\n Text?: TextMessagePartComponent | undefined;\n /** Component for rendering reasoning content (typically hidden) */\n Reasoning?: ReasoningMessagePartComponent | undefined;\n /** Component for rendering source content */\n Source?: SourceMessagePartComponent | undefined;\n /** Component for rendering image content */\n Image?: ImageMessagePartComponent | undefined;\n /** Component for rendering file content */\n File?: FileMessagePartComponent | undefined;\n /**\n * Component for rendering audio content.\n *\n * @deprecated Render audio through the `File` slot instead, branching\n * on an `audio/*` mime type.\n */\n Unstable_Audio?: Unstable_AudioMessagePartComponent | undefined;\n /** Configuration for data part rendering */\n data?:\n | {\n /** Map data event names to specific components */\n by_name?:\n | Record<string, DataMessagePartComponent | undefined>\n | undefined;\n /** Fallback component for unmatched data events */\n Fallback?: DataMessagePartComponent | undefined;\n }\n | undefined;\n /** Configuration for tool call rendering */\n tools?:\n | {\n /** Map of tool names to their specific components */\n by_name?:\n | Record<string, ToolCallMessagePartComponent | undefined>\n | undefined;\n /** Fallback component for unregistered tools */\n Fallback?: ComponentType<ToolCallMessagePartProps> | undefined;\n }\n | {\n /** Override component that handles all tool calls */\n Override: ComponentType<ToolCallMessagePartProps>;\n }\n | undefined;\n\n /**\n * Component for rendering grouped message parts.\n *\n * When provided, this component will automatically wrap message parts that share\n * the same group key as determined by the groupingFunction.\n *\n * The component receives:\n * - `groupKey`: The group key (or undefined for ungrouped parts)\n * - `indices`: Array of indices for the parts in this group\n * - `children`: The rendered message part components\n *\n * @example\n * ```tsx\n * // Collapsible group\n * Group: ({ groupKey, indices, children }) => {\n * if (!groupKey) return <>{children}</>;\n * return (\n * <details className=\"message-group\">\n * <summary>\n * Group {groupKey} ({indices.length} parts)\n * </summary>\n * <div className=\"group-content\">\n * {children}\n * </div>\n * </details>\n * );\n * }\n * ```\n *\n * @param groupKey - The group key (undefined for ungrouped parts)\n * @param indices - Array of indices for the parts in this group\n * @param children - Rendered message part components to display within the group\n */\n Group?: ComponentType<\n PropsWithChildren<{\n groupKey: string | undefined;\n indices: number[];\n }>\n >;\n }\n | undefined;\n };\n}\n\nconst ToolUIDisplay = ({\n Fallback,\n ...props\n}: {\n Fallback: ToolCallMessagePartComponent | undefined;\n} & ToolCallMessagePartProps) => {\n const Render = useAuiState(\n (s) => s.tools.toolUIs[props.toolName]?.[0]?.render ?? Fallback,\n );\n if (!Render) return null;\n return <Render {...props} />;\n};\n\nconst DataUIDisplay = ({\n Fallback,\n ...props\n}: {\n Fallback: DataMessagePartComponent | undefined;\n} & DataMessagePartProps) => {\n const Render = useAuiState((s) => {\n const Render = s.dataRenderers.renderers[props.name] ?? Fallback;\n if (Array.isArray(Render)) return Render[0] ?? Fallback;\n return Render;\n });\n if (!Render) return null;\n return <Render {...props} />;\n};\n\nconst defaultComponents = {\n Text: () => (\n <p style={{ whiteSpace: \"pre-line\" }}>\n <MessagePartPrimitiveText />\n <MessagePartPrimitiveInProgress>\n <span style={{ fontFamily: \"revert\" }}>{\" \\u25CF\"}</span>\n </MessagePartPrimitiveInProgress>\n </p>\n ),\n Reasoning: () => null,\n Source: () => null,\n Image: () => <MessagePartPrimitiveImage />,\n File: () => null,\n Unstable_Audio: () => null,\n Group: ({ children }) => children,\n} satisfies MessagePrimitiveUnstable_PartsGrouped.Props[\"components\"];\n\ntype MessagePartComponentProps = {\n components: MessagePrimitiveUnstable_PartsGrouped.Props[\"components\"];\n};\n\nconst MessagePartComponent: FC<MessagePartComponentProps> = ({\n components: {\n Text = defaultComponents.Text,\n Reasoning = defaultComponents.Reasoning,\n Image = defaultComponents.Image,\n Source = defaultComponents.Source,\n File = defaultComponents.File,\n Unstable_Audio: Audio = defaultComponents.Unstable_Audio,\n tools = {},\n data,\n } = {},\n}) => {\n const aui = useAui();\n const part = useAuiState((s) => s.part);\n\n const type = part.type;\n if (type === \"tool-call\") {\n const addResult = aui.part.addToolResult;\n const resume = aui.part.resumeToolCall;\n const respondToApproval = aui.part.respondToToolApproval;\n if (\"Override\" in tools)\n return (\n <tools.Override\n {...part}\n addResult={addResult}\n resume={resume}\n respondToApproval={respondToApproval}\n />\n );\n const Tool = tools.by_name?.[part.toolName] ?? tools.Fallback;\n return (\n <ToolUIDisplay\n {...part}\n Fallback={Tool}\n addResult={addResult}\n resume={resume}\n respondToApproval={respondToApproval}\n />\n );\n }\n\n if (part.status?.type === \"requires-action\")\n throw new Error(\"Encountered unexpected requires-action status\");\n\n switch (type) {\n case \"text\":\n return <Text {...part} />;\n\n case \"reasoning\":\n return <Reasoning {...part} />;\n\n case \"source\":\n return <Source {...part} />;\n\n case \"image\":\n return <Image {...part} />;\n\n case \"file\":\n return <File {...part} />;\n\n case \"audio\":\n return <Audio {...part} />;\n\n case \"data\": {\n const Data = data?.by_name?.[part.name] ?? data?.Fallback;\n return <DataUIDisplay {...part} Fallback={Data} />;\n }\n\n default:\n console.warn(`Unknown message part type: ${type}`);\n return null;\n }\n};\n\ntype MessagePartProps = {\n partIndex: number;\n components: MessagePrimitiveUnstable_PartsGrouped.Props[\"components\"];\n};\n\nconst MessagePartImpl: FC<MessagePartProps> = ({ partIndex, components }) => {\n return (\n <PartByIndexProvider index={partIndex}>\n <MessagePartComponent components={components} />\n </PartByIndexProvider>\n );\n};\n\nconst MessagePart = memo(\n MessagePartImpl,\n (prev, next) =>\n prev.partIndex === next.partIndex &&\n prev.components?.Text === next.components?.Text &&\n prev.components?.Reasoning === next.components?.Reasoning &&\n prev.components?.Source === next.components?.Source &&\n prev.components?.Image === next.components?.Image &&\n prev.components?.File === next.components?.File &&\n prev.components?.Unstable_Audio === next.components?.Unstable_Audio &&\n prev.components?.tools === next.components?.tools &&\n prev.components?.data === next.components?.data &&\n prev.components?.Group === next.components?.Group,\n);\n\nconst EmptyPartFallback: FC<{\n status: MessagePartStatus;\n component: TextMessagePartComponent;\n}> = ({ status, component: Component }) => {\n return (\n <TextMessagePartProvider text=\"\" isRunning={status.type === \"running\"}>\n <Component type=\"text\" text=\"\" status={status} />\n </TextMessagePartProvider>\n );\n};\n\nconst COMPLETE_STATUS: MessagePartStatus = Object.freeze({\n type: \"complete\",\n});\n\nconst EmptyPartsImpl: FC<MessagePartComponentProps> = ({ components }) => {\n const status = useAuiState(\n (s) => (s.message.status ?? COMPLETE_STATUS) as MessagePartStatus,\n );\n\n if (components?.Empty) return <components.Empty status={status} />;\n\n return (\n <EmptyPartFallback\n status={status}\n component={components?.Text ?? defaultComponents.Text}\n />\n );\n};\n\nconst EmptyParts = memo(\n EmptyPartsImpl,\n (prev, next) =>\n prev.components?.Empty === next.components?.Empty &&\n prev.components?.Text === next.components?.Text,\n);\n\n/**\n * Renders the parts of a message grouped by a custom grouping function.\n *\n * This component allows you to group message parts based on any criteria you define.\n * The grouping function receives all message parts and returns an array of groups,\n * where each group has a key and an array of part indices.\n *\n * @deprecated Prefer `<MessagePrimitive.GroupedParts>` for adjacent\n * grouping — it dispatches all rendering through one `switch (part.type)`\n * and supports nested group paths. Keep this primitive only for\n * non-adjacent clustering (e.g., gathering parts with the same parent-id\n * across the message).\n *\n * @example\n * ```tsx\n * // Group by parent ID (default behavior)\n * <MessagePrimitive.Unstable_PartsGrouped\n * components={{\n * Text: ({ text }) => <p className=\"message-text\">{text}</p>,\n * Image: ({ image }) => <img src={image} alt=\"Message image\" />,\n * Group: ({ groupKey, indices, children }) => {\n * if (!groupKey) return <>{children}</>;\n * return (\n * <div className=\"parent-group border rounded p-4\">\n * <h4>Parent ID: {groupKey}</h4>\n * {children}\n * </div>\n * );\n * }\n * }}\n * />\n * ```\n */\nexport const MessagePrimitiveUnstable_PartsGrouped: FC<\n MessagePrimitiveUnstable_PartsGrouped.Props\n> = ({ groupingFunction, components }) => {\n const contentLength = useAuiState((s) => s.message.parts.length);\n const messageGroups = useMessagePartsGrouped(groupingFunction);\n\n const partsElements = useMemo(() => {\n if (contentLength === 0) {\n return <EmptyParts components={components} />;\n }\n\n return messageGroups.map((group, groupIndex) => {\n const GroupComponent = components?.Group ?? defaultComponents.Group;\n\n return (\n <GroupComponent\n key={`group-${groupIndex}-${group.groupKey ?? \"ungrouped\"}`}\n groupKey={group.groupKey}\n indices={group.indices}\n >\n {group.indices.map((partIndex) => (\n <MessagePart\n key={partIndex}\n partIndex={partIndex}\n components={components}\n />\n ))}\n </GroupComponent>\n );\n });\n }, [messageGroups, components, contentLength]);\n\n return <>{partsElements}</>;\n};\n\nMessagePrimitiveUnstable_PartsGrouped.displayName =\n \"MessagePrimitive.Unstable_PartsGrouped\";\n\n/**\n * Renders the parts of a message grouped by their parent ID.\n * This is a convenience wrapper around Unstable_PartsGrouped with parent ID grouping.\n *\n * @deprecated Use MessagePrimitive.Unstable_PartsGrouped instead for more flexibility\n */\nexport const MessagePrimitiveUnstable_PartsGroupedByParentId: FC<\n Omit<MessagePrimitiveUnstable_PartsGrouped.Props, \"groupingFunction\">\n> = ({ components, ...props }) => {\n return (\n <MessagePrimitiveUnstable_PartsGrouped\n {...props}\n components={components}\n groupingFunction={groupMessagePartsByParentId}\n />\n );\n};\n\nMessagePrimitiveUnstable_PartsGroupedByParentId.displayName =\n \"MessagePrimitive.Unstable_PartsGroupedByParentId\";\n"],"mappings":"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"}
|
|
@@ -14,10 +14,12 @@ import { jsx } from "react/jsx-runtime";
|
|
|
14
14
|
import { useComposedRefs } from "@radix-ui/react-compose-refs";
|
|
15
15
|
//#region src/primitives/thread/ThreadViewport.tsx
|
|
16
16
|
const useViewportSizeRef = () => {
|
|
17
|
-
|
|
17
|
+
const register = useThreadViewport(_temp);
|
|
18
|
+
return useSizeHandle(register, _temp2);
|
|
18
19
|
};
|
|
19
20
|
const useViewportElementRef = () => {
|
|
20
|
-
|
|
21
|
+
const registerViewportElement = useThreadViewport(_temp3);
|
|
22
|
+
return useManagedRef(registerViewportElement);
|
|
21
23
|
};
|
|
22
24
|
const useTopAnchorTurn = (enabled) => {
|
|
23
25
|
const $ = c(21);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThreadViewport.js","names":["c","_c","useComposedRefs","Primitive","ComponentRef","forwardRef","ComponentPropsWithoutRef","useCallback","useLayoutEffect","useMemo","useAuiEvent","useAuiState","useManagedRef","useThreadViewportAutoScroll","ThreadPrimitiveViewportProvider","useSizeHandle","useThreadViewport","useThreadViewportStore","useTopAnchorReserve","getActiveTopAnchorAnchorId","getActiveTopAnchorTargetId","isTopAnchorTurnValid","ThreadPrimitiveViewport","Element","div","Props","autoScroll","turnAnchor","topAnchorMessageClamp","tallerThan","visibleHeight","scrollToBottomOnRunStart","scrollToBottomOnInitialize","scrollToBottomOnThreadSwitch","useViewportSizeRef","register","_temp","getHeight","_temp2","useViewportElementRef","registerViewportElement","_temp3","useTopAnchorTurn","enabled","$","threadViewportStore","t0","s","thread","activeAnchorId","t1","s_0","activeTargetId","topAnchorTurn","_temp4","t2","bb0","t3","anchorId","targetId","activeTurn","s_2","messages","topAnchorTurnIsValid","t4","t5","getState","setTopAnchorTurn","t6","t7","state","current","t8","clearTopAnchorTurn","ThreadPrimitiveViewportScrollable","forwardedRef","children","rest","autoScrollRef","viewportSizeRef","viewportElementRef","topAnchorEnabled","ref","displayName","props","registerViewport","el","clientHeight","s_1"],"sources":["../../../src/primitives/thread/ThreadViewport.tsx"],"sourcesContent":["\"use client\";\n\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\nimport { Primitive } from \"../../utils/Primitive\";\nimport {\n type ComponentRef,\n forwardRef,\n type ComponentPropsWithoutRef,\n useCallback,\n useLayoutEffect,\n useMemo,\n} from \"react\";\nimport { useAuiEvent, useAuiState } from \"@assistant-ui/store\";\nimport { useManagedRef } from \"../../utils/hooks/useManagedRef\";\nimport { useThreadViewportAutoScroll } from \"./useThreadViewportAutoScroll\";\nimport { ThreadPrimitiveViewportProvider } from \"../../context/providers/ThreadViewportProvider\";\nimport { useSizeHandle } from \"../../utils/hooks/useSizeHandle\";\nimport {\n useThreadViewport,\n useThreadViewportStore,\n} from \"../../context/react/ThreadViewportContext\";\nimport { useTopAnchorReserve } from \"./topAnchor/useTopAnchorReserve\";\nimport {\n getActiveTopAnchorAnchorId,\n getActiveTopAnchorTargetId,\n isTopAnchorTurnValid,\n} from \"./topAnchor/topAnchorTurn\";\n\nexport namespace ThreadPrimitiveViewport {\n export type Element = ComponentRef<typeof Primitive.div>;\n export type Props = ComponentPropsWithoutRef<typeof Primitive.div> & {\n /**\n * Whether to automatically scroll to the bottom when new messages are added.\n * When enabled, the viewport will automatically scroll to show the latest content.\n *\n * Default false if `turnAnchor` is \"top\", otherwise defaults to true.\n */\n autoScroll?: boolean | undefined;\n\n /**\n * Controls scroll anchoring behavior for new messages.\n * - \"bottom\" (default): Messages anchor at the bottom, classic chat behavior.\n * - \"top\": New user messages anchor at the top of the viewport for a focused reading experience.\n */\n turnAnchor?: \"top\" | \"bottom\" | undefined;\n\n /**\n * Clamps tall user messages so the assistant response stays in view.\n *\n * @default { tallerThan: \"10em\", visibleHeight: \"6em\" }\n */\n topAnchorMessageClamp?: {\n /**\n * Clamp messages taller than this. Supports `px`, `em`, and `rem`.\n *\n * @default \"10em\"\n */\n tallerThan?: string;\n /**\n * Visible portion of clamped messages. Supports `px`, `em`, and `rem`.\n *\n * @default \"6em\"\n */\n visibleHeight?: string;\n };\n\n /**\n * Whether to scroll to bottom when a new run starts.\n *\n * Defaults to true.\n */\n scrollToBottomOnRunStart?: boolean | undefined;\n\n /**\n * Whether to scroll to bottom when thread history is first loaded.\n *\n * Defaults to true.\n */\n scrollToBottomOnInitialize?: boolean | undefined;\n\n /**\n * Whether to scroll to bottom when switching to a different thread.\n *\n * Defaults to true.\n */\n scrollToBottomOnThreadSwitch?: boolean | undefined;\n };\n}\n\nconst useViewportSizeRef = () => {\n const register = useThreadViewport((s) => s.registerViewport);\n const getHeight = useCallback((el: HTMLElement) => el.clientHeight, []);\n return useSizeHandle(register, getHeight);\n};\n\nconst useViewportElementRef = () => {\n const registerViewportElement = useThreadViewport(\n (s) => s.registerViewportElement,\n );\n\n return useManagedRef(registerViewportElement);\n};\n\nconst useTopAnchorTurn = (enabled: boolean) => {\n const threadViewportStore = useThreadViewportStore();\n const activeAnchorId = useAuiState((s) => {\n if (!enabled) return undefined;\n return getActiveTopAnchorAnchorId(s.thread);\n });\n const activeTargetId = useAuiState((s) => {\n if (!enabled) return undefined;\n return getActiveTopAnchorTargetId(s.thread);\n });\n const topAnchorTurn = useThreadViewport((s) => s.topAnchorTurn);\n const activeTurn = useMemo(() => {\n if (!activeAnchorId || !activeTargetId) return null;\n return { anchorId: activeAnchorId, targetId: activeTargetId };\n }, [activeAnchorId, activeTargetId]);\n\n const topAnchorTurnIsValid = useAuiState(\n (s) =>\n enabled &&\n !!topAnchorTurn &&\n isTopAnchorTurnValid(topAnchorTurn, s.thread.messages),\n );\n\n useLayoutEffect(() => {\n if (!topAnchorTurn || topAnchorTurnIsValid) return;\n\n threadViewportStore.getState().setTopAnchorTurn(null);\n }, [threadViewportStore, topAnchorTurn, topAnchorTurnIsValid]);\n\n useLayoutEffect(() => {\n if (!activeTurn) return;\n\n const state = threadViewportStore.getState();\n const current = state.topAnchorTurn;\n if (\n current?.anchorId === activeTurn.anchorId &&\n current.targetId === activeTurn.targetId\n ) {\n return;\n }\n\n state.setTopAnchorTurn(activeTurn);\n }, [activeTurn, threadViewportStore]);\n\n const clearTopAnchorTurn = useCallback(() => {\n threadViewportStore.getState().setTopAnchorTurn(null);\n }, [threadViewportStore]);\n\n useAuiEvent(\"thread.initialize\", clearTopAnchorTurn);\n useAuiEvent(\"threadListItem.switchedTo\", clearTopAnchorTurn);\n};\n\nconst ThreadPrimitiveViewportScrollable = forwardRef<\n ThreadPrimitiveViewport.Element,\n ThreadPrimitiveViewport.Props\n>(\n (\n {\n autoScroll,\n scrollToBottomOnRunStart,\n scrollToBottomOnInitialize,\n scrollToBottomOnThreadSwitch,\n children,\n ...rest\n },\n forwardedRef,\n ) => {\n const autoScrollRef = useThreadViewportAutoScroll<HTMLDivElement>({\n autoScroll,\n scrollToBottomOnRunStart,\n scrollToBottomOnInitialize,\n scrollToBottomOnThreadSwitch,\n });\n const viewportSizeRef = useViewportSizeRef();\n const viewportElementRef = useViewportElementRef();\n const threadViewportStore = useThreadViewportStore();\n const turnAnchor = threadViewportStore.getState().turnAnchor;\n const topAnchorEnabled = turnAnchor === \"top\";\n useTopAnchorTurn(topAnchorEnabled);\n useTopAnchorReserve(topAnchorEnabled);\n const ref = useComposedRefs(\n forwardedRef,\n autoScrollRef,\n viewportSizeRef,\n viewportElementRef,\n );\n\n return (\n <Primitive.div {...rest} ref={ref}>\n {children}\n </Primitive.div>\n );\n },\n);\n\nThreadPrimitiveViewportScrollable.displayName =\n \"ThreadPrimitive.ViewportScrollable\";\n\n/**\n * A scrollable viewport container for thread messages.\n *\n * This component provides a scrollable area for displaying thread messages with\n * automatic scrolling capabilities. It manages the viewport state and provides\n * context for child components to access viewport-related functionality.\n *\n * @example\n * ```tsx\n * <ThreadPrimitive.Viewport turnAnchor=\"top\">\n * <ThreadPrimitive.Messages>\n * {() => <MyMessage />}\n * </ThreadPrimitive.Messages>\n * </ThreadPrimitive.Viewport>\n * ```\n */\nexport const ThreadPrimitiveViewport = forwardRef<\n ThreadPrimitiveViewport.Element,\n ThreadPrimitiveViewport.Props\n>(({ turnAnchor, topAnchorMessageClamp, ...props }, ref) => {\n return (\n <ThreadPrimitiveViewportProvider\n options={{ turnAnchor, topAnchorMessageClamp }}\n >\n <ThreadPrimitiveViewportScrollable {...props} ref={ref} />\n </ThreadPrimitiveViewportProvider>\n );\n});\n\nThreadPrimitiveViewport.displayName = \"ThreadPrimitive.Viewport\";\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ThreadViewport.js","names":["c","_c","useComposedRefs","Primitive","ComponentRef","forwardRef","ComponentPropsWithoutRef","useCallback","useLayoutEffect","useMemo","useAuiEvent","useAuiState","useManagedRef","useThreadViewportAutoScroll","ThreadPrimitiveViewportProvider","useSizeHandle","useThreadViewport","useThreadViewportStore","useTopAnchorReserve","getActiveTopAnchorAnchorId","getActiveTopAnchorTargetId","isTopAnchorTurnValid","ThreadPrimitiveViewport","Element","div","Props","autoScroll","turnAnchor","topAnchorMessageClamp","tallerThan","visibleHeight","scrollToBottomOnRunStart","scrollToBottomOnInitialize","scrollToBottomOnThreadSwitch","useViewportSizeRef","register","_temp","getHeight","_temp2","useViewportElementRef","registerViewportElement","_temp3","useTopAnchorTurn","enabled","$","threadViewportStore","t0","s","thread","activeAnchorId","t1","s_0","activeTargetId","topAnchorTurn","_temp4","t2","bb0","t3","anchorId","targetId","activeTurn","s_2","messages","topAnchorTurnIsValid","t4","t5","getState","setTopAnchorTurn","t6","t7","state","current","t8","clearTopAnchorTurn","ThreadPrimitiveViewportScrollable","forwardedRef","children","rest","autoScrollRef","viewportSizeRef","viewportElementRef","topAnchorEnabled","ref","displayName","props","registerViewport","el","clientHeight","s_1"],"sources":["../../../src/primitives/thread/ThreadViewport.tsx"],"sourcesContent":["\"use client\";\n\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\nimport { Primitive } from \"../../utils/Primitive\";\nimport {\n type ComponentRef,\n forwardRef,\n type ComponentPropsWithoutRef,\n useCallback,\n useLayoutEffect,\n useMemo,\n} from \"react\";\nimport { useAuiEvent, useAuiState } from \"@assistant-ui/store\";\nimport { useManagedRef } from \"../../utils/hooks/useManagedRef\";\nimport { useThreadViewportAutoScroll } from \"./useThreadViewportAutoScroll\";\nimport { ThreadPrimitiveViewportProvider } from \"../../context/providers/ThreadViewportProvider\";\nimport { useSizeHandle } from \"../../utils/hooks/useSizeHandle\";\nimport {\n useThreadViewport,\n useThreadViewportStore,\n} from \"../../context/react/ThreadViewportContext\";\nimport { useTopAnchorReserve } from \"./topAnchor/useTopAnchorReserve\";\nimport {\n getActiveTopAnchorAnchorId,\n getActiveTopAnchorTargetId,\n isTopAnchorTurnValid,\n} from \"./topAnchor/topAnchorTurn\";\n\nexport namespace ThreadPrimitiveViewport {\n export type Element = ComponentRef<typeof Primitive.div>;\n export type Props = ComponentPropsWithoutRef<typeof Primitive.div> & {\n /**\n * Whether to automatically scroll to the bottom when new messages are added.\n * When enabled, the viewport will automatically scroll to show the latest content.\n *\n * Default false if `turnAnchor` is \"top\", otherwise defaults to true.\n */\n autoScroll?: boolean | undefined;\n\n /**\n * Controls scroll anchoring behavior for new messages.\n * - \"bottom\" (default): Messages anchor at the bottom, classic chat behavior.\n * - \"top\": New user messages anchor at the top of the viewport for a focused reading experience.\n */\n turnAnchor?: \"top\" | \"bottom\" | undefined;\n\n /**\n * Clamps tall user messages so the assistant response stays in view.\n *\n * @default { tallerThan: \"10em\", visibleHeight: \"6em\" }\n */\n topAnchorMessageClamp?: {\n /**\n * Clamp messages taller than this. Supports `px`, `em`, and `rem`.\n *\n * @default \"10em\"\n */\n tallerThan?: string;\n /**\n * Visible portion of clamped messages. Supports `px`, `em`, and `rem`.\n *\n * @default \"6em\"\n */\n visibleHeight?: string;\n };\n\n /**\n * Whether to scroll to bottom when a new run starts.\n *\n * Defaults to true.\n */\n scrollToBottomOnRunStart?: boolean | undefined;\n\n /**\n * Whether to scroll to bottom when thread history is first loaded.\n *\n * Defaults to true.\n */\n scrollToBottomOnInitialize?: boolean | undefined;\n\n /**\n * Whether to scroll to bottom when switching to a different thread.\n *\n * Defaults to true.\n */\n scrollToBottomOnThreadSwitch?: boolean | undefined;\n };\n}\n\nconst useViewportSizeRef = () => {\n const register = useThreadViewport((s) => s.registerViewport);\n const getHeight = useCallback((el: HTMLElement) => el.clientHeight, []);\n return useSizeHandle(register, getHeight);\n};\n\nconst useViewportElementRef = () => {\n const registerViewportElement = useThreadViewport(\n (s) => s.registerViewportElement,\n );\n\n return useManagedRef(registerViewportElement);\n};\n\nconst useTopAnchorTurn = (enabled: boolean) => {\n const threadViewportStore = useThreadViewportStore();\n const activeAnchorId = useAuiState((s) => {\n if (!enabled) return undefined;\n return getActiveTopAnchorAnchorId(s.thread);\n });\n const activeTargetId = useAuiState((s) => {\n if (!enabled) return undefined;\n return getActiveTopAnchorTargetId(s.thread);\n });\n const topAnchorTurn = useThreadViewport((s) => s.topAnchorTurn);\n const activeTurn = useMemo(() => {\n if (!activeAnchorId || !activeTargetId) return null;\n return { anchorId: activeAnchorId, targetId: activeTargetId };\n }, [activeAnchorId, activeTargetId]);\n\n const topAnchorTurnIsValid = useAuiState(\n (s) =>\n enabled &&\n !!topAnchorTurn &&\n isTopAnchorTurnValid(topAnchorTurn, s.thread.messages),\n );\n\n useLayoutEffect(() => {\n if (!topAnchorTurn || topAnchorTurnIsValid) return;\n\n threadViewportStore.getState().setTopAnchorTurn(null);\n }, [threadViewportStore, topAnchorTurn, topAnchorTurnIsValid]);\n\n useLayoutEffect(() => {\n if (!activeTurn) return;\n\n const state = threadViewportStore.getState();\n const current = state.topAnchorTurn;\n if (\n current?.anchorId === activeTurn.anchorId &&\n current.targetId === activeTurn.targetId\n ) {\n return;\n }\n\n state.setTopAnchorTurn(activeTurn);\n }, [activeTurn, threadViewportStore]);\n\n const clearTopAnchorTurn = useCallback(() => {\n threadViewportStore.getState().setTopAnchorTurn(null);\n }, [threadViewportStore]);\n\n useAuiEvent(\"thread.initialize\", clearTopAnchorTurn);\n useAuiEvent(\"threadListItem.switchedTo\", clearTopAnchorTurn);\n};\n\nconst ThreadPrimitiveViewportScrollable = forwardRef<\n ThreadPrimitiveViewport.Element,\n ThreadPrimitiveViewport.Props\n>(\n (\n {\n autoScroll,\n scrollToBottomOnRunStart,\n scrollToBottomOnInitialize,\n scrollToBottomOnThreadSwitch,\n children,\n ...rest\n },\n forwardedRef,\n ) => {\n const autoScrollRef = useThreadViewportAutoScroll<HTMLDivElement>({\n autoScroll,\n scrollToBottomOnRunStart,\n scrollToBottomOnInitialize,\n scrollToBottomOnThreadSwitch,\n });\n const viewportSizeRef = useViewportSizeRef();\n const viewportElementRef = useViewportElementRef();\n const threadViewportStore = useThreadViewportStore();\n const turnAnchor = threadViewportStore.getState().turnAnchor;\n const topAnchorEnabled = turnAnchor === \"top\";\n useTopAnchorTurn(topAnchorEnabled);\n useTopAnchorReserve(topAnchorEnabled);\n const ref = useComposedRefs(\n forwardedRef,\n autoScrollRef,\n viewportSizeRef,\n viewportElementRef,\n );\n\n return (\n <Primitive.div {...rest} ref={ref}>\n {children}\n </Primitive.div>\n );\n },\n);\n\nThreadPrimitiveViewportScrollable.displayName =\n \"ThreadPrimitive.ViewportScrollable\";\n\n/**\n * A scrollable viewport container for thread messages.\n *\n * This component provides a scrollable area for displaying thread messages with\n * automatic scrolling capabilities. It manages the viewport state and provides\n * context for child components to access viewport-related functionality.\n *\n * @example\n * ```tsx\n * <ThreadPrimitive.Viewport turnAnchor=\"top\">\n * <ThreadPrimitive.Messages>\n * {() => <MyMessage />}\n * </ThreadPrimitive.Messages>\n * </ThreadPrimitive.Viewport>\n * ```\n */\nexport const ThreadPrimitiveViewport = forwardRef<\n ThreadPrimitiveViewport.Element,\n ThreadPrimitiveViewport.Props\n>(({ turnAnchor, topAnchorMessageClamp, ...props }, ref) => {\n return (\n <ThreadPrimitiveViewportProvider\n options={{ turnAnchor, topAnchorMessageClamp }}\n >\n <ThreadPrimitiveViewportScrollable {...props} ref={ref} />\n </ThreadPrimitiveViewportProvider>\n );\n});\n\nThreadPrimitiveViewport.displayName = \"ThreadPrimitive.Viewport\";\n"],"mappings":";;;;;;;;;;;;;;;AAyFA,MAAMkC,2BAAqB;CACzB,MAAAC,WAAiBnB,kBAAkBoB,KAAyB;CACY,OACjErB,cAAcoB,UAAUE,MAAS;AAAC;AAG3C,MAAME,8BAAwB;CAC5B,MAAAC,0BAAgCxB,kBAC9ByB,MACF;CAAE,OAEK7B,cAAc4B,uBAAuB;AAAC;AAG/C,MAAME,oBAAmBC,YAAA;CAAA,MAAAC,IAAA3C,EAAA,EAAA;CACvB,MAAA4C,sBAA4B5B,uBAAuB;CAAE,IAAA6B;CAAA,IAAAF,EAAA,OAAAD,SAAA;EAClBG,MAAAC,MAAA;GACjC,IAAI,CAACJ,SAAO;GAAmB,OACxBxB,2BAA2B4B,EAACC,MAAO;EAAC;EAC5CJ,EAAA,KAAAD;EAAAC,EAAA,KAAAE;CAAA,OAAAA,KAAAF,EAAA;CAHD,MAAAK,iBAAuBtC,YAAYmC,EAGlC;CAAE,IAAAI;CAAA,IAAAN,EAAA,OAAAD,SAAA;EACgCO,MAAAC,QAAA;GACjC,IAAI,CAACR,SAAO;GAAmB,OACxBvB,2BAA2B2B,IAACC,MAAO;EAAC;EAC5CJ,EAAA,KAAAD;EAAAC,EAAA,KAAAM;CAAA,OAAAA,KAAAN,EAAA;CAHD,MAAAQ,iBAAuBzC,YAAYuC,EAGlC;CACD,MAAAG,gBAAsBrC,kBAAkBsC,MAAsB;CAAE,IAAAC;CAAAC,KAAA;EAE9D,IAAI,CAACP,kBAAD,CAAoBG,gBAAc;GAAEG,KAAO;GAAP,MAAAC;EAAY;EAAA,IAAAC;EAAA,IAAAb,EAAA,OAAAK,kBAAAL,EAAA,OAAAQ,gBAAA;GAC7CK,KAAA;IAAAC,UAAYT;IAAcU,UAAYP;GAAe;GAACR,EAAA,KAAAK;GAAAL,EAAA,KAAAQ;GAAAR,EAAA,KAAAa;EAAA,OAAAA,KAAAb,EAAA;EAA7DW,KAAOE;CAAuD;CAFhE,MAAAG,aAAmBL;CAGkB,IAAAE;CAAA,IAAAb,EAAA,OAAAD,WAAAC,EAAA,OAAAS,eAAA;EAGnCI,MAAAI,QACElB,WAAA,CACC,CAACU,iBACFhC,qBAAqBgC,eAAeN,IAACC,OAAOc,QAAS;EAAClB,EAAA,KAAAD;EAAAC,EAAA,KAAAS;EAAAT,EAAA,KAAAa;CAAA,OAAAA,KAAAb,EAAA;CAJ1D,MAAAmB,uBAA6BpD,YAC3B8C,EAIF;CAAE,IAAAO;CAAA,IAAAC;CAAA,IAAArB,EAAA,QAAAC,uBAAAD,EAAA,QAAAS,iBAAAT,EAAA,QAAAmB,sBAAA;EAEcC,WAAA;GACd,IAAI,CAACX,iBAADU,sBAAsC;GAE1ClB,oBAAmBqB,SAAU,CAAC,CAAAC,iBAAkB,IAAI;EAAC;EACpDF,KAAA;GAACpB;GAAqBQ;GAAeU;EAAoB;EAACnB,EAAA,MAAAC;EAAAD,EAAA,MAAAS;EAAAT,EAAA,MAAAmB;EAAAnB,EAAA,MAAAoB;EAAApB,EAAA,MAAAqB;CAAA,OAAA;EAAAD,KAAApB,EAAA;EAAAqB,KAAArB,EAAA;CAAA;CAJ7DpC,gBAAgBwD,IAIbC,EAA0D;CAAC,IAAAG;CAAA,IAAAC;CAAA,IAAAzB,EAAA,QAAAgB,cAAAhB,EAAA,QAAAC,qBAAA;EAE9CuB,WAAA;GACd,IAAI,CAACR,YAAU;GAEf,MAAAU,QAAczB,oBAAmBqB,SAAU;GAC3C,MAAAK,UAAgBD,MAAKjB;GACrB,IACEkB,SAAOb,aAAeE,WAAUF,YAChCa,QAAOZ,aAAcC,WAAUD,UAAS;GAK1CW,MAAKH,iBAAkBP,UAAU;EAAC;EACjCS,KAAA,CAACT,YAAYf,mBAAmB;EAACD,EAAA,MAAAgB;EAAAhB,EAAA,MAAAC;EAAAD,EAAA,MAAAwB;EAAAxB,EAAA,MAAAyB;CAAA,OAAA;EAAAD,KAAAxB,EAAA;EAAAyB,KAAAzB,EAAA;CAAA;CAbpCpC,gBAAgB4D,IAabC,EAAiC;CAAC,IAAAG;CAAA,IAAA5B,EAAA,QAAAC,qBAAA;EAEE2B,WAAA;GACrC3B,oBAAmBqB,SAAU,CAAC,CAAAC,iBAAkB,IAAI;EAAC;EACtDvB,EAAA,MAAAC;EAAAD,EAAA,MAAA4B;CAAA,OAAAA,KAAA5B,EAAA;CAFD,MAAA6B,qBAA2BD;CAI3B9D,YAAY,qBAAqB+D,kBAAkB;CACnD/D,YAAY,6BAA6B+D,kBAAkB;AAAC;AAG9D,MAAMC,oCAAoCrE,YAIxCyC,IAAA6B,iBAAA;CAAA,MAAA/B,IAAA3C,EAAA,EAAA;CAAA,IAAAyB;CAAA,IAAAkD;CAAA,IAAAC;CAAA,IAAA7C;CAAA,IAAAD;CAAA,IAAAE;CAAA,IAAAW,EAAA,OAAAE,IAAA;EACE,CAAA,CAAApB,YAAAK,0BAAAC,4BAAAC,8BAAA2C,aAAAC,QAAA/B;EAOCF,EAAA,KAAAE;EAAAF,EAAA,KAAAlB;EAAAkB,EAAA,KAAAgC;EAAAhC,EAAA,KAAAiC;EAAAjC,EAAA,KAAAZ;EAAAY,EAAA,KAAAb;EAAAa,EAAA,KAAAX;CAAA,OAAA;EAAAP,aAAAkB,EAAA;EAAAgC,WAAAhC,EAAA;EAAAiC,OAAAjC,EAAA;EAAAZ,6BAAAY,EAAA;EAAAb,2BAAAa,EAAA;EAAAX,+BAAAW,EAAA;CAAA;CAAA,IAAAM;CAAA,IAAAN,EAAA,OAAAlB,cAAAkB,EAAA,OAAAZ,8BAAAY,EAAA,OAAAb,4BAAAa,EAAA,QAAAX,8BAAA;EAGiEiB,KAAA;GAAAxB;GAAAK;GAAAC;GAAAC;EAKlE;EAACW,EAAA,KAAAlB;EAAAkB,EAAA,KAAAZ;EAAAY,EAAA,KAAAb;EAAAa,EAAA,MAAAX;EAAAW,EAAA,MAAAM;CAAA,OAAAA,KAAAN,EAAA;CALD,MAAAkC,gBAAsBjE,4BAA4CqC,EAKjE;CACD,MAAA6B,kBAAwB7C,mBAAmB;CAC3C,MAAA8C,qBAA2BzC,sBAAsB;CACjD,MAAAM,sBAA4B5B,uBAAuB;CAAE,IAAAsC;CAAA,IAAAX,EAAA,QAAAC,qBAAA;EAClCU,KAAAV,oBAAmBqB,SAAU;EAACtB,EAAA,MAAAC;EAAAD,EAAA,MAAAW;CAAA,OAAAA,KAAAX,EAAA;CACjD,MAAAqC,mBADmB1B,GAA8B5B,eACT;CACxCe,iBAAiBuC,gBAAgB;CACjC/D,oBAAoB+D,gBAAgB;CACpC,MAAAC,MAAYhF,gBACVyE,cACAG,eACAC,iBACAC,kBACF;CAAE,IAAAvB;CAAA,IAAAb,EAAA,QAAAgC,YAAAhC,EAAA,QAAAsC,OAAAtC,EAAA,QAAAiC,MAAA;EAGApB,KAAA,oBAAA,UAAA,KAAA;GAAA,GAAmBoB;GAAWK;GAC3BN;EACH,CAAA;EAAgBhC,EAAA,MAAAgC;EAAAhC,EAAA,MAAAsC;EAAAtC,EAAA,MAAAiC;EAAAjC,EAAA,MAAAa;CAAA,OAAAA,KAAAb,EAAA;CAAA,OAFhBa;AAEgB,CAGtB;AAEAiB,kCAAkCS,cAChC;;;;;;;;;;;;;;;;;AAkBF,MAAa7D,0BAA0BjB,YAGrCyC,IAAAoC,QAAA;CAAA,MAAAtC,IAAA3C,EAAA,EAAA;CAAA,IAAAmF;CAAA,IAAAxD;CAAA,IAAAD;CAAA,IAAAiB,EAAA,OAAAE,IAAA;EAAC,CAAA,CAAAnB,YAAAC,0BAAAwD,SAAAtC;EAA+CF,EAAA,KAAAE;EAAAF,EAAA,KAAAwC;EAAAxC,EAAA,KAAAhB;EAAAgB,EAAA,KAAAjB;CAAA,OAAA;EAAAyD,QAAAxC,EAAA;EAAAhB,wBAAAgB,EAAA;EAAAjB,aAAAiB,EAAA;CAAA;CAAA,IAAAM;CAAA,IAAAN,EAAA,OAAAhB,yBAAAgB,EAAA,OAAAjB,YAAA;EAGnCuB,KAAA;GAAAvB;GAAAC;EAAoC;EAACgB,EAAA,KAAAhB;EAAAgB,EAAA,KAAAjB;EAAAiB,EAAA,KAAAM;CAAA,OAAAA,KAAAN,EAAA;CAAA,IAAAW;CAAA,IAAAX,EAAA,OAAAwC,SAAAxC,EAAA,OAAAsC,KAAA;EAE9C3B,KAAA,oBAAC,mCAAD;GAAkC,GAAK6B;GAAYF;EAAG,CAAA;EAAItC,EAAA,KAAAwC;EAAAxC,EAAA,KAAAsC;EAAAtC,EAAA,KAAAW;CAAA,OAAAA,KAAAX,EAAA;CAAA,IAAAa;CAAA,IAAAb,EAAA,QAAAM,MAAAN,EAAA,QAAAW,IAAA;EAH5DE,KAAA,oBAAC,iCAAD;GACW,SAAAP;GAETK,UAAAA;EAH8B,CAAA;EAIEX,EAAA,MAAAM;EAAAN,EAAA,MAAAW;EAAAX,EAAA,MAAAa;CAAA,OAAAA,KAAAb,EAAA;CAAA,OAJlCa;AAIkC,CAErC;AAEDnC,wBAAwB6D,cAAc;AA7IX,SAAA/C,MAAAW,GAAA;CAAA,OACiBA,EAACsC;AAAiB;AADnC,SAAA/C,OAAAgD,IAAA;CAAA,OAE0BA,GAAEC;AAAa;AAItC,SAAA9C,OAAAM,GAAA;CAAA,OAEnBA,EAACP;AAAwB;AAMX,SAAAc,OAAAkC,KAAA;CAAA,OAUwBzC,IAACM;AAAc"}
|
|
@@ -33,7 +33,9 @@ import { useComposedRefs } from "@radix-ui/react-compose-refs";
|
|
|
33
33
|
*/
|
|
34
34
|
const ThreadPrimitiveViewportFooter = forwardRef((props, forwardedRef) => {
|
|
35
35
|
const $ = c(3);
|
|
36
|
-
const
|
|
36
|
+
const register = useThreadViewport(_temp);
|
|
37
|
+
const resizeRef = useSizeHandle(register, _temp2);
|
|
38
|
+
const ref = useComposedRefs(forwardedRef, resizeRef);
|
|
37
39
|
let t0;
|
|
38
40
|
if ($[0] !== props || $[1] !== ref) {
|
|
39
41
|
t0 = /* @__PURE__ */ jsx(Primitive.div, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThreadViewportFooter.js","names":["c","_c","useComposedRefs","Primitive","ComponentRef","forwardRef","ComponentPropsWithoutRef","useCallback","useSizeHandle","useThreadViewport","ThreadPrimitiveViewportFooter","Element","div","Props","props","forwardedRef","$","register","_temp","getHeight","_temp2","resizeRef","ref","t0","displayName","s","registerContentInset","el","marginTop","parseFloat","getComputedStyle","offsetHeight"],"sources":["../../../src/primitives/thread/ThreadViewportFooter.tsx"],"sourcesContent":["\"use client\";\n\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\nimport { Primitive } from \"../../utils/Primitive\";\nimport {\n type ComponentRef,\n forwardRef,\n type ComponentPropsWithoutRef,\n useCallback,\n} from \"react\";\nimport { useSizeHandle } from \"../../utils/hooks/useSizeHandle\";\nimport { useThreadViewport } from \"../../context/react/ThreadViewportContext\";\n\nexport namespace ThreadPrimitiveViewportFooter {\n export type Element = ComponentRef<typeof Primitive.div>;\n export type Props = ComponentPropsWithoutRef<typeof Primitive.div>;\n}\n\n/**\n * A footer container that measures its height for scroll calculations.\n *\n * This component measures its height and provides it to the viewport context\n * so the auto-scroll system can account for any sticky footer overlapping the\n * message list.\n *\n * Multiple ViewportFooter components can be used - their heights are summed.\n *\n * Typically used with `className=\"sticky bottom-0\"` to keep the footer\n * visible at the bottom of the viewport while scrolling.\n *\n * @example\n * ```tsx\n * <ThreadPrimitive.Viewport>\n * <ThreadPrimitive.Messages>\n * {() => <MyMessage />}\n * </ThreadPrimitive.Messages>\n * <ThreadPrimitive.ViewportFooter className=\"sticky bottom-0\">\n * <Composer />\n * </ThreadPrimitive.ViewportFooter>\n * </ThreadPrimitive.Viewport>\n * ```\n */\nexport const ThreadPrimitiveViewportFooter = forwardRef<\n ThreadPrimitiveViewportFooter.Element,\n ThreadPrimitiveViewportFooter.Props\n>((props, forwardedRef) => {\n const register = useThreadViewport((s) => s.registerContentInset);\n const getHeight = useCallback((el: HTMLElement) => {\n const marginTop = parseFloat(getComputedStyle(el).marginTop) || 0;\n return el.offsetHeight + marginTop;\n }, []);\n\n const resizeRef = useSizeHandle(register, getHeight);\n\n const ref = useComposedRefs(forwardedRef, resizeRef);\n\n return <Primitive.div {...props} ref={ref} />;\n});\n\nThreadPrimitiveViewportFooter.displayName = \"ThreadPrimitive.ViewportFooter\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,MAAaU,gCAAgCL,YAG3CS,OAAAC,iBAAA;CAAA,MAAAC,IAAAf,EAAA,CAAA;
|
|
1
|
+
{"version":3,"file":"ThreadViewportFooter.js","names":["c","_c","useComposedRefs","Primitive","ComponentRef","forwardRef","ComponentPropsWithoutRef","useCallback","useSizeHandle","useThreadViewport","ThreadPrimitiveViewportFooter","Element","div","Props","props","forwardedRef","$","register","_temp","getHeight","_temp2","resizeRef","ref","t0","displayName","s","registerContentInset","el","marginTop","parseFloat","getComputedStyle","offsetHeight"],"sources":["../../../src/primitives/thread/ThreadViewportFooter.tsx"],"sourcesContent":["\"use client\";\n\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\nimport { Primitive } from \"../../utils/Primitive\";\nimport {\n type ComponentRef,\n forwardRef,\n type ComponentPropsWithoutRef,\n useCallback,\n} from \"react\";\nimport { useSizeHandle } from \"../../utils/hooks/useSizeHandle\";\nimport { useThreadViewport } from \"../../context/react/ThreadViewportContext\";\n\nexport namespace ThreadPrimitiveViewportFooter {\n export type Element = ComponentRef<typeof Primitive.div>;\n export type Props = ComponentPropsWithoutRef<typeof Primitive.div>;\n}\n\n/**\n * A footer container that measures its height for scroll calculations.\n *\n * This component measures its height and provides it to the viewport context\n * so the auto-scroll system can account for any sticky footer overlapping the\n * message list.\n *\n * Multiple ViewportFooter components can be used - their heights are summed.\n *\n * Typically used with `className=\"sticky bottom-0\"` to keep the footer\n * visible at the bottom of the viewport while scrolling.\n *\n * @example\n * ```tsx\n * <ThreadPrimitive.Viewport>\n * <ThreadPrimitive.Messages>\n * {() => <MyMessage />}\n * </ThreadPrimitive.Messages>\n * <ThreadPrimitive.ViewportFooter className=\"sticky bottom-0\">\n * <Composer />\n * </ThreadPrimitive.ViewportFooter>\n * </ThreadPrimitive.Viewport>\n * ```\n */\nexport const ThreadPrimitiveViewportFooter = forwardRef<\n ThreadPrimitiveViewportFooter.Element,\n ThreadPrimitiveViewportFooter.Props\n>((props, forwardedRef) => {\n const register = useThreadViewport((s) => s.registerContentInset);\n const getHeight = useCallback((el: HTMLElement) => {\n const marginTop = parseFloat(getComputedStyle(el).marginTop) || 0;\n return el.offsetHeight + marginTop;\n }, []);\n\n const resizeRef = useSizeHandle(register, getHeight);\n\n const ref = useComposedRefs(forwardedRef, resizeRef);\n\n return <Primitive.div {...props} ref={ref} />;\n});\n\nThreadPrimitiveViewportFooter.displayName = \"ThreadPrimitive.ViewportFooter\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0CA,MAAaU,gCAAgCL,YAG3CS,OAAAC,iBAAA;CAAA,MAAAC,IAAAf,EAAA,CAAA;CACA,MAAAgB,WAAiBR,kBAAkBS,KAA6B;CAMhE,MAAAG,YAAkBb,cAAcS,UAAUE,MAAS;CAEnD,MAAAG,MAAYpB,gBAAgBa,cAAcM,SAAS;CAAE,IAAAE;CAAA,IAAAP,EAAA,OAAAF,SAAAE,EAAA,OAAAM,KAAA;EAE9CC,KAAA,oBAAA,UAAA,KAAA;GAAA,GAAmBT;GAAYQ;EAAG,CAAA;EAAIN,EAAA,KAAAF;EAAAE,EAAA,KAAAM;EAAAN,EAAA,KAAAO;CAAA,OAAAA,KAAAP,EAAA;CAAA,OAAtCO;AAAsC,CAC9C;AAEDb,8BAA8Bc,cAAc;AAd1C,SAAAN,MAAAO,GAAA;CAAA,OAC0CA,EAACC;AAAqB;AADhE,SAAAN,OAAAO,IAAA;CAGE,MAAAC,YAAkBC,WAAWC,iBAAiBH,EAAE,CAAC,CAAAC,SAAe,KAA9C;CAAgD,OAC3DD,GAAEI,eAAgBH;AAAS"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThreadListItemRoot.js","names":["Primitive","ComponentRef","forwardRef","ComponentPropsWithoutRef","KeyboardEvent","useMemo","useRef","useAuiState","composeEventHandlers","Direction","ThreadListItemFocusProvider","useThreadListCollection","PrimitiveDivProps","div","ThreadListItemPrimitiveRoot","Element","Props","props","ref","isMain","s","threads","mainThreadId","threadListItem","id","triggerRef","HTMLButtonElement","moreRef","focus","getItems","undefined","direction","useDirection","onKeyDown","event","HTMLDivElement","forwardKey","backKey","trigger","current","more","target","key","triggers","map","item","filter","node","next","indexOf","preventDefault","displayName"],"sources":["../../../src/primitives/threadListItem/ThreadListItemRoot.tsx"],"sourcesContent":["\"use client\";\n\nimport { Primitive } from \"../../utils/Primitive\";\nimport {\n type ComponentRef,\n forwardRef,\n type ComponentPropsWithoutRef,\n type KeyboardEvent,\n useMemo,\n useRef,\n} from \"react\";\nimport { useAuiState } from \"@assistant-ui/store\";\nimport { composeEventHandlers } from \"@radix-ui/primitive\";\nimport { Direction } from \"radix-ui\";\nimport {\n ThreadListItemFocusProvider,\n useThreadListCollection,\n} from \"../threadListFocusGroup\";\n\ntype PrimitiveDivProps = ComponentPropsWithoutRef<typeof Primitive.div>;\n\nexport namespace ThreadListItemPrimitiveRoot {\n export type Element = ComponentRef<typeof Primitive.div>;\n export type Props = PrimitiveDivProps;\n}\n\nexport const ThreadListItemPrimitiveRoot = forwardRef<\n ThreadListItemPrimitiveRoot.Element,\n ThreadListItemPrimitiveRoot.Props\n>((props, ref) => {\n const isMain = useAuiState(\n (s) => s.threads.mainThreadId === s.threadListItem.id,\n );\n\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n const moreRef = useRef<HTMLButtonElement | null>(null);\n const focus = useMemo(() => ({ triggerRef, moreRef }), []);\n\n const getItems = useThreadListCollection(undefined);\n const direction = Direction.useDirection();\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n const forwardKey = direction === \"rtl\" ? \"ArrowLeft\" : \"ArrowRight\";\n const backKey = direction === \"rtl\" ? \"ArrowRight\" : \"ArrowLeft\";\n const trigger = triggerRef.current;\n const more = moreRef.current;\n\n if (trigger && event.target === trigger) {\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n const triggers = getItems()\n .map((item) => item.ref.current)\n .filter((node): node is HTMLButtonElement => node !== null);\n const next =\n triggers[\n triggers.indexOf(trigger) + (event.key === \"ArrowDown\" ? 1 : -1)\n ];\n if (next) {\n next.focus();\n event.preventDefault();\n }\n } else if (event.key === forwardKey && more) {\n more.focus();\n event.preventDefault();\n }\n } else if (more && event.target === more && event.key === backKey) {\n trigger?.focus();\n event.preventDefault();\n }\n };\n\n return (\n <ThreadListItemFocusProvider value={focus}>\n <Primitive.div\n {...(isMain ? { \"data-active\": \"true\", \"aria-current\": \"true\" } : null)}\n {...props}\n onKeyDown={composeEventHandlers(props.onKeyDown, onKeyDown)}\n ref={ref}\n />\n </ThreadListItemFocusProvider>\n );\n});\n\nThreadListItemPrimitiveRoot.displayName = \"ThreadListItemPrimitive.Root\";\n"],"mappings":";;;;;;;;;AA0BA,MAAac,8BAA8BZ,YAGxCe,OAAOC,QAAQ;CAChB,MAAMC,SAASZ,aACZa,MAAMA,EAAEC,QAAQC,iBAAiBF,EAAEG,eAAeC,EACrD;CAEA,MAAMC,aAAanB,OAAiC,IAAI;CACxD,MAAMqB,UAAUrB,OAAiC,IAAI;CACrD,MAAMsB,QAAQvB,eAAe;EAAEoB;EAAYE;CAAQ,IAAI,CAAA,CAAE;CAEzD,MAAME,WAAWlB,wBAAwBmB,KAAAA,CAAS;CAClD,MAAMC,YAAYtB,UAAUuB,aAAa;CAEzC,MAAMC,aAAaC,UAAyC;EAC1D,MAAME,aAAaL,cAAc,QAAQ,cAAc;EACvD,MAAMM,UAAUN,cAAc,QAAQ,eAAe;EACrD,MAAMO,UAAUb,WAAWc;EAC3B,MAAMC,OAAOb,QAAQY;EAErB,IAAID,WAAWJ,MAAMO,WAAWH,
|
|
1
|
+
{"version":3,"file":"ThreadListItemRoot.js","names":["Primitive","ComponentRef","forwardRef","ComponentPropsWithoutRef","KeyboardEvent","useMemo","useRef","useAuiState","composeEventHandlers","Direction","ThreadListItemFocusProvider","useThreadListCollection","PrimitiveDivProps","div","ThreadListItemPrimitiveRoot","Element","Props","props","ref","isMain","s","threads","mainThreadId","threadListItem","id","triggerRef","HTMLButtonElement","moreRef","focus","getItems","undefined","direction","useDirection","onKeyDown","event","HTMLDivElement","forwardKey","backKey","trigger","current","more","target","key","triggers","map","item","filter","node","next","indexOf","preventDefault","displayName"],"sources":["../../../src/primitives/threadListItem/ThreadListItemRoot.tsx"],"sourcesContent":["\"use client\";\n\nimport { Primitive } from \"../../utils/Primitive\";\nimport {\n type ComponentRef,\n forwardRef,\n type ComponentPropsWithoutRef,\n type KeyboardEvent,\n useMemo,\n useRef,\n} from \"react\";\nimport { useAuiState } from \"@assistant-ui/store\";\nimport { composeEventHandlers } from \"@radix-ui/primitive\";\nimport { Direction } from \"radix-ui\";\nimport {\n ThreadListItemFocusProvider,\n useThreadListCollection,\n} from \"../threadListFocusGroup\";\n\ntype PrimitiveDivProps = ComponentPropsWithoutRef<typeof Primitive.div>;\n\nexport namespace ThreadListItemPrimitiveRoot {\n export type Element = ComponentRef<typeof Primitive.div>;\n export type Props = PrimitiveDivProps;\n}\n\nexport const ThreadListItemPrimitiveRoot = forwardRef<\n ThreadListItemPrimitiveRoot.Element,\n ThreadListItemPrimitiveRoot.Props\n>((props, ref) => {\n const isMain = useAuiState(\n (s) => s.threads.mainThreadId === s.threadListItem.id,\n );\n\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n const moreRef = useRef<HTMLButtonElement | null>(null);\n const focus = useMemo(() => ({ triggerRef, moreRef }), []);\n\n const getItems = useThreadListCollection(undefined);\n const direction = Direction.useDirection();\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n const forwardKey = direction === \"rtl\" ? \"ArrowLeft\" : \"ArrowRight\";\n const backKey = direction === \"rtl\" ? \"ArrowRight\" : \"ArrowLeft\";\n const trigger = triggerRef.current;\n const more = moreRef.current;\n\n if (trigger && event.target === trigger) {\n if (event.key === \"ArrowDown\" || event.key === \"ArrowUp\") {\n const triggers = getItems()\n .map((item) => item.ref.current)\n .filter((node): node is HTMLButtonElement => node !== null);\n const next =\n triggers[\n triggers.indexOf(trigger) + (event.key === \"ArrowDown\" ? 1 : -1)\n ];\n if (next) {\n next.focus();\n event.preventDefault();\n }\n } else if (event.key === forwardKey && more) {\n more.focus();\n event.preventDefault();\n }\n } else if (more && event.target === more && event.key === backKey) {\n trigger?.focus();\n event.preventDefault();\n }\n };\n\n return (\n <ThreadListItemFocusProvider value={focus}>\n <Primitive.div\n {...(isMain ? { \"data-active\": \"true\", \"aria-current\": \"true\" } : null)}\n {...props}\n onKeyDown={composeEventHandlers(props.onKeyDown, onKeyDown)}\n ref={ref}\n />\n </ThreadListItemFocusProvider>\n );\n});\n\nThreadListItemPrimitiveRoot.displayName = \"ThreadListItemPrimitive.Root\";\n"],"mappings":";;;;;;;;;AA0BA,MAAac,8BAA8BZ,YAGxCe,OAAOC,QAAQ;CAChB,MAAMC,SAASZ,aACZa,MAAMA,EAAEC,QAAQC,iBAAiBF,EAAEG,eAAeC,EACrD;CAEA,MAAMC,aAAanB,OAAiC,IAAI;CACxD,MAAMqB,UAAUrB,OAAiC,IAAI;CACrD,MAAMsB,QAAQvB,eAAe;EAAEoB;EAAYE;CAAQ,IAAI,CAAA,CAAE;CAEzD,MAAME,WAAWlB,wBAAwBmB,KAAAA,CAAS;CAClD,MAAMC,YAAYtB,UAAUuB,aAAa;CAEzC,MAAMC,aAAaC,UAAyC;EAC1D,MAAME,aAAaL,cAAc,QAAQ,cAAc;EACvD,MAAMM,UAAUN,cAAc,QAAQ,eAAe;EACrD,MAAMO,UAAUb,WAAWc;EAC3B,MAAMC,OAAOb,QAAQY;EAErB,IAAID,WAAWJ,MAAMO,WAAWH,SAAS;GACvC,IAAIJ,MAAMQ,QAAQ,eAAeR,MAAMQ,QAAQ,WAAW;IACxD,MAAMC,WAAWd,SAAS,CAAC,CACxBe,KAAKC,SAASA,KAAK3B,IAAIqB,OAAO,CAAC,CAC/BO,QAAQC,SAAoCA,SAAS,IAAI;IAC5D,MAAMC,OACJL,SACEA,SAASM,QAAQX,OAAO,KAAKJ,MAAMQ,QAAQ,cAAc,IAAI;IAEjE,IAAIM,MAAM;KACRA,KAAKpB,MAAM;KACXM,MAAMgB,eAAe;IACvB;GACF,OAAO,IAAIhB,MAAMQ,QAAQN,cAAcI,MAAM;IAC3CA,KAAKZ,MAAM;IACXM,MAAMgB,eAAe;GACvB;EACF,OAAO,IAAIV,QAAQN,MAAMO,WAAWD,QAAQN,MAAMQ,QAAQL,SAAS;GACjEC,SAASV,MAAM;GACfM,MAAMgB,eAAe;EACvB;CACF;CAEA,OACE,oBAAC,6BAAD;EAA6B,OAAOtB;EAClC,UAAA,oBAAC,UAAU,KAAX;GACE,GAAKT,SAAS;IAAE,eAAe;IAAQ,gBAAgB;GAAO,IAAI;GAClE,GAAIF;GACJ,WAAWT,qBAAqBS,MAAMgB,WAAWA,SAAS;GACrDf;EAAI,CAAA;CAEgB,CAAA;AAEjC,CAAC;AAEDJ,4BAA4BqC,cAAc"}
|
|
@@ -14,7 +14,8 @@ const useThreadListItemTrigger$1 = () => {
|
|
|
14
14
|
const ThreadListItemTriggerButton = createActionButton("ThreadListItemPrimitive.Trigger", useThreadListItemTrigger$1);
|
|
15
15
|
const ThreadListItemPrimitiveTrigger = forwardRef((props, forwardedRef) => {
|
|
16
16
|
const $ = c(3);
|
|
17
|
-
const
|
|
17
|
+
const focus = useThreadListItemFocus();
|
|
18
|
+
const ref = useComposedRefs(forwardedRef, focus?.triggerRef);
|
|
18
19
|
let t0;
|
|
19
20
|
if ($[0] !== props || $[1] !== ref) {
|
|
20
21
|
t0 = /* @__PURE__ */ jsx(ThreadListCollection.ItemSlot, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThreadListItemTrigger.js","names":["c","_c","forwardRef","useComposedRefs","ActionButtonElement","ActionButtonProps","createActionButton","useThreadListItemTrigger","useThreadListItemTriggerBehavior","ThreadListCollection","useThreadListItemFocus","switchTo","ThreadListItemPrimitiveTrigger","Element","Props","ThreadListItemTriggerButton","props","forwardedRef","$","focus","ref","triggerRef","t0","undefined","displayName"],"sources":["../../../src/primitives/threadListItem/ThreadListItemTrigger.tsx"],"sourcesContent":["\"use client\";\n\nimport { forwardRef } from \"react\";\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\nimport {\n type ActionButtonElement,\n type ActionButtonProps,\n createActionButton,\n} from \"../../utils/createActionButton\";\nimport { useThreadListItemTrigger as useThreadListItemTriggerBehavior } from \"@assistant-ui/core/react\";\nimport {\n ThreadListCollection,\n useThreadListItemFocus,\n} from \"../threadListFocusGroup\";\n\nconst useThreadListItemTrigger = () => {\n const { switchTo } = useThreadListItemTriggerBehavior();\n return switchTo;\n};\n\nexport namespace ThreadListItemPrimitiveTrigger {\n export type Element = ActionButtonElement;\n export type Props = ActionButtonProps<typeof useThreadListItemTrigger>;\n}\n\nconst ThreadListItemTriggerButton = createActionButton(\n \"ThreadListItemPrimitive.Trigger\",\n useThreadListItemTrigger,\n);\n\nexport const ThreadListItemPrimitiveTrigger = forwardRef<\n ThreadListItemPrimitiveTrigger.Element,\n ThreadListItemPrimitiveTrigger.Props\n>((props, forwardedRef) => {\n const focus = useThreadListItemFocus();\n const ref = useComposedRefs(forwardedRef, focus?.triggerRef);\n\n return (\n <ThreadListCollection.ItemSlot scope={undefined}>\n <ThreadListItemTriggerButton {...props} ref={ref} />\n </ThreadListCollection.ItemSlot>\n );\n});\n\nThreadListItemPrimitiveTrigger.displayName = \"ThreadListItemPrimitive.Trigger\";\n"],"mappings":";;;;;;;;;AAeA,MAAMO,mCAA2B;CAC/B,MAAA,EAAAI,aAAqBH,yBAAiC;CAAE,OACjDG;AAAQ;AAQjB,MAAMI,8BAA8BT,mBAClC,mCACAC,0BACF;AAEA,MAAaK,iCAAiCV,YAG5Cc,OAAAC,iBAAA;CAAA,MAAAC,IAAAjB,EAAA,CAAA;
|
|
1
|
+
{"version":3,"file":"ThreadListItemTrigger.js","names":["c","_c","forwardRef","useComposedRefs","ActionButtonElement","ActionButtonProps","createActionButton","useThreadListItemTrigger","useThreadListItemTriggerBehavior","ThreadListCollection","useThreadListItemFocus","switchTo","ThreadListItemPrimitiveTrigger","Element","Props","ThreadListItemTriggerButton","props","forwardedRef","$","focus","ref","triggerRef","t0","undefined","displayName"],"sources":["../../../src/primitives/threadListItem/ThreadListItemTrigger.tsx"],"sourcesContent":["\"use client\";\n\nimport { forwardRef } from \"react\";\nimport { useComposedRefs } from \"@radix-ui/react-compose-refs\";\nimport {\n type ActionButtonElement,\n type ActionButtonProps,\n createActionButton,\n} from \"../../utils/createActionButton\";\nimport { useThreadListItemTrigger as useThreadListItemTriggerBehavior } from \"@assistant-ui/core/react\";\nimport {\n ThreadListCollection,\n useThreadListItemFocus,\n} from \"../threadListFocusGroup\";\n\nconst useThreadListItemTrigger = () => {\n const { switchTo } = useThreadListItemTriggerBehavior();\n return switchTo;\n};\n\nexport namespace ThreadListItemPrimitiveTrigger {\n export type Element = ActionButtonElement;\n export type Props = ActionButtonProps<typeof useThreadListItemTrigger>;\n}\n\nconst ThreadListItemTriggerButton = createActionButton(\n \"ThreadListItemPrimitive.Trigger\",\n useThreadListItemTrigger,\n);\n\nexport const ThreadListItemPrimitiveTrigger = forwardRef<\n ThreadListItemPrimitiveTrigger.Element,\n ThreadListItemPrimitiveTrigger.Props\n>((props, forwardedRef) => {\n const focus = useThreadListItemFocus();\n const ref = useComposedRefs(forwardedRef, focus?.triggerRef);\n\n return (\n <ThreadListCollection.ItemSlot scope={undefined}>\n <ThreadListItemTriggerButton {...props} ref={ref} />\n </ThreadListCollection.ItemSlot>\n );\n});\n\nThreadListItemPrimitiveTrigger.displayName = \"ThreadListItemPrimitive.Trigger\";\n"],"mappings":";;;;;;;;;AAeA,MAAMO,mCAA2B;CAC/B,MAAA,EAAAI,aAAqBH,yBAAiC;CAAE,OACjDG;AAAQ;AAQjB,MAAMI,8BAA8BT,mBAClC,mCACAC,0BACF;AAEA,MAAaK,iCAAiCV,YAG5Cc,OAAAC,iBAAA;CAAA,MAAAC,IAAAjB,EAAA,CAAA;CACA,MAAAkB,QAAcT,uBAAuB;CACrC,MAAAU,MAAYjB,gBAAgBc,cAAcE,OAAKE,UAAY;CAAE,IAAAC;CAAA,IAAAJ,EAAA,OAAAF,SAAAE,EAAA,OAAAE,KAAA;EAG3DE,KAAA,oBAAA,qBAAA,UAAA;GAAsCC,OAAAA,KAAAA;GACpC,UAAA,oBAAC,6BAAD;IAA4B,GAAKP;IAAYI;GAAG,CAAA;EAClD,CAAA;EAAgCF,EAAA,KAAAF;EAAAE,EAAA,KAAAE;EAAAF,EAAA,KAAAI;CAAA,OAAAA,KAAAJ,EAAA;CAAA,OAFhCI;AAEgC,CAEnC;AAEDV,+BAA+BY,cAAc"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
//#region src/utils/useToolArgsFieldStatus.d.ts
|
|
2
2
|
declare const useToolArgsFieldStatus: (fieldPath: (string | number)[]) => {
|
|
3
|
+
type: string;
|
|
4
|
+
} | {
|
|
3
5
|
readonly type: "running";
|
|
4
6
|
} | {
|
|
5
7
|
readonly type: "complete";
|
|
@@ -7,8 +9,6 @@ declare const useToolArgsFieldStatus: (fieldPath: (string | number)[]) => {
|
|
|
7
9
|
readonly type: "incomplete";
|
|
8
10
|
readonly reason: "cancelled" | "length" | "content-filter" | "other" | "error";
|
|
9
11
|
readonly error?: unknown;
|
|
10
|
-
} | {
|
|
11
|
-
type: string;
|
|
12
12
|
};
|
|
13
13
|
//#endregion
|
|
14
14
|
export { useToolArgsFieldStatus };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assistant-ui/react",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.11",
|
|
4
4
|
"description": "Open-source TypeScript/React library for building production-grade AI chat experiences",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -55,9 +55,9 @@
|
|
|
55
55
|
],
|
|
56
56
|
"sideEffects": false,
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@assistant-ui/core": "^0.3.
|
|
59
|
-
"@assistant-ui/store": "^0.3.
|
|
60
|
-
"@assistant-ui/tap": "^0.9.
|
|
58
|
+
"@assistant-ui/core": "^0.3.10",
|
|
59
|
+
"@assistant-ui/store": "^0.3.8",
|
|
60
|
+
"@assistant-ui/tap": "^0.9.11",
|
|
61
61
|
"@radix-ui/primitive": "^1.1.7",
|
|
62
62
|
"@radix-ui/react-collection": "^1.1.15",
|
|
63
63
|
"@radix-ui/react-compose-refs": "^1.1.5",
|
|
@@ -66,12 +66,12 @@
|
|
|
66
66
|
"@radix-ui/react-use-callback-ref": "^1.1.4",
|
|
67
67
|
"@radix-ui/react-use-controllable-state": "^1.2.6",
|
|
68
68
|
"@radix-ui/react-use-escape-keydown": "^1.1.5",
|
|
69
|
-
"assistant-cloud": "^0.1.
|
|
70
|
-
"assistant-stream": "^0.3.
|
|
71
|
-
"nanoid": "^6.0.
|
|
69
|
+
"assistant-cloud": "^0.1.39",
|
|
70
|
+
"assistant-stream": "^0.3.36",
|
|
71
|
+
"nanoid": "^6.0.1",
|
|
72
72
|
"radix-ui": "^1.6.7",
|
|
73
73
|
"react-textarea-autosize": "^8.5.9",
|
|
74
|
-
"safe-content-frame": "^0.0.
|
|
74
|
+
"safe-content-frame": "^0.0.27",
|
|
75
75
|
"zod": "^4.4.3",
|
|
76
76
|
"zustand": "^5.0.14"
|
|
77
77
|
},
|
|
@@ -92,15 +92,15 @@
|
|
|
92
92
|
"devDependencies": {
|
|
93
93
|
"@testing-library/react": "^16.3.2",
|
|
94
94
|
"@types/json-schema": "^7.0.15",
|
|
95
|
-
"@types/node": "^26.1.
|
|
96
|
-
"@types/react": "^19.2.
|
|
97
|
-
"@types/react-dom": "^19.2.
|
|
98
|
-
"jsdom": "^
|
|
95
|
+
"@types/node": "^26.1.2",
|
|
96
|
+
"@types/react": "^19.2.18",
|
|
97
|
+
"@types/react-dom": "^19.2.4",
|
|
98
|
+
"jsdom": "^30.0.1",
|
|
99
99
|
"react": "^19.2.8",
|
|
100
100
|
"react-dom": "^19.2.8",
|
|
101
101
|
"vitest": "^4.1.10",
|
|
102
|
-
"@assistant-ui/vite": "0.0.
|
|
103
|
-
"@assistant-ui/x-buildutils": "0.0.
|
|
102
|
+
"@assistant-ui/vite": "0.0.12",
|
|
103
|
+
"@assistant-ui/x-buildutils": "0.0.22"
|
|
104
104
|
},
|
|
105
105
|
"publishConfig": {
|
|
106
106
|
"access": "public",
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
useState,
|
|
3
|
-
useMemo,
|
|
4
|
-
useEffect,
|
|
5
|
-
useEffectEvent,
|
|
6
|
-
useCallback,
|
|
7
|
-
useRef,
|
|
8
|
-
} from "react";
|
|
1
|
+
import { useState, useMemo, useEffect, useCallback, useRef } from "react";
|
|
9
2
|
import { resource, withKey } from "@assistant-ui/tap";
|
|
10
3
|
import {
|
|
11
4
|
type ClientElement,
|
|
@@ -152,7 +145,6 @@ const useMessageClient = ({
|
|
|
152
145
|
}: MessageClientProps): ClientOutput<"message"> => {
|
|
153
146
|
const [isCopied, setIsCopied] = useState(false);
|
|
154
147
|
const [isHovering, setIsHovering] = useState(false);
|
|
155
|
-
const [isEditing, setIsEditing] = useState(false);
|
|
156
148
|
|
|
157
149
|
const partClients = useClientLookup(
|
|
158
150
|
message.content.map((part, idx) =>
|
|
@@ -184,11 +176,6 @@ const useMessageClient = ({
|
|
|
184
176
|
|
|
185
177
|
const handleBeginEdit = () => {
|
|
186
178
|
if (!onEdit) throw new Error("Runtime does not support editing.");
|
|
187
|
-
setIsEditing(true);
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
const handleCancelEdit = () => {
|
|
191
|
-
setIsEditing(false);
|
|
192
179
|
};
|
|
193
180
|
|
|
194
181
|
const handleSendEdit = (msg: AppendMessage) => {
|
|
@@ -198,15 +185,12 @@ const useMessageClient = ({
|
|
|
198
185
|
parentId,
|
|
199
186
|
sourceId: message.id,
|
|
200
187
|
});
|
|
201
|
-
setIsEditing(false);
|
|
202
188
|
};
|
|
203
189
|
|
|
204
190
|
const composerClient = useClientResource(
|
|
205
191
|
ComposerClientResource({
|
|
206
192
|
type: "edit",
|
|
207
|
-
isEditing,
|
|
208
193
|
canCancel: true,
|
|
209
|
-
onCancel: handleCancelEdit,
|
|
210
194
|
onBeginEdit: handleBeginEdit,
|
|
211
195
|
onSend: handleSendEdit,
|
|
212
196
|
message,
|
|
@@ -411,10 +395,9 @@ const AttachmentResource = resource(useAttachmentResource);
|
|
|
411
395
|
|
|
412
396
|
type ComposerClientResourceProps = {
|
|
413
397
|
type: "thread" | "edit";
|
|
414
|
-
isEditing: boolean;
|
|
415
398
|
canCancel: boolean;
|
|
416
399
|
isSendDisabled?: boolean;
|
|
417
|
-
onCancel
|
|
400
|
+
onCancel?: () => void;
|
|
418
401
|
onBeginEdit?: () => void;
|
|
419
402
|
onSend?: (message: AppendMessage) => void;
|
|
420
403
|
message?: ExternalThreadMessage;
|
|
@@ -471,7 +454,6 @@ const useLiveState = <T>(initial: T) => {
|
|
|
471
454
|
// Composer Client - minimal implementation
|
|
472
455
|
const useComposerClientResource = ({
|
|
473
456
|
type,
|
|
474
|
-
isEditing,
|
|
475
457
|
canCancel,
|
|
476
458
|
isSendDisabled = false,
|
|
477
459
|
onCancel,
|
|
@@ -481,6 +463,9 @@ const useComposerClientResource = ({
|
|
|
481
463
|
queue,
|
|
482
464
|
attachmentAdapter,
|
|
483
465
|
}: ComposerClientResourceProps): ClientOutput<"composer"> => {
|
|
466
|
+
const [isEditing, setIsEditing, isEditingRef] = useLiveState(
|
|
467
|
+
type === "thread",
|
|
468
|
+
);
|
|
484
469
|
const [text, setText, textRef] = useLiveState("");
|
|
485
470
|
const [role, setRole, roleRef] = useLiveState<
|
|
486
471
|
"user" | "assistant" | "system"
|
|
@@ -495,26 +480,16 @@ const useComposerClientResource = ({
|
|
|
495
480
|
{ readonly text: string; readonly messageId: string } | undefined
|
|
496
481
|
>(undefined);
|
|
497
482
|
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
setRole(message.role);
|
|
509
|
-
setAttachments(message.attachments ?? []);
|
|
510
|
-
}
|
|
511
|
-
});
|
|
512
|
-
|
|
513
|
-
useEffect(() => {
|
|
514
|
-
if (isEditing) {
|
|
515
|
-
updateFromMessage();
|
|
516
|
-
}
|
|
517
|
-
}, [isEditing]);
|
|
483
|
+
const updateFromMessage = () => {
|
|
484
|
+
if (!message) return;
|
|
485
|
+
const messageText = message.content
|
|
486
|
+
.filter((part) => part.type === "text")
|
|
487
|
+
.map((part) => part.text)
|
|
488
|
+
.join("\n\n");
|
|
489
|
+
setText(messageText);
|
|
490
|
+
setRole(message.role);
|
|
491
|
+
setAttachments(message.attachments ?? []);
|
|
492
|
+
};
|
|
518
493
|
|
|
519
494
|
const attachmentClients = useClientLookup(
|
|
520
495
|
attachments.map((attachment) =>
|
|
@@ -679,7 +654,8 @@ const useComposerClientResource = ({
|
|
|
679
654
|
const currentText = textRef.current;
|
|
680
655
|
const currentAttachments = attachmentsRef.current;
|
|
681
656
|
const isEmpty = !currentText.trim() && !currentAttachments.length;
|
|
682
|
-
if (!
|
|
657
|
+
if (!isEditingRef.current) throw new Error("Composer is not available");
|
|
658
|
+
if (isEmpty || isSendDisabled) return;
|
|
683
659
|
|
|
684
660
|
setText("");
|
|
685
661
|
setAttachments([]);
|
|
@@ -708,6 +684,7 @@ const useComposerClientResource = ({
|
|
|
708
684
|
} else {
|
|
709
685
|
onSend?.(composedMessage);
|
|
710
686
|
}
|
|
687
|
+
if (type === "edit") setIsEditing(false);
|
|
711
688
|
};
|
|
712
689
|
|
|
713
690
|
if (attachmentAdapter && currentAttachments.length > 0) {
|
|
@@ -732,9 +709,16 @@ const useComposerClientResource = ({
|
|
|
732
709
|
dispatch(currentAttachments);
|
|
733
710
|
}
|
|
734
711
|
},
|
|
735
|
-
cancel:
|
|
712
|
+
cancel: () => {
|
|
713
|
+
onCancel?.();
|
|
714
|
+
if (type === "edit") setIsEditing(false);
|
|
715
|
+
},
|
|
736
716
|
beginEdit: () => {
|
|
737
717
|
onBeginEdit?.();
|
|
718
|
+
if (type === "thread") return;
|
|
719
|
+
if (isEditingRef.current) throw new Error("Edit already in progress");
|
|
720
|
+
setIsEditing(true);
|
|
721
|
+
updateFromMessage();
|
|
738
722
|
},
|
|
739
723
|
startDictation: () => {},
|
|
740
724
|
stopDictation: () => {},
|
|
@@ -978,7 +962,6 @@ const useExternalThread = ({
|
|
|
978
962
|
const composerClient = useClientResource(
|
|
979
963
|
ComposerClientResource({
|
|
980
964
|
type: "thread",
|
|
981
|
-
isEditing: true,
|
|
982
965
|
canCancel: isRunning,
|
|
983
966
|
isSendDisabled,
|
|
984
967
|
onCancel: handleCancelRun,
|
|
@@ -129,10 +129,11 @@ const useInMemoryThreadList = (
|
|
|
129
129
|
|
|
130
130
|
const handleDelete = (threadId: string) => {
|
|
131
131
|
setThreads((prev) => prev.filter((t) => t.id !== threadId));
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
132
|
+
setMainThreadId((prev) =>
|
|
133
|
+
prev === threadId
|
|
134
|
+
? threads.find((t) => t.id !== threadId)?.id || "main"
|
|
135
|
+
: prev,
|
|
136
|
+
);
|
|
136
137
|
};
|
|
137
138
|
|
|
138
139
|
const handleSwitchToNewThread = () => {
|