@anvia/react-ui 1.0.0-rc.9 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +46 -37
  2. package/dist/attachment/index.d.ts +2 -2
  3. package/dist/attachment/index.js +4 -4
  4. package/dist/chat/index.d.ts +4 -4
  5. package/dist/chat/index.js +10 -9
  6. package/dist/{chunk-OINUOCTO.js → chunk-647LAYRV.js} +90 -65
  7. package/dist/chunk-647LAYRV.js.map +1 -0
  8. package/dist/chunk-6XOJFLX4.js +22 -0
  9. package/dist/chunk-6XOJFLX4.js.map +1 -0
  10. package/dist/{chunk-JBKSJG5W.js → chunk-CRXNFZRW.js} +45 -80
  11. package/dist/chunk-CRXNFZRW.js.map +1 -0
  12. package/dist/{chunk-EWIHRMU6.js → chunk-CVXLQCDI.js} +13 -21
  13. package/dist/chunk-CVXLQCDI.js.map +1 -0
  14. package/dist/{chunk-ULGJLLZE.js → chunk-F6AKBUO3.js} +12 -12
  15. package/dist/chunk-F6AKBUO3.js.map +1 -0
  16. package/dist/{chunk-XAQA3JIG.js → chunk-HWJIMLHC.js} +41 -70
  17. package/dist/chunk-HWJIMLHC.js.map +1 -0
  18. package/dist/{chunk-BU4ZPDHQ.js → chunk-MISX4WUT.js} +10 -15
  19. package/dist/chunk-MISX4WUT.js.map +1 -0
  20. package/dist/{chunk-PSU4V23X.js → chunk-OQE6SHZE.js} +16 -30
  21. package/dist/chunk-OQE6SHZE.js.map +1 -0
  22. package/dist/{chunk-E5UNQCGM.js → chunk-S4XLE2RN.js} +6 -12
  23. package/dist/chunk-S4XLE2RN.js.map +1 -0
  24. package/dist/{chunk-F76H3VMN.js → chunk-SOG2GVE4.js} +45 -15
  25. package/dist/chunk-SOG2GVE4.js.map +1 -0
  26. package/dist/{chunk-ZPNAX4SA.js → chunk-UCBAG42A.js} +9 -21
  27. package/dist/chunk-UCBAG42A.js.map +1 -0
  28. package/dist/completion/index.d.ts +2 -2
  29. package/dist/completion/index.js +4 -4
  30. package/dist/human-input/index.d.ts +2 -2
  31. package/dist/human-input/index.js +4 -4
  32. package/dist/image/index.d.ts +2 -2
  33. package/dist/image/index.js +4 -4
  34. package/dist/index.d.ts +11 -11
  35. package/dist/index.js +58 -63
  36. package/dist/index.js.map +1 -1
  37. package/dist/message/index.d.ts +2 -2
  38. package/dist/message/index.js +7 -6
  39. package/dist/selection-toolbar/index.d.ts +2 -2
  40. package/dist/selection-toolbar/index.js +5 -4
  41. package/dist/shared.d.ts +1 -1
  42. package/dist/shared.js +1 -1
  43. package/dist/stream/index.d.ts +2 -0
  44. package/dist/stream/index.js +1 -1
  45. package/dist/{thread-uEm8hH0s.d.ts → thread-Bz6-1zaJ.d.ts} +1 -0
  46. package/dist/thread-list/index.d.ts +3 -3
  47. package/dist/thread-list/index.js +6 -6
  48. package/package.json +7 -9
  49. package/dist/chunk-BU4ZPDHQ.js.map +0 -1
  50. package/dist/chunk-E5UNQCGM.js.map +0 -1
  51. package/dist/chunk-EWIHRMU6.js.map +0 -1
  52. package/dist/chunk-F76H3VMN.js.map +0 -1
  53. package/dist/chunk-JBKSJG5W.js.map +0 -1
  54. package/dist/chunk-OINUOCTO.js.map +0 -1
  55. package/dist/chunk-PSU4V23X.js.map +0 -1
  56. package/dist/chunk-ULGJLLZE.js.map +0 -1
  57. package/dist/chunk-XAQA3JIG.js.map +0 -1
  58. package/dist/chunk-ZPNAX4SA.js.map +0 -1
  59. package/dist/stream/styles.css +0 -17
  60. package/dist/styles.css +0 -130
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/image/parts.tsx","../src/image/index.ts"],"sourcesContent":["import type { UIAttachment } from \"@anvia/client\";\nimport {\n forwardRef,\n type KeyboardEvent,\n type MouseEvent,\n type ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\n\nimport {\n type ImageContextValue,\n InternalImageProvider,\n useImage,\n useOptionalAttachment,\n} from \"../contexts\";\nimport { composeRefs, type PrimitiveProps, renderPrimitive } from \"../primitives\";\n\ntype ImageRootChildren = ReactNode | ((image: ImageContextValue) => ReactNode);\ntype ImageRenderWhen = \"image\" | \"always\";\n\ntype ImageRootProps = Omit<PrimitiveProps<\"figure\">, \"children\"> & {\n attachment?: UIAttachment;\n children?: ImageRootChildren;\n renderWhen?: ImageRenderWhen;\n};\n\nconst ImageRoot = forwardRef<HTMLElement, ImageRootProps>(function ImageRoot(\n { attachment: attachmentProp, children, renderWhen = \"image\", ...props },\n ref,\n) {\n const attachmentContext = useOptionalAttachment();\n const attachment = attachmentProp ?? attachmentContext?.attachment;\n const [zoomOpen, setZoomOpen] = useState(false);\n\n if (attachment === undefined) {\n throw new Error(\n \"ImagePrimitive.Root requires an attachment prop or AttachmentPrimitive context.\",\n );\n }\n\n const src = imageSource(attachment);\n const isImage = isImageAttachment(attachment);\n const value = useMemo<ImageContextValue>(() => {\n const context: ImageContextValue = {\n attachment,\n isImage,\n zoomOpen,\n setZoomOpen,\n };\n if (src !== undefined) context.src = src;\n if (attachment.name !== undefined) context.name = attachment.name;\n if (attachment.mediaType !== undefined) context.mediaType = attachment.mediaType;\n return context;\n }, [attachment, attachment.mediaType, attachment.name, isImage, src, zoomOpen]);\n if (!isImage && renderWhen !== \"always\") {\n return null;\n }\n\n const renderedChildren = typeof children === \"function\" ? children(value) : children;\n\n return (\n <InternalImageProvider value={value}>\n {renderPrimitive(\n \"figure\",\n {\n ...props,\n children: renderedChildren ?? (\n <>\n <ImagePreview />\n <ImageName />\n </>\n ),\n \"data-state\": src === undefined ? \"unavailable\" : \"ready\",\n } as PrimitiveProps<\"figure\">,\n ref,\n )}\n </InternalImageProvider>\n );\n});\n\ntype ImagePreviewProps = Omit<PrimitiveProps<\"div\">, \"children\"> & {\n alt?: string;\n errorFallback?: ReactNode;\n loadingFallback?: ReactNode;\n};\n\nconst ImagePreview = forwardRef<HTMLDivElement, ImagePreviewProps>(function ImagePreview(\n { alt, errorFallback, loadingFallback, ...props },\n ref,\n) {\n const image = useImage();\n const [state, setState] = useState<\"loading\" | \"ready\" | \"error\">(\n image.src === undefined ? \"error\" : \"loading\",\n );\n\n useEffect(() => {\n setState(image.src === undefined ? \"error\" : \"loading\");\n }, [image.src]);\n\n const fallback =\n state === \"loading\"\n ? (loadingFallback ?? \"Loading image\")\n : state === \"error\"\n ? (errorFallback ?? \"Image unavailable\")\n : null;\n\n return renderPrimitive(\n \"div\",\n {\n ...props,\n children:\n image.src === undefined ? (\n fallback\n ) : (\n <>\n {state === \"ready\" ? null : <span>{fallback}</span>}\n <img\n alt={alt ?? image.name ?? \"Image\"}\n hidden={state !== \"ready\"}\n onError={() => setState(\"error\")}\n onLoad={() => setState(\"ready\")}\n src={image.src}\n />\n </>\n ),\n \"data-state\": state,\n } as PrimitiveProps<\"div\">,\n ref,\n );\n});\n\nconst ImageName = forwardRef<HTMLElement, PrimitiveProps<\"figcaption\">>(\n function ImageName(props, ref) {\n const image = useImage();\n\n return renderPrimitive(\n \"figcaption\",\n {\n ...props,\n children: props.children ?? image.name ?? image.mediaType ?? image.attachment.type,\n } as PrimitiveProps<\"figcaption\">,\n ref,\n );\n },\n);\n\nconst ImageActions = forwardRef<HTMLDivElement, PrimitiveProps<\"div\">>(\n function ImageActions(props, ref) {\n return renderPrimitive(\n \"div\",\n {\n ...props,\n } as PrimitiveProps<\"div\">,\n ref,\n );\n },\n);\n\ntype ImageActionState = \"idle\" | \"done\" | \"error\";\n\nconst ImageCopy = forwardRef<HTMLButtonElement, PrimitiveProps<\"button\">>(function ImageCopy(\n { onClick, ...props },\n ref,\n) {\n const image = useImage();\n const [copyState, setCopyState] = useState<ImageActionState>(\"idle\");\n const disabled = props.disabled ?? image.src === undefined;\n\n const handleClick = useCallback(\n async (event: MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n if (event.defaultPrevented || disabled || image.src === undefined) {\n return;\n }\n try {\n await copyImage(image);\n setCopyState(\"done\");\n } catch {\n setCopyState(\"error\");\n }\n },\n [disabled, image, onClick],\n );\n\n return renderPrimitive(\n \"button\",\n {\n ...props,\n children: props.children ?? \"Copy image\",\n disabled,\n onClick: handleClick,\n type: props.type ?? \"button\",\n \"data-state\": copyState,\n } as PrimitiveProps<\"button\">,\n ref,\n );\n});\n\ntype ImageDownloadProps = PrimitiveProps<\"button\"> & {\n filename?: string;\n};\n\nconst ImageDownload = forwardRef<HTMLButtonElement, ImageDownloadProps>(function ImageDownload(\n { filename, onClick, ...props },\n ref,\n) {\n const image = useImage();\n const disabled = props.disabled ?? image.src === undefined;\n\n const handleClick = useCallback(\n async (event: MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n if (event.defaultPrevented || disabled || image.src === undefined) {\n return;\n }\n try {\n await downloadImage(image, filename);\n } catch {\n return;\n }\n },\n [disabled, filename, image, onClick],\n );\n\n return renderPrimitive(\n \"button\",\n {\n ...props,\n children: props.children ?? \"Download\",\n disabled,\n onClick: handleClick,\n type: props.type ?? \"button\",\n \"data-state\": disabled ? \"disabled\" : \"enabled\",\n } as PrimitiveProps<\"button\">,\n ref,\n );\n});\n\nconst ImageZoomTrigger = forwardRef<HTMLButtonElement, PrimitiveProps<\"button\">>(\n function ImageZoomTrigger({ onClick, ...props }, ref) {\n const image = useImage();\n const disabled = props.disabled ?? image.src === undefined;\n\n const handleClick = useCallback(\n (event: MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n if (event.defaultPrevented || disabled) {\n return;\n }\n image.setZoomOpen(true);\n },\n [disabled, image, onClick],\n );\n\n return renderPrimitive(\n \"button\",\n {\n ...props,\n children: props.children ?? \"Open image\",\n disabled,\n onClick: handleClick,\n type: props.type ?? \"button\",\n \"data-state\": disabled ? \"disabled\" : \"enabled\",\n } as PrimitiveProps<\"button\">,\n ref,\n );\n },\n);\n\ntype ImageZoomOverlayProps = Omit<PrimitiveProps<\"div\">, \"children\"> & {\n container?: Element | DocumentFragment;\n};\n\nconst ImageZoomOverlay = forwardRef<HTMLDivElement, ImageZoomOverlayProps>(\n function ImageZoomOverlay({ container, onClick, onKeyDown, ...props }, ref) {\n const image = useImage();\n const portalContainer = container ?? globalThis.document?.body;\n const overlayRef = useRef<HTMLDivElement | null>(null);\n const composedRef = useMemo(() => composeRefs(overlayRef, ref), [ref]);\n\n useEffect(() => {\n if (!image.zoomOpen) {\n return;\n }\n const document = globalThis.document;\n if (document === undefined) {\n return;\n }\n const handleKeyDown = (event: globalThis.KeyboardEvent) => {\n if (event.key === \"Escape\") {\n image.setZoomOpen(false);\n }\n };\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => {\n document.removeEventListener(\"keydown\", handleKeyDown);\n };\n }, [image.setZoomOpen, image.zoomOpen]);\n\n useEffect(() => {\n if (!image.zoomOpen) {\n return;\n }\n const activeElement = globalThis.document?.activeElement;\n const previousFocus = activeElement instanceof HTMLElement ? activeElement : undefined;\n focusOverlay(overlayRef.current);\n return () => {\n if (previousFocus?.isConnected === true) {\n previousFocus.focus();\n }\n };\n }, [image.zoomOpen]);\n\n const handleClick = useCallback(\n (event: MouseEvent<HTMLDivElement>) => {\n onClick?.(event);\n if (!event.defaultPrevented) {\n image.setZoomOpen(false);\n }\n },\n [image, onClick],\n );\n\n const handleKeyDown = useCallback(\n (event: KeyboardEvent<HTMLDivElement>) => {\n onKeyDown?.(event);\n if (event.defaultPrevented) {\n return;\n }\n if (event.key === \"Escape\") {\n image.setZoomOpen(false);\n return;\n }\n if (event.key === \"Tab\") {\n trapOverlayFocus(event, overlayRef.current);\n }\n },\n [image, onKeyDown],\n );\n\n if (!image.zoomOpen || image.src === undefined || portalContainer === undefined) {\n return null;\n }\n\n const overlay = renderPrimitive(\n \"div\",\n {\n ...props,\n children: <img alt={image.name ?? \"Image\"} src={image.src} />,\n onClick: handleClick,\n onKeyDown: handleKeyDown,\n \"aria-modal\": props[\"aria-modal\"] ?? true,\n role: props.role ?? \"dialog\",\n tabIndex: props.tabIndex ?? -1,\n } as PrimitiveProps<\"div\">,\n composedRef,\n );\n\n return createPortal(overlay, portalContainer);\n },\n);\n\nfunction isImageAttachment(attachment: UIAttachment): boolean {\n return attachment.type === \"image\" || attachment.mediaType?.startsWith(\"image/\") === true;\n}\n\nfunction imageSource(attachment: UIAttachment): string | undefined {\n if (!isImageAttachment(attachment)) {\n return attachment.url;\n }\n if (attachment.url !== undefined) {\n return attachment.url;\n }\n if (attachment.data !== undefined && attachment.mediaType !== undefined) {\n return `data:${attachment.mediaType};base64,${attachment.data}`;\n }\n return undefined;\n}\n\nasync function copyImage(image: ImageContextValue): Promise<void> {\n if (image.src === undefined) {\n throw new Error(\"Image source is unavailable.\");\n }\n const clipboard = globalThis.navigator?.clipboard as\n | (Clipboard & { write?: (items: ClipboardItem[]) => Promise<void> })\n | undefined;\n const ClipboardItemConstructor = globalThis.ClipboardItem;\n if (clipboard?.write === undefined || ClipboardItemConstructor === undefined) {\n throw new Error(\"Clipboard image copy is unavailable.\");\n }\n const blob = await imageBlob(image);\n await clipboard.write([new ClipboardItemConstructor({ [blob.type]: blob })]);\n}\n\nasync function imageBlob(image: ImageContextValue): Promise<Blob> {\n if (image.attachment.data !== undefined) {\n return base64ToBlob(\n image.attachment.data,\n image.attachment.mediaType ?? image.mediaType ?? \"image/png\",\n );\n }\n if (image.src === undefined || globalThis.fetch === undefined) {\n throw new Error(\"Image source is unavailable.\");\n }\n const response = await fetch(image.src);\n return response.blob();\n}\n\nfunction base64ToBlob(data: string, mediaType: string): Blob {\n const binary = globalThis.atob(data);\n const bytes = new Uint8Array(binary.length);\n for (let index = 0; index < binary.length; index += 1) {\n bytes[index] = binary.charCodeAt(index);\n }\n return new Blob([bytes], { type: mediaType });\n}\n\nasync function downloadImage(\n image: ImageContextValue,\n filename: string | undefined,\n): Promise<void> {\n const document = globalThis.document;\n const url = globalThis.URL;\n if (image.src === undefined || document === undefined || url?.createObjectURL === undefined) {\n return;\n }\n const blobUrl = url.createObjectURL(await imageBlob(image));\n const link = document.createElement(\"a\");\n try {\n link.href = blobUrl;\n link.download = filename ?? image.name ?? defaultImageFilename(image);\n link.rel = \"noopener\";\n document.body.append(link);\n link.click();\n } finally {\n link.remove();\n url.revokeObjectURL(blobUrl);\n }\n}\n\nfunction defaultImageFilename(image: ImageContextValue): string {\n const extension = image.mediaType?.split(\"/\")[1]?.split(\";\")[0] ?? \"png\";\n return `image.${extension}`;\n}\n\nfunction focusOverlay(overlay: HTMLDivElement | null): void {\n if (overlay === null) {\n return;\n }\n const [firstFocusable] = focusableElements(overlay);\n (firstFocusable ?? overlay).focus();\n}\n\nfunction trapOverlayFocus(\n event: KeyboardEvent<HTMLDivElement>,\n overlay: HTMLDivElement | null,\n): void {\n if (overlay === null) {\n return;\n }\n const focusable = focusableElements(overlay);\n if (focusable.length === 0) {\n event.preventDefault();\n overlay.focus();\n return;\n }\n\n const firstFocusable = focusable[0];\n const lastFocusable = focusable[focusable.length - 1];\n const activeElement = globalThis.document?.activeElement;\n if (event.shiftKey && activeElement === firstFocusable) {\n event.preventDefault();\n lastFocusable?.focus();\n return;\n }\n if (!event.shiftKey && activeElement === lastFocusable) {\n event.preventDefault();\n firstFocusable?.focus();\n return;\n }\n if (activeElement instanceof Node && !overlay.contains(activeElement)) {\n event.preventDefault();\n (event.shiftKey ? lastFocusable : firstFocusable)?.focus();\n }\n}\n\nfunction focusableElements(container: HTMLElement): HTMLElement[] {\n return Array.from(\n container.querySelectorAll<HTMLElement>(\n [\n \"a[href]\",\n \"button:not(:disabled)\",\n \"input:not(:disabled)\",\n \"select:not(:disabled)\",\n \"textarea:not(:disabled)\",\n \"[tabindex]\",\n ].join(\",\"),\n ),\n ).filter((element) => element.tabIndex >= 0 && element.getAttribute(\"aria-hidden\") !== \"true\");\n}\n\nexport {\n ImageActions,\n ImageCopy,\n ImageDownload,\n ImageName,\n ImagePreview,\n ImageRoot,\n ImageZoomOverlay,\n ImageZoomTrigger,\n};\n","import {\n ImageActions,\n ImageCopy,\n ImageDownload,\n ImageName,\n ImagePreview,\n ImageRoot,\n ImageZoomOverlay,\n ImageZoomTrigger,\n} from \"./parts\";\n\nexport const ImagePrimitive = {\n Root: ImageRoot,\n Preview: ImagePreview,\n Name: ImageName,\n Actions: ImageActions,\n Copy: ImageCopy,\n Download: ImageDownload,\n ZoomTrigger: ImageZoomTrigger,\n ZoomOverlay: ImageZoomOverlay,\n} as const;\n\nexport type { ImageContextValue } from \"../contexts\";\nexport { useImage } from \"../contexts\";\n"],"mappings":"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","names":["ImageRoot","ImagePreview","ImageName","ImageActions","ImageCopy","ImageDownload","ImageZoomTrigger","ImageZoomOverlay","handleKeyDown"]}
@@ -165,10 +165,10 @@ function wrapStreamRevealGraphemes(targets, graphemes, lifecycleScope, lifecycle
165
165
  type: "element",
166
166
  tagName: "span",
167
167
  properties: {
168
- "data-anvia-stream-duration-ms": String(remainingMs),
169
- "data-anvia-stream-opacity": String(opacity),
170
- "data-anvia-stream-reveal": "",
171
- "data-anvia-stream-reveal-id": revealId
168
+ "data-reveal-duration-ms": String(remainingMs),
169
+ "data-reveal-opacity": String(opacity),
170
+ "data-reveal-id": revealId,
171
+ "data-state": "revealing"
172
172
  },
173
173
  children: [{ type: "text", value: text }]
174
174
  });
