@reforma/components 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/SortableList/SortableList.d.ts +9 -3
- package/dist/SortableList/SortableList.d.ts.map +1 -1
- package/dist/SortableList/SortableList.js +178 -163
- package/dist/SortableList/SortableList.js.map +1 -1
- package/dist/chat/ComposerBanner/ComposerBanner.d.ts +1 -1
- package/dist/chat/ComposerBanner/ComposerBanner.d.ts.map +1 -1
- package/dist/chat/ComposerBanner/ComposerBanner.js.map +1 -1
- package/dist/chat/ComposerBanner/ComposerBanner.module.css +1 -1
- package/dist/chat/ComposerBanner/ComposerBanner.module.css.js +5 -5
- package/dist/chat/Message/segments/MessagePhaseSection.module.css +1 -1
- package/dist/chat/Message/turn/MessageAssistantBody.d.ts +2 -1
- package/dist/chat/Message/turn/MessageAssistantBody.d.ts.map +1 -1
- package/dist/chat/Message/turn/MessageAssistantBody.js +62 -58
- package/dist/chat/Message/turn/MessageAssistantBody.js.map +1 -1
- package/dist/chat/Message/turn/workedCollapse.d.ts +6 -2
- package/dist/chat/Message/turn/workedCollapse.d.ts.map +1 -1
- package/dist/chat/Message/turn/workedCollapse.js +24 -18
- package/dist/chat/Message/turn/workedCollapse.js.map +1 -1
- package/dist/chat/Tool/agent/AgentTool.js +5 -5
- package/dist/chat/Tool/agent/AgentTool.js.map +1 -1
- package/dist/chat/Tool/bash/BashTool.d.ts.map +1 -1
- package/dist/chat/Tool/bash/BashTool.js +50 -57
- package/dist/chat/Tool/bash/BashTool.js.map +1 -1
- package/dist/chat/Tool/bash/BashTool.module.css +1 -1
- package/dist/chat/Tool/bash/BashTool.module.css.js +4 -8
- package/dist/chat/Tool/bash/BashTool.module.css.js.map +1 -1
- package/dist/chat/Tool/image-asset/ImageAssetTool.js +1 -1
- package/dist/chat/Tool/image-asset/ImageAssetTool.js.map +1 -1
- package/dist/chat/Tool/shell/ToolShell.js +1 -1
- package/dist/chat/Tool/shell/ToolShell.js.map +1 -1
- package/dist/chat/Tool/shell/ToolShellCard.js +7 -7
- package/dist/chat/Tool/shell/ToolShellCard.js.map +1 -1
- package/dist/openui/functions/index.d.ts +59 -59
- package/dist/openui/functions/index.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SortableList.js","sources":["../../src/SortableList/SortableList.tsx"],"sourcesContent":["import {\n DragDropProvider,\n DragOverlay,\n PointerSensor,\n useDroppable,\n type DragEndEvent,\n} from '@dnd-kit/react';\nimport { isSortable, useSortable } from '@dnd-kit/react/sortable';\nimport { DotsDrag } from '@reforma/icons/14';\nimport { cn } from '@reforma/lib';\nimport { useCallback, useMemo, useRef } from 'react';\n\nimport { For } from '../For';\nimport styles from './SortableList.module.css';\nimport {\n buildSortableTree,\n findSortableTreeNode,\n moveSortableTreeNodeToIndex,\n restoreSortableTree,\n type SortableTreeNode,\n} from './sortableTree';\n\nimport type { ReactElement, ReactNode } from 'react';\n\nexport type SortableListDragHandleAlignment = 'center' | 'top';\nexport type SortableListDragHandleEdgeOffset = 'none' | 'sm' | 'md';\nexport type SortableListDragHandleVariant = 'plain' | 'surface';\n\nexport interface SortableListDragHandleOptions {\n alignment?: SortableListDragHandleAlignment;\n edgeOffset?: SortableListDragHandleEdgeOffset;\n variant?: SortableListDragHandleVariant;\n}\n\nexport interface SortableListItemContext<T> {\n level: number;\n parent: T | null;\n index: number;\n siblingCount: number;\n isFirst: boolean;\n isLast: boolean;\n hasChildren: boolean;\n canHaveChildren: boolean;\n}\n\nexport interface SortableListItemRenderProps<T> extends SortableListItemContext<T> {\n nestedItems: ReactNode;\n isDragging: boolean;\n isDropTarget: boolean;\n}\n\nexport interface SortableListDropContext<T> {\n items: readonly T[];\n target: T | null;\n sourceParent: T | null;\n sourceLevel: number;\n parent: T | null;\n targetLevel: number;\n dropPosition: 'on' | 'before' | 'after' | 'end';\n}\n\ninterface SortableListBaseProps<T> {\n items: readonly T[];\n getKey?: (item: T, path: readonly number[]) => string;\n getTextValue: (item: T) => string;\n onChange: (items: T[]) => void;\n children: (item: T, props: SortableListItemRenderProps<T>) => ReactNode;\n canDrop?: (context: SortableListDropContext<T>) => boolean;\n getDragHandleOptions?: (\n item: T,\n context: SortableListItemContext<T>\n ) => SortableListDragHandleOptions;\n className?: string;\n gap?: 'sm' | 'md';\n nestedGap?: 'sm' | 'md';\n 'aria-label': string;\n}\n\ninterface FlatSortableListProps {\n getChildren?: never;\n setChildren?: never;\n canHaveChildren?: never;\n}\n\ninterface NestedSortableListProps<T> {\n getChildren: (item: T) => readonly T[];\n setChildren: (item: T, children: T[]) => T;\n canHaveChildren?: (item: T) => boolean;\n}\n\nexport type SortableListProps<T> = SortableListBaseProps<T>\n & (FlatSortableListProps | NestedSortableListProps<T>);\n\ninterface SortableNodeData<T> {\n kind: 'node';\n node: SortableTreeNode<T>;\n}\n\ninterface SortableCollectionData<T> {\n kind: 'collection';\n parentNode: SortableTreeNode<T> | null;\n}\n\ninterface SortableCollectionProps<T> {\n nodes: readonly SortableTreeNode<T>[];\n rootNodes: readonly SortableTreeNode<T>[];\n parentNode: SortableTreeNode<T> | null;\n renderItem: (item: T, props: SortableListItemRenderProps<T>) => ReactNode;\n canDrop?: (context: SortableListDropContext<T>) => boolean;\n getDragHandleOptions?: (\n item: T,\n context: SortableListItemContext<T>\n ) => SortableListDragHandleOptions;\n className?: string;\n gap: 'sm' | 'md';\n nestedGap: 'sm' | 'md';\n ariaLabel: string;\n}\n\ninterface SortableItemProps<T> extends Omit<SortableCollectionProps<T>, 'nodes' | 'className' | 'gap' | 'ariaLabel' | 'parentNode'> {\n node: SortableTreeNode<T>;\n}\n\ninterface SortableDestination<T> {\n parentNode: SortableTreeNode<T> | null;\n index: number;\n dropPosition: 'before' | 'after' | 'end';\n}\n\nconst ROOT_COLLECTION_ID = 'reforma-sortable:root';\nconst CHILD_COLLECTION_PREFIX = 'reforma-sortable:children:';\nconst SORTABLE_ITEM_TYPE = 'reforma-sortable:item';\nconst SORTABLE_COLLECTION_TYPE = 'reforma-sortable:collection';\nconst POINTER_SENSORS = [PointerSensor];\nconst PRIMITIVE_KEY_PREFIX = 'sortable:primitive:';\n\n/**\n * Sortable collection with a dedicated pointer handle and optional child groups.\n *\n * The rendered item is the complete draggable surface. Child collections can\n * accept moves when the caller's drop rules allow it.\n */\nexport function SortableList<T>({\n items,\n getKey: getItemKey,\n getTextValue,\n getChildren,\n setChildren,\n canHaveChildren,\n onChange,\n children,\n canDrop,\n getDragHandleOptions,\n className,\n gap = 'md',\n nestedGap = gap,\n 'aria-label': ariaLabel,\n}: SortableListProps<T>) {\n const keyState = useRef({\n nextId: 0,\n objectKeys: new WeakMap<object, string>(),\n });\n const getNodeKey = useCallback((item: T, path: readonly number[]) => {\n const itemKey = getItemKey?.(item, path);\n\n if (itemKey != null) {\n return itemKey;\n }\n\n if (typeof item !== 'object' || item == null) {\n return `${ PRIMITIVE_KEY_PREFIX }${ path.join('.') }`;\n }\n\n const existingKey = keyState.current.objectKeys.get(item);\n\n if (existingKey) {\n return existingKey;\n }\n\n const key = `sortable:item:${ keyState.current.nextId }`;\n\n keyState.current.nextId += 1;\n keyState.current.objectKeys.set(item, key);\n\n return key;\n }, [getItemKey]);\n const nodes = useMemo(() => buildSortableTree(items, {\n getKey: getNodeKey,\n getTextValue,\n getChildren,\n canHaveChildren,\n }), [canHaveChildren, getChildren, getNodeKey, getTextValue, items]);\n const renderState = useRef({ items, revision: 0 });\n\n if (renderState.current.items !== items) {\n renderState.current = {\n items,\n revision: renderState.current.revision + 1,\n };\n }\n\n function handleDragEnd(event: DragEndEvent) {\n const { canceled, operation } = event;\n const { source, target } = operation;\n\n if (canceled || !source || !isSortable(source)) {\n return;\n }\n\n const sourceNode = nodeData<T>(source)?.node;\n\n if (!sourceNode) {\n return;\n }\n\n const targetData = entityData<T>(target);\n const targetNode = targetData?.kind === 'node' ? targetData.node : null;\n let destination: SortableDestination<T> | null;\n\n if (targetData?.kind === 'collection') {\n destination = {\n parentNode: targetData.parentNode,\n index: targetData.parentNode?.children.length ?? nodes.length,\n dropPosition: 'end' as const,\n };\n }\n else if (targetNode\n && target\n && isSortable(target)) {\n destination = destinationFromSortable(\n nodes,\n target.group,\n source.index,\n targetNode\n );\n }\n else {\n destination = null;\n }\n\n if (!destination) {\n return;\n }\n\n const context = createDropContext(\n sourceNode,\n destination.parentNode,\n targetNode,\n destination.dropPosition\n );\n\n if (!canMoveToParent(sourceNode, destination.parentNode)\n || (canDrop && !canDrop(context))) {\n return;\n }\n\n const initialParentKey = parentKeyFromCollectionId(source.initialGroup);\n const destinationParentKey = destination.parentNode?.id ?? null;\n const isSamePosition = initialParentKey !== undefined\n && initialParentKey === destinationParentKey\n && source.initialIndex === destination.index;\n\n if (isSamePosition) {\n return;\n }\n\n const movedNodes = moveSortableTreeNodeToIndex(\n nodes,\n sourceNode.id,\n destinationParentKey,\n destination.index\n );\n\n onChange(restoreSortableTree(movedNodes, setChildren));\n }\n\n return (\n <DragDropProvider\n key={ renderState.current.revision }\n sensors={ POINTER_SENSORS }\n onDragEnd={ handleDragEnd }\n >\n <SortableCollection\n nodes={ nodes }\n rootNodes={ nodes }\n parentNode={ null }\n renderItem={ children }\n canDrop={ canDrop }\n getDragHandleOptions={ getDragHandleOptions }\n className={ className }\n gap={ gap }\n nestedGap={ nestedGap }\n ariaLabel={ ariaLabel }\n />\n\n <DragOverlay\n className={ styles.dragOverlay }\n dropAnimation={ {\n duration: 160,\n easing: 'cubic-bezier(0.25, 1, 0.5, 1)',\n } }\n >\n { (source) => {\n const node = nodeData<T>(source)?.node;\n\n return node\n ? (\n <SortablePreview\n node={ node }\n renderItem={ children }\n nestedGap={ nestedGap }\n />\n )\n : null;\n } }\n </DragOverlay>\n </DragDropProvider>\n );\n}\n\nfunction SortableCollection<T>({\n nodes,\n rootNodes,\n parentNode,\n renderItem,\n canDrop,\n getDragHandleOptions,\n className,\n gap,\n nestedGap,\n ariaLabel,\n}: SortableCollectionProps<T>) {\n const { ref, isDropTarget } = useDroppable<SortableCollectionData<T>>({\n id: collectionId(parentNode),\n type: SORTABLE_COLLECTION_TYPE,\n data: { kind: 'collection', parentNode },\n disabled: nodes.length > 0,\n collisionPriority: 1,\n accept: source => canAcceptDrop(\n source,\n parentNode,\n null,\n 'end',\n canDrop\n ),\n });\n\n return (\n <div\n ref={ ref }\n role=\"list\"\n className={ cn(styles.list, className) }\n data-gap={ gap }\n data-drop-target={ isDropTarget || undefined }\n aria-label={ ariaLabel }\n >\n <For each={ nodes }>\n { node => (\n <SortableItem\n key={ node.id }\n node={ node }\n rootNodes={ rootNodes }\n renderItem={ renderItem }\n canDrop={ canDrop }\n getDragHandleOptions={ getDragHandleOptions }\n nestedGap={ nestedGap }\n />\n ) }\n </For>\n </div>\n );\n}\n\nfunction SortableItem<T>({\n node,\n rootNodes,\n renderItem,\n canDrop,\n getDragHandleOptions,\n nestedGap,\n}: SortableItemProps<T>) {\n const context = itemContext(node);\n const {\n alignment = 'center',\n edgeOffset = 'none',\n variant = 'plain',\n } = getDragHandleOptions?.(node.value, context) ?? {};\n const {\n handleRef,\n ref,\n targetRef,\n isDragging,\n isDropTarget,\n } = useSortable<SortableNodeData<T>>({\n id: node.id,\n index: node.index,\n group: collectionIdFromParentKey(nodeParentKey(rootNodes, node)),\n type: SORTABLE_ITEM_TYPE,\n data: { kind: 'node', node },\n accept: source => canAcceptDrop(\n source,\n node.parent == null\n ? null\n : findParentNode(rootNodes, node),\n node,\n 'before',\n canDrop\n ),\n });\n const nestedItems = node.canHaveChildren\n ? (\n <SortableCollection\n nodes={ node.children }\n rootNodes={ rootNodes }\n parentNode={ node }\n renderItem={ renderItem }\n canDrop={ canDrop }\n getDragHandleOptions={ getDragHandleOptions }\n gap={ nestedGap }\n nestedGap={ nestedGap }\n ariaLabel={ `${ node.textValue } items` }\n />\n )\n : null;\n\n return (\n <div\n ref={ ref }\n role=\"listitem\"\n className={ styles.item }\n data-level={ node.level }\n data-dragging={ isDragging || undefined }\n data-drop-target={ isDropTarget || undefined }\n >\n <div\n ref={ targetRef }\n className={ styles.dropTarget }\n data-container={ node.canHaveChildren || undefined }\n aria-hidden\n />\n\n <span\n ref={ handleRef }\n className={ styles.dragHandle }\n data-alignment={ alignment }\n data-edge-offset={ edgeOffset }\n data-variant={ variant }\n aria-hidden\n >\n <DotsDrag aria-hidden width={ 14 } height={ 14 } />\n </span>\n\n <div className={ styles.content }>\n { renderItem(node.value, {\n ...context,\n nestedItems,\n isDragging,\n isDropTarget,\n }) }\n </div>\n </div>\n );\n}\n\nfunction SortablePreview<T>({\n node,\n renderItem,\n nestedGap,\n}: {\n node: SortableTreeNode<T>;\n renderItem: (item: T, props: SortableListItemRenderProps<T>) => ReactNode;\n nestedGap: 'sm' | 'md';\n}): ReactElement {\n const nestedItems = node.canHaveChildren\n ? (\n <div className={ styles.previewList } data-gap={ nestedGap }>\n <For each={ node.children }>\n { child => (\n <SortablePreview\n key={ child.id }\n node={ child }\n renderItem={ renderItem }\n nestedGap={ nestedGap }\n />\n ) }\n </For>\n </div>\n )\n : null;\n\n return (\n <div className={ styles.dragPreviewItem }>\n { renderItem(node.value, {\n ...itemContext(node),\n nestedItems,\n isDragging: false,\n isDropTarget: false,\n }) }\n </div>\n );\n}\n\nfunction itemContext<T>(node: SortableTreeNode<T>): SortableListItemContext<T> {\n return {\n level: node.level,\n parent: node.parent,\n index: node.index,\n siblingCount: node.siblingCount,\n isFirst: node.index === 0,\n isLast: node.index === node.siblingCount - 1,\n hasChildren: node.children.length > 0,\n canHaveChildren: node.canHaveChildren,\n };\n}\n\nfunction canAcceptDrop<T>(\n source: { data: Record<string, unknown> },\n parentNode: SortableTreeNode<T> | null,\n targetNode: SortableTreeNode<T> | null,\n dropPosition: SortableListDropContext<T>['dropPosition'],\n canDrop?: (context: SortableListDropContext<T>) => boolean\n): boolean {\n const sourceNode = nodeData<T>(source)?.node;\n\n if (!sourceNode || !canMoveToParent(sourceNode, parentNode)) {\n return false;\n }\n\n return canDrop?.(\n createDropContext(sourceNode, parentNode, targetNode, dropPosition)\n ) ?? true;\n}\n\nfunction createDropContext<T>(\n sourceNode: SortableTreeNode<T>,\n parentNode: SortableTreeNode<T> | null,\n targetNode: SortableTreeNode<T> | null,\n dropPosition: SortableListDropContext<T>['dropPosition']\n): SortableListDropContext<T> {\n return {\n items: [sourceNode.value],\n target: targetNode?.value ?? null,\n sourceParent: sourceNode.parent,\n sourceLevel: sourceNode.level,\n parent: parentNode?.value ?? null,\n targetLevel: parentNode ? parentNode.level + 1 : 1,\n dropPosition,\n };\n}\n\nfunction canMoveToParent<T>(\n sourceNode: SortableTreeNode<T>,\n parentNode: SortableTreeNode<T> | null\n): boolean {\n return parentNode == null\n || (parentNode.id !== sourceNode.id\n && findSortableTreeNode(sourceNode.children, parentNode.id) == null);\n}\n\nfunction destinationFromSortable<T>(\n nodes: readonly SortableTreeNode<T>[],\n group: string | number | undefined,\n index: number,\n targetNode: SortableTreeNode<T> | null\n): SortableDestination<T> | null {\n const parentKey = parentKeyFromCollectionId(group);\n\n if (parentKey === undefined) {\n return null;\n }\n\n const parentNode = parentKey == null\n ? null\n : findSortableTreeNode(nodes, parentKey);\n\n if (parentKey != null && !parentNode) {\n return null;\n }\n\n const isAfterTarget = targetNode != null && index > targetNode.index;\n\n return {\n parentNode,\n index,\n dropPosition: isAfterTarget ? 'after' : 'before',\n };\n}\n\nfunction collectionId<T>(parentNode: SortableTreeNode<T> | null): string {\n return collectionIdFromParentKey(parentNode?.id ?? null);\n}\n\nfunction collectionIdFromParentKey(parentKey: string | null): string {\n return parentKey == null\n ? ROOT_COLLECTION_ID\n : `${ CHILD_COLLECTION_PREFIX }${ parentKey }`;\n}\n\nfunction parentKeyFromCollectionId(\n collectionId: string | number | undefined\n): string | null | undefined {\n if (collectionId === ROOT_COLLECTION_ID) {\n return null;\n }\n\n if (typeof collectionId === 'string'\n && collectionId.startsWith(CHILD_COLLECTION_PREFIX)) {\n return collectionId.slice(CHILD_COLLECTION_PREFIX.length);\n }\n\n return undefined;\n}\n\nfunction nodeParentKey<T>(\n nodes: readonly SortableTreeNode<T>[],\n target: SortableTreeNode<T>\n): string | null {\n return findParentNode(nodes, target)?.id ?? null;\n}\n\nfunction findParentNode<T>(\n nodes: readonly SortableTreeNode<T>[],\n target: SortableTreeNode<T>\n): SortableTreeNode<T> | null {\n for (const node of nodes) {\n if (node.children.some(child => child.id === target.id)) {\n return node;\n }\n\n const parent = findParentNode(node.children, target);\n\n if (parent) {\n return parent;\n }\n }\n\n return null;\n}\n\nfunction entityData<T>(\n entity: { data: Record<string, unknown> } | null\n): SortableNodeData<T> | SortableCollectionData<T> | null {\n const data = entity?.data;\n\n if (data?.kind === 'node' && 'node' in data) {\n return {\n kind: 'node',\n node: data.node as SortableTreeNode<T>,\n };\n }\n\n if (data?.kind === 'collection' && 'parentNode' in data) {\n return {\n kind: 'collection',\n parentNode: data.parentNode as SortableTreeNode<T> | null,\n };\n }\n\n return null;\n}\n\nfunction nodeData<T>(\n entity: { data: Record<string, unknown> } | null\n): SortableNodeData<T> | null {\n const data = entityData<T>(entity);\n\n return data?.kind === 'node' ? data : null;\n}\n\nSortableList.displayName = 'SortableList';\n"],"names":["ROOT_COLLECTION_ID","CHILD_COLLECTION_PREFIX","SORTABLE_ITEM_TYPE","SORTABLE_COLLECTION_TYPE","POINTER_SENSORS","PointerSensor","PRIMITIVE_KEY_PREFIX","SortableList","items","getItemKey","getTextValue","getChildren","setChildren","canHaveChildren","onChange","children","canDrop","getDragHandleOptions","className","gap","nestedGap","ariaLabel","keyState","useRef","getNodeKey","useCallback","item","path","itemKey","existingKey","key","nodes","useMemo","buildSortableTree","renderState","handleDragEnd","event","canceled","operation","source","target","isSortable","sourceNode","nodeData","targetData","entityData","targetNode","destination","destinationFromSortable","context","createDropContext","canMoveToParent","initialParentKey","parentKeyFromCollectionId","destinationParentKey","movedNodes","moveSortableTreeNodeToIndex","restoreSortableTree","DragDropProvider","_jsx","SortableCollection","DragOverlay","styles","node","SortablePreview","rootNodes","parentNode","renderItem","ref","isDropTarget","useDroppable","collectionId","canAcceptDrop","cn","For","SortableItem","itemContext","alignment","edgeOffset","variant","handleRef","targetRef","isDragging","useSortable","collectionIdFromParentKey","nodeParentKey","findParentNode","nestedItems","DotsDrag","child","dropPosition","findSortableTreeNode","group","index","parentKey","isAfterTarget","parent","entity","data"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SortableList.js","sources":["../../src/SortableList/SortableList.tsx"],"sourcesContent":["import {\n DragDropProvider,\n DragOverlay,\n PointerSensor,\n useDroppable,\n type DragEndEvent,\n} from '@dnd-kit/react';\nimport { isSortable, useSortable } from '@dnd-kit/react/sortable';\nimport { DotsDrag } from '@reforma/icons/14';\nimport { cn } from '@reforma/lib';\nimport { useCallback, useMemo, useState } from 'react';\n\nimport { For } from '../For';\nimport { Show } from '../Show';\nimport styles from './SortableList.module.css';\nimport {\n buildSortableTree,\n findSortableTreeNode,\n moveSortableTreeNodeToIndex,\n restoreSortableTree,\n type SortableTreeNode,\n} from './sortableTree';\n\nimport type { ReactElement, ReactNode } from 'react';\n\nexport type SortableListDragHandleAlignment = 'center' | 'top';\nexport type SortableListDragHandleEdgeOffset = 'none' | 'sm' | 'md';\nexport type SortableListDragHandleVariant = 'plain' | 'surface';\n\nexport interface SortableListDragHandleOptions {\n alignment?: SortableListDragHandleAlignment;\n edgeOffset?: SortableListDragHandleEdgeOffset;\n variant?: SortableListDragHandleVariant;\n}\n\nexport interface SortableListItemContext<T> {\n level: number;\n parent: T | null;\n index: number;\n siblingCount: number;\n isFirst: boolean;\n isLast: boolean;\n hasChildren: boolean;\n canHaveChildren: boolean;\n}\n\nexport interface SortableListItemRenderProps<T> extends SortableListItemContext<T> {\n nestedItems: ReactNode;\n isDragging: boolean;\n isDropTarget: boolean;\n}\n\nexport interface SortableListDropContext<T> {\n items: readonly T[];\n target: T | null;\n sourceParent: T | null;\n sourceLevel: number;\n parent: T | null;\n targetLevel: number;\n dropPosition: 'on' | 'before' | 'after' | 'end';\n}\n\ninterface SortableListBaseProps<T> {\n items: readonly T[];\n getKey?: (item: T, path: readonly number[]) => string;\n getTextValue: (item: T) => string;\n /** `move` is the dragged item and its index among its new siblings. */\n onChange: (items: T[], move: { item: T; index: number }) => void;\n children: (item: T, props: SortableListItemRenderProps<T>) => ReactNode;\n canDrop?: (context: SortableListDropContext<T>) => boolean;\n getDragHandleOptions?: (\n item: T,\n context: SortableListItemContext<T>\n ) => SortableListDragHandleOptions;\n className?: string;\n gap?: 'sm' | 'md';\n nestedGap?: 'sm' | 'md';\n /** `false` drops the grip: the whole item starts a drag. Default `true`. */\n handle?: boolean;\n 'aria-label': string;\n}\n\ninterface FlatSortableListProps {\n getChildren?: never;\n setChildren?: never;\n canHaveChildren?: never;\n}\n\ninterface NestedSortableListProps<T> {\n getChildren: (item: T) => readonly T[];\n setChildren: (item: T, children: T[]) => T;\n canHaveChildren?: (item: T) => boolean;\n}\n\nexport type SortableListProps<T> = SortableListBaseProps<T>\n & (FlatSortableListProps | NestedSortableListProps<T>);\n\ninterface SortableNodeData<T> {\n kind: 'node';\n node: SortableTreeNode<T>;\n}\n\ninterface SortableCollectionData<T> {\n kind: 'collection';\n parentNode: SortableTreeNode<T> | null;\n}\n\ninterface SortableCollectionProps<T> {\n nodes: readonly SortableTreeNode<T>[];\n rootNodes: readonly SortableTreeNode<T>[];\n parentNode: SortableTreeNode<T> | null;\n renderItem: (item: T, props: SortableListItemRenderProps<T>) => ReactNode;\n canDrop?: (context: SortableListDropContext<T>) => boolean;\n getDragHandleOptions?: (\n item: T,\n context: SortableListItemContext<T>\n ) => SortableListDragHandleOptions;\n className?: string;\n gap: 'sm' | 'md';\n nestedGap: 'sm' | 'md';\n handle: boolean;\n ariaLabel: string;\n}\n\ninterface SortableItemProps<T> extends Omit<SortableCollectionProps<T>, 'nodes' | 'className' | 'gap' | 'ariaLabel' | 'parentNode'> {\n node: SortableTreeNode<T>;\n}\n\ninterface SortableDestination<T> {\n parentNode: SortableTreeNode<T> | null;\n index: number;\n dropPosition: 'before' | 'after' | 'end';\n}\n\nconst ROOT_COLLECTION_ID = 'reforma-sortable:root';\nconst CHILD_COLLECTION_PREFIX = 'reforma-sortable:children:';\nconst SORTABLE_ITEM_TYPE = 'reforma-sortable:item';\nconst SORTABLE_COLLECTION_TYPE = 'reforma-sortable:collection';\nconst POINTER_SENSORS = [PointerSensor];\nconst PRIMITIVE_KEY_PREFIX = 'sortable:primitive:';\n\n/** Keys for items without `getKey`: stable per object, unique across lists. */\nconst objectKeys = new WeakMap<object, string>();\nlet nextObjectKey = 0;\n\n/**\n * Sortable collection with a pointer handle (or whole-item drag) and optional child groups.\n *\n * The rendered item is the complete draggable surface. Child collections can\n * accept moves when the caller's drop rules allow it.\n */\nexport function SortableList<T>({\n items,\n getKey: getItemKey,\n getTextValue,\n getChildren,\n setChildren,\n canHaveChildren,\n onChange,\n children,\n canDrop,\n getDragHandleOptions,\n className,\n gap = 'md',\n nestedGap = gap,\n handle = true,\n 'aria-label': ariaLabel,\n}: SortableListProps<T>) {\n const getNodeKey = useCallback((item: T, path: readonly number[]) => {\n const itemKey = getItemKey?.(item, path);\n\n if (itemKey != null) {\n return itemKey;\n }\n\n if (typeof item !== 'object' || item == null) {\n return `${ PRIMITIVE_KEY_PREFIX }${ path.join('.') }`;\n }\n\n const existingKey = objectKeys.get(item);\n\n if (existingKey) {\n return existingKey;\n }\n\n const key = `sortable:item:${ nextObjectKey }`;\n\n nextObjectKey += 1;\n objectKeys.set(item, key);\n\n return key;\n }, [getItemKey]);\n const nodes = useMemo(() => buildSortableTree(items, {\n getKey: getNodeKey,\n getTextValue,\n getChildren,\n canHaveChildren,\n }), [canHaveChildren, getChildren, getNodeKey, getTextValue, items]);\n const [renderState, setRenderState] = useState({ items, revision: 0 });\n\n if (renderState.items !== items) {\n setRenderState({ items, revision: renderState.revision + 1 });\n }\n\n function handleDragEnd(event: DragEndEvent) {\n const { canceled, operation } = event;\n const { source, target } = operation;\n\n if (canceled || !source || !isSortable(source)) {\n return;\n }\n\n const sourceNode = nodeData<T>(source)?.node;\n\n if (!sourceNode) {\n return;\n }\n\n const targetData = entityData<T>(target);\n const targetNode = targetData?.kind === 'node' ? targetData.node : null;\n let destination: SortableDestination<T> | null;\n\n if (targetData?.kind === 'collection') {\n destination = {\n parentNode: targetData.parentNode,\n index: targetData.parentNode?.children.length ?? nodes.length,\n dropPosition: 'end' as const,\n };\n }\n else if (targetNode\n && target\n && isSortable(target)) {\n destination = destinationFromSortable(\n nodes,\n target.group,\n source.index,\n targetNode\n );\n }\n else {\n destination = null;\n }\n\n if (!destination) {\n return;\n }\n\n const context = createDropContext(\n sourceNode,\n destination.parentNode,\n targetNode,\n destination.dropPosition\n );\n\n if (!canMoveToParent(sourceNode, destination.parentNode)\n || (canDrop && !canDrop(context))) {\n return;\n }\n\n const initialParentKey = parentKeyFromCollectionId(source.initialGroup);\n const destinationParentKey = destination.parentNode?.id ?? null;\n const isSamePosition = initialParentKey !== undefined\n && initialParentKey === destinationParentKey\n && source.initialIndex === destination.index;\n\n if (isSamePosition) {\n return;\n }\n\n const movedNodes = moveSortableTreeNodeToIndex(\n nodes,\n sourceNode.id,\n destinationParentKey,\n destination.index\n );\n\n onChange(restoreSortableTree(movedNodes, setChildren), {\n item: sourceNode.value,\n index: destination.index,\n });\n }\n\n return (\n <DragDropProvider\n // A cross-parent drop moves DOM nodes React does not own: remount nested trees on change.\n // Flat lists reconcile the optimistic order in place; a remount would cut the drop animation.\n key={ getChildren ? renderState.revision : undefined }\n sensors={ POINTER_SENSORS }\n onDragEnd={ handleDragEnd }\n >\n <SortableCollection\n nodes={ nodes }\n rootNodes={ nodes }\n parentNode={ null }\n renderItem={ children }\n canDrop={ canDrop }\n getDragHandleOptions={ getDragHandleOptions }\n className={ className }\n gap={ gap }\n nestedGap={ nestedGap }\n handle={ handle }\n ariaLabel={ ariaLabel }\n />\n\n <DragOverlay\n className={ styles.dragOverlay }\n dropAnimation={ {\n duration: 160,\n easing: 'cubic-bezier(0.25, 1, 0.5, 1)',\n } }\n >\n { (source) => {\n const node = nodeData<T>(source)?.node;\n\n return node\n ? (\n <SortablePreview\n node={ node }\n renderItem={ children }\n nestedGap={ nestedGap }\n />\n )\n : null;\n } }\n </DragOverlay>\n </DragDropProvider>\n );\n}\n\nfunction SortableCollection<T>({\n nodes,\n rootNodes,\n parentNode,\n renderItem,\n canDrop,\n getDragHandleOptions,\n className,\n gap,\n nestedGap,\n handle,\n ariaLabel,\n}: SortableCollectionProps<T>) {\n const { ref, isDropTarget } = useDroppable<SortableCollectionData<T>>({\n id: collectionId(parentNode),\n type: SORTABLE_COLLECTION_TYPE,\n data: { kind: 'collection', parentNode },\n disabled: nodes.length > 0,\n collisionPriority: 1,\n accept: source => canAcceptDrop(\n source,\n parentNode,\n null,\n 'end',\n canDrop\n ),\n });\n\n return (\n <div\n ref={ ref }\n role=\"list\"\n className={ cn(styles.list, className) }\n data-gap={ gap }\n data-drop-target={ isDropTarget || undefined }\n aria-label={ ariaLabel }\n >\n <For each={ nodes }>\n { node => (\n <SortableItem\n key={ node.id }\n node={ node }\n rootNodes={ rootNodes }\n renderItem={ renderItem }\n canDrop={ canDrop }\n getDragHandleOptions={ getDragHandleOptions }\n nestedGap={ nestedGap }\n handle={ handle }\n />\n ) }\n </For>\n </div>\n );\n}\n\nfunction SortableItem<T>({\n node,\n rootNodes,\n renderItem,\n canDrop,\n getDragHandleOptions,\n nestedGap,\n handle,\n}: SortableItemProps<T>) {\n const context = itemContext(node);\n const {\n alignment = 'center',\n edgeOffset = 'none',\n variant = 'plain',\n } = getDragHandleOptions?.(node.value, context) ?? {};\n const {\n handleRef,\n ref,\n targetRef,\n isDragging,\n isDropTarget,\n } = useSortable<SortableNodeData<T>>({\n id: node.id,\n index: node.index,\n group: collectionIdFromParentKey(nodeParentKey(rootNodes, node)),\n type: SORTABLE_ITEM_TYPE,\n data: { kind: 'node', node },\n accept: source => canAcceptDrop(\n source,\n node.parent == null\n ? null\n : findParentNode(rootNodes, node),\n node,\n 'before',\n canDrop\n ),\n });\n const nestedItems = node.canHaveChildren\n ? (\n <SortableCollection\n nodes={ node.children }\n rootNodes={ rootNodes }\n parentNode={ node }\n renderItem={ renderItem }\n canDrop={ canDrop }\n getDragHandleOptions={ getDragHandleOptions }\n gap={ nestedGap }\n nestedGap={ nestedGap }\n handle={ handle }\n ariaLabel={ `${ node.textValue } items` }\n />\n )\n : null;\n\n return (\n <div\n ref={ ref }\n role=\"listitem\"\n className={ styles.item }\n data-level={ node.level }\n data-dragging={ isDragging || undefined }\n data-drop-target={ isDropTarget || undefined }\n >\n <div\n ref={ targetRef }\n className={ styles.dropTarget }\n data-container={ node.canHaveChildren || undefined }\n aria-hidden\n />\n\n <Show when={ handle }>\n <span\n ref={ handleRef }\n className={ styles.dragHandle }\n data-alignment={ alignment }\n data-edge-offset={ edgeOffset }\n data-variant={ variant }\n aria-hidden\n >\n <DotsDrag aria-hidden width={ 14 } height={ 14 } />\n </span>\n </Show>\n\n <div className={ styles.content }>\n { renderItem(node.value, {\n ...context,\n nestedItems,\n isDragging,\n isDropTarget,\n }) }\n </div>\n </div>\n );\n}\n\nfunction SortablePreview<T>({\n node,\n renderItem,\n nestedGap,\n}: {\n node: SortableTreeNode<T>;\n renderItem: (item: T, props: SortableListItemRenderProps<T>) => ReactNode;\n nestedGap: 'sm' | 'md';\n}): ReactElement {\n const nestedItems = node.canHaveChildren\n ? (\n <div className={ styles.previewList } data-gap={ nestedGap }>\n <For each={ node.children }>\n { child => (\n <SortablePreview\n key={ child.id }\n node={ child }\n renderItem={ renderItem }\n nestedGap={ nestedGap }\n />\n ) }\n </For>\n </div>\n )\n : null;\n\n return (\n <div className={ styles.dragPreviewItem }>\n { renderItem(node.value, {\n ...itemContext(node),\n nestedItems,\n isDragging: false,\n isDropTarget: false,\n }) }\n </div>\n );\n}\n\nfunction itemContext<T>(node: SortableTreeNode<T>): SortableListItemContext<T> {\n return {\n level: node.level,\n parent: node.parent,\n index: node.index,\n siblingCount: node.siblingCount,\n isFirst: node.index === 0,\n isLast: node.index === node.siblingCount - 1,\n hasChildren: node.children.length > 0,\n canHaveChildren: node.canHaveChildren,\n };\n}\n\nfunction canAcceptDrop<T>(\n source: { data: Record<string, unknown> },\n parentNode: SortableTreeNode<T> | null,\n targetNode: SortableTreeNode<T> | null,\n dropPosition: SortableListDropContext<T>['dropPosition'],\n canDrop?: (context: SortableListDropContext<T>) => boolean\n): boolean {\n const sourceNode = nodeData<T>(source)?.node;\n\n if (!sourceNode || !canMoveToParent(sourceNode, parentNode)) {\n return false;\n }\n\n return canDrop?.(\n createDropContext(sourceNode, parentNode, targetNode, dropPosition)\n ) ?? true;\n}\n\nfunction createDropContext<T>(\n sourceNode: SortableTreeNode<T>,\n parentNode: SortableTreeNode<T> | null,\n targetNode: SortableTreeNode<T> | null,\n dropPosition: SortableListDropContext<T>['dropPosition']\n): SortableListDropContext<T> {\n return {\n items: [sourceNode.value],\n target: targetNode?.value ?? null,\n sourceParent: sourceNode.parent,\n sourceLevel: sourceNode.level,\n parent: parentNode?.value ?? null,\n targetLevel: parentNode ? parentNode.level + 1 : 1,\n dropPosition,\n };\n}\n\nfunction canMoveToParent<T>(\n sourceNode: SortableTreeNode<T>,\n parentNode: SortableTreeNode<T> | null\n): boolean {\n return parentNode == null\n || (parentNode.id !== sourceNode.id\n && findSortableTreeNode(sourceNode.children, parentNode.id) == null);\n}\n\nfunction destinationFromSortable<T>(\n nodes: readonly SortableTreeNode<T>[],\n group: string | number | undefined,\n index: number,\n targetNode: SortableTreeNode<T> | null\n): SortableDestination<T> | null {\n const parentKey = parentKeyFromCollectionId(group);\n\n if (parentKey === undefined) {\n return null;\n }\n\n const parentNode = parentKey == null\n ? null\n : findSortableTreeNode(nodes, parentKey);\n\n if (parentKey != null && !parentNode) {\n return null;\n }\n\n const isAfterTarget = targetNode != null && index > targetNode.index;\n\n return {\n parentNode,\n index,\n dropPosition: isAfterTarget ? 'after' : 'before',\n };\n}\n\nfunction collectionId<T>(parentNode: SortableTreeNode<T> | null): string {\n return collectionIdFromParentKey(parentNode?.id ?? null);\n}\n\nfunction collectionIdFromParentKey(parentKey: string | null): string {\n return parentKey == null\n ? ROOT_COLLECTION_ID\n : `${ CHILD_COLLECTION_PREFIX }${ parentKey }`;\n}\n\nfunction parentKeyFromCollectionId(\n collectionId: string | number | undefined\n): string | null | undefined {\n if (collectionId === ROOT_COLLECTION_ID) {\n return null;\n }\n\n if (typeof collectionId === 'string'\n && collectionId.startsWith(CHILD_COLLECTION_PREFIX)) {\n return collectionId.slice(CHILD_COLLECTION_PREFIX.length);\n }\n\n return undefined;\n}\n\nfunction nodeParentKey<T>(\n nodes: readonly SortableTreeNode<T>[],\n target: SortableTreeNode<T>\n): string | null {\n return findParentNode(nodes, target)?.id ?? null;\n}\n\nfunction findParentNode<T>(\n nodes: readonly SortableTreeNode<T>[],\n target: SortableTreeNode<T>\n): SortableTreeNode<T> | null {\n for (const node of nodes) {\n if (node.children.some(child => child.id === target.id)) {\n return node;\n }\n\n const parent = findParentNode(node.children, target);\n\n if (parent) {\n return parent;\n }\n }\n\n return null;\n}\n\nfunction entityData<T>(\n entity: { data: Record<string, unknown> } | null\n): SortableNodeData<T> | SortableCollectionData<T> | null {\n const data = entity?.data;\n\n if (data?.kind === 'node' && 'node' in data) {\n return {\n kind: 'node',\n node: data.node as SortableTreeNode<T>,\n };\n }\n\n if (data?.kind === 'collection' && 'parentNode' in data) {\n return {\n kind: 'collection',\n parentNode: data.parentNode as SortableTreeNode<T> | null,\n };\n }\n\n return null;\n}\n\nfunction nodeData<T>(\n entity: { data: Record<string, unknown> } | null\n): SortableNodeData<T> | null {\n const data = entityData<T>(entity);\n\n return data?.kind === 'node' ? data : null;\n}\n\nSortableList.displayName = 'SortableList';\n"],"names":["ROOT_COLLECTION_ID","CHILD_COLLECTION_PREFIX","SORTABLE_ITEM_TYPE","SORTABLE_COLLECTION_TYPE","POINTER_SENSORS","PointerSensor","PRIMITIVE_KEY_PREFIX","objectKeys","nextObjectKey","SortableList","items","getItemKey","getTextValue","getChildren","setChildren","canHaveChildren","onChange","children","canDrop","getDragHandleOptions","className","gap","nestedGap","handle","ariaLabel","getNodeKey","useCallback","item","path","itemKey","existingKey","key","nodes","useMemo","buildSortableTree","renderState","setRenderState","useState","handleDragEnd","event","canceled","operation","source","target","isSortable","sourceNode","nodeData","targetData","entityData","targetNode","destination","destinationFromSortable","context","createDropContext","canMoveToParent","initialParentKey","parentKeyFromCollectionId","destinationParentKey","movedNodes","moveSortableTreeNodeToIndex","restoreSortableTree","_jsxs","DragDropProvider","_jsx","SortableCollection","DragOverlay","styles","node","SortablePreview","rootNodes","parentNode","renderItem","ref","isDropTarget","useDroppable","collectionId","canAcceptDrop","cn","For","SortableItem","itemContext","alignment","edgeOffset","variant","handleRef","targetRef","isDragging","useSortable","collectionIdFromParentKey","nodeParentKey","findParentNode","nestedItems","Show","DotsDrag","child","dropPosition","findSortableTreeNode","group","index","parentKey","isAfterTarget","parent","entity","data"],"mappings":"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"}
|
|
@@ -13,7 +13,7 @@ export type ComposerBannerStatusProps = HTMLAttributes<HTMLDivElement> & {
|
|
|
13
13
|
onAction?: () => void;
|
|
14
14
|
/** Action button tint. Default `secondary`. */
|
|
15
15
|
actionColor?: ButtonColor;
|
|
16
|
-
/** Press anywhere on the row except the action. */
|
|
16
|
+
/** Press anywhere on the row except the action. The action then shows on hover or focus. */
|
|
17
17
|
onPress?: () => void;
|
|
18
18
|
icon?: ReactNode;
|
|
19
19
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComposerBanner.d.ts","sourceRoot":"","sources":["../../../src/chat/ComposerBanner/ComposerBanner.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAMxD,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvD,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,GAAG;IAC9E,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,yDAAyD;IACzD,KAAK,CAAC,EAAE,QAAQ,CAAC;CACpB,CAAC;AAEF,qDAAqD;AACrD,wBAAgB,cAAc,CAAC,EAC3B,QAAQ,EACR,SAAS,EACT,KAAK,EACL,IAAI,EACJ,GAAG,KAAK,EACX,EAAE,mBAAmB,+BAYrB;AAED,MAAM,MAAM,yBAAyB,GAAG,cAAc,CAAC,cAAc,CAAC,GAAG;IACrE,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,
|
|
1
|
+
{"version":3,"file":"ComposerBanner.d.ts","sourceRoot":"","sources":["../../../src/chat/ComposerBanner/ComposerBanner.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAMxD,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvD,MAAM,MAAM,mBAAmB,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,OAAO,CAAC,GAAG;IAC9E,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,yDAAyD;IACzD,KAAK,CAAC,EAAE,QAAQ,CAAC;CACpB,CAAC;AAEF,qDAAqD;AACrD,wBAAgB,cAAc,CAAC,EAC3B,QAAQ,EACR,SAAS,EACT,KAAK,EACL,IAAI,EACJ,GAAG,KAAK,EACX,EAAE,mBAAmB,+BAYrB;AAED,MAAM,MAAM,yBAAyB,GAAG,cAAc,CAAC,cAAc,CAAC,GAAG;IACrE,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,+CAA+C;IAC/C,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,4FAA4F;IAC5F,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,IAAI,CAAC,EAAE,SAAS,CAAC;CACpB,CAAC;AAEF,uEAAuE;AACvE,wBAAgB,oBAAoB,CAAC,EACjC,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,WAAyB,EACzB,OAAO,EACP,IAAI,EACJ,SAAS,EACT,GAAG,KAAK,EACX,EAAE,yBAAyB,+BAsC3B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComposerBanner.js","sources":["../../../src/chat/ComposerBanner/ComposerBanner.tsx"],"sourcesContent":["import { cn } from '@reforma/lib';\n\nimport { Button, type ButtonColor } from '../../Button';\nimport { Pressable } from '../../Pressable';\nimport { Show } from '../../Show';\nimport { Text } from '../../Text';\nimport styles from './ComposerBanner.module.css';\n\nimport type { HTMLAttributes, ReactNode } from 'react';\n\nexport type ComposerBannerProps = Omit<HTMLAttributes<HTMLDivElement>, 'color'> & {\n children?: ReactNode;\n /** Plate tint. Default is the muted interrupt chrome. */\n color?: 'danger';\n};\n\n/** Shared plate above the composer — chrome only. */\nexport function ComposerBanner({\n children,\n className,\n color,\n role,\n ...props\n}: ComposerBannerProps) {\n return (\n <div\n data-slot=\"composer-banner\"\n data-color={ color }\n role={ role ?? (color === 'danger' ? 'alert' : undefined) }\n className={ cn(styles.root, className) }\n { ...props }\n >\n { children }\n </div>\n );\n}\n\nexport type ComposerBannerStatusProps = HTMLAttributes<HTMLDivElement> & {\n children: ReactNode;\n action: string;\n onAction?: () => void;\n /** Action button tint. Default `secondary`. */\n actionColor?: ButtonColor;\n /** Press anywhere on the row except the action. */\n onPress?: () => void;\n icon?: ReactNode;\n};\n\n/** One status row inside {@link ComposerBanner} — message + action. */\nexport function ComposerBannerStatus({\n children,\n action,\n onAction,\n actionColor = 'secondary',\n onPress,\n icon,\n className,\n ...props\n}: ComposerBannerStatusProps) {\n const message = (\n <>\n <Show when={ icon }>\n <span className={ styles.icon }>\n { icon }\n </span>\n </Show>\n <Text variant=\"xs\" className={ styles.text }>\n { children }\n </Text>\n </>\n );\n\n return (\n <div className={ cn(styles.status, className) } data-pressable={ onPress ? true : undefined } { ...props }>\n <Show when={ onPress } fallback={ message }>\n { press => (\n <Pressable onPress={ press }>\n <span role=\"button\" tabIndex={ 0 } className={ styles.press }>\n { message }\n </span>\n </Pressable>\n ) }\n </Show>\n\n <Button\n size=\"xs\"\n variant=\"ghost\"\n color={ actionColor }\n className={ styles.action }\n isDisabled={ !onAction }\n onPress={ onAction }\n >\n { action }\n </Button>\n </div>\n );\n}\n"],"names":["ComposerBanner","children","className","color","role","props","cn","styles","ComposerBannerStatus","action","onAction","actionColor","onPress","icon","message","_Fragment","_jsx","Show","Text","press","Pressable","Button"],"mappings":";;;;;;;AAQO,SAASA,EAAe;AAAA,EAC7B,UAAAC;AAAA,EACA,WAAAC;AAAA,EACA,OAAAC;AAAA,EACA,MAAAC;AAAA,EACA,GAAGC;AACL,GAAG;AACD,2BAAyB,OAAO;AAAA,IAC9B,aAAa;AAAA,IACb,cAAcF;AAAA,IACd,MAAMC,MAASD,MAAU,WAAW,UAAU;AAAA,IAC9C,WAAWG,EAAGC,EAAO,MAAML,CAAS;AAAA,IACpC,GAAGG;AAAA,IACH,UAAAJ;AAAA,EAAA,CACD;AACH;AAEO,SAASO,EAAqB;AAAA,EACnC,UAAAP;AAAA,EACA,QAAAQ;AAAA,EACA,UAAAC;AAAA,EACA,aAAAC,IAAc;AAAA,EACd,SAAAC;AAAA,EACA,MAAAC;AAAA,EACA,WAAAX;AAAA,EACA,GAAGG;AACL,GAAG;AACD,QAAMS,sBAA6BC,GAAW;AAAA,IAC5C,UAAU,CAAcC,gBAAAA,EAAKC,GAAM;AAAA,MACjC,MAAMJ;AAAA,MACN,4BAA4B,QAAQ;AAAA,QAClC,WAAWN,EAAO;AAAA,QAClB,UAAUM;AAAA,MAAA,CACX;AAAA,IAAA,CACF,GAAgBG,gBAAAA,EAAKE,GAAM;AAAA,MAC1B,SAAS;AAAA,MACT,WAAWX,EAAO;AAAA,MAClB,UAAAN;AAAA,IAAA,CACD,CAAC;AAAA,EAAA,CACH;AACD,2BAA0B,OAAO;AAAA,IAC/B,WAAWK,EAAGC,EAAO,QAAQL,CAAS;AAAA,IACtC,kBAAkBU,IAAU,KAAO;AAAA,IACnC,GAAGP;AAAA,IACH,UAAU,CAAcW,gBAAAA,EAAKC,GAAM;AAAA,MACjC,MAAML;AAAA,MACN,UAAUE;AAAA,MACV,UAAU,CAAAK,MAAsBH,gBAAAA,EAAKI,GAAW;AAAA,QAC9C,SAASD;AAAA,QACT,4BAA4B,QAAQ;AAAA,UAClC,MAAM;AAAA,UACN,UAAU;AAAA,UACV,WAAWZ,EAAO;AAAA,UAClB,UAAUO;AAAA,QAAA,CACX;AAAA,MAAA,CACF;AAAA,IAAA,CACF,GAAgBE,gBAAAA,EAAKK,GAAQ;AAAA,MAC5B,MAAM;AAAA,MACN,SAAS;AAAA,MACT,OAAOV;AAAA,MACP,WAAWJ,EAAO;AAAA,MAClB,YAAY,CAACG;AAAA,MACb,SAASA;AAAA,MACT,UAAUD;AAAA,IAAA,CACX,CAAC;AAAA,EAAA,CACH;AACH;"}
|
|
1
|
+
{"version":3,"file":"ComposerBanner.js","sources":["../../../src/chat/ComposerBanner/ComposerBanner.tsx"],"sourcesContent":["import { cn } from '@reforma/lib';\n\nimport { Button, type ButtonColor } from '../../Button';\nimport { Pressable } from '../../Pressable';\nimport { Show } from '../../Show';\nimport { Text } from '../../Text';\nimport styles from './ComposerBanner.module.css';\n\nimport type { HTMLAttributes, ReactNode } from 'react';\n\nexport type ComposerBannerProps = Omit<HTMLAttributes<HTMLDivElement>, 'color'> & {\n children?: ReactNode;\n /** Plate tint. Default is the muted interrupt chrome. */\n color?: 'danger';\n};\n\n/** Shared plate above the composer — chrome only. */\nexport function ComposerBanner({\n children,\n className,\n color,\n role,\n ...props\n}: ComposerBannerProps) {\n return (\n <div\n data-slot=\"composer-banner\"\n data-color={ color }\n role={ role ?? (color === 'danger' ? 'alert' : undefined) }\n className={ cn(styles.root, className) }\n { ...props }\n >\n { children }\n </div>\n );\n}\n\nexport type ComposerBannerStatusProps = HTMLAttributes<HTMLDivElement> & {\n children: ReactNode;\n action: string;\n onAction?: () => void;\n /** Action button tint. Default `secondary`. */\n actionColor?: ButtonColor;\n /** Press anywhere on the row except the action. The action then shows on hover or focus. */\n onPress?: () => void;\n icon?: ReactNode;\n};\n\n/** One status row inside {@link ComposerBanner} — message + action. */\nexport function ComposerBannerStatus({\n children,\n action,\n onAction,\n actionColor = 'secondary',\n onPress,\n icon,\n className,\n ...props\n}: ComposerBannerStatusProps) {\n const message = (\n <>\n <Show when={ icon }>\n <span className={ styles.icon }>\n { icon }\n </span>\n </Show>\n <Text variant=\"xs\" className={ styles.text }>\n { children }\n </Text>\n </>\n );\n\n return (\n <div className={ cn(styles.status, className) } data-pressable={ onPress ? true : undefined } { ...props }>\n <Show when={ onPress } fallback={ message }>\n { press => (\n <Pressable onPress={ press }>\n <span role=\"button\" tabIndex={ 0 } className={ styles.press }>\n { message }\n </span>\n </Pressable>\n ) }\n </Show>\n\n <Button\n size=\"xs\"\n variant=\"ghost\"\n color={ actionColor }\n className={ styles.action }\n isDisabled={ !onAction }\n onPress={ onAction }\n >\n { action }\n </Button>\n </div>\n );\n}\n"],"names":["ComposerBanner","children","className","color","role","props","cn","styles","ComposerBannerStatus","action","onAction","actionColor","onPress","icon","message","_Fragment","_jsx","Show","Text","press","Pressable","Button"],"mappings":";;;;;;;AAQO,SAASA,EAAe;AAAA,EAC7B,UAAAC;AAAA,EACA,WAAAC;AAAA,EACA,OAAAC;AAAA,EACA,MAAAC;AAAA,EACA,GAAGC;AACL,GAAG;AACD,2BAAyB,OAAO;AAAA,IAC9B,aAAa;AAAA,IACb,cAAcF;AAAA,IACd,MAAMC,MAASD,MAAU,WAAW,UAAU;AAAA,IAC9C,WAAWG,EAAGC,EAAO,MAAML,CAAS;AAAA,IACpC,GAAGG;AAAA,IACH,UAAAJ;AAAA,EAAA,CACD;AACH;AAEO,SAASO,EAAqB;AAAA,EACnC,UAAAP;AAAA,EACA,QAAAQ;AAAA,EACA,UAAAC;AAAA,EACA,aAAAC,IAAc;AAAA,EACd,SAAAC;AAAA,EACA,MAAAC;AAAA,EACA,WAAAX;AAAA,EACA,GAAGG;AACL,GAAG;AACD,QAAMS,sBAA6BC,GAAW;AAAA,IAC5C,UAAU,CAAcC,gBAAAA,EAAKC,GAAM;AAAA,MACjC,MAAMJ;AAAA,MACN,4BAA4B,QAAQ;AAAA,QAClC,WAAWN,EAAO;AAAA,QAClB,UAAUM;AAAA,MAAA,CACX;AAAA,IAAA,CACF,GAAgBG,gBAAAA,EAAKE,GAAM;AAAA,MAC1B,SAAS;AAAA,MACT,WAAWX,EAAO;AAAA,MAClB,UAAAN;AAAA,IAAA,CACD,CAAC;AAAA,EAAA,CACH;AACD,2BAA0B,OAAO;AAAA,IAC/B,WAAWK,EAAGC,EAAO,QAAQL,CAAS;AAAA,IACtC,kBAAkBU,IAAU,KAAO;AAAA,IACnC,GAAGP;AAAA,IACH,UAAU,CAAcW,gBAAAA,EAAKC,GAAM;AAAA,MACjC,MAAML;AAAA,MACN,UAAUE;AAAA,MACV,UAAU,CAAAK,MAAsBH,gBAAAA,EAAKI,GAAW;AAAA,QAC9C,SAASD;AAAA,QACT,4BAA4B,QAAQ;AAAA,UAClC,MAAM;AAAA,UACN,UAAU;AAAA,UACV,WAAWZ,EAAO;AAAA,UAClB,UAAUO;AAAA,QAAA,CACX;AAAA,MAAA,CACF;AAAA,IAAA,CACF,GAAgBE,gBAAAA,EAAKK,GAAQ;AAAA,MAC5B,MAAM;AAAA,MACN,SAAS;AAAA,MACT,OAAOV;AAAA,MACP,WAAWJ,EAAO;AAAA,MAClB,YAAY,CAACG;AAAA,MACb,SAASA;AAAA,MACT,UAAUD;AAAA,IAAA,CACX,CAAC;AAAA,EAAA,CACH;AACH;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
@layer components{.ComposerBanner_root_HyjFf2{display:flex;flex-direction:column;margin:0 var(--spacing-md);border-top-right-radius:calc(var(--radius-md) * var(--squircle-radius-factor));border-top-left-radius:calc(var(--radius-md) * var(--squircle-radius-factor));min-width:0;corner-shape:superellipse(var(--squircle-value)) superellipse(var(--squircle-value)) square square;background-color:var(--color-secondary-muted-light);overflow:hidden}.dark .ComposerBanner_root_HyjFf2:not([data-color]){background-color:var(--color-light-700)}.ComposerBanner_root_HyjFf2[data-color=danger]{background-color:var(--color-danger-muted-light);color:var(--color-danger-text)}.ComposerBanner_status_EIdxnS+.ComposerBanner_status_EIdxnS{position:relative}.ComposerBanner_status_EIdxnS+.ComposerBanner_status_EIdxnS:before{position:absolute;top:0;right:var(--spacing-sm);left:var(--spacing-sm);border-top:1px solid var(--color-secondary-muted-border);content:""}.ComposerBanner_root_HyjFf2[data-color=danger] .ComposerBanner_status_EIdxnS+.ComposerBanner_status_EIdxnS:before{border-top-color:var(--color-danger-muted-border)}.ComposerBanner_status_EIdxnS{display:flex;justify-content:space-between;align-items:center;gap:var(--spacing-sm);padding:var(--spacing-sm) var(--spacing-sm) var(--spacing-sm) var(--spacing-lg);word-wrap:break-word}.ComposerBanner_icon_5Md4lZ{display:flex;flex-shrink:0;color:var(--color-secondary-muted-text)}.ComposerBanner_text_UFktfG{flex:1;max-height:3lh;overflow:hidden}.ComposerBanner_status_EIdxnS[data-pressable]{position:relative}.ComposerBanner_press_FFVYdF{display:flex;flex:1;align-items:center;gap:var(--spacing-sm);cursor:pointer;outline:none;min-width:0}.ComposerBanner_press_FFVYdF:after{position:absolute;inset:0;content:""}.ComposerBanner_press_FFVYdF:focus-visible:after{outline:var(--spacing-4) solid var(--color-primary-muted-border);outline-offset:calc(var(--spacing-4) * -1)}.
|
|
1
|
+
@layer components{.ComposerBanner_root_HyjFf2{display:flex;flex-direction:column;margin:0 var(--spacing-md);border-top-right-radius:calc(var(--radius-md) * var(--squircle-radius-factor));border-top-left-radius:calc(var(--radius-md) * var(--squircle-radius-factor));min-width:0;corner-shape:superellipse(var(--squircle-value)) superellipse(var(--squircle-value)) square square;background-color:var(--color-secondary-muted-light);overflow:hidden}.dark .ComposerBanner_root_HyjFf2:not([data-color]){background-color:var(--color-light-700)}.ComposerBanner_root_HyjFf2[data-color=danger]{background-color:var(--color-danger-muted-light);color:var(--color-danger-text)}.ComposerBanner_status_EIdxnS+.ComposerBanner_status_EIdxnS{position:relative}.ComposerBanner_status_EIdxnS+.ComposerBanner_status_EIdxnS:before{position:absolute;top:0;right:var(--spacing-sm);left:var(--spacing-sm);border-top:1px solid var(--color-secondary-muted-border);content:""}.ComposerBanner_root_HyjFf2[data-color=danger] .ComposerBanner_status_EIdxnS+.ComposerBanner_status_EIdxnS:before{border-top-color:var(--color-danger-muted-border)}.ComposerBanner_status_EIdxnS{display:flex;justify-content:space-between;align-items:center;gap:var(--spacing-sm);padding:var(--spacing-sm) var(--spacing-sm) var(--spacing-sm) var(--spacing-lg);word-wrap:break-word}.ComposerBanner_icon_5Md4lZ{display:flex;flex-shrink:0;color:var(--color-secondary-muted-text)}.ComposerBanner_text_UFktfG{flex:1;max-height:3lh;overflow:hidden}.ComposerBanner_status_EIdxnS[data-pressable]{position:relative;isolation:isolate;min-height:calc(var(--spacing-30) + var(--spacing-xs) * 2)}.ComposerBanner_status_EIdxnS[data-pressable]:after{position:absolute;z-index:-1;inset:var(--spacing-xs);border-radius:calc(var(--radius-sm) * var(--squircle-radius-factor));content:"";corner-shape:superellipse(var(--squircle-value));transition:background-color var(--transition-duration-fast);pointer-events:none}.ComposerBanner_status_EIdxnS[data-pressable]:hover:after{background-color:var(--color-secondary-muted-light)}@media(hover:hover){.ComposerBanner_status_EIdxnS[data-pressable] .ComposerBanner_action_EUqshm{opacity:0;transition:opacity var(--transition-duration-fast)}.ComposerBanner_status_EIdxnS[data-pressable]:hover .ComposerBanner_action_EUqshm,.ComposerBanner_status_EIdxnS[data-pressable]:focus-within .ComposerBanner_action_EUqshm{opacity:1}}.ComposerBanner_press_FFVYdF{display:flex;flex:1;align-items:center;gap:var(--spacing-sm);cursor:pointer;outline:none;min-width:0}.ComposerBanner_press_FFVYdF:after{position:absolute;inset:0;content:""}.ComposerBanner_press_FFVYdF:focus-visible:after{outline:var(--spacing-4) solid var(--color-primary-muted-border);outline-offset:calc(var(--spacing-4) * -1)}.ComposerBanner_action_EUqshm{position:relative}}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
const o = "ComposerBanner_root_HyjFf2", s = "ComposerBanner_status_EIdxnS", t = "ComposerBanner_icon_5Md4lZ", n = "ComposerBanner_text_UFktfG", e = "
|
|
1
|
+
const o = "ComposerBanner_root_HyjFf2", s = "ComposerBanner_status_EIdxnS", t = "ComposerBanner_icon_5Md4lZ", n = "ComposerBanner_text_UFktfG", e = "ComposerBanner_action_EUqshm", r = "ComposerBanner_press_FFVYdF", a = {
|
|
2
2
|
root: o,
|
|
3
3
|
status: s,
|
|
4
4
|
icon: t,
|
|
5
5
|
text: n,
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
action: e,
|
|
7
|
+
press: r
|
|
8
8
|
};
|
|
9
9
|
export {
|
|
10
|
-
|
|
10
|
+
e as action,
|
|
11
11
|
a as default,
|
|
12
12
|
t as icon,
|
|
13
|
-
|
|
13
|
+
r as press,
|
|
14
14
|
o as root,
|
|
15
15
|
s as status,
|
|
16
16
|
n as text
|
|
@@ -1 +1 @@
|
|
|
1
|
-
.MessagePhaseSection_root_Cqd0t1{display:flex;flex-direction:column;gap:var(--spacing-lg);margin-top:var(--spacing-md);width:100%;color:var(--color-text);font-weight:400;font-size:var(--text-md);line-height:var(--leading-md);font-family:Onest,sans-serif;letter-spacing:0}.MessagePhaseSection_root_Cqd0t1:first-child{margin-top:0}.MessagePhaseSection_header_a11Bwm{width:100%;--reforma-button-opacity--hover: 1}.MessagePhaseSection_headerContent_6gdB1H{justify-content:start;gap:var(--spacing-md);width:100%}.MessagePhaseSection_headerTitle_RT3fFZ{display:flex;flex-shrink:0;overflow:hidden}.MessagePhaseSection_headerSummary_HTSuia{display:flex;align-items:center;gap:var(--spacing-md);min-width:0;font-weight:400;font-size:var(--text-sm);line-height:var(--leading-sm);font-family:Onest,sans-serif;letter-spacing:0}.MessagePhaseSection_chevronIcon_7lOW0r{flex-shrink:0;opacity:0;transition:all .15s ease}.MessagePhaseSection_chevronIcon_7lOW0r[aria-expanded=true]{opacity:1}.MessagePhaseSection_header_a11Bwm:hover .MessagePhaseSection_chevronIcon_7lOW0r,.MessagePhaseSection_header_a11Bwm:focus-visible .MessagePhaseSection_chevronIcon_7lOW0r{opacity:1}.MessagePhaseSection_phasePanel_UxIl4o{position:relative;
|
|
1
|
+
.MessagePhaseSection_root_Cqd0t1{display:flex;flex-direction:column;gap:var(--spacing-lg);margin-top:var(--spacing-md);width:100%;color:var(--color-text);font-weight:400;font-size:var(--text-md);line-height:var(--leading-md);font-family:Onest,sans-serif;letter-spacing:0}.MessagePhaseSection_root_Cqd0t1:first-child{margin-top:0}.MessagePhaseSection_header_a11Bwm{width:100%;--reforma-button-opacity--hover: 1}.MessagePhaseSection_headerContent_6gdB1H{justify-content:start;gap:var(--spacing-md);width:100%}.MessagePhaseSection_headerTitle_RT3fFZ{display:flex;flex-shrink:0;overflow:hidden}.MessagePhaseSection_headerSummary_HTSuia{display:flex;align-items:center;gap:var(--spacing-md);min-width:0;font-weight:400;font-size:var(--text-sm);line-height:var(--leading-sm);font-family:Onest,sans-serif;letter-spacing:0}.MessagePhaseSection_chevronIcon_7lOW0r{flex-shrink:0;opacity:0;transition:all .15s ease}.MessagePhaseSection_chevronIcon_7lOW0r[aria-expanded=true]{opacity:1}.MessagePhaseSection_header_a11Bwm:hover .MessagePhaseSection_chevronIcon_7lOW0r,.MessagePhaseSection_header_a11Bwm:focus-visible .MessagePhaseSection_chevronIcon_7lOW0r{opacity:1}.MessagePhaseSection_phasePanel_UxIl4o{position:relative;width:100%}.MessagePhaseSection_phasePanelContent_xFRBiK{display:flex;flex-direction:column;gap:var(--spacing-lg)}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Assistant turn segments and streaming pending loader.
|
|
3
3
|
* A finished text answer folds the work into one "Worked for …" disclosure.
|
|
4
|
-
*
|
|
4
|
+
* The latest turn keeps its phase rows open when cancelled or not ending on text;
|
|
5
|
+
* an older one folds them anyway.
|
|
5
6
|
*/
|
|
6
7
|
export declare const MessageAssistantBody: (({ hideSources, }?: {
|
|
7
8
|
/** Editor footer owns citations — drop in-body Sources groups. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageAssistantBody.d.ts","sourceRoot":"","sources":["../../../../src/chat/Message/turn/MessageAssistantBody.tsx"],"names":[],"mappings":"AAmJA
|
|
1
|
+
{"version":3,"file":"MessageAssistantBody.d.ts","sourceRoot":"","sources":["../../../../src/chat/Message/turn/MessageAssistantBody.tsx"],"names":[],"mappings":"AAmJA;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,uBAE9B;IACC,kEAAkE;IAClE,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;IAFG,kEAAkE;kBACpD,OAAO;;uCAFtB;QACC,kEAAkE;QAClE,WAAW,CAAC,EAAE,OAAO,CAAC;KACzB;CAmFC,CAAC"}
|
|
@@ -1,18 +1,18 @@
|
|
|
1
|
-
import { ChevronDown as
|
|
2
|
-
import { cn as
|
|
3
|
-
import { observer as
|
|
4
|
-
import { Button as
|
|
5
|
-
import { Collapsible as
|
|
6
|
-
import { For as
|
|
7
|
-
import { Show as
|
|
1
|
+
import { ChevronDown as C } from "@reforma/icons/8";
|
|
2
|
+
import { cn as T } from "@reforma/lib";
|
|
3
|
+
import { observer as F } from "mobx-react-lite";
|
|
4
|
+
import { Button as y } from "../../../Button/Button.js";
|
|
5
|
+
import { Collapsible as L, useCollapsible as P, CollapsibleTrigger as M, CollapsibleContent as W } from "../../../Collapsible/Collapsible.js";
|
|
6
|
+
import { For as N } from "../../../For/For.js";
|
|
7
|
+
import { Show as u } from "../../../Show/Show.js";
|
|
8
8
|
import { ConversationPendingLoader as S } from "../../Conversation/ConversationPendingLoader.js";
|
|
9
|
-
import { streamingPhaseActiveIndex as
|
|
10
|
-
import { MessagePhaseSection as
|
|
9
|
+
import { streamingPhaseActiveIndex as j, partsFromSegmentGroups as B } from "../normalize/normalizeMessageParts.js";
|
|
10
|
+
import { MessagePhaseSection as E } from "../segments/MessagePhaseSection.js";
|
|
11
11
|
import v from "./Message.module.css.js";
|
|
12
|
-
import { useMessageTurn as
|
|
13
|
-
import { splitFinishedWork as
|
|
14
|
-
import { jsx as r, jsxs as
|
|
15
|
-
function
|
|
12
|
+
import { useMessageTurn as $ } from "./messageTurnContext.js";
|
|
13
|
+
import { splitFinishedWork as D, workedForLabel as G } from "./workedCollapse.js";
|
|
14
|
+
import { jsx as r, jsxs as p, Fragment as b } from "react/jsx-runtime";
|
|
15
|
+
function I(t) {
|
|
16
16
|
const e = [];
|
|
17
17
|
for (const s of t) {
|
|
18
18
|
const n = s.groups.filter((l) => l.kind !== "sources");
|
|
@@ -23,34 +23,34 @@ function G(t) {
|
|
|
23
23
|
}
|
|
24
24
|
return e;
|
|
25
25
|
}
|
|
26
|
-
function
|
|
26
|
+
function w({
|
|
27
27
|
segments: t,
|
|
28
28
|
messageId: e,
|
|
29
29
|
isStreaming: s,
|
|
30
30
|
isLiveMessage: n,
|
|
31
31
|
turnActive: l,
|
|
32
|
-
phaseActiveIndex:
|
|
32
|
+
phaseActiveIndex: h,
|
|
33
33
|
getPhaseStats: o,
|
|
34
|
-
lastPart:
|
|
34
|
+
lastPart: d,
|
|
35
35
|
loaderParts: f,
|
|
36
36
|
markTail: a
|
|
37
37
|
}) {
|
|
38
|
-
return /* @__PURE__ */ r(
|
|
38
|
+
return /* @__PURE__ */ r(N, {
|
|
39
39
|
each: t,
|
|
40
40
|
children: (i, c, {
|
|
41
41
|
isLast: g
|
|
42
42
|
}) => {
|
|
43
43
|
const m = a && g;
|
|
44
|
-
return /* @__PURE__ */ r(
|
|
44
|
+
return /* @__PURE__ */ r(E, {
|
|
45
45
|
segment: i,
|
|
46
46
|
messageId: e,
|
|
47
47
|
isStreaming: s,
|
|
48
48
|
isLiveMessage: n,
|
|
49
49
|
isLastSegment: m,
|
|
50
|
-
streamActive: l && (m || c ===
|
|
51
|
-
fileStats: i.layout === "grouped" ? o?.(
|
|
50
|
+
streamActive: l && (m || c === h),
|
|
51
|
+
fileStats: i.layout === "grouped" ? o?.(B(i.groups)) : void 0,
|
|
52
52
|
children: m && s ? /* @__PURE__ */ r(S, {
|
|
53
|
-
lastPart:
|
|
53
|
+
lastPart: d,
|
|
54
54
|
messageId: e,
|
|
55
55
|
parts: f
|
|
56
56
|
}) : null
|
|
@@ -58,93 +58,94 @@ function k({
|
|
|
58
58
|
}
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
|
-
function
|
|
61
|
+
function O({
|
|
62
62
|
label: t
|
|
63
63
|
}) {
|
|
64
64
|
const {
|
|
65
65
|
state: e
|
|
66
66
|
} = P();
|
|
67
|
-
return /* @__PURE__ */ r(
|
|
67
|
+
return /* @__PURE__ */ r(M, {
|
|
68
68
|
asChild: !0,
|
|
69
|
-
children: /* @__PURE__ */
|
|
69
|
+
children: /* @__PURE__ */ p(y, {
|
|
70
70
|
type: "button",
|
|
71
71
|
variant: "inline",
|
|
72
72
|
color: "secondary",
|
|
73
73
|
className: v.workedTrigger,
|
|
74
|
-
children: [t, /* @__PURE__ */ r(
|
|
75
|
-
className:
|
|
74
|
+
children: [t, /* @__PURE__ */ r(C, {
|
|
75
|
+
className: T("chevron", "next"),
|
|
76
76
|
"aria-expanded": e.isExpanded,
|
|
77
77
|
"aria-hidden": !0
|
|
78
78
|
})]
|
|
79
79
|
})
|
|
80
80
|
});
|
|
81
81
|
}
|
|
82
|
-
function
|
|
82
|
+
function R({
|
|
83
83
|
children: t
|
|
84
84
|
}) {
|
|
85
85
|
const {
|
|
86
86
|
state: e
|
|
87
87
|
} = P();
|
|
88
|
-
return /* @__PURE__ */ r(
|
|
88
|
+
return /* @__PURE__ */ r(u, {
|
|
89
89
|
when: e.isExpanded,
|
|
90
|
-
children: /* @__PURE__ */ r(
|
|
90
|
+
children: /* @__PURE__ */ r(W, {
|
|
91
91
|
className: v.workedPanel,
|
|
92
92
|
children: t
|
|
93
93
|
})
|
|
94
94
|
});
|
|
95
95
|
}
|
|
96
|
-
function
|
|
96
|
+
function q({
|
|
97
97
|
label: t,
|
|
98
98
|
children: e
|
|
99
99
|
}) {
|
|
100
|
-
return /* @__PURE__ */
|
|
100
|
+
return /* @__PURE__ */ p(L, {
|
|
101
101
|
className: v.worked,
|
|
102
102
|
defaultOpen: !1,
|
|
103
|
-
children: [/* @__PURE__ */ r(
|
|
103
|
+
children: [/* @__PURE__ */ r(O, {
|
|
104
104
|
label: t
|
|
105
|
-
}), /* @__PURE__ */ r(
|
|
105
|
+
}), /* @__PURE__ */ r(R, {
|
|
106
106
|
children: e
|
|
107
107
|
})]
|
|
108
108
|
});
|
|
109
109
|
}
|
|
110
|
-
const
|
|
110
|
+
const se = F(({
|
|
111
111
|
hideSources: t = !1
|
|
112
112
|
} = {}) => {
|
|
113
|
-
const e =
|
|
113
|
+
const e = $();
|
|
114
114
|
if (e?.role !== "assistant" || e.message.role !== "assistant")
|
|
115
115
|
return null;
|
|
116
116
|
const {
|
|
117
117
|
messageId: s,
|
|
118
118
|
segments: n,
|
|
119
119
|
lastPart: l,
|
|
120
|
-
turnActive:
|
|
120
|
+
turnActive: h,
|
|
121
121
|
isStreaming: o,
|
|
122
|
-
isLastMessage:
|
|
122
|
+
isLastMessage: d,
|
|
123
123
|
getPhaseStats: f
|
|
124
|
-
} = e, a = t ?
|
|
124
|
+
} = e, a = t ? I(n) : n, i = e.message.parts, c = e.message.metadata;
|
|
125
125
|
if (a.length === 0 && !o)
|
|
126
126
|
return null;
|
|
127
|
-
const g =
|
|
127
|
+
const g = j(a, o), m = D(a, {
|
|
128
128
|
streaming: o,
|
|
129
|
-
cancelled: c?.stopReason === "cancelled"
|
|
130
|
-
|
|
129
|
+
cancelled: c?.stopReason === "cancelled",
|
|
130
|
+
superseded: !d
|
|
131
|
+
}), k = {
|
|
131
132
|
messageId: s,
|
|
132
133
|
isStreaming: o,
|
|
133
|
-
isLiveMessage:
|
|
134
|
-
turnActive:
|
|
134
|
+
isLiveMessage: d,
|
|
135
|
+
turnActive: h,
|
|
135
136
|
phaseActiveIndex: g,
|
|
136
137
|
getPhaseStats: f,
|
|
137
138
|
lastPart: l,
|
|
138
139
|
loaderParts: i
|
|
139
140
|
};
|
|
140
|
-
return /* @__PURE__ */ r(
|
|
141
|
+
return /* @__PURE__ */ r(u, {
|
|
141
142
|
when: m,
|
|
142
|
-
fallback: /* @__PURE__ */
|
|
143
|
-
children: [/* @__PURE__ */ r(
|
|
144
|
-
...
|
|
143
|
+
fallback: /* @__PURE__ */ p(b, {
|
|
144
|
+
children: [/* @__PURE__ */ r(w, {
|
|
145
|
+
...k,
|
|
145
146
|
segments: a,
|
|
146
147
|
markTail: !0
|
|
147
|
-
}), /* @__PURE__ */ r(
|
|
148
|
+
}), /* @__PURE__ */ r(u, {
|
|
148
149
|
when: o && a.length === 0,
|
|
149
150
|
children: /* @__PURE__ */ r(S, {
|
|
150
151
|
lastPart: l,
|
|
@@ -153,23 +154,26 @@ const te = T(({
|
|
|
153
154
|
})
|
|
154
155
|
})]
|
|
155
156
|
}),
|
|
156
|
-
children: (x) => /* @__PURE__ */
|
|
157
|
-
children: [/* @__PURE__ */ r(
|
|
158
|
-
label:
|
|
159
|
-
children: /* @__PURE__ */ r(
|
|
160
|
-
...
|
|
157
|
+
children: (x) => /* @__PURE__ */ p(b, {
|
|
158
|
+
children: [/* @__PURE__ */ r(q, {
|
|
159
|
+
label: G(c?.startedAt, c?.endedAt),
|
|
160
|
+
children: /* @__PURE__ */ r(w, {
|
|
161
|
+
...k,
|
|
161
162
|
segments: x.work,
|
|
162
163
|
markTail: !1
|
|
163
164
|
})
|
|
164
|
-
}), /* @__PURE__ */ r(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
165
|
+
}), /* @__PURE__ */ r(u, {
|
|
166
|
+
when: x.answer,
|
|
167
|
+
children: (A) => /* @__PURE__ */ r(w, {
|
|
168
|
+
...k,
|
|
169
|
+
segments: [A],
|
|
170
|
+
markTail: !0
|
|
171
|
+
})
|
|
168
172
|
})]
|
|
169
173
|
})
|
|
170
174
|
});
|
|
171
175
|
});
|
|
172
176
|
export {
|
|
173
|
-
|
|
177
|
+
se as MessageAssistantBody
|
|
174
178
|
};
|
|
175
179
|
//# sourceMappingURL=MessageAssistantBody.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MessageAssistantBody.js","sources":["../../../../src/chat/Message/turn/MessageAssistantBody.tsx"],"sourcesContent":["'use client';\n\nimport { ChevronDown } from '@reforma/icons/8';\nimport { cn } from '@reforma/lib';\nimport { observer } from 'mobx-react-lite';\n\nimport { Button } from '../../../Button';\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n useCollapsible,\n} from '../../../Collapsible';\nimport { For } from '../../../For';\nimport { Show } from '../../../Show';\nimport { ConversationPendingLoader } from '../../Conversation/ConversationPendingLoader';\nimport { partsFromSegmentGroups, streamingPhaseActiveIndex } from '../normalize/normalizeMessageParts';\nimport { MessagePhaseSection } from '../segments';\nimport styles from './Message.module.css';\nimport { useMessageTurn } from './messageTurnContext';\nimport { splitFinishedWork, workedForLabel } from './workedCollapse';\n\nimport type { ReactNode } from 'react';\nimport type { MessageSegment } from '../normalize/normalizeMessageParts';\nimport type { ReformaUIMessagePart } from '../types';\nimport type { GetPhaseStats } from './messageTurnContext';\n\nfunction segmentsWithoutSources(segments: readonly MessageSegment[]): MessageSegment[] {\n const next: MessageSegment[] = [];\n\n for (const segment of segments) {\n const groups = segment.groups.filter(group => group.kind !== 'sources');\n\n if (groups.length > 0) {\n next.push({ ...segment, groups });\n }\n }\n\n return next;\n}\n\ntype SegmentListProps = {\n segments: readonly MessageSegment[];\n messageId: string;\n isStreaming: boolean;\n isLiveMessage: boolean;\n turnActive: boolean;\n phaseActiveIndex: number;\n getPhaseStats: GetPhaseStats | undefined;\n lastPart: ReformaUIMessagePart | undefined;\n loaderParts: readonly ReformaUIMessagePart[];\n /** Work under the spoiler is not the message tail, so its phases stay closed. */\n markTail: boolean;\n};\n\nfunction AssistantSegments({\n segments,\n messageId,\n isStreaming,\n isLiveMessage,\n turnActive,\n phaseActiveIndex,\n getPhaseStats,\n lastPart,\n loaderParts,\n markTail,\n}: SegmentListProps) {\n return (\n <For each={ segments }>\n { (segment, segIndex, { isLast }) => {\n const isLastSegment = markTail && isLast;\n\n return (\n <MessagePhaseSection\n key={ `${ messageId }-${ segment.index }` }\n segment={ segment }\n messageId={ messageId }\n isStreaming={ isStreaming }\n isLiveMessage={ isLiveMessage }\n isLastSegment={ isLastSegment }\n streamActive={ turnActive && (isLastSegment || segIndex === phaseActiveIndex) }\n fileStats={\n segment.layout === 'grouped'\n ? getPhaseStats?.(partsFromSegmentGroups(segment.groups))\n : undefined\n }\n >\n { isLastSegment && isStreaming\n ? (\n <ConversationPendingLoader\n lastPart={ lastPart }\n messageId={ messageId }\n parts={ loaderParts }\n />\n )\n : null }\n </MessagePhaseSection>\n );\n } }\n </For>\n );\n}\n\nfunction WorkedTrigger({ label }: { label: string }) {\n const { state } = useCollapsible();\n\n return (\n <CollapsibleTrigger asChild>\n <Button\n type=\"button\"\n variant=\"inline\"\n color=\"secondary\"\n className={ styles.workedTrigger }\n >\n { label }\n <ChevronDown\n className={ cn('chevron', 'next') }\n aria-expanded={ state.isExpanded }\n aria-hidden\n />\n </Button>\n </CollapsibleTrigger>\n );\n}\n\n/** Closed panel stays out of the DOM. `hidden=until-found` is still a flex item and keeps `.worked`'s gap. */\nfunction WorkedPanel({ children }: { children: ReactNode }) {\n const { state } = useCollapsible();\n\n return (\n <Show when={ state.isExpanded }>\n <CollapsibleContent className={ styles.workedPanel }>\n { children }\n </CollapsibleContent>\n </Show>\n );\n}\n\nfunction WorkedFor({ label, children }: { label: string; children: ReactNode }) {\n return (\n <Collapsible className={ styles.worked } defaultOpen={ false }>\n <WorkedTrigger label={ label } />\n <WorkedPanel>{ children }</WorkedPanel>\n </Collapsible>\n );\n}\n\n/**\n * Assistant turn segments and streaming pending loader.\n * A finished text answer folds the work into one \"Worked for …\" disclosure.\n * Cancelled turns and turns that do not end on text keep the phase rows open.\n */\nexport const MessageAssistantBody = observer(({\n hideSources = false,\n}: {\n /** Editor footer owns citations — drop in-body Sources groups. */\n hideSources?: boolean;\n} = {}) => {\n const turn = useMessageTurn();\n\n if (turn?.role !== 'assistant' || turn.message.role !== 'assistant') {\n return null;\n }\n\n const {\n messageId,\n segments: rawSegments,\n lastPart,\n turnActive,\n isStreaming,\n isLastMessage,\n getPhaseStats,\n } = turn;\n const segments = hideSources ? segmentsWithoutSources(rawSegments) : rawSegments;\n const loaderParts = turn.message.parts;\n const metadata = turn.message.metadata;\n\n if (segments.length === 0 && !isStreaming) {\n return null;\n }\n\n const phaseActiveIndex = streamingPhaseActiveIndex(segments, isStreaming);\n const finished = splitFinishedWork(segments, {\n streaming: isStreaming,\n cancelled: metadata?.stopReason === 'cancelled',\n });\n const listProps = {\n messageId,\n isStreaming,\n isLiveMessage: isLastMessage,\n turnActive,\n phaseActiveIndex,\n getPhaseStats,\n lastPart,\n loaderParts,\n };\n\n return (\n <Show\n when={ finished }\n fallback={ (\n <>\n <AssistantSegments\n { ...listProps }\n segments={ segments }\n markTail\n />\n <Show when={ isStreaming && segments.length === 0 }>\n <ConversationPendingLoader\n lastPart={ lastPart }\n messageId={ messageId }\n parts={ loaderParts }\n />\n </Show>\n </>\n ) }\n >\n { split => (\n <>\n <WorkedFor label={ workedForLabel(metadata?.startedAt, metadata?.endedAt) }>\n <AssistantSegments\n { ...listProps }\n segments={ split.work }\n markTail={ false }\n />\n </WorkedFor>\n <AssistantSegments\n { ...listProps }\n segments={ [split.answer] }\n markTail\n />\n </>\n ) }\n </Show>\n );\n});\n"],"names":["segmentsWithoutSources","segments","next","segment","groups","group","AssistantSegments","messageId","isStreaming","isLiveMessage","turnActive","phaseActiveIndex","getPhaseStats","lastPart","loaderParts","markTail","For","segIndex","isLast","isLastSegment","MessagePhaseSection","partsFromSegmentGroups","_jsx","ConversationPendingLoader","WorkedTrigger","label","state","useCollapsible","CollapsibleTrigger","Button","styles","ChevronDown","cn","WorkedPanel","children","Show","CollapsibleContent","WorkedFor","Collapsible","MessageAssistantBody","observer","hideSources","turn","useMessageTurn","rawSegments","isLastMessage","metadata","streamingPhaseActiveIndex","finished","splitFinishedWork","listProps","_Fragment","split","_jsxs","workedForLabel"],"mappings":";;;;;;;;;;;;;;AAgBA,SAASA,EAAuBC,GAAU;AACxC,QAAMC,IAAO,CAAA;AACb,aAAWC,KAAWF,GAAU;AAC9B,UAAMG,IAASD,EAAQ,OAAO,OAAO,CAAAE,MAASA,EAAM,SAAS,SAAS;AACtE,IAAID,EAAO,SAAS,KAClBF,EAAK,KAAK;AAAA,MACR,GAAGC;AAAA,MACH,QAAAC;AAAA,IAAA,CACD;AAAA,EAEL;AACA,SAAOF;AACT;AACA,SAASI,EAAkB;AAAA,EACzB,UAAAL;AAAA,EACA,WAAAM;AAAA,EACA,aAAAC;AAAA,EACA,eAAAC;AAAA,EACA,YAAAC;AAAA,EACA,kBAAAC;AAAA,EACA,eAAAC;AAAA,EACA,UAAAC;AAAA,EACA,aAAAC;AAAA,EACA,UAAAC;AACF,GAAG;AACD,2BAAyBC,GAAK;AAAA,IAC5B,MAAMf;AAAA,IACN,UAAU,CAACE,GAASc,GAAU;AAAA,MAC5B,QAAAC;AAAA,IAAA,MACI;AACJ,YAAMC,IAAgBJ,KAAYG;AAClC,+BAAyBE,GAAqB;AAAA,QAC5C,SAAAjB;AAAA,QACA,WAAAI;AAAA,QACA,aAAAC;AAAA,QACA,eAAAC;AAAA,QACA,eAAAU;AAAA,QACA,cAAcT,MAAeS,KAAiBF,MAAaN;AAAA,QAC3D,WAAWR,EAAQ,WAAW,YAAYS,IAAgBS,EAAuBlB,EAAQ,MAAM,CAAC,IAAI;AAAA,QACpG,UAAUgB,KAAiBX,IAA2Bc,gBAAAA,EAAKC,GAA2B;AAAA,UACpF,UAAAV;AAAA,UACA,WAAAN;AAAA,UACA,OAAOO;AAAA,QAAA,CACR,IAAI;AAAA,MAAA,GACJ,GAAGP,CAAS,IAAIJ,EAAQ,KAAK,EAAE;AAAA,IACpC;AAAA,EAAA,CACD;AACH;AACA,SAASqB,EAAc;AAAA,EACrB,OAAAC;AACF,GAAG;AACD,QAAM;AAAA,IACJ,OAAAC;AAAA,EAAA,IACEC,EAAA;AACJ,2BAAyBC,GAAoB;AAAA,IAC3C,SAAS;AAAA,IACT,4BAA6BC,GAAQ;AAAA,MACnC,MAAM;AAAA,MACN,SAAS;AAAA,MACT,OAAO;AAAA,MACP,WAAWC,EAAO;AAAA,MAClB,UAAU,CAACL,GAAoBH,gBAAAA,EAAKS,GAAa;AAAA,QAC/C,WAAWC,EAAG,WAAW,MAAM;AAAA,QAC/B,iBAAiBN,EAAM;AAAA,QACvB,eAAe;AAAA,MAAA,CAChB,CAAC;AAAA,IAAA,CACH;AAAA,EAAA,CACF;AACH;AAGA,SAASO,EAAY;AAAA,EACnB,UAAAC;AACF,GAAG;AACD,QAAM;AAAA,IACJ,OAAAR;AAAA,EAAA,IACEC,EAAA;AACJ,2BAAyBQ,GAAM;AAAA,IAC7B,MAAMT,EAAM;AAAA,IACZ,4BAA4BU,GAAoB;AAAA,MAC9C,WAAWN,EAAO;AAAA,MAClB,UAAAI;AAAA,IAAA,CACD;AAAA,EAAA,CACF;AACH;AACA,SAASG,EAAU;AAAA,EACjB,OAAAZ;AAAA,EACA,UAAAS;AACF,GAAG;AACD,2BAA0BI,GAAa;AAAA,IACrC,WAAWR,EAAO;AAAA,IAClB,aAAa;AAAA,IACb,UAAU,CAAcR,gBAAAA,EAAKE,GAAe;AAAA,MAC1C,OAAAC;AAAA,IAAA,CACD,GAAgBH,gBAAAA,EAAKW,GAAa;AAAA,MACjC,UAAAC;AAAA,IAAA,CACD,CAAC;AAAA,EAAA,CACH;AACH;AAOO,MAAMK,KAAuBC,EAAS,CAAC;AAAA,EAC5C,aAAAC,IAAc;AAChB,IAAI,OAAO;AACT,QAAMC,IAAOC,EAAA;AACb,MAAID,GAAM,SAAS,eAAeA,EAAK,QAAQ,SAAS;AACtD,WAAO;AAET,QAAM;AAAA,IACJ,WAAAnC;AAAA,IACA,UAAUqC;AAAA,IACV,UAAA/B;AAAA,IACA,YAAAH;AAAA,IACA,aAAAF;AAAA,IACA,eAAAqC;AAAA,IACA,eAAAjC;AAAA,EAAA,IACE8B,GACEzC,IAAWwC,IAAczC,EAAuB4C,CAAW,IAAIA,GAC/D9B,IAAc4B,EAAK,QAAQ,OAC3BI,IAAWJ,EAAK,QAAQ;AAC9B,MAAIzC,EAAS,WAAW,KAAK,CAACO;AAC5B,WAAO;AAET,QAAMG,IAAmBoC,EAA0B9C,GAAUO,CAAW,GAClEwC,IAAWC,EAAkBhD,GAAU;AAAA,IAC3C,WAAWO;AAAA,IACX,WAAWsC,GAAU,eAAe;AAAA,EAAA,CACrC,GACKI,IAAY;AAAA,IAChB,WAAA3C;AAAA,IACA,aAAAC;AAAA,IACA,eAAeqC;AAAA,IACf,YAAAnC;AAAA,IACA,kBAAAC;AAAA,IACA,eAAAC;AAAA,IACA,UAAAC;AAAA,IACA,aAAAC;AAAA,EAAA;AAEF,2BAAyBqB,GAAM;AAAA,IAC7B,MAAMa;AAAA,IACN,4BAA6BG,GAAW;AAAA,MACtC,UAAU,CAAc7B,gBAAAA,EAAKhB,GAAmB;AAAA,QAC9C,GAAG4C;AAAA,QACH,UAAAjD;AAAA,QACA,UAAU;AAAA,MAAA,CACX,GAAgBqB,gBAAAA,EAAKa,GAAM;AAAA,QAC1B,MAAM3B,KAAeP,EAAS,WAAW;AAAA,QACzC,4BAA4BsB,GAA2B;AAAA,UACrD,UAAAV;AAAA,UACA,WAAAN;AAAA,UACA,OAAOO;AAAA,QAAA,CACR;AAAA,MAAA,CACF,CAAC;AAAA,IAAA,CACH;AAAA,IACD,UAAU,CAAAsC,MAAsBC,gBAAAA,EAAMF,GAAW;AAAA,MAC/C,UAAU,CAAc7B,gBAAAA,EAAKe,GAAW;AAAA,QACtC,OAAOiB,EAAeR,GAAU,WAAWA,GAAU,OAAO;AAAA,QAC5D,4BAA4BxC,GAAmB;AAAA,UAC7C,GAAG4C;AAAA,UACH,UAAUE,EAAM;AAAA,UAChB,UAAU;AAAA,QAAA,CACX;AAAA,MAAA,CACF,GAAgB9B,gBAAAA,EAAKhB,GAAmB;AAAA,QACvC,GAAG4C;AAAA,QACH,UAAU,CAACE,EAAM,MAAM;AAAA,QACvB,UAAU;AAAA,MAAA,CACX,CAAC;AAAA,IAAA,CACH;AAAA,EAAA,CACF;AACH,CAAC;"}
|
|
1
|
+
{"version":3,"file":"MessageAssistantBody.js","sources":["../../../../src/chat/Message/turn/MessageAssistantBody.tsx"],"sourcesContent":["'use client';\n\nimport { ChevronDown } from '@reforma/icons/8';\nimport { cn } from '@reforma/lib';\nimport { observer } from 'mobx-react-lite';\n\nimport { Button } from '../../../Button';\nimport {\n Collapsible,\n CollapsibleContent,\n CollapsibleTrigger,\n useCollapsible,\n} from '../../../Collapsible';\nimport { For } from '../../../For';\nimport { Show } from '../../../Show';\nimport { ConversationPendingLoader } from '../../Conversation/ConversationPendingLoader';\nimport { partsFromSegmentGroups, streamingPhaseActiveIndex } from '../normalize/normalizeMessageParts';\nimport { MessagePhaseSection } from '../segments';\nimport styles from './Message.module.css';\nimport { useMessageTurn } from './messageTurnContext';\nimport { splitFinishedWork, workedForLabel } from './workedCollapse';\n\nimport type { ReactNode } from 'react';\nimport type { MessageSegment } from '../normalize/normalizeMessageParts';\nimport type { ReformaUIMessagePart } from '../types';\nimport type { GetPhaseStats } from './messageTurnContext';\n\nfunction segmentsWithoutSources(segments: readonly MessageSegment[]): MessageSegment[] {\n const next: MessageSegment[] = [];\n\n for (const segment of segments) {\n const groups = segment.groups.filter(group => group.kind !== 'sources');\n\n if (groups.length > 0) {\n next.push({ ...segment, groups });\n }\n }\n\n return next;\n}\n\ntype SegmentListProps = {\n segments: readonly MessageSegment[];\n messageId: string;\n isStreaming: boolean;\n isLiveMessage: boolean;\n turnActive: boolean;\n phaseActiveIndex: number;\n getPhaseStats: GetPhaseStats | undefined;\n lastPart: ReformaUIMessagePart | undefined;\n loaderParts: readonly ReformaUIMessagePart[];\n /** Work under the spoiler is not the message tail, so its phases stay closed. */\n markTail: boolean;\n};\n\nfunction AssistantSegments({\n segments,\n messageId,\n isStreaming,\n isLiveMessage,\n turnActive,\n phaseActiveIndex,\n getPhaseStats,\n lastPart,\n loaderParts,\n markTail,\n}: SegmentListProps) {\n return (\n <For each={ segments }>\n { (segment, segIndex, { isLast }) => {\n const isLastSegment = markTail && isLast;\n\n return (\n <MessagePhaseSection\n key={ `${ messageId }-${ segment.index }` }\n segment={ segment }\n messageId={ messageId }\n isStreaming={ isStreaming }\n isLiveMessage={ isLiveMessage }\n isLastSegment={ isLastSegment }\n streamActive={ turnActive && (isLastSegment || segIndex === phaseActiveIndex) }\n fileStats={\n segment.layout === 'grouped'\n ? getPhaseStats?.(partsFromSegmentGroups(segment.groups))\n : undefined\n }\n >\n { isLastSegment && isStreaming\n ? (\n <ConversationPendingLoader\n lastPart={ lastPart }\n messageId={ messageId }\n parts={ loaderParts }\n />\n )\n : null }\n </MessagePhaseSection>\n );\n } }\n </For>\n );\n}\n\nfunction WorkedTrigger({ label }: { label: string }) {\n const { state } = useCollapsible();\n\n return (\n <CollapsibleTrigger asChild>\n <Button\n type=\"button\"\n variant=\"inline\"\n color=\"secondary\"\n className={ styles.workedTrigger }\n >\n { label }\n <ChevronDown\n className={ cn('chevron', 'next') }\n aria-expanded={ state.isExpanded }\n aria-hidden\n />\n </Button>\n </CollapsibleTrigger>\n );\n}\n\n/** Closed panel stays out of the DOM. `hidden=until-found` is still a flex item and keeps `.worked`'s gap. */\nfunction WorkedPanel({ children }: { children: ReactNode }) {\n const { state } = useCollapsible();\n\n return (\n <Show when={ state.isExpanded }>\n <CollapsibleContent className={ styles.workedPanel }>\n { children }\n </CollapsibleContent>\n </Show>\n );\n}\n\nfunction WorkedFor({ label, children }: { label: string; children: ReactNode }) {\n return (\n <Collapsible className={ styles.worked } defaultOpen={ false }>\n <WorkedTrigger label={ label } />\n <WorkedPanel>{ children }</WorkedPanel>\n </Collapsible>\n );\n}\n\n/**\n * Assistant turn segments and streaming pending loader.\n * A finished text answer folds the work into one \"Worked for …\" disclosure.\n * The latest turn keeps its phase rows open when cancelled or not ending on text;\n * an older one folds them anyway.\n */\nexport const MessageAssistantBody = observer(({\n hideSources = false,\n}: {\n /** Editor footer owns citations — drop in-body Sources groups. */\n hideSources?: boolean;\n} = {}) => {\n const turn = useMessageTurn();\n\n if (turn?.role !== 'assistant' || turn.message.role !== 'assistant') {\n return null;\n }\n\n const {\n messageId,\n segments: rawSegments,\n lastPart,\n turnActive,\n isStreaming,\n isLastMessage,\n getPhaseStats,\n } = turn;\n const segments = hideSources ? segmentsWithoutSources(rawSegments) : rawSegments;\n const loaderParts = turn.message.parts;\n const metadata = turn.message.metadata;\n\n if (segments.length === 0 && !isStreaming) {\n return null;\n }\n\n const phaseActiveIndex = streamingPhaseActiveIndex(segments, isStreaming);\n const finished = splitFinishedWork(segments, {\n streaming: isStreaming,\n cancelled: metadata?.stopReason === 'cancelled',\n superseded: !isLastMessage,\n });\n const listProps = {\n messageId,\n isStreaming,\n isLiveMessage: isLastMessage,\n turnActive,\n phaseActiveIndex,\n getPhaseStats,\n lastPart,\n loaderParts,\n };\n\n return (\n <Show\n when={ finished }\n fallback={ (\n <>\n <AssistantSegments\n { ...listProps }\n segments={ segments }\n markTail\n />\n <Show when={ isStreaming && segments.length === 0 }>\n <ConversationPendingLoader\n lastPart={ lastPart }\n messageId={ messageId }\n parts={ loaderParts }\n />\n </Show>\n </>\n ) }\n >\n { split => (\n <>\n <WorkedFor label={ workedForLabel(metadata?.startedAt, metadata?.endedAt) }>\n <AssistantSegments\n { ...listProps }\n segments={ split.work }\n markTail={ false }\n />\n </WorkedFor>\n <Show when={ split.answer }>\n { answer => (\n <AssistantSegments\n { ...listProps }\n segments={ [answer] }\n markTail\n />\n ) }\n </Show>\n </>\n ) }\n </Show>\n );\n});\n"],"names":["segmentsWithoutSources","segments","next","segment","groups","group","AssistantSegments","messageId","isStreaming","isLiveMessage","turnActive","phaseActiveIndex","getPhaseStats","lastPart","loaderParts","markTail","For","segIndex","isLast","isLastSegment","MessagePhaseSection","partsFromSegmentGroups","_jsx","ConversationPendingLoader","WorkedTrigger","label","state","useCollapsible","CollapsibleTrigger","Button","styles","ChevronDown","cn","WorkedPanel","children","Show","CollapsibleContent","WorkedFor","Collapsible","MessageAssistantBody","observer","hideSources","turn","useMessageTurn","rawSegments","isLastMessage","metadata","streamingPhaseActiveIndex","finished","splitFinishedWork","listProps","_Fragment","split","_jsxs","workedForLabel","answer"],"mappings":"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"}
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
import type { MessageSegment } from '../normalize/normalizeMessageParts';
|
|
2
2
|
export type FinishedWorkSplit = {
|
|
3
3
|
work: readonly MessageSegment[];
|
|
4
|
-
answer:
|
|
4
|
+
/** Null when a superseded turn has no text answer: everything folds. */
|
|
5
|
+
answer: MessageSegment | null;
|
|
5
6
|
};
|
|
6
7
|
/**
|
|
7
8
|
* Finished turn whose last visible part is text: tuck every segment before that
|
|
8
|
-
* answer under one disclosure. Streaming
|
|
9
|
+
* answer under one disclosure. Streaming and "still waiting" turns stay open.
|
|
10
|
+
* The latest turn also stays open when cancelled or not ending on text; once a
|
|
11
|
+
* later message supersedes it, its work folds anyway.
|
|
9
12
|
*/
|
|
10
13
|
export declare function splitFinishedWork(segments: readonly MessageSegment[], flags: {
|
|
11
14
|
streaming: boolean;
|
|
12
15
|
cancelled: boolean;
|
|
16
|
+
superseded: boolean;
|
|
13
17
|
}): FinishedWorkSplit | null;
|
|
14
18
|
/** "Worked for 25s" / "Worked for 2m". "Worked" when the turn has no timestamps. */
|
|
15
19
|
export declare function workedForLabel(startedAt: number | undefined, endedAt: number | undefined): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workedCollapse.d.ts","sourceRoot":"","sources":["../../../../src/chat/Message/turn/workedCollapse.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,MAAM,MAAM,iBAAiB,GAAG;IAC5B,IAAI,EAAE,SAAS,cAAc,EAAE,CAAC;IAChC,MAAM,EAAE,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"workedCollapse.d.ts","sourceRoot":"","sources":["../../../../src/chat/Message/turn/workedCollapse.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AAEzE,MAAM,MAAM,iBAAiB,GAAG;IAC5B,IAAI,EAAE,SAAS,cAAc,EAAE,CAAC;IAChC,wEAAwE;IACxE,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC;CACjC,CAAC;AAYF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC7B,QAAQ,EAAE,SAAS,cAAc,EAAE,EACnC,KAAK,EAAE;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,SAAS,EAAE,OAAO,CAAC;IAAC,UAAU,EAAE,OAAO,CAAA;CAAE,GACvE,iBAAiB,GAAG,IAAI,CAgB1B;AAED,oFAAoF;AACpF,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAgCjG"}
|