@devalok/shilp-sutra 0.45.0 → 0.46.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.
- package/MIGRATION.md +836 -808
- package/dist/_chunks/chat.js +157 -156
- package/dist/_chunks/chat.js.map +1 -1
- package/dist/_chunks/document-preview.js +5 -5
- package/dist/_chunks/image-preview.js +7 -7
- package/dist/_chunks/mention.js +5 -0
- package/dist/_chunks/mention.js.map +1 -0
- package/dist/_chunks/success.js +16 -16
- package/dist/composed/activity-feed.js +19 -19
- package/dist/composed/deadline-indicator.d.ts.map +1 -1
- package/dist/composed/deadline-indicator.js +31 -31
- package/dist/composed/deadline-indicator.js.map +1 -1
- package/dist/composed/emoji-picker.js +15 -15
- package/dist/composed/file-preview/video-preview.d.ts.map +1 -1
- package/dist/composed/file-preview.js +36 -34
- package/dist/composed/file-preview.js.map +1 -1
- package/dist/composed/filter-bar.js +1 -1
- package/dist/composed/filter-bar.js.map +1 -1
- package/dist/composed/multi-select-popover.js +1 -1
- package/dist/composed/multi-select-popover.js.map +1 -1
- package/dist/composed/rich-chat-input.d.ts.map +1 -1
- package/dist/composed/rich-chat-input.js +514 -503
- package/dist/composed/rich-chat-input.js.map +1 -1
- package/dist/composed/rich-text-editor.d.ts.map +1 -1
- package/dist/composed/rich-text-editor.js +144 -143
- package/dist/composed/rich-text-editor.js.map +1 -1
- package/dist/tokens/base.css +6 -0
- package/dist/tokens/index.css +1 -1
- package/dist/tokens/semantic.css +1 -1
- package/dist/tokens/typography.css +10 -0
- package/dist/tokens/utilities.css +6 -0
- package/dist/ui/avatar.d.ts.map +1 -1
- package/dist/ui/avatar.js +57 -56
- package/dist/ui/avatar.js.map +1 -1
- package/dist/ui/badge-indicator.js +1 -1
- package/dist/ui/badge-indicator.js.map +1 -1
- package/dist/ui/chat/message.d.ts.map +1 -1
- package/dist/ui/data-table-body.js +27 -27
- package/dist/ui/data-table-card.js +20 -20
- package/dist/ui/data-table-toolbar.d.ts.map +1 -1
- package/dist/ui/data-table-toolbar.js +40 -36
- package/dist/ui/data-table-toolbar.js.map +1 -1
- package/dist/ui/index.d.ts +1 -0
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +37 -36
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/lib/mention.d.ts +11 -0
- package/dist/ui/lib/mention.d.ts.map +1 -0
- package/dist/ui/radio.js +1 -1
- package/dist/ui/radio.js.map +1 -1
- package/dist/ui/sidebar.js +7 -7
- package/dist/ui/stat-card.d.ts.map +1 -1
- package/dist/ui/stat-card.js +48 -47
- package/dist/ui/stat-card.js.map +1 -1
- package/dist/ui/surface.d.ts +46 -0
- package/dist/ui/surface.d.ts.map +1 -0
- package/dist/ui/surface.js +51 -0
- package/dist/ui/surface.js.map +1 -0
- package/dist/ui/text.js +6 -6
- package/dist/ui/text.js.map +1 -1
- package/docs/components/ui/chat.md +1 -1
- package/docs/components/ui/surface.md +55 -0
- package/fonts/Manrope-Variable.woff2 +0 -0
- package/llms.txt +2 -1
- package/make-kit/components/overview.md +7 -3
- package/make-kit/components/surface.md +60 -0
- package/mcp-manifest.json +91 -2
- package/package.json +11 -1
- package/skill/SKILL.md +1 -1
- package/skill/references/components.md +2 -1
package/dist/_chunks/chat.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chat.js","names":[],"sources":["../../src/ui/chat/date-separator.tsx","../../src/ui/chat/message.tsx","../../src/ui/chat/message-input.tsx","../../src/ui/chat/message-list.tsx","../../src/ui/chat/system-message.tsx","../../src/ui/chat/typing-indicator.tsx","../../src/ui/chat/unread-separator.tsx"],"sourcesContent":["import * as React from 'react'\n\nimport { cn } from '../lib/utils'\n\nexport interface DateSeparatorProps {\n date: Date | string\n format?: (date: Date) => string\n className?: string\n}\n\nfunction defaultFormat(date: Date): string {\n const now = new Date()\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())\n const target = new Date(date.getFullYear(), date.getMonth(), date.getDate())\n const diffMs = today.getTime() - target.getTime()\n const diffDays = Math.round(diffMs / (1000 * 60 * 60 * 24))\n\n if (diffDays === 0) return 'Today'\n if (diffDays === 1) return 'Yesterday'\n\n const month = date.toLocaleString('en-US', { month: 'short' })\n const day = date.getDate()\n\n if (date.getFullYear() !== now.getFullYear()) {\n return `${month} ${day}, ${date.getFullYear()}`\n }\n\n return `${month} ${day}`\n}\n\nfunction DateSeparator({ date, format, className }: DateSeparatorProps) {\n const d = typeof date === 'string' ? new Date(date) : date\n const label = format ? format(d) : defaultFormat(d)\n\n return (\n <div className={cn('flex items-center gap-ds-03 py-ds-03', className)}>\n <div className=\"flex-1 border-t border-surface-border-subtle\" />\n <span className=\"text-ds-xs font-medium text-surface-fg-subtle/50 uppercase tracking-wider\">\n {label}\n </span>\n <div className=\"flex-1 border-t border-surface-border-subtle\" />\n </div>\n )\n}\nDateSeparator.displayName = 'DateSeparator'\n\nexport { DateSeparator }\n","'use client'\n\nimport { IconTrash } from '@tabler/icons-react'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { Avatar, AvatarFallback,AvatarImage } from '../avatar'\nimport { Icon } from '../icon'\nimport { IconProvider } from '../icon-context'\nimport type { IconInput } from '../lib/icon-input'\nimport { motionProps,springs } from '../lib/motion'\nimport { normalizeIcon } from '../lib/normalize-icon'\nimport { cn } from '../lib/utils'\nimport { Textarea } from '../textarea'\nimport { Tooltip, TooltipContent,TooltipTrigger } from '../tooltip'\n\n// ── Context ──────────────────────────────────────────────────────────────\n\ninterface MessageContextValue {\n variant: 'flat' | 'bubble'\n placement: 'start' | 'end'\n grouped: boolean\n highlight?: 'mention' | 'internal'\n}\n\nconst MessageContext = React.createContext<MessageContextValue>({\n variant: 'flat',\n placement: 'start',\n grouped: false,\n})\n\nfunction useMessageContext() {\n return React.useContext(MessageContext)\n}\n\n// ── Root ─────────────────────────────────────────────────────────────────\n\nexport interface MessageProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n variant?: 'flat' | 'bubble'\n placement?: 'start' | 'end'\n highlight?: 'mention' | 'internal'\n grouped?: boolean\n deleted?: boolean\n deletedText?: string\n}\n\nconst MessageRoot = React.forwardRef<HTMLDivElement, MessageProps>(\n (\n {\n children,\n variant = 'flat',\n placement = 'start',\n highlight,\n grouped = false,\n deleted = false,\n deletedText = 'This message was deleted',\n className,\n ...props\n },\n ref,\n ) => {\n const ctx = React.useMemo<MessageContextValue>(\n () => ({ variant, placement, grouped, highlight }),\n [variant, placement, grouped, highlight],\n )\n\n if (deleted) {\n return (\n <motion.div\n ref={ref}\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n transition={springs.snappy}\n className={cn(\n 'flex items-center gap-ds-02 py-ds-02 text-ds-xs text-surface-fg-subtle/50 italic',\n className,\n )}\n {...motionProps(props)}\n >\n <Icon icon={IconTrash} size=\"xs\" />\n {deletedText}\n </motion.div>\n )\n }\n\n if (variant === 'bubble') {\n return (\n <MessageContext.Provider value={ctx}>\n <motion.div\n ref={ref}\n data-highlight={highlight}\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n transition={springs.snappy}\n className={cn(\n 'group/message relative flex',\n placement === 'end' ? 'justify-end' : 'justify-start',\n // mention is carried by the in-content @token, not a row tint/rail\n highlight === 'internal' && 'bg-warning-2/50 rounded-control-inner',\n className,\n )}\n {...motionProps(props)}\n >\n <div\n className={cn(\n 'max-w-[85%] rounded-bubble px-ds-04 py-ds-03',\n placement === 'end'\n ? 'bg-accent-3 text-surface-fg'\n : 'bg-surface-raised text-surface-fg',\n )}\n >\n {children}\n </div>\n </motion.div>\n </MessageContext.Provider>\n )\n }\n\n // flat variant (default)\n return (\n <MessageContext.Provider value={ctx}>\n <motion.div\n ref={ref}\n data-highlight={highlight}\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n transition={springs.snappy}\n className={cn(\n 'group/message relative flex gap-ds-04',\n grouped && '-mt-ds-01',\n // mention is carried by the in-content @token, not a row rail/tint\n highlight === 'internal' && 'bg-warning-2/50 rounded-control-inner',\n className,\n )}\n {...motionProps(props)}\n >\n {children}\n </motion.div>\n </MessageContext.Provider>\n )\n },\n)\nMessageRoot.displayName = 'Message'\n\n// ── Avatar ───────────────────────────────────────────────────────────────\n\nexport interface MessageAvatarProps {\n src?: string | null\n fallback?: string\n icon?: IconInput\n size?: 'sm' | 'md'\n children?: React.ReactNode\n}\n\nfunction MessageAvatar({\n src,\n fallback,\n icon,\n size = 'md',\n children,\n}: MessageAvatarProps) {\n const { grouped } = useMessageContext()\n\n const sizeClass = size === 'sm' ? 'w-5' : 'w-6'\n const heightClass = size === 'sm' ? 'h-5' : 'h-6'\n\n if (grouped) {\n return <div className={cn(sizeClass, heightClass, 'shrink-0')} />\n }\n\n if (children) {\n return (\n <div className={cn(sizeClass, 'shrink-0 flex items-start')}>\n {children}\n </div>\n )\n }\n\n if (icon) {\n return (\n <div\n className={cn(\n sizeClass,\n size === 'sm' ? 'h-5' : 'h-6',\n 'shrink-0 flex items-center justify-center rounded-pill bg-surface-raised-hover',\n )}\n >\n <IconProvider size={size === 'sm' ? 'xs' : 'sm'}>{normalizeIcon(icon)}</IconProvider>\n </div>\n )\n }\n\n return (\n <div className={cn(sizeClass, 'shrink-0')}>\n <Avatar size={size === 'sm' ? 'xs' : 'sm'}>\n {src && <AvatarImage src={src} alt={fallback ?? ''} />}\n <AvatarFallback>{fallback ?? ''}</AvatarFallback>\n </Avatar>\n </div>\n )\n}\nMessageAvatar.displayName = 'Message.Avatar'\n\n// ── Content ──────────────────────────────────────────────────────────────\n\nexport interface MessageContentProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n}\n\nfunction MessageContent({ children, className, ...props }: MessageContentProps) {\n return (\n <div className={cn('min-w-0 flex-1 flex flex-col gap-ds-02', className)} {...props}>\n {children}\n </div>\n )\n}\nMessageContent.displayName = 'Message.Content'\n\n// ── Author ───────────────────────────────────────────────────────────────\n\nexport interface MessageAuthorProps {\n name: string\n badge?: React.ReactNode\n timestamp?: Date\n formattedTimestamp?: string\n timestampFormat?: (date: Date) => string\n}\n\nfunction defaultTimestampFormat(date: Date): string {\n return date.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' })\n}\n\nfunction MessageAuthor({\n name,\n badge,\n timestamp,\n formattedTimestamp,\n timestampFormat = defaultTimestampFormat,\n}: MessageAuthorProps) {\n const { grouped } = useMessageContext()\n\n if (grouped) return null\n\n const timeStr = formattedTimestamp\n ?? (timestamp ? timestampFormat(timestamp) : undefined)\n\n return (\n <div className=\"flex items-baseline gap-ds-02\">\n <span className=\"font-semibold text-[13px] text-surface-fg\">{name}</span>\n {badge}\n {timeStr && (\n <span className=\"text-[11px] text-surface-fg-subtle/50\">{timeStr}</span>\n )}\n </div>\n )\n}\nMessageAuthor.displayName = 'Message.Author'\n\n// ── Body ─────────────────────────────────────────────────────────────────\n\nexport interface MessageBodyProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n}\n\nfunction MessageBody({ children, className, ...props }: MessageBodyProps) {\n return (\n <div\n className={cn(\n 'text-[13px] leading-relaxed text-surface-fg whitespace-pre-wrap',\n className,\n )}\n {...props}\n >\n {children}\n </div>\n )\n}\nMessageBody.displayName = 'Message.Body'\n\n// ── EditableBody ─────────────────────────────────────────────────────────\n\nexport interface MessageEditableBodyProps {\n content: string\n onSave: (newContent: string) => void\n onCancel?: () => void\n canEdit?: boolean\n renderContent?: (content: string) => React.ReactNode\n}\n\nfunction MessageEditableBody({\n content,\n onSave,\n onCancel,\n canEdit = false,\n renderContent,\n}: MessageEditableBodyProps) {\n const [isEditing, setIsEditing] = React.useState(false)\n const [editDraft, setEditDraft] = React.useState(content)\n const textareaRef = React.useRef<HTMLTextAreaElement>(null)\n\n React.useEffect(() => {\n if (isEditing && textareaRef.current) {\n textareaRef.current.focus()\n textareaRef.current.select()\n }\n }, [isEditing])\n\n const handleStartEdit = React.useCallback(() => {\n if (!canEdit) return\n setEditDraft(content)\n setIsEditing(true)\n }, [canEdit, content])\n\n const handleSave = React.useCallback(() => {\n const trimmed = editDraft.trim()\n if (trimmed && trimmed !== content) {\n onSave(trimmed)\n }\n setIsEditing(false)\n }, [editDraft, content, onSave])\n\n const handleCancel = React.useCallback(() => {\n setIsEditing(false)\n setEditDraft(content)\n onCancel?.()\n }, [content, onCancel])\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n handleSave()\n } else if (e.key === 'Escape') {\n e.preventDefault()\n handleCancel()\n }\n },\n [handleSave, handleCancel],\n )\n\n if (isEditing) {\n return (\n <div className=\"text-[13px] leading-relaxed\">\n <Textarea\n ref={textareaRef}\n value={editDraft}\n onChange={(e) => setEditDraft(e.target.value)}\n onKeyDown={handleKeyDown}\n onBlur={handleSave}\n // compact inline-edit overrides on top of the Textarea base\n className=\"resize-none rounded-control-inner bg-surface-raised-hover px-ds-02 py-ds-01 text-[13px] leading-relaxed\"\n rows={2}\n />\n <div className=\"mt-ds-01 text-ds-xs text-surface-fg-subtle/50\">\n Enter to save · Escape to cancel\n </div>\n </div>\n )\n }\n\n return (\n <div\n className={cn(\n 'text-[13px] leading-relaxed text-surface-fg whitespace-pre-wrap',\n canEdit && 'cursor-pointer hover:bg-surface-raised-hover rounded-control-inner transition-colors',\n )}\n onClick={handleStartEdit}\n role={canEdit ? 'button' : undefined}\n tabIndex={canEdit ? 0 : undefined}\n onKeyDown={\n canEdit\n ? (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleStartEdit()\n }\n }\n : undefined\n }\n >\n {renderContent ? renderContent(content) : content}\n </div>\n )\n}\nMessageEditableBody.displayName = 'Message.EditableBody'\n\n// ── Reactions ────────────────────────────────────────────────────────────\n\nexport interface MessageReactionsProps {\n reactions: { emoji: string; count: number; reacted: boolean }[]\n onReact: (emoji: string) => void\n}\n\nfunction MessageReactions({ reactions, onReact }: MessageReactionsProps) {\n if (reactions.length === 0) return null\n\n return (\n <div className=\"flex flex-wrap gap-ds-02 mt-ds-03\">\n {reactions.map((r) => (\n <button\n key={r.emoji}\n type=\"button\"\n onClick={() => onReact(r.emoji)}\n aria-label={`${r.emoji} ${r.count} reaction${r.count !== 1 ? 's' : ''}${r.reacted ? ', you reacted' : ''}`}\n className={cn(\n 'inline-flex items-center gap-ds-01 rounded-pill px-ds-02 py-ds-01 text-ds-xs transition-colors',\n r.reacted\n ? 'bg-accent-3 ring-1 ring-accent-6'\n : 'bg-surface-raised-hover hover:bg-surface-raised-active',\n )}\n >\n <span>{r.emoji}</span>\n <span>{r.count}</span>\n </button>\n ))}\n </div>\n )\n}\nMessageReactions.displayName = 'Message.Reactions'\n\n// ── Actions (floating toolbar) ───────────────────────────────────────────\n\nexport interface MessageActionsProps {\n children: React.ReactNode\n delay?: number\n}\n\nfunction MessageActions({ children, delay = 100 }: MessageActionsProps) {\n return (\n <div\n className={cn(\n 'absolute -top-2 right-0 z-10',\n 'flex items-center gap-ds-01 rounded-control bg-surface-raised px-ds-01 py-ds-01 shadow-raised',\n 'opacity-0 group-hover/message:opacity-100 group-focus-within/message:opacity-100 transition-opacity duration-150',\n )}\n style={{ transitionDelay: `${delay}ms` }}\n >\n {children}\n </div>\n )\n}\nMessageActions.displayName = 'Message.Actions'\n\n// ── Action (single icon button) ──────────────────────────────────────────\n\nexport interface MessageActionProps {\n icon: IconInput\n label: string\n onClick: () => void\n variant?: 'default' | 'danger'\n}\n\nfunction MessageAction({\n icon,\n label,\n onClick,\n variant = 'default',\n}: MessageActionProps) {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={label}\n className={cn(\n 'p-ds-02 rounded-control-inner transition-colors',\n variant === 'default' &&\n 'text-surface-fg-subtle hover:text-surface-fg hover:bg-surface-raised-hover',\n variant === 'danger' &&\n 'text-surface-fg-subtle hover:text-error-11 hover:bg-surface-raised-hover',\n )}\n >\n <IconProvider size=\"xs\">{normalizeIcon(icon)}</IconProvider>\n </button>\n </TooltipTrigger>\n <TooltipContent>{label}</TooltipContent>\n </Tooltip>\n )\n}\nMessageAction.displayName = 'Message.Action'\n\n// ── Compound Export ──────────────────────────────────────────────────────\n\nexport const Message = Object.assign(MessageRoot, {\n Avatar: MessageAvatar,\n Content: MessageContent,\n Author: MessageAuthor,\n Body: MessageBody,\n EditableBody: MessageEditableBody,\n Reactions: MessageReactions,\n Actions: MessageActions,\n Action: MessageAction,\n})\n\nexport {\n type MessageContextValue,\n useMessageContext,\n}\n","'use client'\n\nimport { IconSend, IconSquare } from '@tabler/icons-react'\nimport * as React from 'react'\n\nimport { Button } from '../button'\nimport { Icon } from '../icon'\nimport { cn } from '../lib/utils'\n\nexport interface MessageInputProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onSubmit'> {\n onSubmit: (text: string) => void\n placeholder?: string\n disabled?: boolean\n isStreaming?: boolean\n onCancel?: () => void\n leadingSlot?: React.ReactNode\n trailingSlot?: React.ReactNode\n disclaimer?: string\n sendIcon?: React.ReactNode\n}\n\nconst MessageInput = React.forwardRef<HTMLDivElement, MessageInputProps>(\n (\n {\n onSubmit,\n placeholder = 'Type a message...',\n disabled = false,\n isStreaming = false,\n onCancel,\n leadingSlot,\n trailingSlot,\n disclaimer,\n sendIcon,\n className,\n ...props\n },\n ref,\n ) => {\n const [text, setText] = React.useState('')\n const textareaRef = React.useRef<HTMLTextAreaElement>(null)\n\n const resize = React.useCallback(() => {\n const el = textareaRef.current\n if (!el) return\n el.style.height = 'auto'\n el.style.height = `${Math.min(el.scrollHeight, 160)}px`\n }, [])\n\n const handleChange = React.useCallback(\n (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setText(e.target.value)\n resize()\n },\n [resize],\n )\n\n const handleSend = React.useCallback(() => {\n const trimmed = text.trim()\n if (!trimmed || isStreaming) return\n onSubmit(trimmed)\n setText('')\n // Reset height after clearing\n if (textareaRef.current) {\n textareaRef.current.style.height = 'auto'\n }\n }, [text, isStreaming, onSubmit])\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n if (!isStreaming) {\n handleSend()\n }\n }\n },\n [isStreaming, handleSend],\n )\n\n const isEmpty = text.trim().length === 0\n\n return (\n <div\n ref={ref}\n className={cn(\n 'border-t border-surface-border-subtle px-ds-05 py-ds-04',\n className,\n )}\n {...props}\n >\n <div className=\"flex items-end gap-ds-02 rounded-overlay-lg border border-surface-border bg-surface-base p-ds-03\">\n {leadingSlot}\n <textarea\n ref={textareaRef}\n value={text}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n aria-label={placeholder || 'Type a message'}\n disabled={disabled}\n rows={1}\n className=\"flex-1 resize-none bg-transparent px-ds-02 py-ds-01 text-ds-sm text-surface-fg placeholder:text-surface-fg-subtle/50 focus:outline-hidden disabled:opacity-50\"\n style={{ maxHeight: 160 }}\n />\n {isStreaming ? (\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n color=\"error\"\n onClick={onCancel}\n aria-label=\"Stop\"\n >\n <Icon icon={IconSquare} size=\"sm\" />\n </Button>\n ) : (\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={handleSend}\n disabled={isEmpty || disabled}\n aria-label=\"Send\"\n >\n {sendIcon ?? <Icon icon={IconSend} size=\"sm\" />}\n </Button>\n )}\n {trailingSlot}\n </div>\n {disclaimer && (\n <p className=\"mt-ds-02 text-center text-ds-xs text-surface-fg-subtle/50\">\n {disclaimer}\n </p>\n )}\n </div>\n )\n },\n)\nMessageInput.displayName = 'MessageInput'\n\nexport { MessageInput }\n","'use client'\n\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { tweens } from '../lib/motion'\nimport { cn } from '../lib/utils'\nimport { Spinner } from '../spinner'\n\nexport interface MessageListProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n /** Auto-scroll to bottom when new content arrives (default true) */\n autoScroll?: boolean\n /** Number of new messages to show in the floating pill */\n newMessageCount?: number\n /** Called when user clicks the \"N new\" pill */\n onScrollToBottom?: () => void\n /** Called when user scrolls near the top — triggers load-more */\n onLoadMore?: () => void\n /** Whether more messages are currently being loaded */\n loadingMore?: boolean\n /** Content to render when there are no children */\n emptySlot?: React.ReactNode\n /** Custom scroll-to-bottom button (unused slot for future override) */\n scrollToBottomSlot?: React.ReactNode\n /** Content rendered above the scroll container (e.g. channel name) */\n headerSlot?: React.ReactNode\n}\n\nconst MessageList = React.forwardRef<HTMLDivElement, MessageListProps>(\n (\n {\n children,\n autoScroll = true,\n newMessageCount = 0,\n onScrollToBottom,\n onLoadMore,\n loadingMore = false,\n emptySlot,\n scrollToBottomSlot,\n headerSlot,\n className,\n ...props\n },\n ref,\n ) => {\n const scrollRef = React.useRef<HTMLDivElement>(null)\n const isAtBottomRef = React.useRef(true)\n const [isAtBottom, setIsAtBottom] = React.useState(true)\n const loadingMoreRef = React.useRef(false)\n const prevScrollHeightRef = React.useRef(0)\n\n const isEmpty = React.Children.count(children) === 0 && !loadingMore\n\n // ── Scroll handler ────────────────────────────────────────────\n const handleScroll = React.useCallback(() => {\n const el = scrollRef.current\n if (!el) return\n\n const atBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 40\n isAtBottomRef.current = atBottom\n setIsAtBottom(atBottom)\n\n // Load more when near top\n if (el.scrollTop < 100 && onLoadMore && !loadingMoreRef.current) {\n loadingMoreRef.current = true\n prevScrollHeightRef.current = el.scrollHeight\n onLoadMore()\n }\n }, [onLoadMore])\n\n // ── Auto-scroll to bottom when children change ────────────────\n React.useLayoutEffect(() => {\n const el = scrollRef.current\n if (!el) return\n\n // Scroll preservation after load-more\n if (loadingMoreRef.current) {\n const newScrollHeight = el.scrollHeight\n el.scrollTop = newScrollHeight - prevScrollHeightRef.current\n loadingMoreRef.current = false\n return\n }\n\n // Auto-scroll if user was at bottom\n if (autoScroll && isAtBottomRef.current) {\n el.scrollTo({ top: el.scrollHeight, behavior: 'smooth' })\n }\n }, [children, autoScroll])\n\n // ── Reset loading flag when loadingMore goes false ──────────\n React.useEffect(() => {\n if (!loadingMore) {\n loadingMoreRef.current = false\n }\n }, [loadingMore])\n\n // ── \"N new\" pill visibility ───────────────────────────────────\n const showNewPill = newMessageCount > 0 && !isAtBottom\n\n const handleScrollToBottom = React.useCallback(() => {\n const el = scrollRef.current\n if (el) {\n el.scrollTo({ top: el.scrollHeight, behavior: 'smooth' })\n }\n onScrollToBottom?.()\n }, [onScrollToBottom])\n\n return (\n <div\n ref={ref}\n className={cn('relative flex flex-1 flex-col overflow-hidden', className)}\n {...props}\n >\n {headerSlot}\n <div\n ref={scrollRef}\n role=\"log\"\n aria-live=\"polite\"\n aria-relevant=\"additions\"\n className=\"flex-1 overflow-y-auto px-ds-05 py-ds-04\"\n style={{\n scrollbarWidth: 'thin',\n scrollbarColor: 'var(--color-surface-border) transparent',\n }}\n onScroll={handleScroll}\n >\n {loadingMore && (\n <div className=\"flex justify-center py-ds-03\">\n <Spinner size=\"sm\" />\n </div>\n )}\n {isEmpty ? (\n emptySlot\n ) : (\n <div className=\"flex flex-col gap-ds-04\">\n <AnimatePresence initial={false}>{children}</AnimatePresence>\n </div>\n )}\n </div>\n\n {/* \"N new\" floating pill */}\n <AnimatePresence>\n {showNewPill && (\n <motion.button\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 10 }}\n transition={tweens.fade}\n onClick={handleScrollToBottom}\n className=\"absolute bottom-ds-04 left-1/2 z-10 -translate-x-1/2 rounded-pill bg-accent-9 px-ds-04 py-ds-02 text-ds-xs font-medium text-accent-fg shadow-raised transition-colors hover:bg-accent-10\"\n >\n {newMessageCount} new\n </motion.button>\n )}\n </AnimatePresence>\n </div>\n )\n },\n)\nMessageList.displayName = 'MessageList'\n\nexport { MessageList }\n","'use client'\n\nimport { IconAlertCircle } from '@tabler/icons-react'\nimport * as React from 'react'\n\nimport { Icon } from '../icon'\nimport { IconProvider } from '../icon-context'\nimport type { IconInput } from '../lib/icon-input'\nimport { normalizeIcon } from '../lib/normalize-icon'\nimport { cn } from '../lib/utils'\n\nexport interface SystemMessageProps extends React.HTMLAttributes<HTMLDivElement> {\n icon?: IconInput\n timestamp?: string\n variant?: 'event' | 'alert'\n children: React.ReactNode\n}\n\nfunction formatTime(ts: string): string {\n return new Date(ts).toLocaleTimeString('en-US', {\n hour: 'numeric',\n minute: '2-digit',\n })\n}\n\nconst SystemMessage = React.forwardRef<HTMLDivElement, SystemMessageProps>(\n ({ icon, timestamp, variant = 'event', children, className, ...props }, ref) => {\n if (variant === 'alert') {\n return (\n <div\n ref={ref}\n role=\"alert\"\n className={cn('flex justify-center', className)}\n {...props}\n >\n <div className=\"flex items-center gap-ds-03 rounded-surface bg-error-3 px-ds-04 py-ds-03\">\n <IconProvider size=\"sm\">{normalizeIcon(icon) ?? <Icon icon={IconAlertCircle} />}</IconProvider>\n <span className=\"text-ds-sm text-error-11\">{children}</span>\n {timestamp && (\n <span className=\"text-ds-sm text-error-11/60\">\n {formatTime(timestamp)}\n </span>\n )}\n </div>\n </div>\n )\n }\n\n // event variant (default)\n return (\n <div\n ref={ref}\n className={cn(\n 'flex items-center gap-ds-02 rounded-control-inner bg-surface-raised-hover/30 px-ds-02 py-ds-01 -mx-ds-02 text-ds-sm text-surface-fg-subtle/60',\n className,\n )}\n {...props}\n >\n <IconProvider size=\"xs\">{normalizeIcon(icon)}</IconProvider>\n <span className=\"flex-1\">{children}</span>\n {timestamp && <span>{formatTime(timestamp)}</span>}\n </div>\n )\n },\n)\nSystemMessage.displayName = 'SystemMessage'\n\nexport { SystemMessage }\n","'use client'\n\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { cn } from '../lib/utils'\n\nexport interface TypingIndicatorProps {\n users: { name: string; image?: string }[]\n className?: string\n}\n\nfunction formatTypingText(users: { name: string }[]): string {\n if (users.length === 1) return `${users[0].name} is typing...`\n if (users.length === 2) return `${users[0].name} and ${users[1].name} are typing...`\n return 'Several people are typing...'\n}\n\nfunction TypingIndicator({ users, className }: TypingIndicatorProps) {\n return (\n <div className={cn('min-h-[24px] px-ds-05', className)} role=\"status\" aria-live=\"polite\">\n <AnimatePresence>\n {users.length > 0 && (\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n className=\"flex items-center gap-ds-02 text-ds-xs text-surface-fg-subtle\"\n >\n <span className=\"flex items-center gap-ds-01\">\n {[0, 1, 2].map((i) => (\n <motion.span\n key={i}\n className=\"h-1 w-1 rounded-pill bg-surface-fg-subtle\"\n animate={{ y: [0, -3, 0] }}\n transition={{\n duration: 0.5,\n repeat: Infinity,\n delay: i * 0.15,\n }}\n />\n ))}\n </span>\n <span>{formatTypingText(users)}</span>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n )\n}\nTypingIndicator.displayName = 'TypingIndicator'\n\nexport { TypingIndicator }\n","import * as React from 'react'\n\nimport { cn } from '../lib/utils'\n\nexport interface UnreadSeparatorProps {\n label?: string\n count?: number\n className?: string\n}\n\nfunction UnreadSeparator({\n label = 'NEW',\n count,\n className,\n}: UnreadSeparatorProps) {\n return (\n <div className={cn('relative flex items-center py-ds-02', className)}>\n <div className=\"flex-1 border-t-2 border-accent-7\" />\n <span className=\"px-ds-03 text-ds-xs font-semibold text-accent-11\">\n {count ? `${count} ${label}` : label}\n </span>\n <div className=\"flex-1 border-t-2 border-accent-7\" />\n </div>\n )\n}\nUnreadSeparator.displayName = 'UnreadSeparator'\n\nexport { UnreadSeparator }\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chat.js","names":[],"sources":["../../src/ui/chat/date-separator.tsx","../../src/ui/chat/message.tsx","../../src/ui/chat/message-input.tsx","../../src/ui/chat/message-list.tsx","../../src/ui/chat/system-message.tsx","../../src/ui/chat/typing-indicator.tsx","../../src/ui/chat/unread-separator.tsx"],"sourcesContent":["import * as React from 'react'\n\nimport { cn } from '../lib/utils'\n\nexport interface DateSeparatorProps {\n date: Date | string\n format?: (date: Date) => string\n className?: string\n}\n\nfunction defaultFormat(date: Date): string {\n const now = new Date()\n const today = new Date(now.getFullYear(), now.getMonth(), now.getDate())\n const target = new Date(date.getFullYear(), date.getMonth(), date.getDate())\n const diffMs = today.getTime() - target.getTime()\n const diffDays = Math.round(diffMs / (1000 * 60 * 60 * 24))\n\n if (diffDays === 0) return 'Today'\n if (diffDays === 1) return 'Yesterday'\n\n const month = date.toLocaleString('en-US', { month: 'short' })\n const day = date.getDate()\n\n if (date.getFullYear() !== now.getFullYear()) {\n return `${month} ${day}, ${date.getFullYear()}`\n }\n\n return `${month} ${day}`\n}\n\nfunction DateSeparator({ date, format, className }: DateSeparatorProps) {\n const d = typeof date === 'string' ? new Date(date) : date\n const label = format ? format(d) : defaultFormat(d)\n\n return (\n <div className={cn('flex items-center gap-ds-03 py-ds-03', className)}>\n <div className=\"flex-1 border-t border-surface-border-subtle\" />\n <span className=\"text-ds-xs font-medium text-surface-fg-subtle/50 uppercase tracking-wider\">\n {label}\n </span>\n <div className=\"flex-1 border-t border-surface-border-subtle\" />\n </div>\n )\n}\nDateSeparator.displayName = 'DateSeparator'\n\nexport { DateSeparator }\n","'use client'\n\nimport { IconTrash } from '@tabler/icons-react'\nimport { motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { Avatar, AvatarFallback,AvatarImage } from '../avatar'\nimport { Icon } from '../icon'\nimport { IconProvider } from '../icon-context'\nimport type { IconInput } from '../lib/icon-input'\nimport { MENTION_TOKEN_CLASS } from '../lib/mention'\nimport { motionProps,springs } from '../lib/motion'\nimport { normalizeIcon } from '../lib/normalize-icon'\nimport { cn } from '../lib/utils'\nimport { Textarea } from '../textarea'\nimport { Tooltip, TooltipContent,TooltipTrigger } from '../tooltip'\n\n// ── Context ──────────────────────────────────────────────────────────────\n\ninterface MessageContextValue {\n variant: 'flat' | 'bubble'\n placement: 'start' | 'end'\n grouped: boolean\n highlight?: 'mention' | 'internal'\n}\n\nconst MessageContext = React.createContext<MessageContextValue>({\n variant: 'flat',\n placement: 'start',\n grouped: false,\n})\n\nfunction useMessageContext() {\n return React.useContext(MessageContext)\n}\n\n// ── Root ─────────────────────────────────────────────────────────────────\n\nexport interface MessageProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n variant?: 'flat' | 'bubble'\n placement?: 'start' | 'end'\n highlight?: 'mention' | 'internal'\n grouped?: boolean\n deleted?: boolean\n deletedText?: string\n}\n\nconst MessageRoot = React.forwardRef<HTMLDivElement, MessageProps>(\n (\n {\n children,\n variant = 'flat',\n placement = 'start',\n highlight,\n grouped = false,\n deleted = false,\n deletedText = 'This message was deleted',\n className,\n ...props\n },\n ref,\n ) => {\n const ctx = React.useMemo<MessageContextValue>(\n () => ({ variant, placement, grouped, highlight }),\n [variant, placement, grouped, highlight],\n )\n\n if (deleted) {\n return (\n <motion.div\n ref={ref}\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n transition={springs.snappy}\n className={cn(\n 'flex items-center gap-ds-02 py-ds-02 text-ds-xs text-surface-fg-subtle/50 italic',\n className,\n )}\n {...motionProps(props)}\n >\n <Icon icon={IconTrash} size=\"xs\" />\n {deletedText}\n </motion.div>\n )\n }\n\n if (variant === 'bubble') {\n return (\n <MessageContext.Provider value={ctx}>\n <motion.div\n ref={ref}\n data-highlight={highlight}\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n transition={springs.snappy}\n className={cn(\n 'group/message relative flex',\n placement === 'end' ? 'justify-end' : 'justify-start',\n // mention is carried by the styled in-content @token (see MENTION_TOKEN_CLASS), not a row tint/rail\n MENTION_TOKEN_CLASS,\n highlight === 'internal' && 'bg-warning-2/50 rounded-control-inner',\n className,\n )}\n {...motionProps(props)}\n >\n <div\n className={cn(\n 'max-w-[85%] rounded-bubble px-ds-04 py-ds-03',\n placement === 'end'\n ? 'bg-accent-3 text-surface-fg'\n : 'bg-surface-raised text-surface-fg',\n )}\n >\n {children}\n </div>\n </motion.div>\n </MessageContext.Provider>\n )\n }\n\n // flat variant (default)\n return (\n <MessageContext.Provider value={ctx}>\n <motion.div\n ref={ref}\n data-highlight={highlight}\n initial={{ opacity: 0, y: 8 }}\n animate={{ opacity: 1, y: 0 }}\n transition={springs.snappy}\n className={cn(\n 'group/message relative flex gap-ds-04',\n grouped && '-mt-ds-01',\n // mention is carried by the styled in-content @token (see MENTION_TOKEN_CLASS), not a row rail/tint\n MENTION_TOKEN_CLASS,\n highlight === 'internal' && 'bg-warning-2/50 rounded-control-inner',\n className,\n )}\n {...motionProps(props)}\n >\n {children}\n </motion.div>\n </MessageContext.Provider>\n )\n },\n)\nMessageRoot.displayName = 'Message'\n\n// ── Avatar ───────────────────────────────────────────────────────────────\n\nexport interface MessageAvatarProps {\n src?: string | null\n fallback?: string\n icon?: IconInput\n size?: 'sm' | 'md'\n children?: React.ReactNode\n}\n\nfunction MessageAvatar({\n src,\n fallback,\n icon,\n size = 'md',\n children,\n}: MessageAvatarProps) {\n const { grouped } = useMessageContext()\n\n const sizeClass = size === 'sm' ? 'w-5' : 'w-6'\n const heightClass = size === 'sm' ? 'h-5' : 'h-6'\n\n if (grouped) {\n return <div className={cn(sizeClass, heightClass, 'shrink-0')} />\n }\n\n if (children) {\n return (\n <div className={cn(sizeClass, 'shrink-0 flex items-start')}>\n {children}\n </div>\n )\n }\n\n if (icon) {\n return (\n <div\n className={cn(\n sizeClass,\n size === 'sm' ? 'h-5' : 'h-6',\n 'shrink-0 flex items-center justify-center rounded-pill bg-surface-raised-hover',\n )}\n >\n <IconProvider size={size === 'sm' ? 'xs' : 'sm'}>{normalizeIcon(icon)}</IconProvider>\n </div>\n )\n }\n\n return (\n <div className={cn(sizeClass, 'shrink-0')}>\n <Avatar size={size === 'sm' ? 'xs' : 'sm'}>\n {src && <AvatarImage src={src} alt={fallback ?? ''} />}\n <AvatarFallback>{fallback ?? ''}</AvatarFallback>\n </Avatar>\n </div>\n )\n}\nMessageAvatar.displayName = 'Message.Avatar'\n\n// ── Content ──────────────────────────────────────────────────────────────\n\nexport interface MessageContentProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n}\n\nfunction MessageContent({ children, className, ...props }: MessageContentProps) {\n return (\n <div className={cn('min-w-0 flex-1 flex flex-col gap-ds-02', className)} {...props}>\n {children}\n </div>\n )\n}\nMessageContent.displayName = 'Message.Content'\n\n// ── Author ───────────────────────────────────────────────────────────────\n\nexport interface MessageAuthorProps {\n name: string\n badge?: React.ReactNode\n timestamp?: Date\n formattedTimestamp?: string\n timestampFormat?: (date: Date) => string\n}\n\nfunction defaultTimestampFormat(date: Date): string {\n return date.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' })\n}\n\nfunction MessageAuthor({\n name,\n badge,\n timestamp,\n formattedTimestamp,\n timestampFormat = defaultTimestampFormat,\n}: MessageAuthorProps) {\n const { grouped } = useMessageContext()\n\n if (grouped) return null\n\n const timeStr = formattedTimestamp\n ?? (timestamp ? timestampFormat(timestamp) : undefined)\n\n return (\n <div className=\"flex items-baseline gap-ds-02\">\n <span className=\"font-semibold text-ds-md text-surface-fg\">{name}</span>\n {badge}\n {timeStr && (\n <span className=\"text-ds-sm text-surface-fg-subtle/50\">{timeStr}</span>\n )}\n </div>\n )\n}\nMessageAuthor.displayName = 'Message.Author'\n\n// ── Body ─────────────────────────────────────────────────────────────────\n\nexport interface MessageBodyProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n}\n\nfunction MessageBody({ children, className, ...props }: MessageBodyProps) {\n return (\n <div\n className={cn(\n 'text-ds-md leading-relaxed text-surface-fg whitespace-pre-wrap',\n className,\n )}\n {...props}\n >\n {children}\n </div>\n )\n}\nMessageBody.displayName = 'Message.Body'\n\n// ── EditableBody ─────────────────────────────────────────────────────────\n\nexport interface MessageEditableBodyProps {\n content: string\n onSave: (newContent: string) => void\n onCancel?: () => void\n canEdit?: boolean\n renderContent?: (content: string) => React.ReactNode\n}\n\nfunction MessageEditableBody({\n content,\n onSave,\n onCancel,\n canEdit = false,\n renderContent,\n}: MessageEditableBodyProps) {\n const [isEditing, setIsEditing] = React.useState(false)\n const [editDraft, setEditDraft] = React.useState(content)\n const textareaRef = React.useRef<HTMLTextAreaElement>(null)\n\n React.useEffect(() => {\n if (isEditing && textareaRef.current) {\n textareaRef.current.focus()\n textareaRef.current.select()\n }\n }, [isEditing])\n\n const handleStartEdit = React.useCallback(() => {\n if (!canEdit) return\n setEditDraft(content)\n setIsEditing(true)\n }, [canEdit, content])\n\n const handleSave = React.useCallback(() => {\n const trimmed = editDraft.trim()\n if (trimmed && trimmed !== content) {\n onSave(trimmed)\n }\n setIsEditing(false)\n }, [editDraft, content, onSave])\n\n const handleCancel = React.useCallback(() => {\n setIsEditing(false)\n setEditDraft(content)\n onCancel?.()\n }, [content, onCancel])\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n handleSave()\n } else if (e.key === 'Escape') {\n e.preventDefault()\n handleCancel()\n }\n },\n [handleSave, handleCancel],\n )\n\n if (isEditing) {\n return (\n <div className=\"text-ds-md leading-relaxed\">\n <Textarea\n ref={textareaRef}\n value={editDraft}\n onChange={(e) => setEditDraft(e.target.value)}\n onKeyDown={handleKeyDown}\n onBlur={handleSave}\n // compact inline-edit overrides on top of the Textarea base\n className=\"resize-none rounded-control-inner bg-surface-raised-hover px-ds-02 py-ds-01 text-ds-md leading-relaxed\"\n rows={2}\n />\n <div className=\"mt-ds-01 text-ds-xs text-surface-fg-subtle/50\">\n Enter to save · Escape to cancel\n </div>\n </div>\n )\n }\n\n return (\n <div\n className={cn(\n 'text-ds-md leading-relaxed text-surface-fg whitespace-pre-wrap',\n canEdit && 'cursor-pointer hover:bg-surface-raised-hover rounded-control-inner transition-colors',\n )}\n onClick={handleStartEdit}\n role={canEdit ? 'button' : undefined}\n tabIndex={canEdit ? 0 : undefined}\n onKeyDown={\n canEdit\n ? (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleStartEdit()\n }\n }\n : undefined\n }\n >\n {renderContent ? renderContent(content) : content}\n </div>\n )\n}\nMessageEditableBody.displayName = 'Message.EditableBody'\n\n// ── Reactions ────────────────────────────────────────────────────────────\n\nexport interface MessageReactionsProps {\n reactions: { emoji: string; count: number; reacted: boolean }[]\n onReact: (emoji: string) => void\n}\n\nfunction MessageReactions({ reactions, onReact }: MessageReactionsProps) {\n if (reactions.length === 0) return null\n\n return (\n <div className=\"flex flex-wrap gap-ds-02 mt-ds-03\">\n {reactions.map((r) => (\n <button\n key={r.emoji}\n type=\"button\"\n onClick={() => onReact(r.emoji)}\n aria-label={`${r.emoji} ${r.count} reaction${r.count !== 1 ? 's' : ''}${r.reacted ? ', you reacted' : ''}`}\n className={cn(\n 'inline-flex items-center gap-ds-01 rounded-pill px-ds-02 py-ds-01 text-ds-xs transition-colors',\n r.reacted\n ? 'bg-accent-3 ring-1 ring-accent-6'\n : 'bg-surface-raised-hover hover:bg-surface-raised-active',\n )}\n >\n <span>{r.emoji}</span>\n <span>{r.count}</span>\n </button>\n ))}\n </div>\n )\n}\nMessageReactions.displayName = 'Message.Reactions'\n\n// ── Actions (floating toolbar) ───────────────────────────────────────────\n\nexport interface MessageActionsProps {\n children: React.ReactNode\n delay?: number\n}\n\nfunction MessageActions({ children, delay = 100 }: MessageActionsProps) {\n return (\n <div\n className={cn(\n 'absolute -top-2 right-0 z-10',\n 'flex items-center gap-ds-01 rounded-control bg-surface-raised px-ds-01 py-ds-01 shadow-raised',\n 'opacity-0 group-hover/message:opacity-100 group-focus-within/message:opacity-100 transition-opacity duration-150',\n )}\n style={{ transitionDelay: `${delay}ms` }}\n >\n {children}\n </div>\n )\n}\nMessageActions.displayName = 'Message.Actions'\n\n// ── Action (single icon button) ──────────────────────────────────────────\n\nexport interface MessageActionProps {\n icon: IconInput\n label: string\n onClick: () => void\n variant?: 'default' | 'danger'\n}\n\nfunction MessageAction({\n icon,\n label,\n onClick,\n variant = 'default',\n}: MessageActionProps) {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n onClick={onClick}\n aria-label={label}\n className={cn(\n 'p-ds-02 rounded-control-inner transition-colors',\n variant === 'default' &&\n 'text-surface-fg-subtle hover:text-surface-fg hover:bg-surface-raised-hover',\n variant === 'danger' &&\n 'text-surface-fg-subtle hover:text-error-11 hover:bg-surface-raised-hover',\n )}\n >\n <IconProvider size=\"xs\">{normalizeIcon(icon)}</IconProvider>\n </button>\n </TooltipTrigger>\n <TooltipContent>{label}</TooltipContent>\n </Tooltip>\n )\n}\nMessageAction.displayName = 'Message.Action'\n\n// ── Compound Export ──────────────────────────────────────────────────────\n\nexport const Message = Object.assign(MessageRoot, {\n Avatar: MessageAvatar,\n Content: MessageContent,\n Author: MessageAuthor,\n Body: MessageBody,\n EditableBody: MessageEditableBody,\n Reactions: MessageReactions,\n Actions: MessageActions,\n Action: MessageAction,\n})\n\nexport {\n type MessageContextValue,\n useMessageContext,\n}\n","'use client'\n\nimport { IconSend, IconSquare } from '@tabler/icons-react'\nimport * as React from 'react'\n\nimport { Button } from '../button'\nimport { Icon } from '../icon'\nimport { cn } from '../lib/utils'\n\nexport interface MessageInputProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'onSubmit'> {\n onSubmit: (text: string) => void\n placeholder?: string\n disabled?: boolean\n isStreaming?: boolean\n onCancel?: () => void\n leadingSlot?: React.ReactNode\n trailingSlot?: React.ReactNode\n disclaimer?: string\n sendIcon?: React.ReactNode\n}\n\nconst MessageInput = React.forwardRef<HTMLDivElement, MessageInputProps>(\n (\n {\n onSubmit,\n placeholder = 'Type a message...',\n disabled = false,\n isStreaming = false,\n onCancel,\n leadingSlot,\n trailingSlot,\n disclaimer,\n sendIcon,\n className,\n ...props\n },\n ref,\n ) => {\n const [text, setText] = React.useState('')\n const textareaRef = React.useRef<HTMLTextAreaElement>(null)\n\n const resize = React.useCallback(() => {\n const el = textareaRef.current\n if (!el) return\n el.style.height = 'auto'\n el.style.height = `${Math.min(el.scrollHeight, 160)}px`\n }, [])\n\n const handleChange = React.useCallback(\n (e: React.ChangeEvent<HTMLTextAreaElement>) => {\n setText(e.target.value)\n resize()\n },\n [resize],\n )\n\n const handleSend = React.useCallback(() => {\n const trimmed = text.trim()\n if (!trimmed || isStreaming) return\n onSubmit(trimmed)\n setText('')\n // Reset height after clearing\n if (textareaRef.current) {\n textareaRef.current.style.height = 'auto'\n }\n }, [text, isStreaming, onSubmit])\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n if (!isStreaming) {\n handleSend()\n }\n }\n },\n [isStreaming, handleSend],\n )\n\n const isEmpty = text.trim().length === 0\n\n return (\n <div\n ref={ref}\n className={cn(\n 'border-t border-surface-border-subtle px-ds-05 py-ds-04',\n className,\n )}\n {...props}\n >\n <div className=\"flex items-end gap-ds-02 rounded-overlay-lg border border-surface-border bg-surface-base p-ds-03\">\n {leadingSlot}\n <textarea\n ref={textareaRef}\n value={text}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n aria-label={placeholder || 'Type a message'}\n disabled={disabled}\n rows={1}\n className=\"flex-1 resize-none bg-transparent px-ds-02 py-ds-01 text-ds-sm text-surface-fg placeholder:text-surface-fg-subtle/50 focus:outline-hidden disabled:opacity-50\"\n style={{ maxHeight: 160 }}\n />\n {isStreaming ? (\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n color=\"error\"\n onClick={onCancel}\n aria-label=\"Stop\"\n >\n <Icon icon={IconSquare} size=\"sm\" />\n </Button>\n ) : (\n <Button\n variant=\"ghost\"\n size=\"icon-sm\"\n onClick={handleSend}\n disabled={isEmpty || disabled}\n aria-label=\"Send\"\n >\n {sendIcon ?? <Icon icon={IconSend} size=\"sm\" />}\n </Button>\n )}\n {trailingSlot}\n </div>\n {disclaimer && (\n <p className=\"mt-ds-02 text-center text-ds-xs text-surface-fg-subtle/50\">\n {disclaimer}\n </p>\n )}\n </div>\n )\n },\n)\nMessageInput.displayName = 'MessageInput'\n\nexport { MessageInput }\n","'use client'\n\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { tweens } from '../lib/motion'\nimport { cn } from '../lib/utils'\nimport { Spinner } from '../spinner'\n\nexport interface MessageListProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode\n /** Auto-scroll to bottom when new content arrives (default true) */\n autoScroll?: boolean\n /** Number of new messages to show in the floating pill */\n newMessageCount?: number\n /** Called when user clicks the \"N new\" pill */\n onScrollToBottom?: () => void\n /** Called when user scrolls near the top — triggers load-more */\n onLoadMore?: () => void\n /** Whether more messages are currently being loaded */\n loadingMore?: boolean\n /** Content to render when there are no children */\n emptySlot?: React.ReactNode\n /** Custom scroll-to-bottom button (unused slot for future override) */\n scrollToBottomSlot?: React.ReactNode\n /** Content rendered above the scroll container (e.g. channel name) */\n headerSlot?: React.ReactNode\n}\n\nconst MessageList = React.forwardRef<HTMLDivElement, MessageListProps>(\n (\n {\n children,\n autoScroll = true,\n newMessageCount = 0,\n onScrollToBottom,\n onLoadMore,\n loadingMore = false,\n emptySlot,\n scrollToBottomSlot,\n headerSlot,\n className,\n ...props\n },\n ref,\n ) => {\n const scrollRef = React.useRef<HTMLDivElement>(null)\n const isAtBottomRef = React.useRef(true)\n const [isAtBottom, setIsAtBottom] = React.useState(true)\n const loadingMoreRef = React.useRef(false)\n const prevScrollHeightRef = React.useRef(0)\n\n const isEmpty = React.Children.count(children) === 0 && !loadingMore\n\n // ── Scroll handler ────────────────────────────────────────────\n const handleScroll = React.useCallback(() => {\n const el = scrollRef.current\n if (!el) return\n\n const atBottom = el.scrollHeight - el.scrollTop - el.clientHeight < 40\n isAtBottomRef.current = atBottom\n setIsAtBottom(atBottom)\n\n // Load more when near top\n if (el.scrollTop < 100 && onLoadMore && !loadingMoreRef.current) {\n loadingMoreRef.current = true\n prevScrollHeightRef.current = el.scrollHeight\n onLoadMore()\n }\n }, [onLoadMore])\n\n // ── Auto-scroll to bottom when children change ────────────────\n React.useLayoutEffect(() => {\n const el = scrollRef.current\n if (!el) return\n\n // Scroll preservation after load-more\n if (loadingMoreRef.current) {\n const newScrollHeight = el.scrollHeight\n el.scrollTop = newScrollHeight - prevScrollHeightRef.current\n loadingMoreRef.current = false\n return\n }\n\n // Auto-scroll if user was at bottom\n if (autoScroll && isAtBottomRef.current) {\n el.scrollTo({ top: el.scrollHeight, behavior: 'smooth' })\n }\n }, [children, autoScroll])\n\n // ── Reset loading flag when loadingMore goes false ──────────\n React.useEffect(() => {\n if (!loadingMore) {\n loadingMoreRef.current = false\n }\n }, [loadingMore])\n\n // ── \"N new\" pill visibility ───────────────────────────────────\n const showNewPill = newMessageCount > 0 && !isAtBottom\n\n const handleScrollToBottom = React.useCallback(() => {\n const el = scrollRef.current\n if (el) {\n el.scrollTo({ top: el.scrollHeight, behavior: 'smooth' })\n }\n onScrollToBottom?.()\n }, [onScrollToBottom])\n\n return (\n <div\n ref={ref}\n className={cn('relative flex flex-1 flex-col overflow-hidden', className)}\n {...props}\n >\n {headerSlot}\n <div\n ref={scrollRef}\n role=\"log\"\n aria-live=\"polite\"\n aria-relevant=\"additions\"\n className=\"flex-1 overflow-y-auto px-ds-05 py-ds-04\"\n style={{\n scrollbarWidth: 'thin',\n scrollbarColor: 'var(--color-surface-border) transparent',\n }}\n onScroll={handleScroll}\n >\n {loadingMore && (\n <div className=\"flex justify-center py-ds-03\">\n <Spinner size=\"sm\" />\n </div>\n )}\n {isEmpty ? (\n emptySlot\n ) : (\n <div className=\"flex flex-col gap-ds-04\">\n <AnimatePresence initial={false}>{children}</AnimatePresence>\n </div>\n )}\n </div>\n\n {/* \"N new\" floating pill */}\n <AnimatePresence>\n {showNewPill && (\n <motion.button\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: 10 }}\n transition={tweens.fade}\n onClick={handleScrollToBottom}\n className=\"absolute bottom-ds-04 left-1/2 z-10 -translate-x-1/2 rounded-pill bg-accent-9 px-ds-04 py-ds-02 text-ds-xs font-medium text-accent-fg shadow-raised transition-colors hover:bg-accent-10\"\n >\n {newMessageCount} new\n </motion.button>\n )}\n </AnimatePresence>\n </div>\n )\n },\n)\nMessageList.displayName = 'MessageList'\n\nexport { MessageList }\n","'use client'\n\nimport { IconAlertCircle } from '@tabler/icons-react'\nimport * as React from 'react'\n\nimport { Icon } from '../icon'\nimport { IconProvider } from '../icon-context'\nimport type { IconInput } from '../lib/icon-input'\nimport { normalizeIcon } from '../lib/normalize-icon'\nimport { cn } from '../lib/utils'\n\nexport interface SystemMessageProps extends React.HTMLAttributes<HTMLDivElement> {\n icon?: IconInput\n timestamp?: string\n variant?: 'event' | 'alert'\n children: React.ReactNode\n}\n\nfunction formatTime(ts: string): string {\n return new Date(ts).toLocaleTimeString('en-US', {\n hour: 'numeric',\n minute: '2-digit',\n })\n}\n\nconst SystemMessage = React.forwardRef<HTMLDivElement, SystemMessageProps>(\n ({ icon, timestamp, variant = 'event', children, className, ...props }, ref) => {\n if (variant === 'alert') {\n return (\n <div\n ref={ref}\n role=\"alert\"\n className={cn('flex justify-center', className)}\n {...props}\n >\n <div className=\"flex items-center gap-ds-03 rounded-surface bg-error-3 px-ds-04 py-ds-03\">\n <IconProvider size=\"sm\">{normalizeIcon(icon) ?? <Icon icon={IconAlertCircle} />}</IconProvider>\n <span className=\"text-ds-sm text-error-11\">{children}</span>\n {timestamp && (\n <span className=\"text-ds-sm text-error-11/60\">\n {formatTime(timestamp)}\n </span>\n )}\n </div>\n </div>\n )\n }\n\n // event variant (default)\n return (\n <div\n ref={ref}\n className={cn(\n 'flex items-center gap-ds-02 rounded-control-inner bg-surface-raised-hover/30 px-ds-02 py-ds-01 -mx-ds-02 text-ds-sm text-surface-fg-subtle/60',\n className,\n )}\n {...props}\n >\n <IconProvider size=\"xs\">{normalizeIcon(icon)}</IconProvider>\n <span className=\"flex-1\">{children}</span>\n {timestamp && <span>{formatTime(timestamp)}</span>}\n </div>\n )\n },\n)\nSystemMessage.displayName = 'SystemMessage'\n\nexport { SystemMessage }\n","'use client'\n\nimport { AnimatePresence,motion } from 'framer-motion'\nimport * as React from 'react'\n\nimport { cn } from '../lib/utils'\n\nexport interface TypingIndicatorProps {\n users: { name: string; image?: string }[]\n className?: string\n}\n\nfunction formatTypingText(users: { name: string }[]): string {\n if (users.length === 1) return `${users[0].name} is typing...`\n if (users.length === 2) return `${users[0].name} and ${users[1].name} are typing...`\n return 'Several people are typing...'\n}\n\nfunction TypingIndicator({ users, className }: TypingIndicatorProps) {\n return (\n <div className={cn('min-h-[24px] px-ds-05', className)} role=\"status\" aria-live=\"polite\">\n <AnimatePresence>\n {users.length > 0 && (\n <motion.div\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n className=\"flex items-center gap-ds-02 text-ds-xs text-surface-fg-subtle\"\n >\n <span className=\"flex items-center gap-ds-01\">\n {[0, 1, 2].map((i) => (\n <motion.span\n key={i}\n className=\"h-1 w-1 rounded-pill bg-surface-fg-subtle\"\n animate={{ y: [0, -3, 0] }}\n transition={{\n duration: 0.5,\n repeat: Infinity,\n delay: i * 0.15,\n }}\n />\n ))}\n </span>\n <span>{formatTypingText(users)}</span>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n )\n}\nTypingIndicator.displayName = 'TypingIndicator'\n\nexport { TypingIndicator }\n","import * as React from 'react'\n\nimport { cn } from '../lib/utils'\n\nexport interface UnreadSeparatorProps {\n label?: string\n count?: number\n className?: string\n}\n\nfunction UnreadSeparator({\n label = 'NEW',\n count,\n className,\n}: UnreadSeparatorProps) {\n return (\n <div className={cn('relative flex items-center py-ds-02', className)}>\n <div className=\"flex-1 border-t-2 border-accent-7\" />\n <span className=\"px-ds-03 text-ds-xs font-semibold text-accent-11\">\n {count ? `${count} ${label}` : label}\n </span>\n <div className=\"flex-1 border-t-2 border-accent-7\" />\n </div>\n )\n}\nUnreadSeparator.displayName = 'UnreadSeparator'\n\nexport { UnreadSeparator }\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { tweens as e } from "../ui/lib/motion.js";
|
|
3
3
|
import { Icon as t } from "../ui/icon.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { Skeleton as n } from "../ui/skeleton.js";
|
|
5
|
+
import { Button as r } from "../ui/button.js";
|
|
6
6
|
import { r as i, t as a } from "./shared.js";
|
|
7
7
|
import * as o from "react";
|
|
8
8
|
import { jsx as s, jsxs as c } from "react/jsx-runtime";
|
|
@@ -47,7 +47,7 @@ function g({ url: g, initialPage: _, onError: v }) {
|
|
|
47
47
|
onLoadError: () => {
|
|
48
48
|
E(!0), v?.("PDF failed to load");
|
|
49
49
|
},
|
|
50
|
-
loading: /* @__PURE__ */ s(
|
|
50
|
+
loading: /* @__PURE__ */ s(n, { className: "h-[500px] w-[400px]" }),
|
|
51
51
|
error: /* @__PURE__ */ s(a, {
|
|
52
52
|
message: "Failed to load PDF",
|
|
53
53
|
url: g
|
|
@@ -68,7 +68,7 @@ function g({ url: g, initialPage: _, onError: v }) {
|
|
|
68
68
|
})
|
|
69
69
|
})
|
|
70
70
|
}), y > 0 && /* @__PURE__ */ c(i, { children: [
|
|
71
|
-
/* @__PURE__ */ s(
|
|
71
|
+
/* @__PURE__ */ s(r, {
|
|
72
72
|
variant: "ghost",
|
|
73
73
|
size: "icon-xs",
|
|
74
74
|
onClick: () => S((e) => Math.max(1, e - 1)),
|
|
@@ -92,7 +92,7 @@ function g({ url: g, initialPage: _, onError: v }) {
|
|
|
92
92
|
"aria-label": "Page number"
|
|
93
93
|
}), /* @__PURE__ */ c("span", { children: ["/ ", y] })]
|
|
94
94
|
}),
|
|
95
|
-
/* @__PURE__ */ s(
|
|
95
|
+
/* @__PURE__ */ s(r, {
|
|
96
96
|
variant: "ghost",
|
|
97
97
|
size: "icon-xs",
|
|
98
98
|
onClick: () => S((e) => Math.min(y, e + 1)),
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { tweens as e } from "../ui/lib/motion.js";
|
|
3
3
|
import { cn as t } from "../ui/lib/utils.js";
|
|
4
4
|
import { Icon as n } from "../ui/icon.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { Skeleton as r } from "../ui/skeleton.js";
|
|
6
|
+
import { Button as i } from "../ui/button.js";
|
|
7
7
|
import { i as a, r as o, t as s } from "./shared.js";
|
|
8
8
|
import * as c from "react";
|
|
9
9
|
import { Fragment as l, jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
@@ -47,7 +47,7 @@ function b({ url: b, alt: x, onError: S }) {
|
|
|
47
47
|
centerView: T
|
|
48
48
|
}, /* @__PURE__ */ d(l, { children: [/* @__PURE__ */ d("div", {
|
|
49
49
|
className: t("overflow-hidden rounded-control bg-surface-sunken", k ? "flex-1 w-full" : "max-h-[70vh] max-w-full"),
|
|
50
|
-
children: [!C && /* @__PURE__ */ u(
|
|
50
|
+
children: [!C && /* @__PURE__ */ u(r, { className: "h-64 w-full rounded-control" }), /* @__PURE__ */ u(v, {
|
|
51
51
|
wrapperClass: t("w-full!", k && "h-full!"),
|
|
52
52
|
contentClass: "w-full! flex! items-center! justify-center!",
|
|
53
53
|
children: /* @__PURE__ */ u(_.img, {
|
|
@@ -67,7 +67,7 @@ function b({ url: b, alt: x, onError: S }) {
|
|
|
67
67
|
}), C && /* @__PURE__ */ d(o, {
|
|
68
68
|
className: k ? "absolute bottom-ds-06" : void 0,
|
|
69
69
|
children: [
|
|
70
|
-
/* @__PURE__ */ u(
|
|
70
|
+
/* @__PURE__ */ u(i, {
|
|
71
71
|
variant: "ghost",
|
|
72
72
|
size: "icon-xs",
|
|
73
73
|
onClick: () => c(),
|
|
@@ -82,7 +82,7 @@ function b({ url: b, alt: x, onError: S }) {
|
|
|
82
82
|
className: "text-ds-xs font-mono text-surface-fg-muted w-12 text-center tabular-nums select-none",
|
|
83
83
|
children: [D, "%"]
|
|
84
84
|
}),
|
|
85
|
-
/* @__PURE__ */ u(
|
|
85
|
+
/* @__PURE__ */ u(i, {
|
|
86
86
|
variant: "ghost",
|
|
87
87
|
size: "icon-xs",
|
|
88
88
|
onClick: () => s(),
|
|
@@ -94,7 +94,7 @@ function b({ url: b, alt: x, onError: S }) {
|
|
|
94
94
|
})
|
|
95
95
|
}),
|
|
96
96
|
/* @__PURE__ */ u(a, {}),
|
|
97
|
-
/* @__PURE__ */ u(
|
|
97
|
+
/* @__PURE__ */ u(i, {
|
|
98
98
|
variant: "ghost",
|
|
99
99
|
size: "icon-xs",
|
|
100
100
|
onClick: () => y(),
|
|
@@ -106,7 +106,7 @@ function b({ url: b, alt: x, onError: S }) {
|
|
|
106
106
|
})
|
|
107
107
|
}),
|
|
108
108
|
/* @__PURE__ */ u(a, {}),
|
|
109
|
-
/* @__PURE__ */ u(
|
|
109
|
+
/* @__PURE__ */ u(i, {
|
|
110
110
|
variant: "ghost",
|
|
111
111
|
size: "icon-xs",
|
|
112
112
|
onClick: () => A((e) => !e),
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mention.js","names":[],"sources":["../../src/ui/lib/mention.ts"],"sourcesContent":["/**\n * Tailwind classes that style an in-content `@mention` token (`<span class=\"mention\">`).\n *\n * Shared by the rich-text editor, the chat input, AND the read-only Message\n * display so a mention looks identical whether it's being typed or rendered in a\n * timeline. Keep this the single source — three copies drifted before (see #99,\n * where Message never styled the token and `highlight=\"mention\"` went invisible).\n */\nexport const MENTION_TOKEN_CLASS =\n '[&_.mention]:rounded-control-inner [&_.mention]:bg-accent-2 [&_.mention]:px-ds-02 [&_.mention]:py-[1px] [&_.mention]:font-medium [&_.mention]:text-accent-11'\n"],"mappings":";AAQA,IAAa,IACX"}
|
package/dist/_chunks/success.js
CHANGED
|
@@ -3,10 +3,10 @@ import { durations as e, springs as t, tweens as n } from "../ui/lib/motion.js";
|
|
|
3
3
|
import { cn as r } from "../ui/lib/utils.js";
|
|
4
4
|
import { Icon as i } from "../ui/icon.js";
|
|
5
5
|
import { Alert as a } from "../ui/alert.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
6
|
+
import { Skeleton as o } from "../ui/skeleton.js";
|
|
7
|
+
import { n as s } from "./badge-group.js";
|
|
8
|
+
import { Button as c } from "../ui/button.js";
|
|
9
|
+
import { Collapsible as l, CollapsibleContent as u, CollapsibleTrigger as d } from "../ui/collapsible.js";
|
|
10
10
|
import { Table as f, TableBody as p, TableCaption as m, TableCell as h, TableHead as g, TableHeader as _, TableRow as v } from "../ui/table.js";
|
|
11
11
|
import { Separator as y } from "../ui/separator.js";
|
|
12
12
|
import { StatCard as b } from "../ui/stat-card.js";
|
|
@@ -21,14 +21,14 @@ function A(e, t) {
|
|
|
21
21
|
if (t.variant === "badge") {
|
|
22
22
|
if (e && typeof e == "object" && "label" in e) {
|
|
23
23
|
let t = e;
|
|
24
|
-
return /* @__PURE__ */ w(
|
|
24
|
+
return /* @__PURE__ */ w(s, {
|
|
25
25
|
variant: "subtle",
|
|
26
26
|
size: "sm",
|
|
27
27
|
color: t.color,
|
|
28
28
|
children: t.label
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
|
-
return /* @__PURE__ */ w(
|
|
31
|
+
return /* @__PURE__ */ w(s, {
|
|
32
32
|
variant: "subtle",
|
|
33
33
|
size: "sm",
|
|
34
34
|
children: String(e ?? "")
|
|
@@ -129,27 +129,27 @@ var N = C.memo(function({ data: e, confidence: t, onAction: n }) {
|
|
|
129
129
|
}),
|
|
130
130
|
/* @__PURE__ */ T("div", {
|
|
131
131
|
className: "flex items-center gap-3",
|
|
132
|
-
children: [/* @__PURE__ */ w(
|
|
132
|
+
children: [/* @__PURE__ */ w(c, {
|
|
133
133
|
variant: "solid",
|
|
134
134
|
color: e.destructive ? "error" : void 0,
|
|
135
135
|
onClick: r,
|
|
136
136
|
children: e.label
|
|
137
|
-
}), /* @__PURE__ */ w(
|
|
137
|
+
}), /* @__PURE__ */ w(c, {
|
|
138
138
|
variant: "ghost",
|
|
139
139
|
onClick: i,
|
|
140
140
|
children: "Cancel"
|
|
141
141
|
})]
|
|
142
142
|
}),
|
|
143
|
-
e.rationale && /* @__PURE__ */ T(
|
|
143
|
+
e.rationale && /* @__PURE__ */ T(l, {
|
|
144
144
|
className: "mt-3",
|
|
145
|
-
children: [/* @__PURE__ */ w(
|
|
145
|
+
children: [/* @__PURE__ */ w(d, {
|
|
146
146
|
asChild: !0,
|
|
147
147
|
children: /* @__PURE__ */ w("button", {
|
|
148
148
|
type: "button",
|
|
149
149
|
className: "text-ds-xs text-surface-fg-subtle underline cursor-pointer",
|
|
150
150
|
children: "Why this action?"
|
|
151
151
|
})
|
|
152
|
-
}), /* @__PURE__ */ w(
|
|
152
|
+
}), /* @__PURE__ */ w(u, { children: /* @__PURE__ */ w("p", {
|
|
153
153
|
className: "text-ds-sm text-surface-fg-muted mt-2 p-3 bg-surface-raised rounded-surface",
|
|
154
154
|
children: e.rationale
|
|
155
155
|
}) })]
|
|
@@ -235,7 +235,7 @@ var R = C.memo(function({ data: t }) {
|
|
|
235
235
|
"aria-busy": "true",
|
|
236
236
|
"aria-label": "Loading",
|
|
237
237
|
className: "flex flex-col gap-2",
|
|
238
|
-
children: [Array.from({ length: e }).map((t, n) => /* @__PURE__ */ w(
|
|
238
|
+
children: [Array.from({ length: e }).map((t, n) => /* @__PURE__ */ w(o, {
|
|
239
239
|
animation: "shimmer",
|
|
240
240
|
className: r("h-4", n === e - 1 ? "w-3/5" : "w-full")
|
|
241
241
|
}, n)), /* @__PURE__ */ w("span", {
|
|
@@ -327,7 +327,7 @@ z.displayName = "StatRowBlock";
|
|
|
327
327
|
//#endregion
|
|
328
328
|
//#region src/ai/blocks/success.tsx
|
|
329
329
|
var B = 5e3, V = C.memo(function({ data: e, blockId: t, confidence: n, onAction: r }) {
|
|
330
|
-
let { reducedMotion: i } = x(), o = i,
|
|
330
|
+
let { reducedMotion: i } = x(), o = i, s = e.undoTimeout ?? B, [l, u] = C.useState(s), [d, f] = C.useState(!!e.undoable);
|
|
331
331
|
C.useEffect(() => {
|
|
332
332
|
if (!e.undoable) return;
|
|
333
333
|
let t = setInterval(() => {
|
|
@@ -337,7 +337,7 @@ var B = 5e3, V = C.memo(function({ data: e, blockId: t, confidence: n, onAction:
|
|
|
337
337
|
});
|
|
338
338
|
}, 100);
|
|
339
339
|
return () => clearInterval(t);
|
|
340
|
-
}, [e.undoable,
|
|
340
|
+
}, [e.undoable, s]);
|
|
341
341
|
let p = C.useCallback(() => {
|
|
342
342
|
r?.(t || "unknown", "undo");
|
|
343
343
|
}, [t, r]), m = Math.ceil(l / 1e3), h = 2 * Math.PI * 9;
|
|
@@ -350,7 +350,7 @@ var B = 5e3, V = C.memo(function({ data: e, blockId: t, confidence: n, onAction:
|
|
|
350
350
|
children: e.message
|
|
351
351
|
}), d && e.undoable && /* @__PURE__ */ w("div", {
|
|
352
352
|
className: "mt-2 flex items-center gap-2",
|
|
353
|
-
children: /* @__PURE__ */ w(
|
|
353
|
+
children: /* @__PURE__ */ w(c, {
|
|
354
354
|
variant: "ghost",
|
|
355
355
|
size: "sm",
|
|
356
356
|
onClick: p,
|
|
@@ -382,7 +382,7 @@ var B = 5e3, V = C.memo(function({ data: e, blockId: t, confidence: n, onAction:
|
|
|
382
382
|
initial: o ? void 0 : { strokeDashoffset: 0 },
|
|
383
383
|
animate: { strokeDashoffset: h },
|
|
384
384
|
transition: o ? { duration: 0 } : {
|
|
385
|
-
duration:
|
|
385
|
+
duration: s / 1e3,
|
|
386
386
|
ease: "linear"
|
|
387
387
|
}
|
|
388
388
|
})]
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
import { tweens as e } from "../ui/lib/motion.js";
|
|
3
3
|
import { cn as t } from "../ui/lib/utils.js";
|
|
4
4
|
import { Icon as n } from "../ui/icon.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
5
|
+
import { Skeleton as r } from "../ui/skeleton.js";
|
|
6
|
+
import { Avatar as i, AvatarFallback as a, AvatarImage as o } from "../ui/avatar.js";
|
|
7
|
+
import { Button as s } from "../ui/button.js";
|
|
8
8
|
import { formatRelativeTime as c } from "../ui/lib/date-utils.js";
|
|
9
9
|
import { getInitials as l } from "./lib/string-utils.js";
|
|
10
10
|
import * as u from "react";
|
|
@@ -58,26 +58,26 @@ function v({ compact: e }) {
|
|
|
58
58
|
].map((n) => /* @__PURE__ */ f("div", {
|
|
59
59
|
className: "flex items-center gap-ds-03",
|
|
60
60
|
children: [
|
|
61
|
-
/* @__PURE__ */ d(
|
|
62
|
-
!e && /* @__PURE__ */ d(
|
|
63
|
-
/* @__PURE__ */ d(
|
|
64
|
-
/* @__PURE__ */ d(
|
|
61
|
+
/* @__PURE__ */ d(r, { className: "h-2 w-2 shrink-0 rounded-pill" }),
|
|
62
|
+
!e && /* @__PURE__ */ d(r, { className: "h-4 w-4 shrink-0 rounded-pill" }),
|
|
63
|
+
/* @__PURE__ */ d(r, { className: t("flex-1", e ? "h-3" : "h-4") }),
|
|
64
|
+
/* @__PURE__ */ d(r, { className: "h-3 w-12" })
|
|
65
65
|
]
|
|
66
66
|
}, n))
|
|
67
67
|
});
|
|
68
68
|
}
|
|
69
|
-
function y({ item: e, compact:
|
|
69
|
+
function y({ item: e, compact: r }) {
|
|
70
70
|
let [s, m] = u.useState(!1), g = u.useId(), _ = e.color ?? "default";
|
|
71
71
|
return /* @__PURE__ */ f("div", {
|
|
72
|
-
className: t("relative flex items-start",
|
|
72
|
+
className: t("relative flex items-start", r ? "gap-ds-02" : "gap-ds-03"),
|
|
73
73
|
children: [
|
|
74
74
|
/* @__PURE__ */ d("div", { className: t("relative z-10 mt-1.5 h-2 w-2 shrink-0 rounded-pill ring-2 ring-surface-base", h[_]) }),
|
|
75
|
-
!
|
|
75
|
+
!r && e.actor && /* @__PURE__ */ f(i, {
|
|
76
76
|
className: "h-5 w-5 shrink-0 text-[9px]",
|
|
77
|
-
children: [e.actor.image && /* @__PURE__ */ d(
|
|
77
|
+
children: [e.actor.image && /* @__PURE__ */ d(o, {
|
|
78
78
|
src: e.actor.image,
|
|
79
79
|
alt: e.actor.name
|
|
80
|
-
}), /* @__PURE__ */ d(
|
|
80
|
+
}), /* @__PURE__ */ d(a, {
|
|
81
81
|
className: "text-[9px]",
|
|
82
82
|
children: l(e.actor.name)
|
|
83
83
|
})]
|
|
@@ -87,7 +87,7 @@ function y({ item: e, compact: o }) {
|
|
|
87
87
|
children: [/* @__PURE__ */ f("div", {
|
|
88
88
|
className: "flex items-center justify-between gap-ds-02",
|
|
89
89
|
children: [/* @__PURE__ */ f("div", {
|
|
90
|
-
className: t("min-w-0 flex-1 flex items-center gap-ds-01 flex-wrap",
|
|
90
|
+
className: t("min-w-0 flex-1 flex items-center gap-ds-01 flex-wrap", r ? "text-ds-xs" : "text-ds-sm"),
|
|
91
91
|
children: [
|
|
92
92
|
e.actor && /* @__PURE__ */ f("span", {
|
|
93
93
|
className: "font-medium text-surface-fg",
|
|
@@ -113,7 +113,7 @@ function y({ item: e, compact: o }) {
|
|
|
113
113
|
})
|
|
114
114
|
]
|
|
115
115
|
}), /* @__PURE__ */ d("time", {
|
|
116
|
-
className: t("shrink-0 whitespace-nowrap text-surface-fg-subtle",
|
|
116
|
+
className: t("shrink-0 whitespace-nowrap text-surface-fg-subtle", r ? "text-ds-xs" : "text-ds-sm"),
|
|
117
117
|
dateTime: (typeof e.timestamp == "string" ? new Date(e.timestamp) : e.timestamp).toISOString(),
|
|
118
118
|
children: c(e.timestamp)
|
|
119
119
|
})]
|
|
@@ -152,7 +152,7 @@ function x({ label: n, isFirst: r }) {
|
|
|
152
152
|
]
|
|
153
153
|
});
|
|
154
154
|
}
|
|
155
|
-
var S = u.forwardRef(({ items: n, onLoadMore: r, loading: i = !1, hasMore: a = !1, emptyState:
|
|
155
|
+
var S = u.forwardRef(({ items: n, onLoadMore: r, loading: i = !1, hasMore: a = !1, emptyState: o, compact: c = !1, maxInitialItems: l, groupBy: p = "none", groupLabels: h, renderItem: g, className: S, ...C }, w) => {
|
|
156
156
|
let [T, E] = u.useState(!1);
|
|
157
157
|
if (i) return /* @__PURE__ */ d("div", {
|
|
158
158
|
ref: w,
|
|
@@ -160,11 +160,11 @@ var S = u.forwardRef(({ items: n, onLoadMore: r, loading: i = !1, hasMore: a = !
|
|
|
160
160
|
...C,
|
|
161
161
|
children: /* @__PURE__ */ d(v, { compact: c })
|
|
162
162
|
});
|
|
163
|
-
if (n.length === 0) return
|
|
163
|
+
if (n.length === 0) return o ? /* @__PURE__ */ d("div", {
|
|
164
164
|
ref: w,
|
|
165
165
|
className: S,
|
|
166
166
|
...C,
|
|
167
|
-
children:
|
|
167
|
+
children: o
|
|
168
168
|
}) : null;
|
|
169
169
|
let D = l != null && !T && n.length > l, O = D ? n.slice(0, l) : n, k = p === "time", A = (e, t) => {
|
|
170
170
|
if (g) {
|
|
@@ -213,7 +213,7 @@ var S = u.forwardRef(({ items: n, onLoadMore: r, loading: i = !1, hasMore: a = !
|
|
|
213
213
|
}),
|
|
214
214
|
D && /* @__PURE__ */ d("div", {
|
|
215
215
|
className: "relative mt-ds-03 flex justify-center",
|
|
216
|
-
children: /* @__PURE__ */ f(
|
|
216
|
+
children: /* @__PURE__ */ f(s, {
|
|
217
217
|
variant: "ghost",
|
|
218
218
|
size: "sm",
|
|
219
219
|
onClick: () => E(!0),
|
|
@@ -226,7 +226,7 @@ var S = u.forwardRef(({ items: n, onLoadMore: r, loading: i = !1, hasMore: a = !
|
|
|
226
226
|
}),
|
|
227
227
|
a && r && !D && /* @__PURE__ */ d("div", {
|
|
228
228
|
className: "relative mt-ds-03 flex justify-center",
|
|
229
|
-
children: /* @__PURE__ */ d(
|
|
229
|
+
children: /* @__PURE__ */ d(s, {
|
|
230
230
|
variant: "ghost",
|
|
231
231
|
size: "sm",
|
|
232
232
|
onClick: r,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deadline-indicator.d.ts","sourceRoot":"","sources":["../../src/composed/deadline-indicator.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAW9B,MAAM,WAAW,sBAAuB,SAAQ,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC;IACnF,QAAQ,EAAE,IAAI,GAAG,MAAM,CAAA;IACvB,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,uEAAuE;IACvE,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,0BAA0B;IAC1B,MAAM,CAAC,EAAE,UAAU,GAAG,UAAU,CAAA;IAChC,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,kFAAkF;IAClF,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AA8BD,QAAA,MAAM,iBAAiB,
|
|
1
|
+
{"version":3,"file":"deadline-indicator.d.ts","sourceRoot":"","sources":["../../src/composed/deadline-indicator.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAW9B,MAAM,WAAW,sBAAuB,SAAQ,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC;IACnF,QAAQ,EAAE,IAAI,GAAG,MAAM,CAAA;IACvB,wEAAwE;IACxE,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,uEAAuE;IACvE,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,0BAA0B;IAC1B,MAAM,CAAC,EAAE,UAAU,GAAG,UAAU,CAAA;IAChC,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,kFAAkF;IAClF,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AA8BD,QAAA,MAAM,iBAAiB,gGA6ErB,CAAA;AAGF,OAAO,EAAE,iBAAiB,EAAE,CAAA"}
|