@@ -293,8 +293,8 @@ var StreamMarkdown = forwardRef(
293
293
  },
294
294
  block.startOffset
295
295
  )),
296
- "data-anvia-stream-markdown": "",
297
- "data-live": live ? "" : void 0
296
+ "data-role": "markdown",
297
+ "data-state": props["data-state"] ?? (live ? "streaming" : "idle")
298
298
  },
299
299
  ref
300
300
  );
@@ -323,7 +323,7 @@ function withStreamRevealComponent(components, onRevealSettled) {
323
323
  span(spanProps) {
324
324
  const safeProps = componentPropsWithoutKey(spanProps);
325
325
  const internalProps = safeProps;
326
- if (internalProps["data-anvia-stream-reveal"] !== void 0) {
326
+ if (internalProps["data-state"] === "revealing") {
327
327
  return streamRevealSpan(internalProps, onRevealSettled);
328
328
  }
329
329
  if (consumerSpan !== void 0) {
@@ -347,9 +347,9 @@ function streamRevealSpan(props, onRevealSettled) {
347
347
  const {
348
348
  children,
349
349
  node: _node,
350
- "data-anvia-stream-duration-ms": durationMs,
351
- "data-anvia-stream-opacity": opacity,
352
- "data-anvia-stream-reveal-id": revealId,
350
+ "data-reveal-duration-ms": durationMs,
351
+ "data-reveal-opacity": opacity,
352
+ "data-reveal-id": revealId,
353
353
  onAnimationEnd,
354
354
  ...elementProps
355
355
  } = props;
@@ -359,7 +359,7 @@ function streamRevealSpan(props, onRevealSettled) {
359
359
  "span",
360
360
  {
361
361
  ...elementProps,
362
- "data-anvia-stream-reveal-id": revealId,
362
+ "data-state": "revealing",
363
363
  key: revealId ?? "stream-reveal",
364
364
  onAnimationEnd: (event) => {
365
365
  onAnimationEnd?.(event);
@@ -377,4 +377,4 @@ function streamRevealSpan(props, onRevealSettled) {
377
377
  export {
378
378
  StreamMarkdown
379
379
  };
380
- //# sourceMappingURL=chunk-ULGJLLZE.js.map
380
+ //# sourceMappingURL=chunk-F6AKBUO3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/stream/markdown.tsx","../src/stream/markdown-blocks.ts","../src/stream/markdown-reveal.ts"],"sourcesContent":["import {\n type ComponentPropsWithoutRef,\n type CSSProperties,\n createElement,\n forwardRef,\n memo,\n type ReactNode,\n useCallback,\n useMemo,\n useRef,\n} from \"react\";\nimport ReactMarkdown, {\n type Components,\n type Options as ReactMarkdownOptions,\n} from \"react-markdown\";\nimport remarkGfm from \"remark-gfm\";\n\nimport { type PrimitiveProps, renderPrimitive } from \"../primitives\";\nimport { splitStreamMarkdownBlocks } from \"./markdown-blocks\";\nimport { createStreamGradientRevealPlugin, type StreamRevealLifecycle } from \"./markdown-reveal\";\n\nexport type StreamMarkdownProps = Omit<PrimitiveProps<\"div\">, \"children\"> & {\n \"data-state\"?: string | undefined;\n components?: Components;\n content: string;\n live?: boolean;\n remarkPlugins?: ReactMarkdownOptions[\"remarkPlugins\"];\n remarkRehypeOptions?: ReactMarkdownOptions[\"remarkRehypeOptions\"];\n};\n\nconst defaultRemarkPlugins: NonNullable<ReactMarkdownOptions[\"remarkPlugins\"]> = [remarkGfm];\n\nexport const StreamMarkdown = forwardRef<HTMLDivElement, StreamMarkdownProps>(\n function StreamMarkdown(\n { components, content, live = false, remarkPlugins, remarkRehypeOptions, ...props },\n ref,\n ) {\n const revealLifecycleRef = useRef({\n activeScope: null,\n content,\n id: 0,\n settledRevealIds: new Set<string>(),\n startedAtByRevealId: new Map<string, number>(),\n } satisfies StreamRevealLifecycle & { content: string; id: number });\n const revealLifecycle = revealLifecycleRef.current;\n if (revealLifecycle.content !== content) {\n if (!content.startsWith(revealLifecycle.content)) {\n revealLifecycle.id += 1;\n revealLifecycle.activeScope = null;\n revealLifecycle.settledRevealIds.clear();\n revealLifecycle.startedAtByRevealId.clear();\n }\n revealLifecycle.content = content;\n }\n if (!live && revealLifecycle.activeScope !== null) {\n for (const revealId of revealLifecycle.startedAtByRevealId.keys()) {\n revealLifecycle.settledRevealIds.add(revealId);\n }\n }\n const settleReveal = useCallback((revealId: string) => {\n revealLifecycleRef.current.settledRevealIds.add(revealId);\n }, []);\n\n const blocks = useMemo(\n () =>\n splitStreamMarkdownBlocks(content, {\n singleDocument: remarkPlugins !== undefined,\n }),\n [content, remarkPlugins],\n );\n const streamingComponents = useMemo(\n () => withStreamRevealComponent(components, settleReveal),\n [components, settleReveal],\n );\n\n return renderPrimitive(\n \"div\",\n {\n ...props,\n children: blocks.map((block, index) => (\n <StreamMarkdownBlock\n components={streamingComponents}\n content={block.content}\n live={live && index === blocks.length - 1}\n revealLifecycle={revealLifecycle}\n revealScope={`${revealLifecycle.id}:${block.startOffset}`}\n remarkPlugins={remarkPlugins ?? defaultRemarkPlugins}\n remarkRehypeOptions={remarkRehypeOptions}\n key={block.startOffset}\n />\n )),\n \"data-role\": \"markdown\",\n \"data-state\": props[\"data-state\"] ?? (live ? \"streaming\" : \"idle\"),\n } as PrimitiveProps<\"div\">,\n ref,\n );\n },\n);\n\nconst StreamMarkdownBlock = memo(function StreamMarkdownBlock(props: {\n components: Components;\n content: string;\n live: boolean;\n revealLifecycle: StreamRevealLifecycle;\n revealScope: string;\n remarkPlugins: ReactMarkdownOptions[\"remarkPlugins\"];\n remarkRehypeOptions: ReactMarkdownOptions[\"remarkRehypeOptions\"];\n}) {\n const revealPlugin = useMemo(\n () => createStreamGradientRevealPlugin(props.revealScope, props.revealLifecycle),\n [props.revealScope, props.revealLifecycle],\n );\n return (\n <ReactMarkdown\n components={props.components}\n rehypePlugins={props.live ? [revealPlugin] : undefined}\n remarkPlugins={props.remarkPlugins}\n remarkRehypeOptions={props.remarkRehypeOptions}\n >\n {props.content}\n </ReactMarkdown>\n );\n});\n\nfunction withStreamRevealComponent(\n components: Components | undefined,\n onRevealSettled: (revealId: string) => void,\n): Components {\n const consumerSpan = components?.span;\n return {\n ...components,\n span(spanProps) {\n const safeProps = componentPropsWithoutKey(spanProps);\n const internalProps = safeProps as typeof safeProps & {\n \"data-reveal-duration-ms\"?: string | undefined;\n \"data-reveal-opacity\"?: string | undefined;\n \"data-reveal-id\"?: string | undefined;\n \"data-state\"?: string | undefined;\n };\n if (internalProps[\"data-state\"] === \"revealing\") {\n return streamRevealSpan(internalProps, onRevealSettled);\n }\n if (consumerSpan !== undefined) {\n return createElement(consumerSpan, safeProps);\n }\n const { node: _node, ...elementProps } = safeProps;\n return <span {...elementProps} />;\n },\n };\n}\n\nfunction componentPropsWithoutKey<T extends object>(props: T): T {\n const result: Record<string, unknown> = {};\n for (const name of Object.keys(props)) {\n if (name !== \"key\") {\n result[name] = (props as Record<string, unknown>)[name];\n }\n }\n return result as T;\n}\n\nfunction streamRevealSpan(\n props: ComponentPropsWithoutRef<\"span\"> & {\n node?: unknown;\n \"data-reveal-duration-ms\"?: string | undefined;\n \"data-reveal-opacity\"?: string | undefined;\n \"data-reveal-id\"?: string | undefined;\n },\n onRevealSettled: (revealId: string) => void,\n): ReactNode {\n const {\n children,\n node: _node,\n \"data-reveal-duration-ms\": durationMs,\n \"data-reveal-opacity\": opacity,\n \"data-reveal-id\": revealId,\n onAnimationEnd,\n ...elementProps\n } = props;\n const parsedOpacity = Number(opacity);\n const parsedDurationMs = Number(durationMs);\n return (\n <span\n {...elementProps}\n data-state=\"revealing\"\n key={revealId ?? \"stream-reveal\"}\n onAnimationEnd={(event) => {\n onAnimationEnd?.(event);\n if (revealId !== undefined) onRevealSettled(revealId);\n }}\n style={\n {\n \"--anvia-stream-reveal-opacity\": Number.isFinite(parsedOpacity) ? parsedOpacity : 1,\n \"--anvia-stream-reveal-duration\": `${Number.isFinite(parsedDurationMs) ? parsedDurationMs : 180}ms`,\n } as CSSProperties\n }\n >\n {children}\n </span>\n );\n}\n","import { lexer } from \"marked\";\n\nexport type StreamMarkdownBlock = {\n content: string;\n startOffset: number;\n};\n\nexport function splitStreamMarkdownBlocks(\n content: string,\n options: { singleDocument?: boolean } = {},\n): StreamMarkdownBlock[] {\n if (content.length === 0) {\n return [];\n }\n if (options.singleDocument === true) {\n return [{ content, startOffset: 0 }];\n }\n\n try {\n const tokens = lexer(content, { gfm: false });\n if (tokens.some((token) => token.type === \"def\") || Object.keys(tokens.links).length > 0) {\n return [{ content, startOffset: 0 }];\n }\n\n const rawBlocks: string[] = [];\n for (const token of tokens) {\n if (token.type === \"space\" && rawBlocks.length > 0) {\n const lastIndex = rawBlocks.length - 1;\n rawBlocks[lastIndex] = `${rawBlocks[lastIndex] ?? \"\"}${token.raw}`;\n } else {\n rawBlocks.push(token.raw);\n }\n }\n\n if (rawBlocks.length === 0 || rawBlocks.join(\"\") !== content) {\n return [{ content, startOffset: 0 }];\n }\n\n let startOffset = 0;\n return rawBlocks.map((block) => {\n const result = { content: block, startOffset };\n startOffset += block.length;\n return result;\n });\n } catch {\n return [{ content, startOffset: 0 }];\n }\n}\n","export const streamRevealConfig = {\n bandGraphemes: 2,\n durationMs: 180,\n minimumOpacity: 0.12,\n tailGraphemes: 24,\n} as const;\n\nexport type StreamRevealLifecycle = {\n activeScope: string | null;\n settledRevealIds: Set<string>;\n startedAtByRevealId: Map<string, number>;\n};\n\ntype MarkdownNode = {\n type: string;\n tagName?: string;\n value?: string;\n properties?: Record<string, unknown>;\n children?: MarkdownNode[];\n};\n\ntype TextTarget = {\n endOffset: number;\n index: number;\n node: MarkdownNode;\n parent: MarkdownNode;\n startOffset: number;\n};\n\ntype RevealGrapheme = {\n endOffset: number;\n opacity: number;\n startOffset: number;\n};\n\nexport function createStreamGradientRevealPlugin(\n lifecycleScope: string,\n lifecycle: StreamRevealLifecycle,\n) {\n return function streamGradientRevealPlugin() {\n return (tree: MarkdownNode) => {\n if (lifecycle.activeScope !== lifecycleScope) {\n lifecycle.activeScope = lifecycleScope;\n lifecycle.settledRevealIds.clear();\n lifecycle.startedAtByRevealId.clear();\n }\n const targets = collectTextTargets(tree);\n const renderedText = targets.map((target) => target.node.value ?? \"\").join(\"\");\n const graphemes = createRevealGraphemes(renderedText);\n wrapStreamRevealGraphemes(targets, graphemes, lifecycleScope, lifecycle);\n };\n };\n}\n\nfunction collectTextTargets(tree: MarkdownNode): TextTarget[] {\n const targets: TextTarget[] = [];\n let offset = 0;\n\n function visit(node: MarkdownNode, parent: MarkdownNode | undefined, index: number): void {\n if (node.type === \"element\" && node.tagName === \"pre\") {\n return;\n }\n if (node.type === \"text\" && node.value !== undefined && parent !== undefined) {\n if (!/\\S/u.test(node.value)) {\n return;\n }\n const startOffset = offset;\n offset += node.value.length;\n targets.push({\n endOffset: offset,\n index,\n node,\n parent,\n startOffset,\n });\n return;\n }\n for (const [childIndex, child] of (node.children ?? []).entries()) {\n visit(child, node, childIndex);\n }\n }\n\n visit(tree, undefined, 0);\n return targets;\n}\n\nfunction createRevealGraphemes(content: string): RevealGrapheme[] {\n const tail = segmentTailGraphemeRanges(content, streamRevealConfig.tailGraphemes);\n const graphemes: RevealGrapheme[] = [];\n\n for (let index = 0; index < tail.length; index += 1) {\n const grapheme = tail[index];\n const bandStartIndex =\n Math.floor(index / streamRevealConfig.bandGraphemes) * streamRevealConfig.bandGraphemes;\n const bandEndIndex =\n Math.min(bandStartIndex + streamRevealConfig.bandGraphemes, tail.length) - 1;\n if (grapheme === undefined) {\n continue;\n }\n const progress = tail.length === 1 ? 1 : bandEndIndex / (tail.length - 1);\n graphemes.push({\n startOffset: grapheme.startOffset,\n endOffset: grapheme.endOffset,\n opacity: Math.max(\n streamRevealConfig.minimumOpacity,\n 1 - progress * (1 - streamRevealConfig.minimumOpacity),\n ),\n });\n }\n return graphemes;\n}\n\nfunction wrapStreamRevealGraphemes(\n targets: readonly TextTarget[],\n graphemes: readonly RevealGrapheme[],\n lifecycleScope: string,\n lifecycle: StreamRevealLifecycle,\n): void {\n const activeRevealIds = new Set<string>();\n const nowMs = Date.now();\n for (const target of [...targets].reverse()) {\n const value = target.node.value ?? \"\";\n const intersectingGraphemes = graphemes.filter(\n (grapheme) =>\n grapheme.endOffset > target.startOffset && grapheme.startOffset < target.endOffset,\n );\n if (intersectingGraphemes.length === 0) {\n continue;\n }\n\n const replacement: MarkdownNode[] = [];\n let cursor = 0;\n for (const grapheme of intersectingGraphemes) {\n const start = Math.max(0, grapheme.startOffset - target.startOffset);\n const end = Math.min(value.length, grapheme.endOffset - target.startOffset);\n if (start > cursor) {\n replacement.push({ type: \"text\", value: value.slice(cursor, start) });\n }\n if (end > start) {\n const text = value.slice(start, end);\n const absoluteStart = target.startOffset + start;\n const absoluteEnd = target.startOffset + end;\n const revealId = `${lifecycleScope}:${absoluteStart}:${absoluteEnd}:${hashText(text)}`;\n activeRevealIds.add(revealId);\n const startedAt = lifecycle.startedAtByRevealId.get(revealId) ?? nowMs;\n lifecycle.startedAtByRevealId.set(revealId, startedAt);\n const elapsedMs = Math.max(0, nowMs - startedAt);\n if (elapsedMs >= streamRevealConfig.durationMs) {\n lifecycle.settledRevealIds.add(revealId);\n }\n if (lifecycle.settledRevealIds.has(revealId)) {\n replacement.push({ type: \"text\", value: text });\n } else {\n const progress = Math.min(elapsedMs / streamRevealConfig.durationMs, 1);\n const opacity = grapheme.opacity + (1 - grapheme.opacity) * progress;\n const remainingMs = Math.max(1, streamRevealConfig.durationMs - elapsedMs);\n replacement.push({\n type: \"element\",\n tagName: \"span\",\n properties: {\n \"data-reveal-duration-ms\": String(remainingMs),\n \"data-reveal-opacity\": String(opacity),\n \"data-reveal-id\": revealId,\n \"data-state\": \"revealing\",\n },\n children: [{ type: \"text\", value: text }],\n });\n }\n }\n cursor = Math.max(cursor, end);\n }\n if (cursor < value.length) {\n replacement.push({ type: \"text\", value: value.slice(cursor) });\n }\n target.parent.children?.splice(target.index, 1, ...replacement);\n }\n\n pruneRevealLifecycle(lifecycle, activeRevealIds);\n}\n\nfunction pruneRevealLifecycle(\n lifecycle: StreamRevealLifecycle,\n activeRevealIds: ReadonlySet<string>,\n): void {\n for (const revealId of lifecycle.startedAtByRevealId.keys()) {\n if (!activeRevealIds.has(revealId)) lifecycle.startedAtByRevealId.delete(revealId);\n }\n for (const revealId of lifecycle.settledRevealIds) {\n if (!activeRevealIds.has(revealId)) lifecycle.settledRevealIds.delete(revealId);\n }\n}\n\nfunction hashText(text: string): string {\n let hash = 2_166_136_261;\n for (let index = 0; index < text.length; index += 1) {\n hash ^= text.charCodeAt(index);\n hash = Math.imul(hash, 16_777_619);\n }\n return (hash >>> 0).toString(36);\n}\n\nfunction segmentTailGraphemeRanges(\n content: string,\n limit: number,\n): Array<{\n endOffset: number;\n startOffset: number;\n}> {\n if (typeof Intl !== \"undefined\" && typeof Intl.Segmenter === \"function\") {\n const segmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n const segments = segmenter.segment(content);\n const ranges: Array<{ endOffset: number; startOffset: number }> = [];\n let cursor = content.length;\n while (cursor > 0 && ranges.length < limit) {\n const segment = segments.containing(cursor - 1);\n if (segment === undefined) {\n break;\n }\n ranges.unshift({\n startOffset: segment.index,\n endOffset: segment.index + segment.segment.length,\n });\n cursor = segment.index;\n }\n return ranges;\n }\n\n const ranges: Array<{ endOffset: number; startOffset: number }> = [];\n let cursor = content.length;\n while (cursor > 0 && ranges.length < limit) {\n let startOffset = cursor - 1;\n const code = content.charCodeAt(startOffset);\n if (code >= 0xdc00 && code <= 0xdfff && startOffset > 0) {\n const previousCode = content.charCodeAt(startOffset - 1);\n if (previousCode >= 0xd800 && previousCode <= 0xdbff) {\n startOffset -= 1;\n }\n }\n ranges.unshift({ startOffset, endOffset: cursor });\n cursor = startOffset;\n }\n return ranges;\n}\n"],"mappings":"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","names":["ranges","cursor","createElement","StreamMarkdown","StreamMarkdownBlock"]}
@@ -1,11 +1,11 @@
1
1
  import {
2
- Message,
2
+ MessagePrimitive,
3
3
  isComposerEntityData,
4
4
  shiftComposerEntityRanges
5
- } from "./chunk-JBKSJG5W.js";
5
+ } from "./chunk-CRXNFZRW.js";
6
6
  import {
7
- Attachment
8
- } from "./chunk-BU4ZPDHQ.js";
7
+ AttachmentPrimitive
8
+ } from "./chunk-MISX4WUT.js";
9
9
  import {
10
10
  composeRefs,
11
11
  renderPrimitive
@@ -18,7 +18,7 @@ import {
18
18
  useChatContext,
19
19
  useComposer,
20
20
  useThread
21
- } from "./chunk-F76H3VMN.js";
21
+ } from "./chunk-SOG2GVE4.js";
22
22
 
23
23
  // src/chat/composer.tsx
24
24
  import { mergeAttributes } from "@tiptap/core";
@@ -274,7 +274,6 @@ var ComposerRoot = forwardRef(function ComposerRoot2({
274
274
  {
275
275
  ...props,
276
276
  onSubmit: handleSubmit,
277
- "data-anvia-composer": "",
278
277
  "data-state": chat.status
279
278
  },
280
279
  ref
@@ -292,9 +291,7 @@ var ComposerQuotePreview = forwardRef(
292
291
  "blockquote",
293
292
  {
294
293
  ...props,
295
- children: renderedChildren,
296
- "data-anvia-composer-quote": "",
297
- "data-message-id": quote.messageId
294
+ children: renderedChildren
298
295
  },
299
296
  ref
300
297
  );
@@ -322,7 +319,6 @@ var ComposerClearQuote = forwardRef(
322
319
  disabled,
323
320
  onClick: handleClick,
324
321
  type: props.type ?? "button",
325
- "data-anvia-clear-quote": "",
326
322
  "data-state": disabled ? "disabled" : "enabled"
327
323
  },
328
324
  ref
@@ -364,7 +360,6 @@ var ComposerInput = forwardRef(function ComposerInput2({
364
360
  attributes: {
365
361
  "aria-label": props["aria-label"] ?? "Message",
366
362
  "aria-multiline": "true",
367
- "data-anvia-composer-editor": "",
368
363
  role: "textbox"
369
364
  },
370
365
  handleKeyDown: (_view, event) => submitComposerFromEditorKeyDown(event, composerRef)
@@ -448,9 +443,8 @@ var ComposerInput = forwardRef(function ComposerInput2({
448
443
  ...props,
449
444
  children: /* @__PURE__ */ jsx(EditorContent, { editor }),
450
445
  "aria-disabled": composerDisabled ? true : props["aria-disabled"],
451
- "data-anvia-composer-input": "",
446
+ "data-role": "editor",
452
447
  "data-state": composerDisabled ? "disabled" : "enabled",
453
- "data-auto-resize": autoResize ? "" : void 0,
454
448
  onKeyDown: handleKeyDown,
455
449
  style: inputStyle
456
450
  },
@@ -517,9 +511,7 @@ var ComposerTextareaInput = forwardRef(
517
511
  onChange: handleChange,
518
512
  onKeyDown: handleKeyDown,
519
513
  rows: autoResize ? minRows : rows,
520
- value: composer.input,
521
- "data-anvia-composer-input": "",
522
- "data-anvia-composer-textarea-input": ""
514
+ value: composer.input
523
515
  },
524
516
  composedInputRef
525
517
  );
@@ -584,16 +576,12 @@ function composerInputExtensions({
584
576
  HardBreak,
585
577
  Placeholder.configure(placeholder === void 0 ? {} : { placeholder }),
586
578
  ComposerEntityExtension.configure({
587
- HTMLAttributes: {
588
- "data-anvia-composer-entity": ""
589
- },
579
+ HTMLAttributes: {},
590
580
  deleteTriggerWithBackspace: true,
591
581
  renderText: ({ node }) => composerEntityText(node.attrs),
592
582
  renderHTML: ({ node, options }) => [
593
583
  "span",
594
- mergeAttributes(options.HTMLAttributes, {
595
- "data-anvia-composer-entity": ""
596
- }),
584
+ mergeAttributes(options.HTMLAttributes, {}),
597
585
  composerEntityText(node.attrs)
598
586
  ],
599
587
  suggestions: triggers.map((trigger) => composerSuggestion(trigger, composerRef))
@@ -980,7 +968,6 @@ var ComposerSubmit = forwardRef(
980
968
  children: props.children ?? "Send",
981
969
  disabled,
982
970
  type: props.type ?? "submit",
983
- "data-anvia-submit": "",
984
971
  "data-state": disabled ? "disabled" : "enabled"
985
972
  },
986
973
  ref
@@ -1008,7 +995,6 @@ var ComposerStop = forwardRef(function ComposerStop2({ onClick, ...props }, ref)
1008
995
  disabled,
1009
996
  onClick: handleClick,
1010
997
  type: props.type ?? "button",
1011
- "data-anvia-stop": "",
1012
998
  "data-state": disabled ? "disabled" : "enabled"
1013
999
  },
1014
1000
  ref
@@ -1036,11 +1022,7 @@ var ComposerTriggerMenu = forwardRef(
1036
1022
  children: renderedChildren,
1037
1023
  role: props.role ?? "listbox",
1038
1024
  style: menuStyle,
1039
- "data-anvia-composer-trigger-menu": "",
1040
- "data-empty": empty ? "" : void 0,
1041
- "data-loading": activeTrigger?.loading ? "" : void 0,
1042
- "data-trigger": activeTrigger?.trigger.char,
1043
- "data-trigger-id": activeTrigger?.trigger.id
1025
+ "data-state": activeTrigger === void 0 ? "closed" : activeTrigger.loading ? "loading" : empty ? "empty" : "open"
1044
1026
  },
1045
1027
  ref
1046
1028
  );
@@ -1081,12 +1063,7 @@ var ComposerTriggerItem = forwardRef(
1081
1063
  role: props.role ?? "option",
1082
1064
  type: props.type ?? "button",
1083
1065
  "aria-selected": selected,
1084
- "data-anvia-composer-trigger-item": "",
1085
- "data-disabled": disabled ? "" : void 0,
1086
- "data-item-id": item.id,
1087
- "data-selected": selected ? "" : void 0,
1088
- "data-trigger": activeTrigger.trigger.char,
1089
- "data-trigger-id": activeTrigger.trigger.id
1066
+ "data-state": disabled ? "disabled" : selected ? "selected" : "idle"
1090
1067
  },
1091
1068
  ref
1092
1069
  );
@@ -1112,12 +1089,12 @@ var ComposerAttachments = forwardRef(
1112
1089
  composer.removeAttachment(attachment.id);
1113
1090
  }
1114
1091
  },
1115
- children: typeof children === "function" ? children(attachment) : children ?? /* @__PURE__ */ jsx(Attachment.Root, {})
1092
+ children: typeof children === "function" ? children(attachment) : children ?? /* @__PURE__ */ jsx(AttachmentPrimitive.Root, {})
1116
1093
  },
1117
1094
  attachment.id
1118
1095
  )),
1119
- "data-anvia-composer-attachments": "",
1120
- "data-empty": empty ? "" : void 0
1096
+ "data-role": "attachments",
1097
+ "data-state": empty ? "empty" : "populated"
1121
1098
  },
1122
1099
  ref
1123
1100
  );
@@ -1150,7 +1127,6 @@ var ComposerAttachmentInput = forwardRef(
1150
1127
  void handleChange(event);
1151
1128
  },
1152
1129
  type: "file",
1153
- "data-anvia-attachment-input": "",
1154
1130
  "data-state": disabled ? "disabled" : "enabled"
1155
1131
  },
1156
1132
  ref
@@ -1181,7 +1157,6 @@ var ComposerAddAttachment = forwardRef(
1181
1157
  disabled,
1182
1158
  onClick: handleClick,
1183
1159
  type: props.type ?? "button",
1184
- "data-anvia-add-attachment": "",
1185
1160
  "data-state": disabled ? "disabled" : "enabled"
1186
1161
  },
1187
1162
  ref
@@ -1245,9 +1220,7 @@ var ComposerAttachmentDropzone = forwardRef(
1245
1220
  onDragLeave: handleDragLeave,
1246
1221
  onDragOver: handleDragOver,
1247
1222
  onDrop: handleDrop,
1248
- "data-anvia-attachment-dropzone": "",
1249
- "data-dragging": dragging ? "" : void 0,
1250
- "data-state": disabled ? "disabled" : "enabled"
1223
+ "data-state": disabled ? "disabled" : dragging ? "dragging" : "enabled"
1251
1224
  },
1252
1225
  ref
1253
1226
  );
@@ -1293,7 +1266,7 @@ function createAttachmentId() {
1293
1266
  nextAttachmentId += 1;
1294
1267
  return `attachment_${nextAttachmentId.toString(36)}`;
1295
1268
  }
1296
- var Composer = {
1269
+ var ComposerPrimitive = {
1297
1270
  Root: ComposerRoot,
1298
1271
  Quote: ComposerQuotePreview,
1299
1272
  ClearQuote: ComposerClearQuote,
@@ -1324,6 +1297,7 @@ var ThreadRoot = forwardRef2(
1324
1297
  function ThreadRoot2(props, ref) {
1325
1298
  const chat = useChatContext();
1326
1299
  const viewportRef = useRef2(null);
1300
+ const messagesRef = useRef2(null);
1327
1301
  const [atBottom, setAtBottom] = useState2(true);
1328
1302
  const scrollToBottom = useCallback2((behavior = "smooth") => {
1329
1303
  const viewport = viewportRef.current;
@@ -1333,14 +1307,13 @@ var ThreadRoot = forwardRef2(
1333
1307
  viewport.scrollTo({ top: viewport.scrollHeight, behavior });
1334
1308
  }, []);
1335
1309
  const thread = useMemo2(
1336
- () => ({ viewportRef, atBottom, setAtBottom, scrollToBottom }),
1310
+ () => ({ viewportRef, messagesRef, atBottom, setAtBottom, scrollToBottom }),
1337
1311
  [atBottom, scrollToBottom]
1338
1312
  );
1339
1313
  return /* @__PURE__ */ jsx2(InternalThreadProvider, { value: thread, children: renderPrimitive(
1340
1314
  "div",
1341
1315
  {
1342
1316
  ...props,
1343
- "data-anvia-thread": "",
1344
1317
  "data-state": chat.status
1345
1318
  },
1346
1319
  ref
@@ -1368,7 +1341,7 @@ var ThreadViewport = forwardRef2(function ThreadViewport2({ autoScroll = true, o
1368
1341
  if (viewport === null || !autoScroll || typeof ResizeObserver !== "function") {
1369
1342
  return;
1370
1343
  }
1371
- const content = viewport.querySelector("[data-anvia-thread-messages]");
1344
+ const content = thread.messagesRef.current;
1372
1345
  if (content === null) {
1373
1346
  return;
1374
1347
  }
@@ -1395,7 +1368,6 @@ var ThreadViewport = forwardRef2(function ThreadViewport2({ autoScroll = true, o
1395
1368
  {
1396
1369
  ...props,
1397
1370
  onScroll: handleScroll,
1398
- "data-anvia-thread-viewport": "",
1399
1371
  "data-state": thread.atBottom ? "bottom" : "away"
1400
1372
  },
1401
1373
  composedRef
@@ -1406,8 +1378,7 @@ var ThreadViewportFooter = forwardRef2(
1406
1378
  return renderPrimitive(
1407
1379
  "div",
1408
1380
  {
1409
- ...props,
1410
- "data-anvia-thread-viewport-footer": ""
1381
+ ...props
1411
1382
  },
1412
1383
  ref
1413
1384
  );
@@ -1422,8 +1393,7 @@ var ThreadEmpty = forwardRef2(
1422
1393
  return renderPrimitive(
1423
1394
  "div",
1424
1395
  {
1425
- ...props,
1426
- "data-anvia-thread-empty": ""
1396
+ ...props
1427
1397
  },
1428
1398
  ref
1429
1399
  );
@@ -1437,7 +1407,6 @@ var ThreadStatus = forwardRef2(function ThreadStatus2({ children, ...props }, re
1437
1407
  {
1438
1408
  ...props,
1439
1409
  children: renderedChildren ?? chat.status,
1440
- "data-anvia-thread-status": "",
1441
1410
  "data-state": chat.status
1442
1411
  },
1443
1412
  ref
@@ -1453,8 +1422,7 @@ var ThreadLoading = forwardRef2(
1453
1422
  "div",
1454
1423
  {
1455
1424
  ...props,
1456
- children: props.children ?? "Loading",
1457
- "data-anvia-thread-loading": ""
1425
+ children: props.children ?? "Loading"
1458
1426
  },
1459
1427
  ref
1460
1428
  );
@@ -1471,7 +1439,6 @@ var ThreadError = forwardRef2(function ThreadError2({ children, ...props }, ref)
1471
1439
  {
1472
1440
  ...props,
1473
1441
  children: renderedChildren ?? errorMessage(chat.error),
1474
- "data-anvia-thread-error": "",
1475
1442
  role: props.role ?? "alert"
1476
1443
  },
1477
1444
  ref
@@ -1479,6 +1446,13 @@ var ThreadError = forwardRef2(function ThreadError2({ children, ...props }, ref)
1479
1446
  });
1480
1447
  var ThreadMessages = forwardRef2(function ThreadMessages2({ children, keepMounted = true, ...props }, ref) {
1481
1448
  const chat = useChatContext();
1449
+ const thread = useThread();
1450
+ const composedRef = useMemo2(
1451
+ () => composeRefs(ref, (node) => {
1452
+ thread.messagesRef.current = node;
1453
+ }),
1454
+ [ref, thread.messagesRef]
1455
+ );
1482
1456
  const empty = chat.messages.length === 0;
1483
1457
  if (empty && !keepMounted) {
1484
1458
  return null;
@@ -1488,10 +1462,9 @@ var ThreadMessages = forwardRef2(function ThreadMessages2({ children, keepMounte
1488
1462
  {
1489
1463
  ...props,
1490
1464
  children: chat.messages.map((message) => /* @__PURE__ */ jsx2(InternalMessageProvider, { message, children: typeof children === "function" ? children(message) : children ?? defaultMessage() }, message.id)),
1491
- "data-anvia-thread-messages": "",
1492
- "data-empty": empty ? "" : void 0
1465
+ "data-state": empty ? "empty" : "populated"
1493
1466
  },
1494
- ref
1467
+ composedRef
1495
1468
  );
1496
1469
  });
1497
1470
  var ThreadSuggestions = forwardRef2(
@@ -1509,8 +1482,8 @@ var ThreadSuggestions = forwardRef2(
1509
1482
  children: suggestions.map(
1510
1483
  (suggestion) => typeof children === "function" ? /* @__PURE__ */ jsx2(Fragment2, { children: children(suggestion) }, suggestion.id) : /* @__PURE__ */ jsx2(ThreadSuggestion, { suggestion, children }, suggestion.id)
1511
1484
  ),
1512
- "data-anvia-thread-suggestions": "",
1513
- "data-empty": empty ? "" : void 0
1485
+ "data-role": "suggestions",
1486
+ "data-state": empty ? "empty" : "populated"
1514
1487
  },
1515
1488
  ref
1516
1489
  );
@@ -1539,7 +1512,6 @@ var ThreadSuggestion = forwardRef2(
1539
1512
  disabled,
1540
1513
  onClick: handleClick,
1541
1514
  type: props.type ?? "button",
1542
- "data-anvia-thread-suggestion": "",
1543
1515
  "data-state": disabled ? "disabled" : "enabled"
1544
1516
  },
1545
1517
  ref
@@ -1568,7 +1540,6 @@ var ThreadScrollToBottom = forwardRef2(
1568
1540
  disabled,
1569
1541
  onClick: handleClick,
1570
1542
  type: props.type ?? "button",
1571
- "data-anvia-scroll-to-bottom": "",
1572
1543
  "data-state": thread.atBottom ? "bottom" : "away"
1573
1544
  },
1574
1545
  ref
@@ -1576,9 +1547,9 @@ var ThreadScrollToBottom = forwardRef2(
1576
1547
  }
1577
1548
  );
1578
1549
  function defaultMessage() {
1579
- return /* @__PURE__ */ jsxs2(Message.Root, { children: [
1580
- /* @__PURE__ */ jsx2(Message.Content, { children: /* @__PURE__ */ jsx2(Message.Parts, {}) }),
1581
- /* @__PURE__ */ jsx2(Message.Actions, {})
1550
+ return /* @__PURE__ */ jsxs2(MessagePrimitive.Root, { children: [
1551
+ /* @__PURE__ */ jsx2(MessagePrimitive.Content, { children: /* @__PURE__ */ jsx2(MessagePrimitive.Parts, {}) }),
1552
+ /* @__PURE__ */ jsx2(MessagePrimitive.Actions, {})
1582
1553
  ] });
1583
1554
  }
1584
1555
  function errorMessage(error) {
@@ -1590,7 +1561,7 @@ function errorMessage(error) {
1590
1561
  }
1591
1562
  return "Something went wrong.";
1592
1563
  }
1593
- var Thread = {
1564
+ var ThreadPrimitive = {
1594
1565
  Root: ThreadRoot,
1595
1566
  Viewport: ThreadViewport,
1596
1567
  ViewportFooter: ThreadViewportFooter,
@@ -1605,7 +1576,7 @@ var Thread = {
1605
1576
  };
1606
1577
 
1607
1578
  export {
1608
- Composer,
1609
- Thread
1579
+ ComposerPrimitive,
1580
+ ThreadPrimitive
1610
1581
  };
1611
- //# sourceMappingURL=chunk-XAQA3JIG.js.map
1582
+ //# sourceMappingURL=chunk-HWJIMLHC.js.map