@tutti-os/ui-rich-text 0.0.11 → 0.0.13

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/at-panel/MentionPalette.tsx","../../src/at-panel/mentionPaletteScrollbar.tsx","../../src/at-panel/MentionRow.tsx","../../src/at-panel/mentionRowDataAttributes.ts","../../src/at-panel/useAtPanelKeyboard.ts"],"sourcesContent":["import {\n useEffect,\n useRef,\n useState,\n type CSSProperties,\n type JSX,\n type MutableRefObject,\n type ReactNode\n} from \"react\";\nimport {\n FolderFailedFilledIcon,\n KeyboardFilledIcon\n} from \"@tutti-os/ui-system/icons\";\nimport { Spinner, UnderlineTabs } from \"@tutti-os/ui-system/components\";\nimport { cn } from \"@tutti-os/ui-system/utils\";\nimport { flattenMentionPaletteEntries } from \"./mentionPaletteEntries.ts\";\nimport { MentionPaletteScrollbar } from \"./mentionPaletteScrollbar.tsx\";\nimport type {\n MentionPaletteGroup,\n MentionPaletteProps,\n MentionPaletteState,\n MentionPaletteTheme\n} from \"./mentionPaletteTypes.ts\";\nimport \"./mentionPalette.css\";\n\nconst DEFAULT_THEME = {\n classNames: {\n palette: \"rich-text-at-mention-palette\",\n header: \"rich-text-at-mention-palette-header\",\n footer: \"rich-text-at-mention-palette-footer\",\n tabs: \"rich-text-at-mention-palette-tabs\",\n scrollRegion: \"rich-text-at-mention-palette-scroll-region\",\n scrollbar: \"rich-text-at-mention-palette-scrollbar\",\n scrollbarThumb: \"rich-text-at-mention-palette-scrollbar-thumb\",\n hint: \"rich-text-at-mention-palette-hint\",\n hintItem: \"rich-text-at-mention-palette-hint-item\",\n hintButton: \"rich-text-at-mention-palette-hint-button\",\n hintSeparator: \"rich-text-at-mention-palette-hint-separator\",\n shortcut: \"rich-text-at-mention-palette-shortcut\",\n shortcutArrow: \"rich-text-at-mention-palette-shortcut--arrow\",\n shortcutButton: \"rich-text-at-mention-palette-shortcut-button\",\n shortcutGroup: \"rich-text-at-mention-palette-shortcut-group\"\n },\n testIds: {\n emptyState: \"rich-text-at-mention-palette-empty-state\",\n hint: \"rich-text-at-mention-palette-hint\",\n scrollbar: \"rich-text-at-mention-palette-scrollbar\",\n loadingSpinner: \"rich-text-at-mention-loading-spinner\"\n },\n groupDividerAttribute: \"data-rich-text-at-mention-group-divider\"\n} as const;\n\ninterface ResolvedMentionPaletteTheme {\n classNames: Required<NonNullable<MentionPaletteTheme[\"classNames\"]>>;\n testIds: Required<NonNullable<MentionPaletteTheme[\"testIds\"]>>;\n groupDividerAttribute: string;\n}\n\nfunction resolveMentionPaletteTheme(\n theme: MentionPaletteTheme | undefined\n): ResolvedMentionPaletteTheme {\n return {\n classNames: { ...DEFAULT_THEME.classNames, ...theme?.classNames },\n testIds: { ...DEFAULT_THEME.testIds, ...theme?.testIds },\n groupDividerAttribute:\n theme?.groupDividerAttribute ?? DEFAULT_THEME.groupDividerAttribute\n };\n}\n\nconst paletteStyles = {\n palette:\n \"nodrag grid h-full max-h-[320px] min-h-0 grid-rows-[auto_minmax(0,1fr)_auto] overflow-hidden text-[13px] [-webkit-app-region:no-drag]\",\n header: \"relative z-10 shrink-0\",\n footer: \"shrink-0\",\n scrollShell: \"relative min-h-0 overflow-hidden\",\n scrollBody:\n \"h-full min-h-0 overflow-y-auto overscroll-contain px-1 pb-1 pt-2\",\n rowButton:\n \"nodrag relative flex min-h-9 w-full min-w-0 cursor-pointer select-none items-center gap-1.5 overflow-hidden rounded-[6px] border-0 bg-transparent px-2.5 py-2 text-left text-[13px] text-[var(--text-primary)] outline-hidden transition-colors duration-200 [-webkit-app-region:no-drag] active:bg-[var(--transparency-active)] data-[highlighted]:bg-[var(--transparency-block)] data-[highlighted]:text-[var(--text-primary)] [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:min-w-0 *:[span]:last:flex-1 *:[span]:last:items-center *:[span]:last:gap-2\",\n categoryButton:\n \"nodrag flex min-h-[72px] w-full items-center gap-3.5 rounded-[6px] border-0 bg-transparent px-2.5 py-2.5 text-left text-[var(--text-primary)] transition-[background-color,color] hover:bg-[var(--transparency-block)] focus-visible:bg-[var(--transparency-block)] focus-visible:outline-none active:bg-[var(--transparency-active)]\",\n expandButton:\n \"nodrag flex w-full items-center justify-center rounded-[6px] px-3 py-2 text-[13px] font-medium text-[var(--text-secondary)] transition focus-visible:outline-none active:bg-[var(--transparency-active)] data-[highlighted]:bg-[var(--transparency-block)] data-[highlighted]:text-[var(--text-primary)]\"\n} as const;\n\nconst MENTION_PALETTE_LOADING_MIN_VISIBLE_MS = 320;\n\nexport function MentionPalette<TItem>(\n props: MentionPaletteProps<TItem>\n): JSX.Element {\n \"use memo\";\n const {\n state,\n highlightedKey,\n getItemKey,\n renderItem,\n labels,\n hintLabels,\n maxHeightPx,\n onHighlightChange,\n onSelectItem,\n onSelectCategory,\n onSelectFilter,\n onExpandGroup,\n onCycleFilter,\n onMoveSelection,\n renderListFooter,\n loadingBanner,\n scrollHighlightedIntoViewCentered = false,\n theme: themeProp\n } = props;\n const theme = resolveMentionPaletteTheme(themeProp);\n\n const highlightedOptionRef = useRef<HTMLButtonElement | null>(null);\n const scrollBodyRef = useRef<HTMLDivElement | null>(null);\n const loadingVisibleUntilRef = useRef(0);\n const loadingHideTimerRef = useRef<ReturnType<typeof setTimeout> | null>(\n null\n );\n const [loadingIndicatorVisible, setLoadingIndicatorVisible] = useState(\n state.status === \"loading\"\n );\n\n const interactiveEntries = flattenMentionPaletteEntries(\n state,\n (item, groupId) => getItemKey(item, findGroup(state.groups, groupId))\n );\n const hasInteractiveEntries = interactiveEntries.some(\n (entry) => entry.type === \"item\" || entry.type === \"expand\"\n );\n\n const showLoadingState =\n loadingIndicatorVisible &&\n (!hasInteractiveEntries || state.mode === \"browse\");\n const showLoadingBanner =\n Boolean(loadingBanner) &&\n loadingIndicatorVisible &&\n hasInteractiveEntries &&\n state.mode === \"results\";\n\n useEffect(() => {\n const highlightedElement = highlightedOptionRef.current;\n if (!highlightedElement) {\n return;\n }\n const scrollContainer = scrollBodyRef.current;\n if (!scrollContainer || !scrollContainer.contains(highlightedElement)) {\n highlightedElement.scrollIntoView({ block: \"nearest\" });\n return;\n }\n if (!scrollHighlightedIntoViewCentered) {\n return;\n }\n centerElementInScrollContainer(scrollContainer, highlightedElement);\n }, [highlightedKey, scrollHighlightedIntoViewCentered]);\n\n useEffect(() => {\n if (loadingHideTimerRef.current !== null) {\n clearTimeout(loadingHideTimerRef.current);\n loadingHideTimerRef.current = null;\n }\n\n if (state.status === \"loading\") {\n loadingVisibleUntilRef.current =\n Date.now() + MENTION_PALETTE_LOADING_MIN_VISIBLE_MS;\n setLoadingIndicatorVisible(true);\n return;\n }\n\n const remainingMs = loadingVisibleUntilRef.current - Date.now();\n if (remainingMs <= 0) {\n setLoadingIndicatorVisible(false);\n return;\n }\n\n loadingHideTimerRef.current = setTimeout(() => {\n loadingHideTimerRef.current = null;\n setLoadingIndicatorVisible(false);\n }, remainingMs);\n\n return () => {\n if (loadingHideTimerRef.current !== null) {\n clearTimeout(loadingHideTimerRef.current);\n loadingHideTimerRef.current = null;\n }\n };\n }, [state.status]);\n\n const paletteMaxHeightStyle: CSSProperties | undefined =\n maxHeightPx > 0 ? { maxHeight: `${maxHeightPx}px` } : undefined;\n\n if (state.status === \"error\") {\n return (\n <div\n className={cn(theme.classNames.palette, paletteStyles.palette)}\n style={paletteMaxHeightStyle}\n role=\"listbox\"\n aria-label={labels.listbox ?? labels.tabHint}\n >\n <MentionPaletteEmptyState\n icon=\"folder-failed\"\n label={labels.error}\n testId={theme.testIds.emptyState}\n />\n </div>\n );\n }\n\n const isBrowse = state.mode === \"browse\";\n\n let body: ReactNode;\n if (showLoadingState) {\n body = (\n <MentionPaletteLoading\n label={labels.loading}\n spinnerTestId={theme.testIds.loadingSpinner}\n />\n );\n } else if (state.groups.length === 0) {\n body = (\n <MentionPaletteEmptyState\n icon={isBrowse ? \"keyboard\" : \"folder-failed\"}\n label={labels.empty}\n testId={theme.testIds.emptyState}\n />\n );\n } else {\n body = (\n <MentionPaletteGroups\n state={state}\n highlightedKey={highlightedKey}\n highlightedOptionRef={highlightedOptionRef}\n getItemKey={getItemKey}\n renderItem={renderItem}\n onHighlightChange={onHighlightChange}\n onSelectItem={onSelectItem}\n onExpandGroup={onExpandGroup}\n renderListFooter={renderListFooter}\n groupDividerAttribute={theme.groupDividerAttribute}\n />\n );\n }\n\n return (\n <div\n className={cn(theme.classNames.palette, paletteStyles.palette)}\n style={paletteMaxHeightStyle}\n role=\"listbox\"\n aria-label={labels.listbox ?? labels.tabHint}\n >\n <div className={cn(theme.classNames.header, paletteStyles.header)}>\n <UnderlineTabs\n tabs={state.categories.map((category) => ({\n value: category.id,\n label: category.label\n }))}\n value={state.filter}\n onValueChange={isBrowse ? onSelectCategory : onSelectFilter}\n className={theme.classNames.tabs}\n preventMouseDownDefault\n />\n {showLoadingBanner ? loadingBanner : null}\n </div>\n <div className={paletteStyles.scrollShell}>\n <div\n ref={scrollBodyRef}\n className={cn(\n theme.classNames.scrollRegion,\n paletteStyles.scrollBody\n )}\n >\n {body}\n </div>\n <MentionPaletteScrollbar\n scrollBodyRef={scrollBodyRef}\n className={theme.classNames.scrollbar}\n thumbClassName={theme.classNames.scrollbarThumb}\n testId={theme.testIds.scrollbar}\n />\n </div>\n <div className={cn(theme.classNames.footer, paletteStyles.footer)}>\n <MentionPaletteHint\n ariaLabel={labels.tabHint}\n cycleFilterLabel={hintLabels.cycleFilter}\n moveSelectionLabel={hintLabels.moveSelection}\n onCycleFilter={onCycleFilter}\n onMoveSelection={onMoveSelection}\n classNames={theme.classNames}\n testId={theme.testIds.hint}\n />\n </div>\n </div>\n );\n}\n\nfunction centerElementInScrollContainer(\n container: HTMLElement,\n element: HTMLElement\n): void {\n const containerRect = container.getBoundingClientRect();\n const elementRect = element.getBoundingClientRect();\n const currentScrollTop = container.scrollTop;\n const elementTop = elementRect.top - containerRect.top + currentScrollTop;\n const centeredScrollTop =\n elementTop - (container.clientHeight - elementRect.height) / 2;\n const maxScrollTop = Math.max(\n 0,\n container.scrollHeight - container.clientHeight\n );\n const nextScrollTop = Math.min(Math.max(0, centeredScrollTop), maxScrollTop);\n container.scrollTo({ top: nextScrollTop, behavior: \"auto\" });\n}\n\nfunction findGroup<TItem>(\n groups: MentionPaletteState<TItem>[\"groups\"],\n groupId: string\n): MentionPaletteGroup<TItem> {\n const group = groups.find((candidate) => candidate.id === groupId);\n if (!group) {\n throw new Error(`MentionPalette: unknown group id \"${groupId}\"`);\n }\n return group;\n}\n\nfunction MentionPaletteGroups<TItem>({\n state,\n highlightedKey,\n highlightedOptionRef,\n getItemKey,\n renderItem,\n onHighlightChange,\n onSelectItem,\n onExpandGroup,\n renderListFooter,\n groupDividerAttribute\n}: {\n state: MentionPaletteState<TItem>;\n highlightedKey: string | null;\n highlightedOptionRef: MutableRefObject<HTMLButtonElement | null>;\n getItemKey: (item: TItem, group: MentionPaletteGroup<TItem>) => string;\n renderItem: (item: TItem, ctx: { active: boolean }) => ReactNode;\n onHighlightChange: (key: string) => void;\n onSelectItem: (item: TItem, group: MentionPaletteGroup<TItem>) => void;\n onExpandGroup: (groupId: string) => void;\n renderListFooter?: () => ReactNode;\n groupDividerAttribute: string;\n}): JSX.Element {\n return (\n <div className=\"grid gap-3\">\n {state.groups.map((group, index) => {\n const showGroupDivider = index > 0 && !group.hideTopDivider;\n return (\n <section\n key={group.id}\n className={cn(\"grid gap-1\", group.sectionClassName)}\n >\n {showGroupDivider ? (\n <div\n className=\"mx-3 mb-2 border-t border-[var(--line-1)]\"\n {...{ [groupDividerAttribute]: \"true\" }}\n aria-hidden=\"true\"\n />\n ) : null}\n {group.label ? (\n <div className=\"px-3 text-[13px] font-normal text-[var(--text-secondary)]\">\n {group.label}\n </div>\n ) : null}\n <div className=\"grid gap-1\">\n {group.items.length === 0 && group.emptyLabel ? (\n <div className=\"px-3 py-1 text-[13px] font-normal text-[var(--text-tertiary)]\">\n {group.emptyLabel}\n </div>\n ) : null}\n {group.items.map((item) => {\n const entryKey = `${group.id}:${getItemKey(item, group)}`;\n const isHighlighted = entryKey === highlightedKey;\n return (\n <button\n key={entryKey}\n ref={isHighlighted ? highlightedOptionRef : null}\n type=\"button\"\n className={cn(\n paletteStyles.rowButton,\n isHighlighted && \"bg-[var(--transparency-block)]\"\n )}\n role=\"option\"\n aria-selected={isHighlighted}\n data-highlighted={isHighlighted ? \"\" : undefined}\n onMouseEnter={() => onHighlightChange(entryKey)}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => onSelectItem(item, group)}\n >\n {renderItem(item, { active: isHighlighted })}\n </button>\n );\n })}\n {group.hasMore ? (\n <button\n key={`expand:${group.id}`}\n ref={\n `expand:${group.id}` === highlightedKey\n ? highlightedOptionRef\n : null\n }\n type=\"button\"\n className={cn(\n paletteStyles.expandButton,\n `expand:${group.id}` === highlightedKey &&\n \"bg-[var(--transparency-block)] text-[var(--text-primary)]\"\n )}\n data-highlighted={\n `expand:${group.id}` === highlightedKey ? \"\" : undefined\n }\n onMouseEnter={() => onHighlightChange(`expand:${group.id}`)}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => onExpandGroup(group.id)}\n >\n {group.expandLabel ??\n `+${Math.max(0, group.totalCount - group.visibleCount)}`}\n </button>\n ) : null}\n </div>\n </section>\n );\n })}\n {renderListFooter?.()}\n </div>\n );\n}\n\nfunction MentionPaletteEmptyState({\n icon = \"folder-failed\",\n label,\n testId\n}: {\n icon?: \"folder-failed\" | \"keyboard\";\n label: string;\n testId: string;\n}): JSX.Element {\n \"use memo\";\n const EmptyStateIcon =\n icon === \"keyboard\" ? KeyboardFilledIcon : FolderFailedFilledIcon;\n\n return (\n <div\n className=\"flex h-full min-h-0 flex-1 items-center justify-center px-4 py-6 text-center text-[13px] text-[var(--text-tertiary)]\"\n data-empty-state-icon={icon}\n data-testid={testId}\n >\n <div className=\"flex max-w-[28ch] flex-col items-center justify-center gap-3\">\n <EmptyStateIcon\n className=\"h-6 w-6 text-[var(--text-tertiary)]\"\n aria-hidden=\"true\"\n />\n <span className=\"leading-5 text-[var(--text-tertiary)]\">{label}</span>\n </div>\n </div>\n );\n}\n\nfunction MentionPaletteLoading({\n label,\n spinnerTestId\n}: {\n label: string;\n spinnerTestId: string;\n}): JSX.Element {\n \"use memo\";\n return (\n <div className=\"flex min-h-[52px] items-center gap-2 rounded-xl px-3 text-[13px] text-[var(--text-secondary)]\">\n <Spinner\n size={16}\n className=\"text-[var(--text-secondary)]\"\n testId={spinnerTestId}\n />\n <span>{label}</span>\n </div>\n );\n}\n\nfunction MentionPaletteHint({\n ariaLabel,\n cycleFilterLabel,\n moveSelectionLabel,\n onCycleFilter,\n onMoveSelection,\n classNames,\n testId\n}: {\n ariaLabel: string;\n cycleFilterLabel: string;\n moveSelectionLabel: string;\n onCycleFilter: (delta: 1 | -1) => void;\n onMoveSelection: (delta: 1 | -1) => void;\n classNames: ResolvedMentionPaletteTheme[\"classNames\"];\n testId: string;\n}): JSX.Element {\n \"use memo\";\n return (\n <div\n className={classNames.hint}\n aria-label={ariaLabel}\n data-testid={testId}\n >\n <button\n className={cn(classNames.hintItem, classNames.hintButton)}\n type=\"button\"\n aria-label={cycleFilterLabel}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => onCycleFilter(1)}\n >\n {/* i18n-check-ignore: Keyboard key label. */}\n <kbd className={classNames.shortcut}>Tab</kbd>\n <span>{cycleFilterLabel}</span>\n </button>\n <span className={classNames.hintSeparator} aria-hidden=\"true\">\n |\n </span>\n <span className={classNames.hintItem}>\n <span className={classNames.shortcutGroup}>\n <button\n className={cn(\n classNames.shortcut,\n classNames.shortcutArrow,\n classNames.shortcutButton\n )}\n type=\"button\"\n aria-label={`↑ ${moveSelectionLabel}`}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => onMoveSelection(-1)}\n >\n ↑\n </button>\n <button\n className={cn(\n classNames.shortcut,\n classNames.shortcutArrow,\n classNames.shortcutButton\n )}\n type=\"button\"\n aria-label={`↓ ${moveSelectionLabel}`}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => onMoveSelection(1)}\n >\n ↓\n </button>\n </span>\n <span>{moveSelectionLabel}</span>\n </span>\n </div>\n );\n}\n","import {\n useCallback,\n useEffect,\n useRef,\n useState,\n type JSX,\n type MouseEvent as ReactMouseEvent,\n type RefObject\n} from \"react\";\nimport { cn } from \"@tutti-os/ui-system/utils\";\n\ninterface MentionPaletteScrollbarState {\n scrollable: boolean;\n thumbHeight: number;\n thumbTop: number;\n}\n\ninterface MentionPaletteScrollbarDragState {\n maxScrollTop: number;\n maxThumbTop: number;\n startClientY: number;\n startScrollTop: number;\n}\n\nconst MENTION_PALETTE_SCROLLBAR_MIN_THUMB_HEIGHT = 24;\nconst MENTION_PALETTE_SCROLLBAR_HIDDEN_STATE: MentionPaletteScrollbarState = {\n scrollable: false,\n thumbHeight: 0,\n thumbTop: 0\n};\n\nexport function MentionPaletteScrollbar({\n scrollBodyRef,\n className,\n thumbClassName,\n testId\n}: {\n scrollBodyRef: RefObject<HTMLDivElement | null>;\n className: string;\n thumbClassName: string;\n testId: string;\n}): JSX.Element {\n \"use memo\";\n const trackRef = useRef<HTMLDivElement | null>(null);\n const dragStateRef = useRef<MentionPaletteScrollbarDragState | null>(null);\n const [scrollbarState, setScrollbarState] =\n useState<MentionPaletteScrollbarState>({\n scrollable: false,\n thumbHeight: 0,\n thumbTop: 0\n });\n const [dragging, setDragging] = useState(false);\n\n const hideScrollbar = useCallback((): void => {\n setScrollbarState((previous) =>\n previous.scrollable ||\n previous.thumbHeight !== 0 ||\n previous.thumbTop !== 0\n ? MENTION_PALETTE_SCROLLBAR_HIDDEN_STATE\n : previous\n );\n }, []);\n\n const syncScrollbarState = useCallback((): void => {\n const contentElement = scrollBodyRef.current;\n if (!contentElement) {\n hideScrollbar();\n return;\n }\n\n const { scrollHeight, scrollTop, clientHeight } = contentElement;\n const measuredTrackHeight = trackRef.current?.clientHeight ?? 0;\n const trackHeight =\n measuredTrackHeight > 0 ? measuredTrackHeight : clientHeight;\n const maxScrollTop = Math.max(0, scrollHeight - clientHeight);\n\n if (clientHeight <= 0 || trackHeight <= 0 || maxScrollTop <= 0) {\n hideScrollbar();\n return;\n }\n\n const thumbHeight = Math.max(\n MENTION_PALETTE_SCROLLBAR_MIN_THUMB_HEIGHT,\n Math.round((clientHeight / scrollHeight) * trackHeight)\n );\n const maxThumbTop = Math.max(0, trackHeight - thumbHeight);\n const thumbTop = Math.round((scrollTop / maxScrollTop) * maxThumbTop);\n setScrollbarState((previous) =>\n previous.scrollable &&\n previous.thumbHeight === thumbHeight &&\n previous.thumbTop === thumbTop\n ? previous\n : { scrollable: true, thumbHeight, thumbTop }\n );\n }, [hideScrollbar, scrollBodyRef]);\n\n useEffect(() => {\n const contentElement = scrollBodyRef.current;\n if (!contentElement) {\n hideScrollbar();\n return;\n }\n\n syncScrollbarState();\n contentElement.addEventListener(\"scroll\", syncScrollbarState, {\n passive: true\n });\n const resizeObserver =\n typeof ResizeObserver !== \"undefined\"\n ? new ResizeObserver(syncScrollbarState)\n : null;\n resizeObserver?.observe(contentElement);\n if (trackRef.current) {\n resizeObserver?.observe(trackRef.current);\n }\n const animationFrameId = window.requestAnimationFrame(syncScrollbarState);\n return () => {\n contentElement.removeEventListener(\"scroll\", syncScrollbarState);\n resizeObserver?.disconnect();\n window.cancelAnimationFrame(animationFrameId);\n };\n }, [hideScrollbar, scrollBodyRef, syncScrollbarState]);\n\n useEffect(() => {\n if (!dragging) {\n return;\n }\n\n const handleMouseMove = (event: MouseEvent): void => {\n const contentElement = scrollBodyRef.current;\n const dragState = dragStateRef.current;\n if (!contentElement || !dragState || dragState.maxThumbTop <= 0) {\n return;\n }\n const delta = event.clientY - dragState.startClientY;\n const nextThumbTop =\n (dragState.startScrollTop / dragState.maxScrollTop) *\n dragState.maxThumbTop +\n delta;\n contentElement.scrollTop =\n (Math.min(Math.max(0, nextThumbTop), dragState.maxThumbTop) /\n dragState.maxThumbTop) *\n dragState.maxScrollTop;\n syncScrollbarState();\n };\n\n const handleMouseUp = (): void => {\n dragStateRef.current = null;\n setDragging(false);\n };\n\n window.addEventListener(\"mousemove\", handleMouseMove);\n window.addEventListener(\"mouseup\", handleMouseUp);\n return () => {\n window.removeEventListener(\"mousemove\", handleMouseMove);\n window.removeEventListener(\"mouseup\", handleMouseUp);\n };\n }, [dragging, scrollBodyRef, syncScrollbarState]);\n\n const scrollContentToThumbTop = (thumbTop: number): void => {\n const contentElement = scrollBodyRef.current;\n const trackElement = trackRef.current;\n if (!contentElement || !trackElement) {\n return;\n }\n const maxScrollTop = Math.max(\n 0,\n contentElement.scrollHeight - contentElement.clientHeight\n );\n const maxThumbTop = Math.max(\n 0,\n trackElement.clientHeight - scrollbarState.thumbHeight\n );\n if (maxScrollTop <= 0 || maxThumbTop <= 0) {\n return;\n }\n contentElement.scrollTop =\n (Math.min(Math.max(0, thumbTop), maxThumbTop) / maxThumbTop) *\n maxScrollTop;\n syncScrollbarState();\n };\n\n const handleTrackMouseDown = (\n event: ReactMouseEvent<HTMLDivElement>\n ): void => {\n if (\n event.button !== 0 ||\n !scrollbarState.scrollable ||\n event.target !== event.currentTarget\n ) {\n return;\n }\n event.preventDefault();\n const trackRect = event.currentTarget.getBoundingClientRect();\n scrollContentToThumbTop(\n event.clientY - trackRect.top - scrollbarState.thumbHeight / 2\n );\n };\n\n const handleThumbMouseDown = (\n event: ReactMouseEvent<HTMLDivElement>\n ): void => {\n if (event.button !== 0 || !scrollbarState.scrollable) {\n return;\n }\n const contentElement = scrollBodyRef.current;\n const trackElement = trackRef.current;\n if (!contentElement || !trackElement) {\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n dragStateRef.current = {\n maxScrollTop: Math.max(\n 0,\n contentElement.scrollHeight - contentElement.clientHeight\n ),\n maxThumbTop: Math.max(\n 0,\n trackElement.clientHeight - scrollbarState.thumbHeight\n ),\n startClientY: event.clientY,\n startScrollTop: contentElement.scrollTop\n };\n setDragging(true);\n };\n\n if (!scrollbarState.scrollable && !dragging) {\n return <div ref={trackRef} className=\"hidden\" aria-hidden=\"true\" />;\n }\n\n return (\n <div\n ref={trackRef}\n className={cn(\"group/status-scrollbar\", className)}\n data-scrollable={scrollbarState.scrollable ? \"true\" : \"false\"}\n data-dragging={dragging ? \"true\" : \"false\"}\n data-testid={testId}\n aria-hidden=\"true\"\n onMouseDown={handleTrackMouseDown}\n >\n <div\n className={thumbClassName}\n onMouseDown={handleThumbMouseDown}\n style={{\n height: `${scrollbarState.thumbHeight}px`,\n transform: `translateY(${scrollbarState.thumbTop}px)`\n }}\n />\n </div>\n );\n}\n","import {\n ArrowLeftIcon,\n Badge,\n FileCodeIcon,\n FileTextIcon,\n FolderIcon,\n ImageFileIcon,\n ProductIcon,\n StatusDot,\n VideoFileIcon,\n cn,\n type IconProps\n} from \"@tutti-os/ui-system\";\nimport type { MentionFileVisualKind } from \"./mentionFileVisualKind.ts\";\nimport {\n mentionRowDataAttribute,\n mentionRowRootDataAttributes,\n type MentionRowDataAttributeMode\n} from \"./mentionRowDataAttributes.ts\";\nimport type {\n MentionRowFileItem,\n MentionRowItem,\n MentionRowSessionItem,\n MentionRowStatusTag\n} from \"./mentionRowTypes.ts\";\nimport { mentionStatusBadgeClassName } from \"./mentionStatusTone.ts\";\n\n/**\n * Default file kind-icon shapes for surfaces that do NOT ship the agent's\n * CSS-masked glyph stylesheet. These mirror the agent's mask glyph shapes\n * (`agentactivity.css`: folder-filled / doc-filled / code-filled / image-filled\n * / video-filled / arrow-left-filled) using ui-system icon components, so a\n * file row renders a real glyph without `agentactivity.css`. The agent composer\n * passes its own `fileIcon` class and keeps rendering the masked `<span>`.\n */\nconst MENTION_FILE_VISUAL_KIND_ICON: Record<\n MentionFileVisualKind,\n (props: IconProps) => React.JSX.Element\n> = {\n back: ArrowLeftIcon,\n folder: FolderIcon,\n document: FileTextIcon,\n // The agent maps markdown to `product-filled.svg`; ProductIcon is the\n // matching boundary-safe ui-system glyph.\n markdown: ProductIcon,\n code: FileCodeIcon,\n image: ImageFileIcon,\n video: VideoFileIcon\n};\n\n/**\n * Structural class-name hooks for the elements a {@link MentionRow} renders that\n * rely on a stylesheet (file icon/thumb, the app fallback kind-icon, and the\n * session avatar placeholder modifier). Every key is optional and defaults to a\n * PACKAGE-OWNED `rich-text-at-mention-*` class whose CSS ships with\n * `mentionPalette.css`, so any consumer renders styled rows out of the box.\n *\n * Surfaces with their own stylesheet (e.g. the agent composer) pass their exact\n * existing class names here so their rendered DOM stays byte-identical.\n */\nexport interface MentionRowClassNames {\n /** The masked file kind-icon `<span>`. */\n fileIcon?: string;\n /** The image-thumbnail wrapper `<span>` (rendered for image files). */\n fileThumb?: string;\n /** The fallback app icon glyph rendered when no `iconUrl` is present. */\n kindIcon?: string;\n /**\n * Modifier class added to the session user avatar `<img>` when the user has no\n * avatar URL and the placeholder asset is shown.\n */\n avatarImgUserPlaceholder?: string;\n}\n\nexport interface MentionRowRenderOptions {\n classNames?: MentionRowClassNames;\n dataAttributeMode?: MentionRowDataAttributeMode;\n}\n\ninterface ResolvedMentionRowRenderOptions {\n classNames?: MentionRowClassNames;\n dataAttributeMode: MentionRowDataAttributeMode;\n}\n\nconst DEFAULT_MENTION_ROW_CLASS_NAMES = {\n fileIcon: \"rich-text-at-mention-file-icon\",\n fileThumb: \"rich-text-at-mention-file-thumb\",\n kindIcon: \"rich-text-at-mention-kind-icon\",\n avatarImgUserPlaceholder: \"rich-text-at-mention-avatar-img--user-placeholder\"\n} as const satisfies Required<MentionRowClassNames>;\n\nfunction resolveMentionRowClassNames(\n classNames?: MentionRowClassNames\n): Required<MentionRowClassNames> {\n return {\n fileIcon: classNames?.fileIcon ?? DEFAULT_MENTION_ROW_CLASS_NAMES.fileIcon,\n fileThumb:\n classNames?.fileThumb ?? DEFAULT_MENTION_ROW_CLASS_NAMES.fileThumb,\n kindIcon: classNames?.kindIcon ?? DEFAULT_MENTION_ROW_CLASS_NAMES.kindIcon,\n avatarImgUserPlaceholder:\n classNames?.avatarImgUserPlaceholder ??\n DEFAULT_MENTION_ROW_CLASS_NAMES.avatarImgUserPlaceholder\n };\n}\n\nfunction resolveMentionRowRenderOptions(\n options?: MentionRowClassNames | MentionRowRenderOptions\n): ResolvedMentionRowRenderOptions {\n if (isMentionRowRenderOptions(options)) {\n return {\n classNames: options.classNames,\n dataAttributeMode: options.dataAttributeMode ?? \"shared\"\n };\n }\n return {\n classNames: options,\n dataAttributeMode: \"shared\"\n };\n}\n\nfunction isMentionRowRenderOptions(\n options: MentionRowClassNames | MentionRowRenderOptions | undefined\n): options is MentionRowRenderOptions {\n return (\n options !== undefined &&\n (\"classNames\" in options || \"dataAttributeMode\" in options)\n );\n}\n\n/**\n * Render the inner content of a single `@`-mention palette row from a\n * fully-resolved {@link MentionRowItem}. The surrounding option button / active\n * state is provided by the shared `MentionPalette` shell; this renders only the\n * row body.\n *\n * Pass {@link classNames} to override the package-owned structural class hooks\n * (e.g. so the agent composer keeps emitting its own stylesheet's class names).\n */\nexport function renderMentionRow(\n item: MentionRowItem,\n options?: MentionRowClassNames | MentionRowRenderOptions\n): React.ReactNode {\n const { classNames, dataAttributeMode } =\n resolveMentionRowRenderOptions(options);\n const resolved = resolveMentionRowClassNames(classNames);\n if (item.kind === \"file\") {\n return (\n <MentionFileRow\n item={item}\n classNames={resolved}\n dataAttributeMode={dataAttributeMode}\n />\n );\n }\n\n if (item.kind === \"session\") {\n return (\n <span className=\"grid w-full min-w-0 grid-cols-[minmax(0,1fr)_auto] items-center gap-3\">\n <span className=\"flex min-w-0 items-center gap-2 overflow-hidden\">\n <MentionSessionAvatarStack\n item={item}\n classNames={resolved}\n dataAttributeMode={dataAttributeMode}\n />\n <span className=\"min-w-0 truncate text-[13px] font-semibold leading-[16px] text-[var(--text-primary)]\">\n <MentionSessionTitle item={item} />\n </span>\n </span>\n {item.statusTag ? (\n <MentionStatusBadge\n statusTag={item.statusTag}\n dataAttributeMode={dataAttributeMode}\n />\n ) : null}\n </span>\n );\n }\n\n if (item.kind === \"app\") {\n return (\n <span className=\"flex min-w-0 items-center gap-2 overflow-hidden\">\n <MentionWorkspaceAppIcon\n iconUrl={item.iconUrl}\n kindIconClassName={resolved.kindIcon}\n dataAttributeMode={dataAttributeMode}\n />\n <span className=\"flex min-w-0 flex-1 items-baseline gap-1 overflow-hidden\">\n <span className=\"min-w-0 max-w-[40%] shrink-0 truncate text-[13px] font-semibold text-[var(--text-primary)]\">\n {item.name}\n </span>\n {item.description ? (\n <span className=\"min-w-0 flex-1 truncate text-[13px] font-normal text-[var(--text-secondary)]\">\n {item.description}\n </span>\n ) : null}\n </span>\n </span>\n );\n }\n\n if (item.kind === \"app-factory\") {\n return (\n <span className=\"grid min-w-0 overflow-hidden gap-1\">\n <span className=\"min-w-0 flex-1 truncate text-[13px] font-semibold text-[var(--text-primary)]\">\n {item.name}\n </span>\n </span>\n );\n }\n\n return (\n <span className=\"grid min-w-0 overflow-hidden gap-1\">\n <span className=\"flex min-w-0 items-center gap-2 overflow-hidden\">\n <span className=\"min-w-0 truncate text-[13px] font-semibold text-[var(--text-primary)]\">\n {item.title}\n </span>\n {item.statusTag ? (\n <MentionStatusBadge\n statusTag={item.statusTag}\n dataAttributeMode={dataAttributeMode}\n />\n ) : null}\n </span>\n {item.creatorName ? (\n <span className=\"truncate text-[13px] font-normal text-[var(--text-secondary)]\">\n {item.creatorName}\n </span>\n ) : null}\n </span>\n );\n}\n\nfunction MentionFileRow({\n item,\n classNames,\n dataAttributeMode\n}: {\n item: MentionRowFileItem;\n classNames: Required<MentionRowClassNames>;\n dataAttributeMode: MentionRowDataAttributeMode;\n}): React.JSX.Element {\n return (\n <span\n className=\"flex min-w-0 items-center gap-2\"\n {...mentionRowRootDataAttributes(dataAttributeMode, \"file\")}\n {...(item.entryKind\n ? mentionRowDataAttribute(\n dataAttributeMode,\n \"fileEntryKind\",\n item.entryKind\n )\n : {})}\n {...mentionRowDataAttribute(\n dataAttributeMode,\n \"fileVisualKind\",\n item.visualKind\n )}\n {...(item.mentionNavigation\n ? mentionRowDataAttribute(\n dataAttributeMode,\n \"navigation\",\n item.mentionNavigation\n )\n : {})}\n >\n <MentionFileIcon\n item={item}\n classNames={classNames}\n dataAttributeMode={dataAttributeMode}\n />\n <span className=\"flex min-w-0 items-baseline gap-1 overflow-hidden\">\n <span className=\"min-w-0 truncate text-[13px] font-semibold text-[var(--text-primary)]\">\n {item.name}\n </span>\n {item.childCountLabel ? (\n <span className=\"shrink-0 text-[13px] font-normal text-[var(--text-secondary)]\">\n {item.childCountLabel}\n </span>\n ) : null}\n </span>\n </span>\n );\n}\n\nfunction MentionFileIcon({\n item,\n classNames,\n dataAttributeMode\n}: {\n item: MentionRowFileItem;\n classNames: Required<MentionRowClassNames>;\n dataAttributeMode: MentionRowDataAttributeMode;\n}): React.JSX.Element {\n const thumbnailUrl =\n item.visualKind === \"image\" ? item.thumbnailUrl?.trim() || \"\" : \"\";\n if (thumbnailUrl) {\n return (\n <span\n className={classNames.fileThumb}\n {...mentionRowDataAttribute(dataAttributeMode, \"fileThumb\", \"true\")}\n aria-hidden=\"true\"\n >\n <img\n src={thumbnailUrl}\n alt=\"\"\n className=\"h-full w-full object-cover\"\n decoding=\"async\"\n loading=\"lazy\"\n draggable={false}\n />\n </span>\n );\n }\n\n // Surfaces that ship a custom file-icon stylesheet (e.g. the agent composer\n // via `agentactivity.css`) render the empty CSS-masked `<span>` so their DOM\n // stays byte-identical. Surfaces using the package default class have no such\n // stylesheet, so render a real ui-system kind glyph instead of an empty box.\n const usesDefaultFileIcon =\n classNames.fileIcon === DEFAULT_MENTION_ROW_CLASS_NAMES.fileIcon;\n if (usesDefaultFileIcon) {\n const Icon = MENTION_FILE_VISUAL_KIND_ICON[item.visualKind];\n return (\n <span\n className={cn(\n classNames.fileIcon,\n \"grid h-4 w-4 shrink-0 place-items-center text-[var(--text-secondary)]\"\n )}\n {...mentionRowDataAttribute(\n dataAttributeMode,\n \"fileVisualKind\",\n item.visualKind\n )}\n aria-hidden=\"true\"\n >\n <Icon size={16} />\n </span>\n );\n }\n\n return (\n <span\n className={classNames.fileIcon}\n {...mentionRowDataAttribute(\n dataAttributeMode,\n \"fileVisualKind\",\n item.visualKind\n )}\n aria-hidden=\"true\"\n />\n );\n}\n\nfunction MentionWorkspaceAppIcon({\n iconUrl,\n kindIconClassName,\n dataAttributeMode\n}: {\n iconUrl?: string | null;\n kindIconClassName: string;\n dataAttributeMode: MentionRowDataAttributeMode;\n}): React.JSX.Element {\n const normalizedIconUrl = iconUrl?.trim() ?? \"\";\n return (\n <span\n className=\"grid h-5 w-5 shrink-0 place-items-center overflow-hidden rounded-[5px] bg-block text-[var(--text-secondary)]\"\n {...mentionRowDataAttribute(dataAttributeMode, \"appIcon\", \"true\")}\n data-workspace-app-icon=\"true\"\n aria-hidden=\"true\"\n >\n {normalizedIconUrl ? (\n <img\n src={normalizedIconUrl}\n alt=\"\"\n className=\"h-full w-full object-cover\"\n decoding=\"async\"\n loading=\"lazy\"\n draggable={false}\n />\n ) : (\n <span className={cn(kindIconClassName, \"h-4 w-4\")} />\n )}\n </span>\n );\n}\n\nfunction MentionSessionAvatarStack({\n item,\n classNames,\n dataAttributeMode\n}: {\n item: MentionRowSessionItem;\n classNames: Required<MentionRowClassNames>;\n dataAttributeMode: MentionRowDataAttributeMode;\n}): React.JSX.Element {\n const userAvatarUrl = item.userAvatarUrl?.trim() ?? \"\";\n const placeholderUrl = item.userAvatarPlaceholderUrl;\n const userImageUrl = userAvatarUrl || placeholderUrl;\n return (\n <span\n className=\"relative isolate block h-5 w-9 shrink-0\"\n aria-hidden=\"true\"\n >\n <span\n className=\"absolute left-0 top-0 z-0 grid h-5 w-5 overflow-hidden rounded-full bg-block\"\n {...mentionRowDataAttribute(dataAttributeMode, \"userAvatar\", \"true\")}\n >\n <img\n src={userImageUrl}\n alt=\"\"\n className={cn(\n \"h-full w-full object-cover\",\n !userAvatarUrl && classNames.avatarImgUserPlaceholder\n )}\n decoding=\"async\"\n loading=\"lazy\"\n referrerPolicy=\"no-referrer\"\n draggable={false}\n onError={(event) => {\n if (event.currentTarget.dataset.fallbackAvatarApplied === \"true\") {\n return;\n }\n event.currentTarget.dataset.fallbackAvatarApplied = \"true\";\n event.currentTarget.src = placeholderUrl;\n event.currentTarget.classList.add(\n classNames.avatarImgUserPlaceholder\n );\n }}\n />\n </span>\n <span\n className=\"absolute left-4 top-0 z-10 grid h-5 w-5 overflow-hidden rounded-full bg-block\"\n {...mentionRowDataAttribute(dataAttributeMode, \"agentAvatar\", \"true\")}\n >\n <img\n src={item.agentIconUrl}\n alt=\"\"\n className=\"h-full w-full object-cover\"\n decoding=\"async\"\n loading=\"lazy\"\n draggable={false}\n />\n </span>\n </span>\n );\n}\n\nfunction MentionSessionTitle({\n item\n}: {\n item: MentionRowSessionItem;\n}): React.JSX.Element {\n return (\n <>\n <span className=\"text-[13px] leading-[16px]\">{item.participant}</span>\n <span className=\"text-[13px] font-normal leading-[16px] text-[var(--text-secondary)]\">\n {\" \"}\n {item.summary ?? \"\"}\n </span>\n </>\n );\n}\n\nfunction MentionStatusBadge({\n statusTag,\n dataAttributeMode\n}: {\n statusTag: MentionRowStatusTag;\n dataAttributeMode: MentionRowDataAttributeMode;\n}): React.JSX.Element {\n if (statusTag.variant === \"issue\") {\n return (\n <Badge\n variant=\"secondary\"\n className={cn(\n \"shrink-0 text-[13px]\",\n mentionStatusBadgeClassName({\n tone: statusTag.tone,\n variant: \"issue\"\n })\n )}\n {...mentionRowDataAttribute(dataAttributeMode, \"statusTag\", \"true\")}\n {...(statusTag.dataStatus\n ? { \"data-status\": statusTag.dataStatus }\n : {})}\n >\n {statusTag.label}\n </Badge>\n );\n }\n\n return (\n <Badge\n variant=\"secondary\"\n className={cn(\n \"inline-flex h-5 shrink-0 items-center gap-1.5 rounded-[4px] px-2 text-[11px] font-semibold leading-none\",\n mentionStatusBadgeClassName({\n tone: statusTag.tone,\n variant: \"activity\"\n })\n )}\n {...mentionRowDataAttribute(dataAttributeMode, \"statusTag\", \"true\")}\n {...(statusTag.dataStatus ? { \"data-status\": statusTag.dataStatus } : {})}\n data-tone={statusTag.tone}\n title={statusTag.label}\n >\n <StatusDot\n tone={statusTag.tone}\n pulse={statusTag.pulse ?? false}\n size=\"xs\"\n title={statusTag.label}\n />\n <span>{statusTag.label}</span>\n </Badge>\n );\n}\n","import type { MentionRowItem } from \"./mentionRowTypes.ts\";\n\nexport type MentionRowDataAttributeMode = \"shared\" | \"agent\";\n\nexport type MentionRowDataAttributeKey =\n | \"agentAvatar\"\n | \"appIcon\"\n | \"fileEntryKind\"\n | \"fileThumb\"\n | \"fileVisualKind\"\n | \"navigation\"\n | \"statusTag\"\n | \"userAvatar\";\n\nconst MENTION_ROW_DATA_ATTRIBUTES: Record<\n MentionRowDataAttributeMode,\n Record<MentionRowDataAttributeKey, string>\n> = {\n shared: {\n agentAvatar: \"data-rich-text-at-mention-agent-avatar\",\n appIcon: \"data-rich-text-at-mention-app-icon\",\n fileEntryKind: \"data-rich-text-at-mention-file-entry-kind\",\n fileThumb: \"data-rich-text-at-mention-file-thumb\",\n fileVisualKind: \"data-rich-text-at-mention-file-visual-kind\",\n navigation: \"data-rich-text-at-mention-navigation\",\n statusTag: \"data-rich-text-at-mention-status-tag\",\n userAvatar: \"data-rich-text-at-mention-user-avatar\"\n },\n agent: {\n agentAvatar: \"data-agent-mention-agent-avatar\",\n appIcon: \"data-agent-mention-app-icon\",\n fileEntryKind: \"data-agent-file-entry-kind\",\n fileThumb: \"data-agent-mention-file-thumb\",\n fileVisualKind: \"data-agent-file-visual-kind\",\n navigation: \"data-agent-mention-navigation\",\n statusTag: \"data-agent-mention-status-tag\",\n userAvatar: \"data-agent-mention-user-avatar\"\n }\n};\n\nexport function mentionRowRootDataAttributes(\n mode: MentionRowDataAttributeMode,\n kind: MentionRowItem[\"kind\"]\n): Record<string, string> {\n return mode === \"agent\"\n ? {\n \"data-agent-file-mention\": \"true\",\n \"data-agent-mention-kind\": kind\n }\n : {\n \"data-rich-text-at-mention-row\": \"true\",\n \"data-rich-text-at-mention-kind\": kind\n };\n}\n\nexport function mentionRowDataAttribute(\n mode: MentionRowDataAttributeMode,\n key: MentionRowDataAttributeKey,\n value: string\n): Record<string, string> {\n return {\n [MENTION_ROW_DATA_ATTRIBUTES[mode][key]]: value\n };\n}\n","export interface AtPanelKeyboardActions {\n moveSelection: (delta: 1 | -1) => void;\n commitSelection: () => void;\n close: () => void;\n cycleFilter?: (delta: 1 | -1) => void;\n}\n\nexport interface AtPanelKeyboardEventLike {\n key: string;\n shiftKey?: boolean;\n preventDefault: () => void;\n}\n\nexport function makeAtPanelKeyDown(actions: AtPanelKeyboardActions) {\n return (event: AtPanelKeyboardEventLike): boolean => {\n if (event.key === \"ArrowDown\") {\n event.preventDefault();\n actions.moveSelection(1);\n return true;\n }\n if (event.key === \"ArrowUp\") {\n event.preventDefault();\n actions.moveSelection(-1);\n return true;\n }\n if (event.key === \"Escape\") {\n event.preventDefault();\n actions.close();\n return true;\n }\n if (event.key === \"Tab\" && actions.cycleFilter) {\n event.preventDefault();\n actions.cycleFilter(event.shiftKey ? -1 : 1);\n return true;\n }\n if (event.key === \"Enter\") {\n event.preventDefault();\n actions.commitSelection();\n return true;\n }\n return false;\n };\n}\n\nexport function useAtPanelKeyboard(actions: AtPanelKeyboardActions) {\n return makeAtPanelKeyDown(actions);\n}\n"],"mappings":"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","names":["useEffect","useRef","useState","cn","jsx","useRef","useState","useEffect","cn","cn","jsx","jsxs","cn"]}
@@ -0,0 +1,386 @@
1
+ import { RichTextTriggerQueryMatch, RichTextTriggerInsertResult } from '../types/index.js';
2
+ import { ReactNode } from 'react';
3
+ import '../mention-CgUcsO8r.js';
4
+
5
+ type MentionPaletteFilterId = string;
6
+ type MentionPaletteGroupId = string;
7
+ interface MentionPaletteCategory {
8
+ id: MentionPaletteFilterId;
9
+ label: string;
10
+ }
11
+ interface MentionPaletteGroup<TItem> {
12
+ id: MentionPaletteGroupId;
13
+ label?: string;
14
+ items: readonly TItem[];
15
+ totalCount: number;
16
+ visibleCount: number;
17
+ hasMore: boolean;
18
+ emptyLabel?: string;
19
+ /**
20
+ * Optional precomputed label for the "show more" expand control. When omitted
21
+ * the shell falls back to `+<remaining>`. Surfaces that need exact wording
22
+ * (e.g. the agent's translated "show N more") compute this themselves so the
23
+ * shell stays free of surface-specific i18n.
24
+ */
25
+ expandLabel?: string;
26
+ /**
27
+ * Optional extra class names applied to the group `<section>` element. Lets a
28
+ * consumer add bespoke spacing between specific groups (e.g. extra top margin
29
+ * when one group directly follows a related one) without the shell needing to
30
+ * know about surface-specific group relationships.
31
+ */
32
+ sectionClassName?: string;
33
+ /**
34
+ * When true the shell omits the divider it would otherwise render above this
35
+ * group (the divider normally appears before every group after the first).
36
+ * Lets a consumer suppress inter-group chrome in specific contexts (e.g. while
37
+ * showing a flat, ungrouped search result list).
38
+ */
39
+ hideTopDivider?: boolean;
40
+ }
41
+ /**
42
+ * Generic theming hooks so a consumer can keep its own stylesheet class names,
43
+ * test ids, and divider data-attribute when migrating onto the shared shell.
44
+ * Every field is optional and defaults to the shell's own `rich-text-at-*`
45
+ * identifiers, so the shell stays surface-agnostic.
46
+ */
47
+ interface MentionPaletteTheme {
48
+ classNames?: {
49
+ palette?: string;
50
+ header?: string;
51
+ footer?: string;
52
+ tabs?: string;
53
+ scrollRegion?: string;
54
+ scrollbar?: string;
55
+ scrollbarThumb?: string;
56
+ hint?: string;
57
+ hintItem?: string;
58
+ hintButton?: string;
59
+ hintSeparator?: string;
60
+ shortcut?: string;
61
+ shortcutArrow?: string;
62
+ shortcutButton?: string;
63
+ shortcutGroup?: string;
64
+ };
65
+ testIds?: {
66
+ emptyState?: string;
67
+ hint?: string;
68
+ scrollbar?: string;
69
+ loadingSpinner?: string;
70
+ };
71
+ /** data-attribute (without value) used to mark the inter-group divider. */
72
+ groupDividerAttribute?: string;
73
+ }
74
+ type MentionPaletteState<TItem> = {
75
+ status: "idle";
76
+ query: string;
77
+ mode: "browse";
78
+ filter: MentionPaletteFilterId;
79
+ categories: readonly MentionPaletteCategory[];
80
+ groups: readonly MentionPaletteGroup<TItem>[];
81
+ error: null;
82
+ } | {
83
+ status: "loading" | "ready";
84
+ query: string;
85
+ mode: "browse" | "results";
86
+ filter: MentionPaletteFilterId;
87
+ categories: readonly MentionPaletteCategory[];
88
+ groups: readonly MentionPaletteGroup<TItem>[];
89
+ error: null;
90
+ } | {
91
+ status: "error";
92
+ query: string;
93
+ mode: "browse" | "results";
94
+ filter: MentionPaletteFilterId;
95
+ categories: readonly MentionPaletteCategory[];
96
+ groups: readonly MentionPaletteGroup<TItem>[];
97
+ error: string;
98
+ };
99
+ interface MentionPaletteEntry {
100
+ key: string;
101
+ type: "category" | "item" | "expand";
102
+ categoryId?: MentionPaletteFilterId;
103
+ groupId?: MentionPaletteGroupId;
104
+ itemIndex?: number;
105
+ }
106
+ interface MentionPaletteProps<TItem> {
107
+ state: MentionPaletteState<TItem>;
108
+ highlightedKey: string | null;
109
+ getItemKey: (item: TItem, group: MentionPaletteGroup<TItem>) => string;
110
+ renderItem: (item: TItem, ctx: {
111
+ active: boolean;
112
+ }) => ReactNode;
113
+ labels: {
114
+ loading: string;
115
+ empty: string;
116
+ error: string;
117
+ tabHint: string;
118
+ /**
119
+ * Accessible name for the listbox container. Defaults to `tabHint` when
120
+ * omitted; consumers that label the whole palette differently from the
121
+ * keyboard-hint bar supply it explicitly.
122
+ */
123
+ listbox?: string;
124
+ };
125
+ hintLabels: {
126
+ cycleFilter: string;
127
+ moveSelection: string;
128
+ };
129
+ maxHeightPx: number;
130
+ onHighlightChange: (key: string) => void;
131
+ onSelectItem: (item: TItem, group: MentionPaletteGroup<TItem>) => void;
132
+ onSelectCategory: (categoryId: MentionPaletteFilterId) => void;
133
+ onSelectFilter: (filter: MentionPaletteFilterId) => void;
134
+ onExpandGroup: (groupId: MentionPaletteGroupId) => void;
135
+ onCycleFilter: (delta: 1 | -1) => void;
136
+ onMoveSelection: (delta: 1 | -1) => void;
137
+ /** Rendered after the groups, before the keyboard hint bar. */
138
+ renderListFooter?: () => ReactNode;
139
+ /**
140
+ * Rendered inside the header, directly under the category tabs, while results
141
+ * are refreshing in-place (i.e. existing results stay visible). Consumers that
142
+ * want an inline "refreshing" banner supply it here; omit for none.
143
+ */
144
+ loadingBanner?: ReactNode;
145
+ /**
146
+ * When true, scrolling the highlighted row into view centers it within the
147
+ * scroll container instead of using the default `block: "nearest"` behavior.
148
+ */
149
+ scrollHighlightedIntoViewCentered?: boolean;
150
+ /** Optional generic theming overrides; defaults to the shell's own styling. */
151
+ theme?: MentionPaletteTheme;
152
+ }
153
+
154
+ type RichTextAtFilterId = string;
155
+ type RichTextAtGroupId = string;
156
+ interface RichTextAtFilterTab {
157
+ id: RichTextAtFilterId;
158
+ label: string;
159
+ }
160
+ interface RichTextTriggerProviderGroup {
161
+ id: RichTextAtGroupId;
162
+ label: string;
163
+ providerIds: readonly string[];
164
+ filterId?: RichTextAtFilterId;
165
+ emptyLabel?: string;
166
+ pageSize?: number;
167
+ }
168
+ interface RichTextAtPanelReferenceItem {
169
+ key: string;
170
+ label: string;
171
+ subtitle?: string;
172
+ thumbnailUrl?: string | null;
173
+ insertResult: RichTextTriggerInsertResult;
174
+ }
175
+ interface RichTextAtPanelMatch<TItem = unknown> extends RichTextTriggerQueryMatch<TItem> {
176
+ thumbnailUrl?: string;
177
+ referenceItems?: readonly RichTextAtPanelReferenceItem[];
178
+ referenceItemsLoading?: boolean;
179
+ referenceNextCursor?: string | null;
180
+ }
181
+ interface RichTextAtSearchGroup<TItem = unknown> {
182
+ id: RichTextAtGroupId;
183
+ label: string;
184
+ items: readonly RichTextAtPanelMatch<TItem>[];
185
+ totalCount: number;
186
+ visibleCount: number;
187
+ hasMore: boolean;
188
+ emptyLabel?: string;
189
+ }
190
+
191
+ declare function buildMentionPaletteState(input: {
192
+ matches: readonly RichTextTriggerQueryMatch[];
193
+ providerGroups: readonly RichTextTriggerProviderGroup[];
194
+ filterTabs: readonly {
195
+ id: string;
196
+ label: string;
197
+ }[];
198
+ activeFilterId: string;
199
+ expandedCounts: Record<string, number | undefined>;
200
+ query: string;
201
+ isLoading: boolean;
202
+ pageSize?: number;
203
+ showMoreLabel?: (count: number) => string;
204
+ /**
205
+ * Optional predicate gating whether a group's header label is emitted. When
206
+ * provided and it returns false, the group renders without a label (matching
207
+ * the agent composer's conditional `shouldRenderMentionGroupLabel` rule, e.g.
208
+ * hiding a single group's header when it just duplicates the active filter
209
+ * tab). When omitted, the group label is always emitted (legacy behavior).
210
+ */
211
+ shouldRenderGroupLabel?: (groupId: string, groupCount: number) => boolean;
212
+ }): MentionPaletteState<RichTextTriggerQueryMatch>;
213
+
214
+ /**
215
+ * Pure, dependency-free file visual-kind helpers shared by every `@`-mention
216
+ * surface that renders a {@link MentionRow}. The *base* extension → kind
217
+ * resolution lives in each surface (the agent maps file-manager kinds, etc.);
218
+ * this module owns only the surface-agnostic vocabulary and the thumbnail rule
219
+ * so the shared row renderer never imports a workspace feature.
220
+ */
221
+ type MentionFileVisualKind = "back" | "document" | "code" | "markdown" | "image" | "video" | "folder";
222
+ interface MentionFileVisualKindInput {
223
+ entryKind?: string | null;
224
+ mentionNavigation?: string | null;
225
+ /**
226
+ * The base visual kind already resolved from the file extension/name by the
227
+ * surface (e.g. the agent's file-manager mapping). Used as the fallback when
228
+ * the entry is neither a back-navigation marker nor a directory.
229
+ */
230
+ baseVisualKind: MentionFileVisualKind;
231
+ }
232
+ /**
233
+ * Resolve the row's visual kind from a pre-resolved {@link MentionFileVisualKindInput.baseVisualKind}
234
+ * plus the structural markers (back navigation, directory) that override it.
235
+ */
236
+ declare function resolveMentionFileVisualKind(input: MentionFileVisualKindInput): MentionFileVisualKind;
237
+ /**
238
+ * The thumbnail is only shown for image entries with a non-empty thumbnail URL.
239
+ */
240
+ declare function resolveMentionFileThumbnailUrl(input: {
241
+ visualKind: MentionFileVisualKind;
242
+ thumbnailUrl?: string | null;
243
+ }): string | undefined;
244
+
245
+ /**
246
+ * Tone → className maps for the {@link MentionStatusBadge} rendered inside a
247
+ * {@link MentionRow}. The surface resolves a status into a data-only
248
+ * {@link MentionRowStatusTag} (label + tone + variant); this module owns the
249
+ * presentational mapping so the styling stays in one place and identical across
250
+ * surfaces.
251
+ */
252
+ type MentionRowStatusTone = "amber" | "blue" | "green" | "neutral" | "red";
253
+ type MentionRowStatusVariant = "activity" | "issue";
254
+ /**
255
+ * Background/text classes for the agent activity status badge. Ported verbatim
256
+ * from the agent's `mentionStatusBadgeClassName` so the rendered DOM is
257
+ * unchanged.
258
+ */
259
+ declare function activityMentionStatusBadgeClassName(tone: MentionRowStatusTone): string;
260
+ /**
261
+ * Background/text classes for the issue status badge. Ported verbatim from the
262
+ * agent's `issueMentionStatusBadgeClassName` (keyed by the issue tone the
263
+ * surface resolves).
264
+ */
265
+ declare function issueMentionStatusBadgeClassName(tone: MentionRowStatusTone): string;
266
+ declare function mentionStatusBadgeClassName(input: {
267
+ tone: MentionRowStatusTone;
268
+ variant: MentionRowStatusVariant;
269
+ }): string;
270
+ /**
271
+ * Map a normalized agent-activity display status to its badge tone. Shared by
272
+ * every `@`-mention surface that renders a session row (agent composer,
273
+ * issue-manager) so the activity status badge color is identical across
274
+ * surfaces. Mirrors the agent composer's local `mentionStatusTone` mapping
275
+ * verbatim (the agent keeps its own copy producing identical values). The label
276
+ * is resolved by each surface; only the tone lives here.
277
+ */
278
+ declare function activityMentionStatusTone(status: string): MentionRowStatusTone;
279
+ /**
280
+ * Map an issue status string to its badge tone. Shared by every `@`-mention
281
+ * surface that renders an issue row (agent composer, issue-manager) so the
282
+ * status badge color is identical across surfaces. The label is resolved by
283
+ * each surface's own i18n; only the tone lives here.
284
+ */
285
+ declare function issueMentionStatusTone(status: string): MentionRowStatusTone;
286
+
287
+ /**
288
+ * A fully-resolved, display-ready status badge for a {@link MentionRowItem}.
289
+ * The surface resolves the localized {@link label} and {@link tone}; the shared
290
+ * row renderer only maps tone → className and renders the markup.
291
+ */
292
+ interface MentionRowStatusTag {
293
+ label: string;
294
+ tone: MentionRowStatusTone;
295
+ /** Whether the status dot should pulse (activity variant only). */
296
+ pulse?: boolean;
297
+ variant: MentionRowStatusVariant;
298
+ /**
299
+ * Stable `data-status` attribute value (e.g. the normalized activity status
300
+ * or issue status) preserved so existing DOM assertions keep matching.
301
+ */
302
+ dataStatus?: string;
303
+ }
304
+ interface MentionRowFileItem {
305
+ kind: "file";
306
+ name: string;
307
+ visualKind: MentionFileVisualKind;
308
+ thumbnailUrl?: string | null;
309
+ childCountLabel?: string | null;
310
+ /** Optional file entry kind surfaced as a row data attribute. */
311
+ entryKind?: string | null;
312
+ /** Optional navigation marker surfaced as a row data attribute. */
313
+ mentionNavigation?: string | null;
314
+ }
315
+ interface MentionRowAppItem {
316
+ kind: "app";
317
+ name: string;
318
+ description?: string | null;
319
+ iconUrl?: string | null;
320
+ }
321
+ interface MentionRowAppFactoryItem {
322
+ kind: "app-factory";
323
+ name: string;
324
+ }
325
+ interface MentionRowSessionItem {
326
+ kind: "session";
327
+ /** The "Initiator & Agent" participant line. */
328
+ participant: string;
329
+ summary?: string | null;
330
+ userAvatarUrl?: string | null;
331
+ userAvatarPlaceholderUrl: string;
332
+ agentIconUrl: string;
333
+ statusTag?: MentionRowStatusTag | null;
334
+ }
335
+ interface MentionRowIssueItem {
336
+ kind: "issue";
337
+ title: string;
338
+ creatorName?: string | null;
339
+ statusTag?: MentionRowStatusTag | null;
340
+ }
341
+ /**
342
+ * The kind-discriminated view-model the shared {@link MentionRow} renders.
343
+ * Carries ONLY display-ready fields — no surface types, no i18n calls, no asset
344
+ * imports. Every surface maps its own items onto this so the rendered row stays
345
+ * consistent across shared mention surfaces.
346
+ */
347
+ type MentionRowItem = MentionRowFileItem | MentionRowAppItem | MentionRowAppFactoryItem | MentionRowSessionItem | MentionRowIssueItem;
348
+
349
+ /**
350
+ * Flatten the palette state into a stable, ordered list of navigable entries.
351
+ *
352
+ * Mirrors the ordering and key format of `flattenAgentMentionPaletteEntries`
353
+ * from AgentFileMentionPalette.tsx, but is generic over item type.
354
+ *
355
+ * Key formats:
356
+ * category entry → `category:<categoryId>`
357
+ * item entry → `<groupId>:<getItemKey(item, groupId)>`
358
+ * expand entry → `expand:<groupId>`
359
+ */
360
+ declare function flattenMentionPaletteEntries<TItem>(state: MentionPaletteState<TItem>, getItemKey: (item: TItem, groupId: string) => string): MentionPaletteEntry[];
361
+
362
+ declare const RICH_TEXT_AT_ALL_FILTER_ID = "all";
363
+ declare const DEFAULT_RICH_TEXT_AT_PANEL_PAGE_SIZE = 5;
364
+ declare function normalizeAtPanelQuery(value: string): string;
365
+ declare function buildDefaultRichTextTriggerProviderGroups(input: {
366
+ providers: readonly {
367
+ id: string;
368
+ }[];
369
+ labels?: Readonly<Record<string, string>>;
370
+ }): RichTextTriggerProviderGroup[];
371
+ declare function buildRichTextAtFilterTabs(input: {
372
+ allLabel: string;
373
+ groups: readonly RichTextTriggerProviderGroup[];
374
+ labels?: Readonly<Record<string, string>>;
375
+ }): RichTextAtFilterTab[];
376
+ declare function groupRichTextAtMatches(input: {
377
+ expandedCounts?: Readonly<Record<string, number | undefined>>;
378
+ filterId: RichTextAtFilterId;
379
+ groups: readonly RichTextTriggerProviderGroup[];
380
+ matches: readonly RichTextTriggerQueryMatch[];
381
+ pageSize?: number;
382
+ }): RichTextAtSearchGroup[];
383
+ declare function richTextAtGroupExpandCount(group: RichTextAtSearchGroup, pageSize?: number): number;
384
+ declare function findRichTextTriggerProviderGroup(groups: readonly RichTextTriggerProviderGroup[], groupId: RichTextAtGroupId): RichTextTriggerProviderGroup | undefined;
385
+
386
+ export { DEFAULT_RICH_TEXT_AT_PANEL_PAGE_SIZE, type MentionFileVisualKind, type MentionFileVisualKindInput, type MentionPaletteCategory, type MentionPaletteEntry, type MentionPaletteFilterId, type MentionPaletteGroup, type MentionPaletteGroupId, type MentionPaletteProps, type MentionPaletteState, type MentionPaletteTheme, type MentionRowAppFactoryItem, type MentionRowAppItem, type MentionRowFileItem, type MentionRowIssueItem, type MentionRowItem, type MentionRowSessionItem, type MentionRowStatusTag, type MentionRowStatusTone, type MentionRowStatusVariant, RICH_TEXT_AT_ALL_FILTER_ID, type RichTextAtFilterId, type RichTextAtFilterTab, type RichTextAtGroupId, type RichTextAtSearchGroup, type RichTextTriggerProviderGroup, activityMentionStatusBadgeClassName, activityMentionStatusTone, buildDefaultRichTextTriggerProviderGroups, buildMentionPaletteState, buildRichTextAtFilterTabs, findRichTextTriggerProviderGroup, flattenMentionPaletteEntries, groupRichTextAtMatches, issueMentionStatusBadgeClassName, issueMentionStatusTone, mentionStatusBadgeClassName, normalizeAtPanelQuery, resolveMentionFileThumbnailUrl, resolveMentionFileVisualKind, richTextAtGroupExpandCount };
@@ -0,0 +1,39 @@
1
+ import {
2
+ DEFAULT_RICH_TEXT_AT_PANEL_PAGE_SIZE,
3
+ RICH_TEXT_AT_ALL_FILTER_ID,
4
+ activityMentionStatusBadgeClassName,
5
+ activityMentionStatusTone,
6
+ buildDefaultRichTextTriggerProviderGroups,
7
+ buildMentionPaletteState,
8
+ buildRichTextAtFilterTabs,
9
+ findRichTextTriggerProviderGroup,
10
+ flattenMentionPaletteEntries,
11
+ groupRichTextAtMatches,
12
+ issueMentionStatusBadgeClassName,
13
+ issueMentionStatusTone,
14
+ mentionStatusBadgeClassName,
15
+ normalizeAtPanelQuery,
16
+ resolveMentionFileThumbnailUrl,
17
+ resolveMentionFileVisualKind,
18
+ richTextAtGroupExpandCount
19
+ } from "../chunk-E4PWFY3N.js";
20
+ export {
21
+ DEFAULT_RICH_TEXT_AT_PANEL_PAGE_SIZE,
22
+ RICH_TEXT_AT_ALL_FILTER_ID,
23
+ activityMentionStatusBadgeClassName,
24
+ activityMentionStatusTone,
25
+ buildDefaultRichTextTriggerProviderGroups,
26
+ buildMentionPaletteState,
27
+ buildRichTextAtFilterTabs,
28
+ findRichTextTriggerProviderGroup,
29
+ flattenMentionPaletteEntries,
30
+ groupRichTextAtMatches,
31
+ issueMentionStatusBadgeClassName,
32
+ issueMentionStatusTone,
33
+ mentionStatusBadgeClassName,
34
+ normalizeAtPanelQuery,
35
+ resolveMentionFileThumbnailUrl,
36
+ resolveMentionFileVisualKind,
37
+ richTextAtGroupExpandCount
38
+ };
39
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}