@humain/ui 2.1.62 → 2.1.65

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 (160) hide show
  1. package/dist/components/organisms/ai/AIToolCall/AIToolCall.d.ts +9 -3
  2. package/dist/components/organisms/ai/AIToolRun/index.d.ts +1 -1
  3. package/dist/components/organisms/ai/AIToolRun/validation.d.ts +24 -3
  4. package/dist/components/organisms/ai/_shared/format-ai-duration.d.ts +1 -0
  5. package/dist/components/organisms/ai/_shared/workflow-step-renderer.d.ts +1 -0
  6. package/dist/index.js +52 -52
  7. package/dist/index151.js +1 -1
  8. package/dist/index174.js +10 -333
  9. package/dist/index174.js.map +1 -1
  10. package/dist/index175.js +310 -137
  11. package/dist/index175.js.map +1 -1
  12. package/dist/index176.js +148 -174
  13. package/dist/index176.js.map +1 -1
  14. package/dist/index177.js +186 -78
  15. package/dist/index177.js.map +1 -1
  16. package/dist/index178.js +74 -124
  17. package/dist/index178.js.map +1 -1
  18. package/dist/index179.js +133 -1
  19. package/dist/index179.js.map +1 -0
  20. package/dist/index180.js +2 -201
  21. package/dist/index181.js +201 -0
  22. package/dist/{index180.js.map → index181.js.map} +1 -1
  23. package/dist/index183.js +130 -166
  24. package/dist/index183.js.map +1 -1
  25. package/dist/index184.js +195 -983
  26. package/dist/index184.js.map +1 -1
  27. package/dist/index185.js +1069 -369
  28. package/dist/index185.js.map +1 -1
  29. package/dist/index186.js +395 -197
  30. package/dist/index186.js.map +1 -1
  31. package/dist/index187.js +198 -243
  32. package/dist/index187.js.map +1 -1
  33. package/dist/index188.js +263 -3
  34. package/dist/index188.js.map +1 -1
  35. package/dist/index189.js +3 -209
  36. package/dist/index189.js.map +1 -1
  37. package/dist/index190.js +190 -777
  38. package/dist/index190.js.map +1 -1
  39. package/dist/index191.js +771 -252
  40. package/dist/index191.js.map +1 -1
  41. package/dist/index192.js +250 -65
  42. package/dist/index192.js.map +1 -1
  43. package/dist/index193.js +72 -523
  44. package/dist/index193.js.map +1 -1
  45. package/dist/index194.js +537 -144
  46. package/dist/index194.js.map +1 -1
  47. package/dist/index195.js +139 -720
  48. package/dist/index195.js.map +1 -1
  49. package/dist/index196.js +707 -167
  50. package/dist/index196.js.map +1 -1
  51. package/dist/index197.js +175 -151
  52. package/dist/index197.js.map +1 -1
  53. package/dist/index198.js +152 -487
  54. package/dist/index198.js.map +1 -1
  55. package/dist/index199.js +472 -225
  56. package/dist/index199.js.map +1 -1
  57. package/dist/index200.js +236 -260
  58. package/dist/index200.js.map +1 -1
  59. package/dist/index201.js +265 -215
  60. package/dist/index201.js.map +1 -1
  61. package/dist/index202.js +207 -307
  62. package/dist/index202.js.map +1 -1
  63. package/dist/index203.js +302 -135
  64. package/dist/index203.js.map +1 -1
  65. package/dist/index204.js +140 -271
  66. package/dist/index204.js.map +1 -1
  67. package/dist/index205.js +263 -253
  68. package/dist/index205.js.map +1 -1
  69. package/dist/index206.js +244 -137
  70. package/dist/index206.js.map +1 -1
  71. package/dist/index207.js +100 -238
  72. package/dist/index207.js.map +1 -1
  73. package/dist/index208.js +278 -74
  74. package/dist/index208.js.map +1 -1
  75. package/dist/index209.js +56 -97
  76. package/dist/index209.js.map +1 -1
  77. package/dist/index210.js +142 -47
  78. package/dist/index210.js.map +1 -1
  79. package/dist/index211.js +38 -84
  80. package/dist/index211.js.map +1 -1
  81. package/dist/index212.js +72 -252
  82. package/dist/index212.js.map +1 -1
  83. package/dist/index213.js +274 -26
  84. package/dist/index213.js.map +1 -1
  85. package/dist/index214.js +29 -94
  86. package/dist/index214.js.map +1 -1
  87. package/dist/index215.js +98 -25
  88. package/dist/index215.js.map +1 -1
  89. package/dist/index216.js +20 -565
  90. package/dist/index216.js.map +1 -1
  91. package/dist/index217.js +564 -17
  92. package/dist/index217.js.map +1 -1
  93. package/dist/index218.js +20 -23
  94. package/dist/index218.js.map +1 -1
  95. package/dist/index219.js +20 -95
  96. package/dist/index219.js.map +1 -1
  97. package/dist/index220.js +92 -88
  98. package/dist/index220.js.map +1 -1
  99. package/dist/index221.js +97 -29
  100. package/dist/index221.js.map +1 -1
  101. package/dist/index222.js +24 -470
  102. package/dist/index222.js.map +1 -1
  103. package/dist/index223.js +446 -196
  104. package/dist/index223.js.map +1 -1
  105. package/dist/index224.js +199 -729
  106. package/dist/index224.js.map +1 -1
  107. package/dist/index225.js +750 -61
  108. package/dist/index225.js.map +1 -1
  109. package/dist/index226.js +58 -181
  110. package/dist/index226.js.map +1 -1
  111. package/dist/index227.js +175 -259
  112. package/dist/index227.js.map +1 -1
  113. package/dist/index228.js +246 -172
  114. package/dist/index228.js.map +1 -1
  115. package/dist/index229.js +195 -32
  116. package/dist/index229.js.map +1 -1
  117. package/dist/index230.js +12 -40
  118. package/dist/index230.js.map +1 -1
  119. package/dist/index231.js +23 -26
  120. package/dist/index231.js.map +1 -1
  121. package/dist/index232.js +45 -22
  122. package/dist/index232.js.map +1 -1
  123. package/dist/index233.js +27 -48
  124. package/dist/index233.js.map +1 -1
  125. package/dist/index234.js +52 -26
  126. package/dist/index234.js.map +1 -1
  127. package/dist/index235.js +40 -225
  128. package/dist/index235.js.map +1 -1
  129. package/dist/index236.js +217 -39
  130. package/dist/index236.js.map +1 -1
  131. package/dist/index237.js +50 -0
  132. package/dist/index237.js.map +1 -0
  133. package/dist/styles.css +1 -1
  134. package/dist/wc/AIToolCall.js +218 -0
  135. package/dist/wc/AIToolCall.js.map +1 -0
  136. package/dist/wc/hf-ai-tool-call.js +34 -219
  137. package/dist/wc/hf-ai-tool-call.js.map +1 -1
  138. package/dist/wc/hf-ai-tool-run.js +673 -576
  139. package/dist/wc/hf-ai-tool-run.js.map +1 -1
  140. package/dist/wc/workflow-step-renderer.js +94 -86
  141. package/dist/wc/workflow-step-renderer.js.map +1 -1
  142. package/dist/wc-react/AIToolCall.js +218 -0
  143. package/dist/wc-react/AIToolCall.js.map +1 -0
  144. package/dist/wc-react/hf-ai-tool-call.js +32 -217
  145. package/dist/wc-react/hf-ai-tool-call.js.map +1 -1
  146. package/dist/wc-react/hf-ai-tool-run.js +698 -601
  147. package/dist/wc-react/hf-ai-tool-run.js.map +1 -1
  148. package/dist/wc-react/workflow-step-renderer.js +76 -68
  149. package/dist/wc-react/workflow-step-renderer.js.map +1 -1
  150. package/package.json +1 -1
  151. package/skills/humain-ui/SKILL.md +1 -1
  152. package/skills/humain-ui-wc/SKILL.md +1 -1
  153. package/skills/humain-ui-wc.skill +0 -0
  154. package/skills/humain-ui.skill +0 -0
  155. package/dist/index182.js +0 -143
  156. package/dist/index182.js.map +0 -1
  157. package/dist/wc/wrench.js +0 -10
  158. package/dist/wc/wrench.js.map +0 -1
  159. package/dist/wc-react/wrench.js +0 -10
  160. package/dist/wc-react/wrench.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index186.js","names":[],"sources":["../src/components/organisms/content/ActivityFeed/ActivityFeed.tsx"],"sourcesContent":["import { cva, type VariantProps } from 'class-variance-authority';\nimport * as React from 'react';\nimport { Badge, type BadgeProps } from '@/components/atoms/display/Badge';\nimport { Avatar, type AvatarProps } from '@/components/molecules/data/Avatar';\nimport { FileTypeIcon } from '@/components/molecules/files/FileUpload';\nimport { cn } from '@/lib/utils';\n\n/* -------------------------------------------------------------------------------------------------\n * ActivityFeed Types and Variants\n * -------------------------------------------------------------------------------------------------*/\n\nconst activityFeedVariants = cva('flex flex-col', {\n variants: {\n divider: {\n divider: 'divide-y divide-border',\n connector: 'px-6 py-4',\n none: 'gap-4',\n },\n },\n defaultVariants: {\n divider: 'divider',\n },\n});\n\nconst activityItemVariants = cva('flex gap-3 relative', {\n variants: {\n type: {\n notifications: '',\n messages: '',\n },\n divider: {\n divider: 'px-4 py-4',\n connector: 'pt-0',\n none: 'px-4 py-4',\n },\n },\n defaultVariants: {\n type: 'notifications',\n divider: 'divider',\n },\n});\n\n/* -------------------------------------------------------------------------------------------------\n * ActivityFeedItemContent - Renders different content types\n * -------------------------------------------------------------------------------------------------*/\n\nexport type ActivityItemContentType = 'file' | 'message' | 'labels' | 'simple';\n\nexport interface FileContent {\n type: 'file';\n fileName: string;\n fileSize: string;\n fileExtension?: string;\n}\n\nexport interface MessageContent {\n type: 'message';\n message: string;\n /** Optional @mentions to highlight */\n mentions?: string[];\n}\n\nexport interface LabelsContent {\n type: 'labels';\n labels: Array<{\n text: string;\n color?: BadgeProps['color'];\n }>;\n}\n\nexport interface SimpleContent {\n type: 'simple';\n}\n\nexport type ActivityContent =\n | FileContent\n | MessageContent\n | LabelsContent\n | SimpleContent;\n\n/* -------------------------------------------------------------------------------------------------\n * ActivityFeedItem\n * -------------------------------------------------------------------------------------------------*/\n\nexport interface ActivityFeedItemProps\n extends Omit<React.HTMLAttributes<HTMLElement>, 'content'> {\n /** User/person info */\n user: {\n name: string;\n avatarSrc?: string;\n online?: boolean;\n };\n /** Timestamp (e.g., \"Just now\", \"2 mins ago\", \"5:20pm 20 Jan 2025\") */\n timestamp: string;\n /** Machine-readable ISO 8601 timestamp for the <time> element */\n dateTime?: string;\n /** Activity description with optional link text */\n activity: {\n /** Plain text part of activity (e.g., \"Added a file to\") */\n text: string;\n /** Link text to highlight (e.g., \"Marketing site redesign\") */\n link?: string;\n /** Link href */\n linkHref?: string;\n };\n /** Additional content (file attachment, message bubble, labels) */\n content?: ActivityContent;\n /** Show unread dot indicator */\n unread?: boolean;\n /** Avatar size */\n avatarSize?: AvatarProps['size'];\n /** Divider style - affects connector line visibility */\n divider?: 'divider' | 'connector' | 'none';\n /** Feed type */\n feedType?: 'notifications' | 'messages';\n /** For messages type: show username handle */\n userHandle?: string;\n /** Whether to show content details. Defaults to true. */\n expanded?: boolean;\n /** Internal: whether this is the last item (hides connector) */\n isLast?: boolean;\n}\n\nfunction getActivityFeedItemKey(item: ActivityFeedItemProps): React.Key {\n return (\n item.id ??\n `${item.user.name}:${item.timestamp}:${item.activity.text}:${item.activity.link ?? 'no-link'}`\n );\n}\n\ninterface MessageSegment {\n key: string;\n text: string;\n isMention: boolean;\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction getMessageSegments(\n message: string,\n mentions: string[],\n): MessageSegment[] {\n const mentionSet = new Set<string>();\n\n for (const mention of mentions) {\n const trimmedMention = mention.trim();\n if (trimmedMention) {\n mentionSet.add(trimmedMention);\n }\n }\n\n const uniqueMentions = Array.from(mentionSet);\n\n if (uniqueMentions.length === 0) {\n return [];\n }\n\n const mentionPattern = new RegExp(\n `@(?:${uniqueMentions.map(escapeRegExp).join('|')})`,\n 'gi',\n );\n const segments: MessageSegment[] = [];\n let cursor = 0;\n\n for (const match of message.matchAll(mentionPattern)) {\n const start = match.index ?? 0;\n const text = match[0];\n const end = start + text.length;\n\n if (start > cursor) {\n segments.push({\n key: `text:${cursor}:${start}`,\n text: message.slice(cursor, start),\n isMention: false,\n });\n }\n\n segments.push({\n key: `mention:${start}:${end}:${text.toLowerCase()}`,\n text,\n isMention: true,\n });\n cursor = end;\n }\n\n if (cursor < message.length) {\n segments.push({\n key: `text:${cursor}:${message.length}`,\n text: message.slice(cursor),\n isMention: false,\n });\n }\n\n return segments;\n}\n\ninterface ActivityFeedItemContentProps {\n content?: ActivityContent;\n expanded?: boolean;\n}\n\nfunction ActivityFeedMessageContent({\n message,\n mentions,\n}: {\n message: string;\n mentions?: string[];\n}) {\n if (!mentions || mentions.length === 0) {\n return <>{`\"${message}\"`}</>;\n }\n\n return (\n <>\n {getMessageSegments(message, mentions).map((segment) => (\n <span\n key={segment.key}\n className={\n segment.isMention ? 'font-semibold text-primary' : undefined\n }\n >\n {segment.text}\n </span>\n ))}\n </>\n );\n}\n\nfunction ActivityFeedItemContent({\n content,\n expanded,\n}: ActivityFeedItemContentProps) {\n if (!content || expanded === false) return null;\n\n switch (content.type) {\n case 'file':\n return (\n <div className=\"group/file flex gap-3 items-start w-full mt-3 rounded-lg transition-[background-color,transform] duration-150 ease-out motion-reduce:transition-none hover:bg-muted/40 active:scale-[0.99] motion-reduce:active:scale-100 cursor-default\">\n <FileTypeIcon extension={content.fileExtension} size=\"md\" />\n <div className=\"flex flex-col min-w-0 flex-1\">\n <p className=\"text-sm font-medium text-secondary-foreground truncate\">\n {content.fileName}\n </p>\n <p className=\"text-sm text-muted-foreground\">{content.fileSize}</p>\n </div>\n </div>\n );\n\n case 'message':\n return (\n <div className=\"mt-3 border border-border rounded-ee-md rounded-es-md rounded-se-md p-3 shadow-xs w-full transition-shadow duration-200 ease-out hover:shadow-sm motion-reduce:transition-none\">\n <p className=\"text-sm text-secondary-foreground\">\n <ActivityFeedMessageContent\n message={content.message}\n mentions={content.mentions}\n />\n </p>\n </div>\n );\n\n case 'labels':\n return (\n <div className=\"flex flex-wrap gap-1 mt-3\">\n {content.labels.map((label, i) => (\n <Badge\n key={label.text}\n variant=\"outline\"\n color={label.color || 'primary'}\n size=\"sm\"\n className=\"delight-stagger transition-transform duration-150 ease-out motion-reduce:transition-none hover:scale-105 motion-reduce:hover:scale-100\"\n style={\n {\n '--delight-delay': `${i * 50}ms`,\n } as React.CSSProperties\n }\n >\n {label.text}\n </Badge>\n ))}\n </div>\n );\n\n default:\n return null;\n }\n}\n\nconst ActivityFeedItem = React.memo(\n React.forwardRef<HTMLElement, ActivityFeedItemProps>(\n (\n {\n className,\n user,\n timestamp,\n dateTime,\n activity,\n content,\n unread = false,\n avatarSize = 'lg',\n divider = 'divider',\n feedType = 'notifications',\n userHandle,\n expanded,\n isLast = false,\n ...props\n },\n ref,\n ) => {\n return (\n <article\n ref={ref}\n data-slot=\"activity-feed-item\"\n aria-label={`${user.name}: ${activity.text}${activity.link ? ` ${activity.link}` : ''}`}\n className={cn(\n activityItemVariants({ type: feedType, divider }),\n 'transition-colors duration-150 ease-out motion-reduce:transition-none',\n 'hover:bg-muted/30',\n className,\n )}\n {...props}\n >\n {/* Avatar wrap with connector */}\n <div\n className={cn(\n 'flex flex-col items-center gap-0.5 self-stretch shrink-0',\n divider === 'connector' && !isLast && 'pb-0.5',\n )}\n >\n <Avatar\n src={user.avatarSrc}\n fallback={user.name}\n size={avatarSize}\n indicator={\n user.online === true\n ? 'online'\n : user.online === false\n ? 'offline'\n : undefined\n }\n />\n {/* Connector line - only show for connector divider and not last item */}\n {divider === 'connector' && !isLast && (\n <div className=\"flex-1 w-0.5 min-h-4 rounded-sm bg-border delight-connector-grow\" />\n )}\n </div>\n\n {/* Content */}\n <div\n className={cn(\n 'flex flex-col flex-1 min-w-0',\n divider === 'connector' && 'pb-8',\n )}\n >\n {/* Header */}\n <div className=\"flex flex-col\">\n <div className=\"flex items-center gap-2 flex-wrap\">\n <span className=\"text-sm font-medium text-secondary-foreground\">\n {user.name}\n </span>\n {feedType === 'messages' && userHandle && (\n <span className=\"text-sm text-muted-foreground\">\n @{userHandle}\n </span>\n )}\n {dateTime ? (\n <time\n dateTime={dateTime}\n className=\"text-xs text-muted-foreground\"\n >\n {timestamp}\n </time>\n ) : (\n <span className=\"text-xs text-muted-foreground\">\n {timestamp}\n </span>\n )}\n </div>\n\n {/* Activity description */}\n <p className=\"text-sm text-muted-foreground\">\n {activity.text}\n {activity.link && (\n <>\n {' '}\n {activity.linkHref ? (\n <a\n href={activity.linkHref}\n className=\"font-medium text-primary hover:text-primary/80 transition-colors duration-150 ease-out focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-1 rounded-sm\"\n >\n {activity.link}\n </a>\n ) : (\n <span className=\"font-medium text-secondary-foreground\">\n {activity.link}\n </span>\n )}\n </>\n )}\n </p>\n </div>\n\n {/* Additional content */}\n <ActivityFeedItemContent content={content} expanded={expanded} />\n </div>\n\n {/* Unread indicator */}\n {unread && (\n <div className=\"absolute top-2 end-1 size-2.5\" aria-hidden=\"true\">\n <div className=\"size-2 rounded-full bg-primary delight-unread-pulse\" />\n </div>\n )}\n </article>\n );\n },\n ),\n);\n\nActivityFeedItem.displayName = 'ActivityFeedItem';\n\n/* -------------------------------------------------------------------------------------------------\n * ActivityFeed\n * -------------------------------------------------------------------------------------------------*/\n\nexport interface ActivityFeedProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof activityFeedVariants> {\n /** Feed items */\n items?: ActivityFeedItemProps[];\n /** Feed type affects styling */\n type?: 'notifications' | 'messages';\n /** Whether the feed is loading/updating (sets aria-busy) */\n loading?: boolean;\n /** Children (alternative to items prop — note: stagger animations are not auto-applied to children) */\n children?: React.ReactNode;\n}\n\nconst ActivityFeed = React.forwardRef<HTMLDivElement, ActivityFeedProps>(\n (\n {\n className,\n divider = 'divider',\n items,\n type = 'notifications',\n loading,\n children,\n ...props\n },\n ref,\n ) => {\n return (\n <div\n ref={ref}\n data-slot=\"activity-feed\"\n role=\"feed\"\n aria-label=\"Activity feed\"\n aria-busy={loading || undefined}\n className={cn(activityFeedVariants({ divider }), className)}\n {...props}\n >\n {items\n ? items.map((item, index) => (\n <ActivityFeedItem\n key={getActivityFeedItemKey(item)}\n {...item}\n aria-setsize={items.length}\n aria-posinset={index + 1}\n divider={divider ?? 'divider'}\n feedType={type}\n isLast={index === items.length - 1}\n className={cn('delight-stagger', item.className)}\n style={\n {\n '--delight-delay': `${index * 60}ms`,\n ...item.style,\n } as React.CSSProperties\n }\n />\n ))\n : children}\n </div>\n );\n },\n);\n\nActivityFeed.displayName = 'ActivityFeed';\n\nexport {\n ActivityFeed,\n ActivityFeedItem,\n activityFeedVariants,\n activityItemVariants,\n};\n"],"mappings":";;;;;;;;AAWA,IAAM,uBAAuB,IAAI,iBAAiB;CAChD,UAAU,EACR,SAAS;EACP,SAAS;EACT,WAAW;EACX,MAAM;CACR,EACF;CACA,iBAAiB,EACf,SAAS,UACX;AACF,CAAC;AAED,IAAM,uBAAuB,IAAI,uBAAuB;CACtD,UAAU;EACR,MAAM;GACJ,eAAe;GACf,UAAU;EACZ;EACA,SAAS;GACP,SAAS;GACT,WAAW;GACX,MAAM;EACR;CACF;CACA,iBAAiB;EACf,MAAM;EACN,SAAS;CACX;AACF,CAAC;AAmFD,SAAS,uBAAuB,MAAwC;CACtE,OACE,KAAK,MACL,GAAG,KAAK,KAAK,KAAK,GAAG,KAAK,UAAU,GAAG,KAAK,SAAS,KAAK,GAAG,KAAK,SAAS,QAAQ;AAEvF;AAQA,SAAS,aAAa,OAAuB;CAC3C,OAAO,MAAM,QAAQ,uBAAuB,MAAM;AACpD;AAEA,SAAS,mBACP,SACA,UACkB;CAClB,MAAM,6BAAa,IAAI,IAAY;CAEnC,KAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,iBAAiB,QAAQ,KAAK;EACpC,IAAI,gBACF,WAAW,IAAI,cAAc;CAEjC;CAEA,MAAM,iBAAiB,MAAM,KAAK,UAAU;CAE5C,IAAI,eAAe,WAAW,GAC5B,OAAO,CAAC;CAGV,MAAM,iBAAiB,IAAI,OACzB,OAAO,eAAe,IAAI,YAAY,CAAC,CAAC,KAAK,GAAG,EAAE,IAClD,IACF;CACA,MAAM,WAA6B,CAAC;CACpC,IAAI,SAAS;CAEb,KAAK,MAAM,SAAS,QAAQ,SAAS,cAAc,GAAG;EACpD,MAAM,QAAQ,MAAM,SAAS;EAC7B,MAAM,OAAO,MAAM;EACnB,MAAM,MAAM,QAAQ,KAAK;EAEzB,IAAI,QAAQ,QACV,SAAS,KAAK;GACZ,KAAK,QAAQ,OAAO,GAAG;GACvB,MAAM,QAAQ,MAAM,QAAQ,KAAK;GACjC,WAAW;EACb,CAAC;EAGH,SAAS,KAAK;GACZ,KAAK,WAAW,MAAM,GAAG,IAAI,GAAG,KAAK,YAAY;GACjD;GACA,WAAW;EACb,CAAC;EACD,SAAS;CACX;CAEA,IAAI,SAAS,QAAQ,QACnB,SAAS,KAAK;EACZ,KAAK,QAAQ,OAAO,GAAG,QAAQ;EAC/B,MAAM,QAAQ,MAAM,MAAM;EAC1B,WAAW;CACb,CAAC;CAGH,OAAO;AACT;AAOA,SAAS,2BAA2B,EAClC,SACA,YAIC;CACD,IAAI,CAAC,YAAY,SAAS,WAAW,GACnC,OAAO,oBAAA,UAAA,EAAA,UAAG,IAAI,QAAQ,GAAK,CAAA;CAG7B,OACE,oBAAA,UAAA,EAAA,UACG,mBAAmB,SAAS,QAAQ,CAAC,CAAC,KAAK,YAC1C,oBAAC,QAAD;EAEE,WACE,QAAQ,YAAY,+BAA+B,KAAA;YAGpD,QAAQ;CACL,GANC,QAAQ,GAMT,CACP,EACD,CAAA;AAEN;AAEA,SAAS,wBAAwB,EAC/B,SACA,YAC+B;CAC/B,IAAI,CAAC,WAAW,aAAa,OAAO,OAAO;CAE3C,QAAQ,QAAQ,MAAhB;EACE,KAAK,QACH,OACE,qBAAC,OAAD;GAAK,WAAU;aAAf,CACE,oBAAC,cAAD;IAAc,WAAW,QAAQ;IAAe,MAAK;GAAM,CAAA,GAC3D,qBAAC,OAAD;IAAK,WAAU;cAAf,CACE,oBAAC,KAAD;KAAG,WAAU;eACV,QAAQ;IACR,CAAA,GACH,oBAAC,KAAD;KAAG,WAAU;eAAiC,QAAQ;IAAY,CAAA,CAC/D;KACF;;EAGT,KAAK,WACH,OACE,oBAAC,OAAD;GAAK,WAAU;aACb,oBAAC,KAAD;IAAG,WAAU;cACX,oBAAC,4BAAD;KACE,SAAS,QAAQ;KACjB,UAAU,QAAQ;IACnB,CAAA;GACA,CAAA;EACA,CAAA;EAGT,KAAK,UACH,OACE,oBAAC,OAAD;GAAK,WAAU;aACZ,QAAQ,OAAO,KAAK,OAAO,MAC1B,oBAAC,OAAD;IAEE,SAAQ;IACR,OAAO,MAAM,SAAS;IACtB,MAAK;IACL,WAAU;IACV,OACE,EACE,mBAAmB,GAAG,IAAI,GAAG,IAC/B;cAGD,MAAM;GACF,GAZA,MAAM,IAYN,CACR;EACE,CAAA;EAGT,SACE,OAAO;CACX;AACF;AAEA,IAAM,mBAAmB,MAAM,KAC7B,MAAM,YAEF,EACE,WACA,MACA,WACA,UACA,UACA,SACA,SAAS,OACT,aAAa,MACb,UAAU,WACV,WAAW,iBACX,YACA,UACA,SAAS,OACT,GAAG,SAEL,QACG;CACH,OACE,qBAAC,WAAD;EACO;EACL,aAAU;EACV,cAAY,GAAG,KAAK,KAAK,IAAI,SAAS,OAAO,SAAS,OAAO,IAAI,SAAS,SAAS;EACnF,WAAW,GACT,qBAAqB;GAAE,MAAM;GAAU;EAAQ,CAAC,GAChD,yEACA,qBACA,SACF;EACA,GAAI;YAVN;GAaE,qBAAC,OAAD;IACE,WAAW,GACT,4DACA,YAAY,eAAe,CAAC,UAAU,QACxC;cAJF,CAME,oBAAC,QAAD;KACE,KAAK,KAAK;KACV,UAAU,KAAK;KACf,MAAM;KACN,WACE,KAAK,WAAW,OACZ,WACA,KAAK,WAAW,QACd,YACA,KAAA;IAET,CAAA,GAEA,YAAY,eAAe,CAAC,UAC3B,oBAAC,OAAD,EAAK,WAAU,mEAAoE,CAAA,CAElF;;GAGL,qBAAC,OAAD;IACE,WAAW,GACT,gCACA,YAAY,eAAe,MAC7B;cAJF,CAOE,qBAAC,OAAD;KAAK,WAAU;eAAf,CACE,qBAAC,OAAD;MAAK,WAAU;gBAAf;OACE,oBAAC,QAAD;QAAM,WAAU;kBACb,KAAK;OACF,CAAA;OACL,aAAa,cAAc,cAC1B,qBAAC,QAAD;QAAM,WAAU;kBAAhB,CAAgD,KAC5C,UACE;;OAEP,WACC,oBAAC,QAAD;QACY;QACV,WAAU;kBAET;OACG,CAAA,IAEN,oBAAC,QAAD;QAAM,WAAU;kBACb;OACG,CAAA;MAEL;SAGL,qBAAC,KAAD;MAAG,WAAU;gBAAb,CACG,SAAS,MACT,SAAS,QACR,qBAAA,UAAA,EAAA,UAAA,CACG,KACA,SAAS,WACR,oBAAC,KAAD;OACE,MAAM,SAAS;OACf,WAAU;iBAET,SAAS;MACT,CAAA,IAEH,oBAAC,QAAD;OAAM,WAAU;iBACb,SAAS;MACN,CAAA,CAER,EAAA,CAAA,CAEH;OACA;QAGL,oBAAC,yBAAD;KAAkC;KAAmB;IAAW,CAAA,CAC7D;;GAGJ,UACC,oBAAC,OAAD;IAAK,WAAU;IAAgC,eAAY;cACzD,oBAAC,OAAD,EAAK,WAAU,sDAAuD,CAAA;GACnE,CAAA;EAEA;;AAEb,CACF,CACF;AAEA,iBAAiB,cAAc;AAmB/B,IAAM,eAAe,MAAM,YAEvB,EACE,WACA,UAAU,WACV,OACA,OAAO,iBACP,SACA,UACA,GAAG,SAEL,QACG;CACH,OACE,oBAAC,OAAD;EACO;EACL,aAAU;EACV,MAAK;EACL,cAAW;EACX,aAAW,WAAW,KAAA;EACtB,WAAW,GAAG,qBAAqB,EAAE,QAAQ,CAAC,GAAG,SAAS;EAC1D,GAAI;YAEH,QACG,MAAM,KAAK,MAAM,UACf,oBAAC,kBAAD;GAEE,GAAI;GACJ,gBAAc,MAAM;GACpB,iBAAe,QAAQ;GACvB,SAAS,WAAW;GACpB,UAAU;GACV,QAAQ,UAAU,MAAM,SAAS;GACjC,WAAW,GAAG,mBAAmB,KAAK,SAAS;GAC/C,OACE;IACE,mBAAmB,GAAG,QAAQ,GAAG;IACjC,GAAG,KAAK;GACV;EAEH,GAdM,uBAAuB,IAAI,CAcjC,CACF,IACD;CACD,CAAA;AAET,CACF;AAEA,aAAa,cAAc"}
1
+ {"version":3,"file":"index186.js","names":[],"sources":["../src/components/organisms/ai/AIToolRun/AIToolRun.tsx"],"sourcesContent":["'use client';\n\nimport {\n AlertCircle,\n Check,\n ChevronDown,\n ChevronRight,\n CirclePause,\n Clock,\n Wrench,\n} from 'lucide-react';\nimport * as React from 'react';\nimport { Button } from '@/components/atoms/buttons/Button';\nimport { Progress } from '@/components/atoms/display/Progress';\nimport { Card } from '@/components/atoms/layout/Card';\nimport { formatAIDuration } from '@/components/organisms/ai/_shared/format-ai-duration';\nimport {\n WorkflowStepRenderer,\n type WorkflowStepStatus,\n type WorkflowStepViewModel,\n} from '@/components/organisms/ai/_shared/workflow-step-renderer';\nimport { AISource } from '@/components/organisms/ai/AISource';\nimport { AIToolCallList } from '@/components/organisms/ai/AIToolCall';\nimport { assertNever, cn } from '@/lib/utils';\nimport {\n type AIToolRunAction,\n type AIToolRunActionEvent,\n type AIToolRunActionKind,\n type AIToolRunProgress,\n type AIToolRunSnapshot,\n type AIToolRunSource,\n type AIToolRunStep,\n type AIToolRunTechnicalDetails,\n validateAIToolRunSnapshot,\n} from './validation';\n\nexport interface AIToolRunProps\n extends Omit<\n React.ComponentPropsWithoutRef<'section'>,\n 'children' | 'dangerouslySetInnerHTML'\n > {\n run: AIToolRunSnapshot;\n headingLevel?: 2 | 3 | 4 | 5 | 6;\n open?: boolean;\n defaultOpen?: boolean;\n onOpenChange?: (open: boolean) => void;\n expandedStepIds?: readonly string[];\n defaultExpandedStepIds?: readonly string[];\n onExpandedStepIdsChange?: (ids: readonly string[]) => void;\n onAction?: (event: AIToolRunActionEvent) => void;\n}\n\ninterface AIToolRunRuntimeBoundaryInput\n extends Omit<\n AIToolRunProps,\n | 'run'\n | 'headingLevel'\n | 'open'\n | 'defaultOpen'\n | 'expandedStepIds'\n | 'defaultExpandedStepIds'\n > {\n run: unknown;\n dangerouslySetInnerHTML?: unknown;\n headingLevel?: unknown;\n open?: unknown;\n defaultOpen?: unknown;\n expandedStepIds?: unknown;\n defaultExpandedStepIds?: unknown;\n}\n\ninterface AIToolRunViewOptions {\n headingLevel?: AIToolRunProps['headingLevel'];\n open?: boolean;\n defaultOpen?: boolean;\n expandedStepIds?: readonly string[];\n defaultExpandedStepIds?: readonly string[];\n}\n\ntype AIToolRunViewValidationResult =\n | { valid: true; value: AIToolRunViewOptions }\n | { valid: false; issues: readonly string[] };\n\nconst MAX_RUNTIME_EXPANDED_STEP_IDS = 10_000;\nconst INVALID_RUNTIME_STRING_ARRAY = Symbol('invalid-runtime-string-array');\nconst ARRAY_PROTOTYPE_MEMBER_KEYS = Reflect.ownKeys(Array.prototype).filter(\n (key) => key !== 'length',\n);\n\nfunction cloneRuntimeStringArray(\n value: unknown,\n): string[] | typeof INVALID_RUNTIME_STRING_ARRAY {\n try {\n if (!Array.isArray(value)) {\n return INVALID_RUNTIME_STRING_ARRAY;\n }\n\n const lengthDescriptor = Reflect.getOwnPropertyDescriptor(value, 'length');\n if (\n lengthDescriptor === undefined ||\n lengthDescriptor.enumerable ||\n !Object.hasOwn(lengthDescriptor, 'value') ||\n typeof lengthDescriptor.value !== 'number' ||\n !Number.isInteger(lengthDescriptor.value) ||\n lengthDescriptor.value < 0 ||\n lengthDescriptor.value > MAX_RUNTIME_EXPANDED_STEP_IDS ||\n !Object.is(Reflect.get(value, 'length'), lengthDescriptor.value)\n ) {\n return INVALID_RUNTIME_STRING_ARRAY;\n }\n\n for (const key of ARRAY_PROTOTYPE_MEMBER_KEYS) {\n if (Reflect.getOwnPropertyDescriptor(value, key) !== undefined) {\n return INVALID_RUNTIME_STRING_ARRAY;\n }\n }\n\n const copy: string[] = [];\n for (let index = 0; index < lengthDescriptor.value; index += 1) {\n const key = String(index);\n const descriptor = Reflect.getOwnPropertyDescriptor(value, key);\n if (\n descriptor === undefined ||\n descriptor.enumerable !== true ||\n !Object.hasOwn(descriptor, 'value') ||\n typeof descriptor.value !== 'string' ||\n !Object.is(Reflect.get(value, key), descriptor.value)\n ) {\n return INVALID_RUNTIME_STRING_ARRAY;\n }\n copy.push(descriptor.value);\n }\n return copy;\n } catch {\n return INVALID_RUNTIME_STRING_ARRAY;\n }\n}\n\nfunction validateRuntimeViewProps({\n headingLevel,\n open,\n defaultOpen,\n expandedStepIds,\n defaultExpandedStepIds,\n}: Pick<\n AIToolRunRuntimeBoundaryInput,\n | 'headingLevel'\n | 'open'\n | 'defaultOpen'\n | 'expandedStepIds'\n | 'defaultExpandedStepIds'\n>): AIToolRunViewValidationResult {\n const issues: string[] = [];\n let validatedExpandedStepIds: string[] | undefined;\n let validatedDefaultExpandedStepIds: string[] | undefined;\n\n if (\n headingLevel !== undefined &&\n (typeof headingLevel !== 'number' ||\n !Number.isInteger(headingLevel) ||\n headingLevel < 2 ||\n headingLevel > 6)\n ) {\n issues.push('headingLevel must be an integer from 2 through 6');\n }\n if (open !== undefined && typeof open !== 'boolean') {\n issues.push('open must be a boolean');\n }\n if (defaultOpen !== undefined && typeof defaultOpen !== 'boolean') {\n issues.push('defaultOpen must be a boolean');\n }\n if (expandedStepIds !== undefined) {\n const cloned = cloneRuntimeStringArray(expandedStepIds);\n if (cloned === INVALID_RUNTIME_STRING_ARRAY) {\n issues.push('expandedStepIds must be an array of strings');\n } else {\n validatedExpandedStepIds = cloned;\n }\n }\n if (defaultExpandedStepIds !== undefined) {\n const cloned = cloneRuntimeStringArray(defaultExpandedStepIds);\n if (cloned === INVALID_RUNTIME_STRING_ARRAY) {\n issues.push('defaultExpandedStepIds must be an array of strings');\n } else {\n validatedDefaultExpandedStepIds = cloned;\n }\n }\n\n if (issues.length > 0) return { valid: false, issues };\n\n return {\n valid: true,\n value: {\n ...(headingLevel === undefined\n ? {}\n : { headingLevel: headingLevel as AIToolRunProps['headingLevel'] }),\n ...(open === undefined ? {} : { open: open as boolean }),\n ...(defaultOpen === undefined\n ? {}\n : { defaultOpen: defaultOpen as boolean }),\n ...(expandedStepIds === undefined\n ? {}\n : { expandedStepIds: validatedExpandedStepIds }),\n ...(defaultExpandedStepIds === undefined\n ? {}\n : {\n defaultExpandedStepIds: validatedDefaultExpandedStepIds,\n }),\n },\n };\n}\n\nconst InvalidAIToolRun = React.forwardRef<\n HTMLElement,\n React.ComponentPropsWithoutRef<'section'>\n>(({ className, ...sectionProps }, ref) => (\n <section\n {...sectionProps}\n ref={ref}\n data-slot=\"ai-tool-run\"\n role=\"alert\"\n aria-label=\"Tool run\"\n className={cn('w-full min-w-0', className)}\n >\n Unable to display tool run.\n </section>\n));\n\nInvalidAIToolRun.displayName = 'InvalidAIToolRun';\n\nconst RUN_STATUS_LABELS = {\n ready: 'Ready',\n running: 'Running',\n paused: 'Paused',\n completed: 'Completed',\n error: 'Failed',\n} as const satisfies Record<AIToolRunSnapshot['status'], string>;\n\nconst STANDARD_ACTION_LABELS = {\n start: 'Start',\n pause: 'Pause',\n resume: 'Resume',\n retry: 'Retry',\n dismiss: 'Dismiss',\n} as const satisfies Record<Exclude<AIToolRunActionKind, 'custom'>, string>;\n\nconst PAUSED_PROGRESS_CLASS_NAME =\n '[&_[data-slot=progress-indicator]]:!transition-none [&_[data-slot=progress-indicator]]:!animate-none';\n\nfunction RunStatusIcon({ status }: { status: AIToolRunSnapshot['status'] }) {\n switch (status) {\n case 'ready':\n return (\n <Wrench aria-hidden=\"true\" className=\"size-4 text-muted-foreground\" />\n );\n case 'running':\n return (\n <Clock\n aria-hidden=\"true\"\n className=\"size-4 text-primary animate-pulse motion-reduce:animate-none\"\n />\n );\n case 'paused':\n return <CirclePause aria-hidden=\"true\" className=\"size-4 text-warning\" />;\n case 'completed':\n return <Check aria-hidden=\"true\" className=\"size-4 text-success\" />;\n case 'error':\n return (\n <AlertCircle aria-hidden=\"true\" className=\"size-4 text-destructive\" />\n );\n default:\n return assertNever(status);\n }\n}\n\nRunStatusIcon.displayName = 'RunStatusIcon';\n\nfunction getActionLabel(action: AIToolRunAction): string {\n if (action.kind === 'custom') return action.label;\n return action.label ?? STANDARD_ACTION_LABELS[action.kind];\n}\n\nfunction getPoliteAnnouncement(run: AIToolRunSnapshot): string {\n if (run.status === 'error') return '';\n\n const activeStep =\n run.activeStepId === undefined\n ? undefined\n : run.steps.find((step) => step.toolCall.toolCallId === run.activeStepId);\n const statusLabel = RUN_STATUS_LABELS[run.status];\n\n return activeStep\n ? `${statusLabel}. Current step: ${activeStep.title ?? activeStep.toolCall.toolName}.`\n : `${statusLabel}.`;\n}\n\nfunction getWorkflowStepStatus(\n runStatus: AIToolRunSnapshot['status'],\n step: AIToolRunStep,\n): WorkflowStepStatus {\n const toolStatus = step.toolCall.status;\n switch (toolStatus) {\n case 'pending':\n return 'pending';\n case 'running':\n return runStatus === 'paused' ? 'suspended' : 'running';\n case 'success':\n return 'completed';\n case 'error':\n return 'error';\n default:\n return assertNever(toolStatus);\n }\n}\n\nfunction AIToolRunStepContent({\n progress,\n sources,\n title,\n paused,\n technicalDetails,\n}: {\n progress?: AIToolRunProgress;\n sources: readonly AIToolRunSource[];\n title: string;\n paused: boolean;\n technicalDetails?: AIToolRunTechnicalDetails;\n}) {\n const failedToolCallIds =\n technicalDetails?.toolCalls.flatMap((toolCall) =>\n toolCall.status === 'error' ? [toolCall.toolCallId] : [],\n ) ?? [];\n\n return (\n <div className=\"grid min-w-0 gap-3\">\n {progress && (\n <Progress\n value={progress.value}\n label={progress.label}\n subLabel={progress.meta}\n className={paused ? PAUSED_PROGRESS_CLASS_NAME : undefined}\n />\n )}\n {sources.length > 0 && (\n <ul aria-label={`Sources for ${title}`} className=\"grid min-w-0 gap-2\">\n {sources.map((item, index) => (\n <li\n key={`${item.id}-${index}`}\n className=\"flex min-w-0 items-center gap-2\"\n >\n {item.kind === 'reference' ? (\n <span\n data-slot=\"ai-tool-run-reference\"\n className=\"min-w-0 truncate text-sm text-secondary-foreground\"\n title={item.description}\n >\n {item.title}\n </span>\n ) : (\n <AISource\n source={item}\n variant=\"minimal\"\n showTooltip={false}\n className=\"min-w-0 max-w-none\"\n />\n )}\n </li>\n ))}\n </ul>\n )}\n {technicalDetails && technicalDetails.toolCalls.length > 0 && (\n <div className=\"grid min-w-0 gap-2\">\n {technicalDetails.label && (\n <p className=\"text-xs font-medium text-secondary-foreground\">\n {technicalDetails.label}\n </p>\n )}\n <AIToolCallList\n toolCalls={technicalDetails.toolCalls}\n defaultOpenToolCallIds={failedToolCallIds}\n />\n </div>\n )}\n </div>\n );\n}\n\nAIToolRunStepContent.displayName = 'AIToolRunStepContent';\n\nfunction toWorkflowStep(\n runStatus: AIToolRunSnapshot['status'],\n step: AIToolRunStep,\n sourcesById: ReadonlyMap<string, AIToolRunSource>,\n): WorkflowStepViewModel {\n const title = step.title ?? step.toolCall.toolName;\n const stepSources = (step.sourceIds ?? []).flatMap((sourceId) => {\n const source = sourcesById.get(sourceId);\n return source === undefined ? [] : [source];\n });\n const hasContent =\n step.progress !== undefined ||\n stepSources.length > 0 ||\n step.technicalDetails !== undefined;\n\n return {\n id: step.toolCall.toolCallId,\n title,\n description: step.description,\n contextLabel: step.context?.label,\n status: getWorkflowStepStatus(runStatus, step),\n content: hasContent ? (\n <AIToolRunStepContent\n progress={step.progress}\n sources={stepSources}\n title={title}\n paused={runStatus === 'paused'}\n technicalDetails={step.technicalDetails}\n />\n ) : undefined,\n durationMs: step.durationMs,\n error: step.toolCall.status === 'error' ? step.toolCall.error : undefined,\n };\n}\n\nfunction useAIToolRunOpenState({\n open,\n defaultOpen,\n onOpenChange,\n}: Pick<AIToolRunProps, 'open' | 'defaultOpen' | 'onOpenChange'>) {\n const isControlled = open !== undefined;\n const [uncontrolledOpen, setUncontrolledOpen] = React.useState(\n defaultOpen ?? true,\n );\n const lastControlledOpenRef = React.useRef(open ?? uncontrolledOpen);\n const wasControlledRef = React.useRef(isControlled);\n\n React.useLayoutEffect(() => {\n if (open !== undefined) {\n lastControlledOpenRef.current = open;\n }\n }, [open]);\n\n React.useLayoutEffect(() => {\n const wasControlled = wasControlledRef.current;\n wasControlledRef.current = isControlled;\n\n if (isControlled || !wasControlled) {\n return;\n }\n\n setUncontrolledOpen((currentOpen) =>\n currentOpen === lastControlledOpenRef.current\n ? currentOpen\n : lastControlledOpenRef.current,\n );\n }, [isControlled]);\n\n const setOpen = React.useCallback(\n (nextOpen: boolean) => {\n if (!isControlled) {\n setUncontrolledOpen(nextOpen);\n }\n onOpenChange?.(nextOpen);\n },\n [isControlled, onOpenChange],\n );\n\n return [isControlled ? open : uncontrolledOpen, setOpen] as const;\n}\n\nconst AIToolRunPresentation = React.forwardRef<HTMLElement, AIToolRunProps>(\n (\n {\n run,\n headingLevel = 2,\n open,\n defaultOpen,\n onOpenChange,\n expandedStepIds,\n defaultExpandedStepIds,\n onExpandedStepIdsChange,\n onAction,\n className,\n ...sectionProps\n },\n ref,\n ) => {\n const headingId = React.useId();\n const detailsId = React.useId();\n const Heading = `h${headingLevel}` as 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n const [isOpen, setIsOpen] = useAIToolRunOpenState({\n open,\n defaultOpen,\n onOpenChange,\n });\n const sourcesById = React.useMemo(\n () => new Map((run.sources ?? []).map((source) => [source.id, source])),\n [run.sources],\n );\n const workflowSteps = React.useMemo(\n () =>\n run.steps.map((step) => toWorkflowStep(run.status, step, sourcesById)),\n [run.status, run.steps, sourcesById],\n );\n const initialExpandedStepIds = React.useMemo(() => {\n const requested = new Set(defaultExpandedStepIds);\n for (const step of run.steps) {\n if (step.toolCall.status === 'error') {\n requested.add(step.toolCall.toolCallId);\n }\n }\n return run.steps.flatMap((step) =>\n requested.has(step.toolCall.toolCallId)\n ? [step.toolCall.toolCallId]\n : [],\n );\n }, [defaultExpandedStepIds, run.steps]);\n const rootError = run.status === 'error' ? run.error.message : undefined;\n const politeAnnouncement = getPoliteAnnouncement(run);\n const { 'aria-busy': _ariaBusy, ...nativeSectionProps } = sectionProps;\n\n return (\n <section\n {...nativeSectionProps}\n ref={ref}\n data-slot=\"ai-tool-run\"\n aria-labelledby={headingId}\n className={cn('relative w-full min-w-0', className)}\n >\n <Card\n aria-busy={run.status === 'running' ? true : undefined}\n className=\"rounded-2xl\"\n >\n <Card.Header>\n <div className=\"grid min-w-0 gap-1\">\n <div className=\"flex min-w-0 items-center gap-2 text-xs font-medium text-secondary-foreground\">\n <RunStatusIcon status={run.status} />\n <span>Status: {RUN_STATUS_LABELS[run.status]}</span>\n {run.durationMs !== undefined && (\n <span>{formatAIDuration(run.durationMs)}</span>\n )}\n </div>\n <Heading\n id={headingId}\n className=\"min-w-0 truncate text-base font-semibold text-foreground\"\n >\n {run.header.title}\n </Heading>\n {run.header.description && (\n <p className=\"line-clamp-2 text-sm text-secondary-foreground\">\n {run.header.description}\n </p>\n )}\n {run.header.metadata && run.header.metadata.length > 0 && (\n <dl className=\"flex flex-wrap gap-x-3 gap-y-1 text-xs text-secondary-foreground\">\n {run.header.metadata.map((item, index) => (\n <div\n key={`${item.label}-${index}`}\n className=\"flex min-w-0 items-center gap-1\"\n >\n <dt className=\"text-muted-foreground\">{item.label}:</dt>\n <dd className=\"min-w-0 truncate\">{item.value}</dd>\n </div>\n ))}\n </dl>\n )}\n {!isOpen && run.progress && (\n <Progress\n value={run.progress.value}\n label={run.progress.label}\n subLabel={run.progress.meta}\n className={\n run.status === 'paused'\n ? PAUSED_PROGRESS_CLASS_NAME\n : undefined\n }\n />\n )}\n </div>\n <Card.Action>\n <Button\n appearance=\"ghost\"\n variant=\"secondary\"\n size=\"icon-xl\"\n iconOnly\n aria-label={isOpen ? 'Collapse tool run' : 'Expand tool run'}\n aria-expanded={isOpen}\n aria-controls={detailsId}\n onClick={() => setIsOpen(!isOpen)}\n >\n {isOpen ? (\n <ChevronDown aria-hidden=\"true\" />\n ) : (\n <ChevronRight aria-hidden=\"true\" className=\"rtl:rotate-180\" />\n )}\n </Button>\n </Card.Action>\n </Card.Header>\n <Card.Content\n id={detailsId}\n hidden={!isOpen}\n className=\"grid min-w-0 gap-4\"\n >\n {run.progress && (\n <Progress\n value={run.progress.value}\n label={run.progress.label}\n subLabel={run.progress.meta}\n className={\n run.status === 'paused'\n ? PAUSED_PROGRESS_CLASS_NAME\n : undefined\n }\n />\n )}\n {rootError && (\n <div className=\"flex min-w-0 items-start gap-2 rounded-lg border border-destructive/50 bg-destructive/10 p-3\">\n <AlertCircle\n aria-hidden=\"true\"\n className=\"mt-0.5 size-4 shrink-0 text-destructive\"\n />\n <p className=\"min-w-0 text-sm text-destructive\">{rootError}</p>\n </div>\n )}\n <WorkflowStepRenderer\n key={run.runId}\n appearance=\"timeline\"\n steps={workflowSteps}\n activeStepId={run.activeStepId}\n expandedStepIds={expandedStepIds}\n defaultExpandedStepIds={initialExpandedStepIds}\n onExpandedStepIdsChange={onExpandedStepIdsChange}\n renderItems={isOpen}\n />\n </Card.Content>\n {run.actions && run.actions.length > 0 && (\n <Card.Footer className=\"flex flex-wrap gap-2\">\n {run.actions.map((action) => (\n <Button\n key={action.id}\n appearance=\"outline\"\n variant=\"secondary\"\n disabled={action.disabled}\n loading={action.loading}\n aria-label={getActionLabel(action)}\n className=\"min-w-0 w-full max-w-full min-[480px]:w-auto h-auto min-h-9 whitespace-normal break-words [overflow-wrap:anywhere] [&>span]:min-w-0\"\n onClick={() => {\n if (action.disabled || action.loading) return;\n onAction?.({\n runId: run.runId,\n actionId: action.id,\n kind: action.kind,\n });\n }}\n >\n {getActionLabel(action)}\n </Button>\n ))}\n </Card.Footer>\n )}\n </Card>\n {rootError ? (\n <div\n role=\"alert\"\n aria-live=\"assertive\"\n className=\"sr-only left-0 top-0\"\n >\n {rootError}\n </div>\n ) : (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"sr-only left-0 top-0\"\n >\n {politeAnnouncement}\n </div>\n )}\n </section>\n );\n },\n);\n\nAIToolRunPresentation.displayName = 'AIToolRunPresentation';\n\nexport const AIToolRunRuntimeBoundary = React.forwardRef<\n HTMLElement,\n AIToolRunRuntimeBoundaryInput\n>((props, ref) => {\n const {\n run,\n headingLevel,\n open,\n defaultOpen,\n expandedStepIds,\n defaultExpandedStepIds,\n dangerouslySetInnerHTML: unsafeHtml,\n onOpenChange,\n onExpandedStepIdsChange,\n onAction,\n ...sectionProps\n } = props;\n void unsafeHtml;\n const snapshotResult = validateAIToolRunSnapshot(run);\n const viewResult = validateRuntimeViewProps({\n headingLevel,\n open,\n defaultOpen,\n expandedStepIds,\n defaultExpandedStepIds,\n });\n\n if (!snapshotResult.valid || !viewResult.valid) {\n return <InvalidAIToolRun {...sectionProps} ref={ref} />;\n }\n\n return (\n <AIToolRunPresentation\n {...sectionProps}\n {...viewResult.value}\n onOpenChange={onOpenChange}\n onExpandedStepIdsChange={onExpandedStepIdsChange}\n onAction={onAction}\n ref={ref}\n run={snapshotResult.value}\n />\n );\n});\n\n/**\n * Displays one validated AI tool run with lifecycle, progress, sources,\n * disclosure, and action intents.\n *\n * @llms Validated AI tool-run timeline with lifecycle, progress, sources, disclosure, and actions\n */\nexport const AIToolRun = React.forwardRef<HTMLElement, AIToolRunProps>(\n (props, ref) => <AIToolRunRuntimeBoundary {...props} ref={ref} />,\n);\n\nAIToolRunRuntimeBoundary.displayName = 'AIToolRunRuntimeBoundary';\nAIToolRun.displayName = 'AIToolRun';\n"],"mappings":"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"}
package/dist/index187.js CHANGED
@@ -1,266 +1,221 @@
1
- "use client";
2
- import { cn, extractText } from "./index2.js";
1
+ import { cn } from "./index2.js";
2
+ import { Badge } from "./index14.js";
3
+ import { Avatar } from "./index70.js";
4
+ import { FileTypeIcon } from "./index115.js";
3
5
  import { cva } from "class-variance-authority";
4
6
  import * as React from "react";
5
- import { jsx, jsxs } from "react/jsx-runtime";
6
- import { Tooltip } from "@base-ui/react/tooltip";
7
- //#region src/components/organisms/overlays/Tooltip/Tooltip.tsx
8
- var tooltipVariants = cva("data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 motion-reduce:animate-none z-50 w-fit max-w-xs origin-(--transform-origin) px-3 py-1.5 text-xs shadow-[var(--shadow-tooltip)]", {
7
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
+ //#region src/components/organisms/content/ActivityFeed/ActivityFeed.tsx
9
+ var activityFeedVariants = cva("flex flex-col", {
10
+ variants: { divider: {
11
+ divider: "divide-y divide-border",
12
+ connector: "px-6 py-4",
13
+ none: "gap-4"
14
+ } },
15
+ defaultVariants: { divider: "divider" }
16
+ });
17
+ var activityItemVariants = cva("flex gap-3 relative", {
9
18
  variants: {
10
- variant: {
11
- primary: "bg-foreground text-background",
12
- secondary: "bg-secondary text-secondary-foreground border border-border shadow-sm",
13
- info: "bg-info text-primary-foreground",
14
- success: "bg-success text-primary-foreground",
15
- warning: "bg-warning text-primary-foreground",
16
- destructive: "bg-destructive text-primary-foreground"
19
+ type: {
20
+ notifications: "",
21
+ messages: ""
17
22
  },
18
- shape: {
19
- default: "rounded-md",
20
- rounded: "rounded-full"
23
+ divider: {
24
+ divider: "px-4 py-4",
25
+ connector: "pt-0",
26
+ none: "px-4 py-4"
21
27
  }
22
28
  },
23
29
  defaultVariants: {
24
- variant: "primary",
25
- shape: "default"
30
+ type: "notifications",
31
+ divider: "divider"
26
32
  }
27
33
  });
28
- var arrowVariants = cva("size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] z-50 data-[side=bottom]:top-1 data-[side=left]:top-1/2! data-[side=left]:-right-1 data-[side=left]:-translate-y-1/2 data-[side=right]:top-1/2! data-[side=right]:-left-1 data-[side=right]:-translate-y-1/2 data-[side=top]:-bottom-2.5", {
29
- variants: { variant: {
30
- primary: "bg-foreground fill-foreground",
31
- secondary: "bg-secondary fill-secondary",
32
- info: "bg-info fill-info",
33
- success: "bg-success fill-success",
34
- warning: "bg-warning fill-warning",
35
- destructive: "bg-destructive fill-destructive"
36
- } },
37
- defaultVariants: { variant: "primary" }
38
- });
39
- function TooltipProvider({ delay = 0, ...props }) {
40
- return /* @__PURE__ */ jsx(Tooltip.Provider, {
41
- "data-slot": "tooltip-provider",
42
- delay,
43
- ...props
44
- });
45
- }
46
- function TooltipRoot(props) {
47
- return /* @__PURE__ */ jsx(Tooltip.Root, {
48
- "data-slot": "tooltip",
49
- ...props
50
- });
51
- }
52
- var TooltipTrigger = React.forwardRef(function TooltipTrigger(props, ref) {
53
- return /* @__PURE__ */ jsx(Tooltip.Trigger, {
54
- ref,
55
- "data-slot": "tooltip-trigger",
56
- ...props
57
- });
58
- });
59
- function TooltipPopup({ className, side = "top", sideOffset = 4, align = "center", alignOffset = 0, variant = "primary", shape = "default", hideArrow = false, container, children, ...props }) {
60
- return /* @__PURE__ */ jsx(Tooltip.Portal, {
61
- container,
62
- children: /* @__PURE__ */ jsx(Tooltip.Positioner, {
63
- align,
64
- alignOffset,
65
- side,
66
- sideOffset,
67
- className: "isolate z-50",
68
- children: /* @__PURE__ */ jsxs(Tooltip.Popup, {
69
- "data-slot": "tooltip-popup",
70
- className: cn(tooltipVariants({
71
- variant,
72
- shape
73
- }), className),
74
- ...props,
75
- children: [children, !hideArrow && /* @__PURE__ */ jsx(Tooltip.Arrow, { className: arrowVariants({ variant }) })]
76
- })
77
- })
78
- });
79
- }
80
- function TooltipIcon({ children, className }) {
81
- return /* @__PURE__ */ jsx("span", {
82
- "data-slot": "tooltip-icon",
83
- className: cn("shrink-0 [&>svg]:size-4", className),
84
- children
85
- });
86
- }
87
- TooltipIcon.displayName = "Tooltip.Icon";
88
- function TooltipAvatar({ src, alt, children, className }) {
89
- if (children) return /* @__PURE__ */ jsx("span", {
90
- "data-slot": "tooltip-avatar",
91
- className: cn("shrink-0", className),
92
- children
93
- });
94
- return /* @__PURE__ */ jsx("img", {
95
- "data-slot": "tooltip-avatar",
96
- src,
97
- alt,
98
- className: cn("size-4 shrink-0 rounded-full object-cover", className)
99
- });
34
+ function getActivityFeedItemKey(item) {
35
+ return item.id ?? `${item.user.name}:${item.timestamp}:${item.activity.text}:${item.activity.link ?? "no-link"}`;
100
36
  }
101
- TooltipAvatar.displayName = "Tooltip.Avatar";
102
- function TooltipContent({ children, className }) {
103
- return /* @__PURE__ */ jsx("div", {
104
- "data-slot": "tooltip-content",
105
- className: cn("flex flex-col gap-0.5", className),
106
- children
107
- });
37
+ function escapeRegExp(value) {
38
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
108
39
  }
109
- TooltipContent.displayName = "Tooltip.Content";
110
- function TooltipTitle({ children, className }) {
111
- return /* @__PURE__ */ jsx("span", {
112
- "data-slot": "tooltip-title",
113
- className: cn("text-xs font-semibold leading-4", className),
114
- children
115
- });
116
- }
117
- TooltipTitle.displayName = "Tooltip.Title";
118
- function TooltipSubtitle({ children, className, variant = "primary" }) {
119
- return /* @__PURE__ */ jsx("span", {
120
- "data-slot": "tooltip-subtitle",
121
- className: cn("text-xs font-medium leading-4", variant === "secondary" ? "text-muted-foreground" : "text-inherit opacity-70", className),
122
- children
40
+ function getMessageSegments(message, mentions) {
41
+ const mentionSet = /* @__PURE__ */ new Set();
42
+ for (const mention of mentions) {
43
+ const trimmedMention = mention.trim();
44
+ if (trimmedMention) mentionSet.add(trimmedMention);
45
+ }
46
+ const uniqueMentions = Array.from(mentionSet);
47
+ if (uniqueMentions.length === 0) return [];
48
+ const mentionPattern = new RegExp(`@(?:${uniqueMentions.map(escapeRegExp).join("|")})`, "gi");
49
+ const segments = [];
50
+ let cursor = 0;
51
+ for (const match of message.matchAll(mentionPattern)) {
52
+ const start = match.index ?? 0;
53
+ const text = match[0];
54
+ const end = start + text.length;
55
+ if (start > cursor) segments.push({
56
+ key: `text:${cursor}:${start}`,
57
+ text: message.slice(cursor, start),
58
+ isMention: false
59
+ });
60
+ segments.push({
61
+ key: `mention:${start}:${end}:${text.toLowerCase()}`,
62
+ text,
63
+ isMention: true
64
+ });
65
+ cursor = end;
66
+ }
67
+ if (cursor < message.length) segments.push({
68
+ key: `text:${cursor}:${message.length}`,
69
+ text: message.slice(cursor),
70
+ isMention: false
123
71
  });
72
+ return segments;
124
73
  }
125
- TooltipSubtitle.displayName = "Tooltip.Subtitle";
126
- function TooltipBadge({ children, className }) {
127
- return /* @__PURE__ */ jsx("span", {
128
- "data-slot": "tooltip-badge",
129
- className: cn("shrink-0", className),
130
- children
131
- });
74
+ function ActivityFeedMessageContent({ message, mentions }) {
75
+ if (!mentions || mentions.length === 0) return /* @__PURE__ */ jsx(Fragment, { children: `"${message}"` });
76
+ return /* @__PURE__ */ jsx(Fragment, { children: getMessageSegments(message, mentions).map((segment) => /* @__PURE__ */ jsx("span", {
77
+ className: segment.isMention ? "font-semibold text-primary" : void 0,
78
+ children: segment.text
79
+ }, segment.key)) });
132
80
  }
133
- TooltipBadge.displayName = "Tooltip.Badge";
134
- function TooltipImage({ src, alt, layout = "vertical", className }) {
135
- return /* @__PURE__ */ jsx("img", {
136
- "data-slot": "tooltip-image",
137
- src,
138
- alt,
139
- className: cn("rounded-md object-cover", layout === "vertical" ? "w-full h-20" : "w-20 h-14 shrink-0", className)
140
- });
81
+ function ActivityFeedItemContent({ content, expanded }) {
82
+ if (!content || expanded === false) return null;
83
+ switch (content.type) {
84
+ case "file": return /* @__PURE__ */ jsxs("div", {
85
+ className: "group/file flex gap-3 items-start w-full mt-3 rounded-lg transition-[background-color,transform] duration-150 ease-out motion-reduce:transition-none hover:bg-muted/40 active:scale-[0.99] motion-reduce:active:scale-100 cursor-default",
86
+ children: [/* @__PURE__ */ jsx(FileTypeIcon, {
87
+ extension: content.fileExtension,
88
+ size: "md"
89
+ }), /* @__PURE__ */ jsxs("div", {
90
+ className: "flex flex-col min-w-0 flex-1",
91
+ children: [/* @__PURE__ */ jsx("p", {
92
+ className: "text-sm font-medium text-secondary-foreground truncate",
93
+ children: content.fileName
94
+ }), /* @__PURE__ */ jsx("p", {
95
+ className: "text-sm text-muted-foreground",
96
+ children: content.fileSize
97
+ })]
98
+ })]
99
+ });
100
+ case "message": return /* @__PURE__ */ jsx("div", {
101
+ className: "mt-3 border border-border rounded-ee-md rounded-es-md rounded-se-md p-3 shadow-xs w-full transition-shadow duration-200 ease-out hover:shadow-sm motion-reduce:transition-none",
102
+ children: /* @__PURE__ */ jsx("p", {
103
+ className: "text-sm text-secondary-foreground",
104
+ children: /* @__PURE__ */ jsx(ActivityFeedMessageContent, {
105
+ message: content.message,
106
+ mentions: content.mentions
107
+ })
108
+ })
109
+ });
110
+ case "labels": return /* @__PURE__ */ jsx("div", {
111
+ className: "flex flex-wrap gap-1 mt-3",
112
+ children: content.labels.map((label, i) => /* @__PURE__ */ jsx(Badge, {
113
+ variant: "outline",
114
+ color: label.color || "primary",
115
+ size: "sm",
116
+ className: "delight-stagger transition-transform duration-150 ease-out motion-reduce:transition-none hover:scale-105 motion-reduce:hover:scale-100",
117
+ style: { "--delight-delay": `${i * 50}ms` },
118
+ children: label.text
119
+ }, label.text))
120
+ });
121
+ default: return null;
122
+ }
141
123
  }
142
- TooltipImage.displayName = "Tooltip.Image";
143
- function TooltipRenderedContent({ children, content, variant, icon, avatar, subtitle, badge, image, imageLayout, hasRichContent, contentAlt }) {
144
- if (children) return children;
145
- const subtitleElement = subtitle && /* @__PURE__ */ jsx(TooltipSubtitle, {
146
- variant,
147
- children: subtitle
148
- });
149
- if (image) return /* @__PURE__ */ jsxs("div", {
150
- className: cn("flex gap-1.5 delight-tooltip-stagger", imageLayout === "vertical" ? "flex-col" : "flex-row items-center"),
151
- children: [/* @__PURE__ */ jsx(TooltipImage, {
152
- src: image,
153
- alt: contentAlt,
154
- layout: imageLayout,
155
- className: "delight-tooltip-image"
156
- }), /* @__PURE__ */ jsxs(TooltipContent, { children: [/* @__PURE__ */ jsx(TooltipTitle, { children: content }), subtitleElement] })]
157
- });
158
- if (!hasRichContent) return content;
159
- return /* @__PURE__ */ jsxs("div", {
160
- className: "flex items-center gap-1.5 delight-tooltip-stagger",
124
+ var ActivityFeedItem = React.memo(React.forwardRef(({ className, user, timestamp, dateTime, activity, content, unread = false, avatarSize = "lg", divider = "divider", feedType = "notifications", userHandle, expanded, isLast = false, ...props }, ref) => {
125
+ return /* @__PURE__ */ jsxs("article", {
126
+ ref,
127
+ "data-slot": "activity-feed-item",
128
+ "aria-label": `${user.name}: ${activity.text}${activity.link ? ` ${activity.link}` : ""}`,
129
+ className: cn(activityItemVariants({
130
+ type: feedType,
131
+ divider
132
+ }), "transition-colors duration-150 ease-out motion-reduce:transition-none", "hover:bg-muted/30", className),
133
+ ...props,
161
134
  children: [
162
- avatar && (typeof avatar === "string" ? /* @__PURE__ */ jsx(TooltipAvatar, {
163
- src: avatar,
164
- alt: contentAlt
165
- }) : /* @__PURE__ */ jsx(TooltipAvatar, {
166
- alt: contentAlt,
167
- children: avatar
168
- })),
169
- icon && /* @__PURE__ */ jsx(TooltipIcon, { children: icon }),
170
- /* @__PURE__ */ jsxs(TooltipContent, { children: [/* @__PURE__ */ jsx(TooltipTitle, { children: content }), subtitleElement] }),
171
- badge && /* @__PURE__ */ jsx(TooltipBadge, { children: badge })
135
+ /* @__PURE__ */ jsxs("div", {
136
+ className: cn("flex flex-col items-center gap-0.5 self-stretch shrink-0", divider === "connector" && !isLast && "pb-0.5"),
137
+ children: [/* @__PURE__ */ jsx(Avatar, {
138
+ src: user.avatarSrc,
139
+ fallback: user.name,
140
+ size: avatarSize,
141
+ indicator: user.online === true ? "online" : user.online === false ? "offline" : void 0
142
+ }), divider === "connector" && !isLast && /* @__PURE__ */ jsx("div", { className: "flex-1 w-0.5 min-h-4 rounded-sm bg-border delight-connector-grow" })]
143
+ }),
144
+ /* @__PURE__ */ jsxs("div", {
145
+ className: cn("flex flex-col flex-1 min-w-0", divider === "connector" && "pb-8"),
146
+ children: [/* @__PURE__ */ jsxs("div", {
147
+ className: "flex flex-col",
148
+ children: [/* @__PURE__ */ jsxs("div", {
149
+ className: "flex items-center gap-2 flex-wrap",
150
+ children: [
151
+ /* @__PURE__ */ jsx("span", {
152
+ className: "text-sm font-medium text-secondary-foreground",
153
+ children: user.name
154
+ }),
155
+ feedType === "messages" && userHandle && /* @__PURE__ */ jsxs("span", {
156
+ className: "text-sm text-muted-foreground",
157
+ children: ["@", userHandle]
158
+ }),
159
+ dateTime ? /* @__PURE__ */ jsx("time", {
160
+ dateTime,
161
+ className: "text-xs text-muted-foreground",
162
+ children: timestamp
163
+ }) : /* @__PURE__ */ jsx("span", {
164
+ className: "text-xs text-muted-foreground",
165
+ children: timestamp
166
+ })
167
+ ]
168
+ }), /* @__PURE__ */ jsxs("p", {
169
+ className: "text-sm text-muted-foreground",
170
+ children: [activity.text, activity.link && /* @__PURE__ */ jsxs(Fragment, { children: [" ", activity.linkHref ? /* @__PURE__ */ jsx("a", {
171
+ href: activity.linkHref,
172
+ className: "font-medium text-primary hover:text-primary/80 transition-colors duration-150 ease-out focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-1 rounded-sm",
173
+ children: activity.link
174
+ }) : /* @__PURE__ */ jsx("span", {
175
+ className: "font-medium text-secondary-foreground",
176
+ children: activity.link
177
+ })] })]
178
+ })]
179
+ }), /* @__PURE__ */ jsx(ActivityFeedItemContent, {
180
+ content,
181
+ expanded
182
+ })]
183
+ }),
184
+ unread && /* @__PURE__ */ jsx("div", {
185
+ className: "absolute top-2 end-1 size-2.5",
186
+ "aria-hidden": "true",
187
+ children: /* @__PURE__ */ jsx("div", { className: "size-2 rounded-full bg-primary delight-unread-pulse" })
188
+ })
172
189
  ]
173
190
  });
174
- }
175
- var Tooltip$1 = ({ trigger, content, variant = "primary", shape = "default", position = "top", align = "center", delayDuration, sideOffset = 6, icon, avatar, subtitle, badge, image, imageLayout, container, children }) => {
176
- const [triggerElement, setTriggerElement] = React.useState(null);
177
- const [triggerPortalContainer, setTriggerPortalContainer] = React.useState(null);
178
- const setTriggerRef = React.useCallback((element) => {
179
- setTriggerElement((currentElement) => currentElement === element ? currentElement : element);
180
- }, []);
181
- React.useEffect(() => {
182
- const nextContainer = triggerElement?.ownerDocument.body ?? null;
183
- setTriggerPortalContainer((currentContainer) => currentContainer === nextContainer ? currentContainer : nextContainer);
184
- }, [triggerElement]);
185
- const hasRichContent = icon || avatar || subtitle || badge || image;
186
- const resolvedImageLayout = imageLayout ?? "vertical";
187
- const contentAlt = extractText(content);
188
- return /* @__PURE__ */ jsx(TooltipProvider, {
189
- delay: delayDuration,
190
- children: /* @__PURE__ */ jsxs(TooltipRoot, { children: [/* @__PURE__ */ jsx(TooltipTrigger, {
191
- ref: setTriggerRef,
192
- render: trigger
193
- }), /* @__PURE__ */ jsx(TooltipPopup, {
194
- container: container === void 0 ? triggerPortalContainer : container,
195
- side: position === "none" ? "top" : position,
196
- align,
197
- sideOffset,
198
- variant,
199
- shape,
200
- hideArrow: position === "none",
201
- className: cn(hasRichContent && "p-2"),
202
- children: /* @__PURE__ */ jsx(TooltipRenderedContent, {
203
- content,
204
- variant,
205
- icon,
206
- avatar,
207
- subtitle,
208
- badge,
209
- image,
210
- imageLayout: resolvedImageLayout,
211
- hasRichContent,
212
- contentAlt,
213
- children
214
- })
215
- })] })
191
+ }));
192
+ ActivityFeedItem.displayName = "ActivityFeedItem";
193
+ var ActivityFeed = React.forwardRef(({ className, divider = "divider", items, type = "notifications", loading, children, ...props }, ref) => {
194
+ return /* @__PURE__ */ jsx("div", {
195
+ ref,
196
+ "data-slot": "activity-feed",
197
+ role: "feed",
198
+ "aria-label": "Activity feed",
199
+ "aria-busy": loading || void 0,
200
+ className: cn(activityFeedVariants({ divider }), className),
201
+ ...props,
202
+ children: items ? items.map((item, index) => /* @__PURE__ */ jsx(ActivityFeedItem, {
203
+ ...item,
204
+ "aria-setsize": items.length,
205
+ "aria-posinset": index + 1,
206
+ divider: divider ?? "divider",
207
+ feedType: type,
208
+ isLast: index === items.length - 1,
209
+ className: cn("delight-stagger", item.className),
210
+ style: {
211
+ "--delight-delay": `${index * 60}ms`,
212
+ ...item.style
213
+ }
214
+ }, getActivityFeedItemKey(item))) : children
216
215
  });
217
- };
218
- Tooltip$1.displayName = "Tooltip";
219
- TooltipProvider.displayName = "Tooltip.Provider";
220
- TooltipRoot.displayName = "Tooltip.Root";
221
- TooltipTrigger.displayName = "Tooltip.Trigger";
222
- TooltipPopup.displayName = "Tooltip.Popup";
223
- /**
224
- * Tooltip component with dot notation for compound parts.
225
- *
226
- * @example
227
- * ```tsx
228
- * // Simple usage (recommended for most cases)
229
- * <Tooltip trigger={<Button>Hover me</Button>} content="Tooltip text" />
230
- *
231
- * // With variants
232
- * <Tooltip trigger={<Button>Save</Button>} content="Saved!" variant="success" shape="rounded" />
233
- *
234
- * // With rich content
235
- * <Tooltip trigger={<Button>Info</Button>} content="Title" icon={<InfoIcon />} subtitle="Description" />
236
- *
237
- * // Advanced usage with dot notation
238
- * <Tooltip.Root>
239
- * <Tooltip.Trigger render={<Button>Hover me</Button>} />
240
- * <Tooltip.Popup variant="info">
241
- * <Tooltip.Icon><InfoIcon /></Tooltip.Icon>
242
- * <Tooltip.Content>
243
- * <Tooltip.Title>Title</Tooltip.Title>
244
- * <Tooltip.Subtitle>Description</Tooltip.Subtitle>
245
- * </Tooltip.Content>
246
- * </Tooltip.Popup>
247
- * </Tooltip.Root>
248
- * ```
249
- */
250
- var TooltipCompound = Object.assign(Tooltip$1, {
251
- Root: TooltipRoot,
252
- Provider: TooltipProvider,
253
- Trigger: TooltipTrigger,
254
- Popup: TooltipPopup,
255
- Icon: TooltipIcon,
256
- Avatar: TooltipAvatar,
257
- Content: TooltipContent,
258
- Title: TooltipTitle,
259
- Subtitle: TooltipSubtitle,
260
- Badge: TooltipBadge,
261
- Image: TooltipImage
262
216
  });
217
+ ActivityFeed.displayName = "ActivityFeed";
263
218
  //#endregion
264
- export { TooltipCompound as Tooltip, TooltipAvatar, TooltipBadge, TooltipContent, TooltipIcon, TooltipImage, TooltipPopup, TooltipProvider, TooltipRoot, TooltipSubtitle, TooltipTitle, TooltipTrigger, arrowVariants, tooltipVariants };
219
+ export { ActivityFeed, ActivityFeedItem, activityFeedVariants, activityItemVariants };
265
220
 
266
221
  //# sourceMappingURL=index187.js.map