@agimon-ai/doompi-web-components 0.0.1-alpha.58 → 0.0.1-alpha.60

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/README.md +23 -6
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.d.mts +6 -1
  4. package/dist/index.mjs +1 -1
  5. package/dist/packages/core/doompi-web-components/src/components/DiffView.d.mts +16 -0
  6. package/dist/packages/core/doompi-web-components/src/components/DiffView.d.mts.map +1 -0
  7. package/dist/packages/core/doompi-web-components/src/components/DiffView.mjs +2 -0
  8. package/dist/packages/core/doompi-web-components/src/components/DiffView.mjs.map +1 -0
  9. package/dist/packages/core/doompi-web-components/src/components/ReviewCommentDraft.d.mts +24 -0
  10. package/dist/packages/core/doompi-web-components/src/components/ReviewCommentDraft.d.mts.map +1 -0
  11. package/dist/packages/core/doompi-web-components/src/components/ReviewCommentDraft.mjs +2 -0
  12. package/dist/packages/core/doompi-web-components/src/components/ReviewCommentDraft.mjs.map +1 -0
  13. package/dist/packages/core/doompi-web-components/src/lib/pathGroups.d.mts +23 -0
  14. package/dist/packages/core/doompi-web-components/src/lib/pathGroups.d.mts.map +1 -0
  15. package/dist/packages/core/doompi-web-components/src/lib/pathGroups.mjs +2 -0
  16. package/dist/packages/core/doompi-web-components/src/lib/pathGroups.mjs.map +1 -0
  17. package/dist/packages/core/doompi-web-components/src/lib/review.d.mts +40 -0
  18. package/dist/packages/core/doompi-web-components/src/lib/review.d.mts.map +1 -0
  19. package/dist/packages/core/doompi-web-components/src/lib/review.mjs +8 -0
  20. package/dist/packages/core/doompi-web-components/src/lib/review.mjs.map +1 -0
  21. package/dist/packages/core/doompi-web-components/src/types/diff.d.mts +46 -0
  22. package/dist/packages/core/doompi-web-components/src/types/diff.d.mts.map +1 -0
  23. package/dist/src/components/DiffView.cjs +2 -0
  24. package/dist/src/components/DiffView.cjs.map +1 -0
  25. package/dist/src/components/ReviewCommentDraft.cjs +2 -0
  26. package/dist/src/components/ReviewCommentDraft.cjs.map +1 -0
  27. package/dist/src/lib/pathGroups.cjs +2 -0
  28. package/dist/src/lib/pathGroups.cjs.map +1 -0
  29. package/dist/src/lib/review.cjs +8 -0
  30. package/dist/src/lib/review.cjs.map +1 -0
  31. package/package.json +3 -3
package/README.md CHANGED
@@ -11,12 +11,12 @@ Because every colour is a token, a theme config recolours the whole cockpit at r
11
11
 
12
12
  ## What it ships
13
13
 
14
- | Export | Components |
15
- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
16
- | `.` | Actions and chips: `Button`, `Badge`, `StatusBadge`, `Dot`, `Kbd`, `NavTab*`, `Tabs*`. Fields: `Input`, `Textarea`, `Label`, `Checkbox`, `Switch`, `RadioGroup*`, `Select*`. Overlays: `Dialog*`, `Sheet*`, `Popover*`, `DropdownMenu*`, `Tooltip*`, `Toast*`, `Command*`. Layout and content: `Panel*`, `SectionLabel`, `Separator`, `EmptyState`, `ScrollArea`, `Collapsible*`, `Accordion*`, `OptionList`, `OptionRow`, `MessageItem*`, `MessageLines`. Feedback: `Spinner`, `Progress`, `Skeleton`, `Avatar*`, `StreamCursor`. Files: `CodeEditor`, `MediaPreview`. Plus the curated icon set, `cn`, `collapseLines`, `grammarKeyOf`, `mediaKindOf`, the option-list key helpers, and the tone vocabularies with the maps between them |
17
- | `./theme` | `ThemeConfig`, the token lists, `BUILTIN_THEMES`, `applyTheme`, `parseThemeConfig`, `themeFromPiTheme`, the stored-preference helpers |
18
- | `./styles.css` | The token stylesheet: `:root` defaults, the Tailwind `@theme inline` mapping, shadcn semantic aliases, base styles, and the `@source` for this package's classes |
19
- | `./themes/*.json` | The shipped theme configs: `doom-one-dark` (default), `doom-one-light`, `doom-nord-dark` |
14
+ | Export | Components |
15
+ | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
16
+ | `.` | Actions and chips: `Button`, `Badge`, `StatusBadge`, `Dot`, `Kbd`, `NavTab*`, `Tabs*`. Fields: `Input`, `Textarea`, `Label`, `Checkbox`, `Switch`, `RadioGroup*`, `Select*`. Overlays: `Dialog*`, `Sheet*`, `Popover*`, `DropdownMenu*`, `Tooltip*`, `Toast*`, `Command*`. Layout and content: `Panel*`, `SectionLabel`, `Separator`, `EmptyState`, `ScrollArea`, `Collapsible*`, `Accordion*`, `OptionList`, `OptionRow`, `MessageItem*`, `MessageLines`. Feedback: `Spinner`, `Progress`, `Skeleton`, `Avatar*`, `StreamCursor`. Files: `CodeEditor`, `MediaPreview`. Review: `DiffView`, `ReviewCommentDraft`. Plus the curated icon set, `cn`, `collapseLines`, `grammarKeyOf`, `mediaKindOf`, the review helpers (`buildReviewPrompt`, `reviewCommentAnchor`, `diffRangeOf`), `groupByDirectory`, the option-list key helpers, and the tone vocabularies with the maps between them |
17
+ | `./theme` | `ThemeConfig`, the token lists, `BUILTIN_THEMES`, `applyTheme`, `parseThemeConfig`, `themeFromPiTheme`, the stored-preference helpers |
18
+ | `./styles.css` | The token stylesheet: `:root` defaults, the Tailwind `@theme inline` mapping, shadcn semantic aliases, base styles, and the `@source` for this package's classes |
19
+ | `./themes/*.json` | The shipped theme configs: `doom-one-dark` (default), `doom-one-light`, `doom-nord-dark` |
20
20
 
21
21
  ## Using it from the cockpit host
22
22
 
@@ -76,6 +76,23 @@ the same classification on its own, for a caller deciding between the editor and
76
76
  Neither converts a format. A `.docx` rendered as HTML is a different document, so it is offered as
77
77
  a download rather than as something that looks editable.
78
78
 
79
+ ## Review
80
+
81
+ `DiffView` draws hunks with a numbered gutter and a wash per row. With `onSelect` set, highlighting
82
+ text reports the lines it touches and clicking a line number reports that one line; either way the
83
+ selection names its side, so a note on a removed line points at the old file. `renderAfterRow`
84
+ places inline content, such as an open draft, under a row.
85
+
86
+ `ReviewCommentDraft` is the box a selection raises: the quoted snippet, its range, and a note.
87
+ `testIdPrefix` names its test ids (`<prefix>-draft`, `-body`, `-add`, `-cancel`).
88
+
89
+ `buildReviewPrompt(comments, heading?)` folds every note into one message, each headed by
90
+ `reviewCommentAnchor`: `path:12-14` on the new side, `path (removed lines 3-4)` on the old.
91
+
92
+ ```tsx
93
+ <DiffView hunks={hunks} testId="review-diff" onSelect={setDraft} />
94
+ ```
95
+
79
96
  ## Using it from a plugin's `web/` client
80
97
 
81
98
  A web plugin's client code may import `react`, the `@tanstack` store packages,
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require("./src/icons/icons.cjs");const e=require("./src/lib/cn.cjs"),t=require("./src/components/Accordion.cjs"),n=require("./src/lib/ansiSpans.cjs"),r=require("./src/components/AnsiText.cjs"),i=require("./src/components/Avatar.cjs"),a=require("./src/components/Badge.cjs"),o=require("./src/components/Tooltip.cjs"),s=require("./src/components/Breadcrumb.cjs"),c=require("./src/components/Spinner.cjs"),l=require("./src/components/Button.cjs"),u=require("./src/components/Dialog.cjs"),d=require("./src/components/Dot.cjs"),f=require("./src/components/Drawer.cjs"),p=require("./src/components/DropdownMenu.cjs"),m=require("./src/components/Checkbox.cjs"),h=require("./src/lib/editorLanguage.cjs"),g=require("./src/lib/syntaxHighlight.cjs"),_=require("./src/components/SyntaxText.cjs"),v=require("./src/components/CodeBlock.cjs"),y=require("./src/components/Skeleton.cjs"),ee=require("./src/components/CodeEditor.cjs"),b=require("./src/components/Collapsible.cjs"),x=require("./src/components/Input.cjs"),S=require("./src/lib/optionList.cjs"),C=require("./src/components/OptionList.cjs"),w=require("./src/components/Command.cjs"),T=require("./src/components/EmptyState.cjs"),E=require("./src/lib/hashlineHighlight.cjs"),D=require("./src/components/HashlineLines.cjs"),O=require("./src/components/Kbd.cjs"),k=require("./src/components/McpToolWidget.cjs"),A=require("./src/components/Label.cjs"),te=require("./src/components/Markdown.cjs"),ne=require("./src/lib/media.cjs"),j=require("./src/components/PdfPreview.cjs"),re=require("./src/components/MediaPreview.cjs"),M=require("./src/components/StatusBadge.cjs"),N=require("./src/components/MessageItem.cjs"),P=require("./src/components/MessageLines.cjs"),F=require("./src/components/Panel.cjs"),I=require("./src/components/Popover.cjs"),L=require("./src/components/Progress.cjs"),R=require("./src/components/RadioGroup.cjs"),z=require("./src/components/ScrollArea.cjs"),B=require("./src/components/SectionLabel.cjs"),V=require("./src/components/Select.cjs"),H=require("./src/components/Separator.cjs"),U=require("./src/components/Sheet.cjs"),W=require("./src/components/StreamCursor.cjs"),G=require("./src/components/Switch.cjs"),K=require("./src/components/Tabs.cjs"),q=require("./src/components/TerminalView.cjs"),J=require("./src/components/Textarea.cjs"),Y=require("./src/components/Toast.cjs"),ie=require("./src/components/ToolPathLink.cjs"),ae=require("./src/lib/collapse.cjs"),X=require("./src/lib/hashlineView.cjs"),Z=require("./src/lib/tone.cjs"),oe=require("./src/types/editor.cjs"),Q=require("./src/types/tone.cjs");let $=require("lucide-react");exports.ACCENT_TONES=Q.ACCENT_TONES,exports.Accordion=t.Accordion,exports.AccordionContent=t.AccordionContent,exports.AccordionItem=t.AccordionItem,exports.AccordionTrigger=t.AccordionTrigger,Object.defineProperty(exports,"ActivityIcon",{enumerable:!0,get:function(){return $.Activity}}),Object.defineProperty(exports,"AlertIcon",{enumerable:!0,get:function(){return $.CircleAlert}}),exports.AnsiLine=r.AnsiLine,exports.AnsiText=r.AnsiText,Object.defineProperty(exports,"AudioLinesIcon",{enumerable:!0,get:function(){return $.AudioLines}}),exports.Avatar=i.Avatar,exports.AvatarFallback=i.AvatarFallback,exports.AvatarImage=i.AvatarImage,exports.BREADCRUMB_ELLIPSIS=s.BREADCRUMB_ELLIPSIS,exports.Badge=a.Badge,Object.defineProperty(exports,"BookmarkPlusIcon",{enumerable:!0,get:function(){return $.BookmarkPlus}}),Object.defineProperty(exports,"BranchIcon",{enumerable:!0,get:function(){return $.GitBranch}}),exports.Breadcrumb=s.Breadcrumb,exports.Button=l.Button,exports.CHIP_TONES=Q.CHIP_TONES,exports.CHIP_TO_STATUS=Z.CHIP_TO_STATUS,Object.defineProperty(exports,"CheckIcon",{enumerable:!0,get:function(){return $.Check}}),exports.Checkbox=m.Checkbox,Object.defineProperty(exports,"ChevronDownIcon",{enumerable:!0,get:function(){return $.ChevronDown}}),Object.defineProperty(exports,"ChevronRightIcon",{enumerable:!0,get:function(){return $.ChevronRight}}),Object.defineProperty(exports,"ChevronUpIcon",{enumerable:!0,get:function(){return $.ChevronUp}}),Object.defineProperty(exports,"CloseIcon",{enumerable:!0,get:function(){return $.X}}),exports.CodeBlock=v.CodeBlock,exports.CodeEditor=ee.CodeEditor,exports.Collapsible=b.Collapsible,exports.CollapsibleContent=b.CollapsibleContent,exports.CollapsibleTrigger=b.CollapsibleTrigger,exports.CommandDialog=w.CommandDialog,exports.CommandEmpty=w.CommandEmpty,exports.CommandFooter=w.CommandFooter,exports.CommandGroup=w.CommandGroup,exports.CommandGroupLabel=w.CommandGroupLabel,exports.CommandHeader=w.CommandHeader,exports.CommandInput=w.CommandInput,exports.CommandItem=w.CommandItem,exports.CommandItemLabel=w.CommandItemLabel,exports.CommandList=w.CommandList,Object.defineProperty(exports,"CopyIcon",{enumerable:!0,get:function(){return $.Copy}}),exports.DOT_TONES=Q.DOT_TONES,exports.Dialog=u.Dialog,exports.DialogBody=u.DialogBody,exports.DialogClose=u.DialogClose,exports.DialogContent=u.DialogContent,exports.DialogDescription=u.DialogDescription,exports.DialogFooter=u.DialogFooter,exports.DialogHeader=u.DialogHeader,exports.DialogTitle=u.DialogTitle,exports.DialogTrigger=u.DialogTrigger,exports.Dot=d.Dot,exports.Drawer=f.Drawer,exports.DropdownMenu=p.DropdownMenu,exports.DropdownMenuCheckboxItem=p.DropdownMenuCheckboxItem,exports.DropdownMenuContent=p.DropdownMenuContent,exports.DropdownMenuGroup=p.DropdownMenuGroup,exports.DropdownMenuItem=p.DropdownMenuItem,exports.DropdownMenuLabel=p.DropdownMenuLabel,exports.DropdownMenuRadioGroup=p.DropdownMenuRadioGroup,exports.DropdownMenuRadioItem=p.DropdownMenuRadioItem,exports.DropdownMenuSeparator=p.DropdownMenuSeparator,exports.DropdownMenuShortcut=p.DropdownMenuShortcut,exports.DropdownMenuSub=p.DropdownMenuSub,exports.DropdownMenuSubContent=p.DropdownMenuSubContent,exports.DropdownMenuSubTrigger=p.DropdownMenuSubTrigger,exports.DropdownMenuTrigger=p.DropdownMenuTrigger,Object.defineProperty(exports,"EditIcon",{enumerable:!0,get:function(){return $.Pencil}}),exports.EmptyState=T.EmptyState,Object.defineProperty(exports,"EnterIcon",{enumerable:!0,get:function(){return $.CornerDownLeft}}),Object.defineProperty(exports,"ExternalLinkIcon",{enumerable:!0,get:function(){return $.ExternalLink}}),Object.defineProperty(exports,"FileIcon",{enumerable:!0,get:function(){return $.FileText}}),Object.defineProperty(exports,"ForkIcon",{enumerable:!0,get:function(){return $.GitFork}}),exports.GREP_COLLAPSED_LINES=X.GREP_COLLAPSED_LINES,Object.defineProperty(exports,"GearIcon",{enumerable:!0,get:function(){return $.Settings}}),exports.HashlineLines=D.HashlineLines,exports.Input=x.Input,exports.Kbd=O.Kbd,Object.defineProperty(exports,"KebabIcon",{enumerable:!0,get:function(){return $.MoreVertical}}),exports.LINE_TONE_TO_STATUS=Z.LINE_TONE_TO_STATUS,exports.Label=A.Label,Object.defineProperty(exports,"LoaderIcon",{enumerable:!0,get:function(){return $.Loader2}}),exports.MAX_DIGIT_SHORTCUT=S.MAX_DIGIT_SHORTCUT,exports.MEDIA_KINDS=oe.MEDIA_KINDS,exports.MESSAGE_LINE_TONES=Q.MESSAGE_LINE_TONES,exports.Markdown=te.Markdown,exports.McpToolFields=k.McpToolFields,exports.McpToolFrame=k.McpToolFrame,exports.McpToolOutput=k.McpToolOutput,exports.MediaPreview=re.MediaPreview,Object.defineProperty(exports,"MessageIcon",{enumerable:!0,get:function(){return $.MessageCircle}}),exports.MessageItem=N.MessageItem,exports.MessageItemBody=N.MessageItemBody,exports.MessageItemGroup=N.MessageItemGroup,exports.MessageItemHeader=N.MessageItemHeader,exports.MessageItemStatus=N.MessageItemStatus,exports.MessageLines=P.MessageLines,Object.defineProperty(exports,"MicIcon",{enumerable:!0,get:function(){return $.Mic}}),exports.NavTab=K.NavTab,exports.NavTabBadge=K.NavTabBadge,exports.OptionLabel=C.OptionLabel,exports.OptionList=C.OptionList,exports.OptionRow=C.OptionRow,Object.defineProperty(exports,"PaletteIcon",{enumerable:!0,get:function(){return $.Palette}}),exports.Panel=F.Panel,exports.PanelBody=F.PanelBody,exports.PanelHeader=F.PanelHeader,exports.PdfPreview=j.PdfPreview,Object.defineProperty(exports,"PlusIcon",{enumerable:!0,get:function(){return $.Plus}}),exports.Popover=I.Popover,exports.PopoverAnchor=I.PopoverAnchor,exports.PopoverClose=I.PopoverClose,exports.PopoverContent=I.PopoverContent,exports.PopoverFooter=I.PopoverFooter,exports.PopoverHeader=I.PopoverHeader,exports.PopoverTrigger=I.PopoverTrigger,exports.Progress=L.Progress,Object.defineProperty(exports,"QuoteIcon",{enumerable:!0,get:function(){return $.Quote}}),exports.READ_COLLAPSED_LINES=X.READ_COLLAPSED_LINES,exports.RadioGroup=R.RadioGroup,exports.RadioGroupCard=R.RadioGroupCard,exports.RadioGroupItem=R.RadioGroupItem,Object.defineProperty(exports,"RefreshIcon",{enumerable:!0,get:function(){return $.RefreshCw}}),Object.defineProperty(exports,"RewindIcon",{enumerable:!0,get:function(){return $.Rewind}}),exports.STATUS_EDGE=M.STATUS_EDGE,exports.STATUS_GLYPH=N.STATUS_GLYPH,exports.STATUS_LABEL=N.STATUS_LABEL,exports.STATUS_TONES=Q.STATUS_TONES,exports.STATUS_TO_CHIP=Z.STATUS_TO_CHIP,exports.STATUS_TO_DOT=Z.STATUS_TO_DOT,exports.ScrollArea=z.ScrollArea,exports.ScrollBar=z.ScrollBar,Object.defineProperty(exports,"SearchIcon",{enumerable:!0,get:function(){return $.Search}}),exports.SectionLabel=B.SectionLabel,exports.Select=V.Select,exports.SelectContent=V.SelectContent,exports.SelectGroup=V.SelectGroup,exports.SelectItem=V.SelectItem,exports.SelectLabel=V.SelectLabel,exports.SelectSeparator=V.SelectSeparator,exports.SelectTrigger=V.SelectTrigger,exports.SelectValue=V.SelectValue,Object.defineProperty(exports,"SendIcon",{enumerable:!0,get:function(){return $.Send}}),exports.Separator=H.Separator,exports.Sheet=U.Sheet,exports.SheetBody=U.SheetBody,exports.SheetClose=U.SheetClose,exports.SheetContent=U.SheetContent,exports.SheetDescription=U.SheetDescription,exports.SheetFooter=U.SheetFooter,exports.SheetHeader=U.SheetHeader,exports.SheetOverlay=U.SheetOverlay,exports.SheetTitle=U.SheetTitle,exports.SheetTrigger=U.SheetTrigger,Object.defineProperty(exports,"ShieldIcon",{enumerable:!0,get:function(){return $.ShieldCheck}}),exports.Skeleton=y.Skeleton,exports.Spinner=c.Spinner,exports.StatusBadge=M.StatusBadge,Object.defineProperty(exports,"StopIcon",{enumerable:!0,get:function(){return $.Square}}),exports.StreamCursor=W.StreamCursor,exports.Switch=G.Switch,exports.SyntaxLine=_.SyntaxLine,exports.SyntaxText=_.SyntaxText,exports.Tabs=K.Tabs,exports.TabsContent=K.TabsContent,exports.TabsList=K.TabsList,exports.TabsTrigger=K.TabsTrigger,exports.TerminalView=q.TerminalView,exports.Textarea=J.Textarea,exports.Toast=Y.Toast,exports.ToastAction=Y.ToastAction,exports.ToastClose=Y.ToastClose,exports.ToastDescription=Y.ToastDescription,exports.ToastProvider=Y.ToastProvider,exports.ToastTitle=Y.ToastTitle,exports.ToastViewport=Y.ToastViewport,exports.ToolPathLink=ie.ToolPathLink,exports.Tooltip=o.Tooltip,exports.TooltipContent=o.TooltipContent,exports.TooltipProvider=o.TooltipProvider,exports.TooltipTrigger=o.TooltipTrigger,Object.defineProperty(exports,"TrashIcon",{enumerable:!0,get:function(){return $.Trash2}}),Object.defineProperty(exports,"UserIcon",{enumerable:!0,get:function(){return $.UserRound}}),Object.defineProperty(exports,"VolumeIcon",{enumerable:!0,get:function(){return $.Volume2}}),exports.ansiSpans=n.ansiSpans,exports.badgeVariants=a.badgeVariants,exports.breadcrumbSegments=s.breadcrumbSegments,exports.buttonVariants=l.buttonVariants,exports.cn=e.cn,exports.collapseLines=ae.collapseLines,exports.compactDetails=X.compactDetails,exports.detectGrammar=g.detectGrammar,exports.dialogFooterVariants=u.dialogFooterVariants,exports.dotVariants=d.dotVariants,exports.dropdownMenuItemVariants=p.dropdownMenuItemVariants,exports.fieldVariants=x.fieldVariants,exports.grammarKeyOf=h.grammarKeyOf,exports.handleOptionListKey=S.handleOptionListKey,exports.hashlineBody=X.hashlineBody,exports.hashlineGroups=E.hashlineGroups,exports.hashlineGroupsKey=E.hashlineGroupsKey,exports.highlightToLines=g.highlightToLines,exports.mediaKindOf=ne.mediaKindOf,exports.messageItemRowVariants=N.messageItemRowVariants,exports.messageItemStatusVariants=N.messageItemStatusVariants,exports.messageItemVariants=N.messageItemVariants,exports.messageLineVariants=P.messageLineVariants,exports.optionListHint=S.optionListHint,exports.optionListVariants=C.optionListVariants,exports.optionMarker=S.optionMarker,exports.optionMarkerVariants=C.optionMarkerVariants,exports.optionRowVariants=C.optionRowVariants,exports.parseFileHeader=X.parseFileHeader,exports.parseTaggedLine=X.parseTaggedLine,exports.presentHashlineLines=X.presentHashlineLines,exports.resolvePdfViewportRegion=j.resolvePdfViewportRegion,exports.resultTextLines=X.resultTextLines,exports.statusBadgeVariants=M.statusBadgeVariants,exports.syntaxStyleOf=g.syntaxStyleOf,exports.tabBadgeVariants=K.tabBadgeVariants,exports.tabVariants=K.tabVariants,exports.takeTrailingNotice=X.takeTrailingNotice,exports.toastVariants=Y.toastVariants,exports.toolTone=N.toolTone,exports.useMessageItem=N.useMessageItem,exports.useSyntaxLines=_.useSyntaxLines;
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require("./src/icons/icons.cjs");const e=require("./src/lib/cn.cjs"),t=require("./src/components/Accordion.cjs"),n=require("./src/lib/ansiSpans.cjs"),r=require("./src/components/AnsiText.cjs"),i=require("./src/components/Avatar.cjs"),a=require("./src/components/Badge.cjs"),o=require("./src/components/Tooltip.cjs"),s=require("./src/components/Breadcrumb.cjs"),ee=require("./src/components/Spinner.cjs"),c=require("./src/components/Button.cjs"),l=require("./src/components/Dialog.cjs"),u=require("./src/lib/review.cjs"),d=require("./src/components/DiffView.cjs"),f=require("./src/components/Dot.cjs"),te=require("./src/components/Drawer.cjs"),p=require("./src/components/DropdownMenu.cjs"),ne=require("./src/components/Checkbox.cjs"),re=require("./src/lib/editorLanguage.cjs"),m=require("./src/lib/syntaxHighlight.cjs"),h=require("./src/components/SyntaxText.cjs"),g=require("./src/components/CodeBlock.cjs"),_=require("./src/components/Skeleton.cjs"),v=require("./src/components/CodeEditor.cjs"),y=require("./src/components/Collapsible.cjs"),b=require("./src/components/Input.cjs"),x=require("./src/lib/optionList.cjs"),S=require("./src/components/OptionList.cjs"),C=require("./src/components/Command.cjs"),ie=require("./src/components/EmptyState.cjs"),w=require("./src/lib/hashlineHighlight.cjs"),ae=require("./src/components/HashlineLines.cjs"),T=require("./src/components/Kbd.cjs"),E=require("./src/components/McpToolWidget.cjs"),D=require("./src/components/Label.cjs"),O=require("./src/components/Markdown.cjs"),k=require("./src/lib/media.cjs"),A=require("./src/components/PdfPreview.cjs"),oe=require("./src/components/MediaPreview.cjs"),j=require("./src/components/StatusBadge.cjs"),M=require("./src/components/MessageItem.cjs"),N=require("./src/components/MessageLines.cjs"),P=require("./src/components/Panel.cjs"),F=require("./src/components/Popover.cjs"),I=require("./src/components/Progress.cjs"),L=require("./src/components/RadioGroup.cjs"),R=require("./src/components/Textarea.cjs"),z=require("./src/components/ReviewCommentDraft.cjs"),B=require("./src/components/ScrollArea.cjs"),V=require("./src/components/SectionLabel.cjs"),H=require("./src/components/Select.cjs"),U=require("./src/components/Separator.cjs"),W=require("./src/components/Sheet.cjs"),G=require("./src/components/StreamCursor.cjs"),K=require("./src/components/Switch.cjs"),q=require("./src/components/Tabs.cjs"),se=require("./src/components/TerminalView.cjs"),J=require("./src/components/Toast.cjs"),ce=require("./src/components/ToolPathLink.cjs"),le=require("./src/lib/collapse.cjs"),Y=require("./src/lib/hashlineView.cjs"),X=require("./src/lib/pathGroups.cjs"),Z=require("./src/lib/tone.cjs"),ue=require("./src/types/editor.cjs"),Q=require("./src/types/tone.cjs");let $=require("lucide-react");exports.ACCENT_TONES=Q.ACCENT_TONES,exports.Accordion=t.Accordion,exports.AccordionContent=t.AccordionContent,exports.AccordionItem=t.AccordionItem,exports.AccordionTrigger=t.AccordionTrigger,Object.defineProperty(exports,"ActivityIcon",{enumerable:!0,get:function(){return $.Activity}}),Object.defineProperty(exports,"AlertIcon",{enumerable:!0,get:function(){return $.CircleAlert}}),exports.AnsiLine=r.AnsiLine,exports.AnsiText=r.AnsiText,Object.defineProperty(exports,"AudioLinesIcon",{enumerable:!0,get:function(){return $.AudioLines}}),exports.Avatar=i.Avatar,exports.AvatarFallback=i.AvatarFallback,exports.AvatarImage=i.AvatarImage,exports.BREADCRUMB_ELLIPSIS=s.BREADCRUMB_ELLIPSIS,exports.Badge=a.Badge,Object.defineProperty(exports,"BookmarkPlusIcon",{enumerable:!0,get:function(){return $.BookmarkPlus}}),Object.defineProperty(exports,"BranchIcon",{enumerable:!0,get:function(){return $.GitBranch}}),exports.Breadcrumb=s.Breadcrumb,exports.Button=c.Button,exports.CHIP_TONES=Q.CHIP_TONES,exports.CHIP_TO_STATUS=Z.CHIP_TO_STATUS,Object.defineProperty(exports,"CheckIcon",{enumerable:!0,get:function(){return $.Check}}),exports.Checkbox=ne.Checkbox,Object.defineProperty(exports,"ChevronDownIcon",{enumerable:!0,get:function(){return $.ChevronDown}}),Object.defineProperty(exports,"ChevronRightIcon",{enumerable:!0,get:function(){return $.ChevronRight}}),Object.defineProperty(exports,"ChevronUpIcon",{enumerable:!0,get:function(){return $.ChevronUp}}),Object.defineProperty(exports,"CloseIcon",{enumerable:!0,get:function(){return $.X}}),exports.CodeBlock=g.CodeBlock,exports.CodeEditor=v.CodeEditor,exports.Collapsible=y.Collapsible,exports.CollapsibleContent=y.CollapsibleContent,exports.CollapsibleTrigger=y.CollapsibleTrigger,exports.CommandDialog=C.CommandDialog,exports.CommandEmpty=C.CommandEmpty,exports.CommandFooter=C.CommandFooter,exports.CommandGroup=C.CommandGroup,exports.CommandGroupLabel=C.CommandGroupLabel,exports.CommandHeader=C.CommandHeader,exports.CommandInput=C.CommandInput,exports.CommandItem=C.CommandItem,exports.CommandItemLabel=C.CommandItemLabel,exports.CommandList=C.CommandList,Object.defineProperty(exports,"CopyIcon",{enumerable:!0,get:function(){return $.Copy}}),exports.DOT_TONES=Q.DOT_TONES,exports.Dialog=l.Dialog,exports.DialogBody=l.DialogBody,exports.DialogClose=l.DialogClose,exports.DialogContent=l.DialogContent,exports.DialogDescription=l.DialogDescription,exports.DialogFooter=l.DialogFooter,exports.DialogHeader=l.DialogHeader,exports.DialogTitle=l.DialogTitle,exports.DialogTrigger=l.DialogTrigger,exports.DiffView=d.DiffView,exports.Dot=f.Dot,exports.Drawer=te.Drawer,exports.DropdownMenu=p.DropdownMenu,exports.DropdownMenuCheckboxItem=p.DropdownMenuCheckboxItem,exports.DropdownMenuContent=p.DropdownMenuContent,exports.DropdownMenuGroup=p.DropdownMenuGroup,exports.DropdownMenuItem=p.DropdownMenuItem,exports.DropdownMenuLabel=p.DropdownMenuLabel,exports.DropdownMenuRadioGroup=p.DropdownMenuRadioGroup,exports.DropdownMenuRadioItem=p.DropdownMenuRadioItem,exports.DropdownMenuSeparator=p.DropdownMenuSeparator,exports.DropdownMenuShortcut=p.DropdownMenuShortcut,exports.DropdownMenuSub=p.DropdownMenuSub,exports.DropdownMenuSubContent=p.DropdownMenuSubContent,exports.DropdownMenuSubTrigger=p.DropdownMenuSubTrigger,exports.DropdownMenuTrigger=p.DropdownMenuTrigger,Object.defineProperty(exports,"EditIcon",{enumerable:!0,get:function(){return $.Pencil}}),exports.EmptyState=ie.EmptyState,Object.defineProperty(exports,"EnterIcon",{enumerable:!0,get:function(){return $.CornerDownLeft}}),Object.defineProperty(exports,"ExternalLinkIcon",{enumerable:!0,get:function(){return $.ExternalLink}}),Object.defineProperty(exports,"FileIcon",{enumerable:!0,get:function(){return $.FileText}}),Object.defineProperty(exports,"ForkIcon",{enumerable:!0,get:function(){return $.GitFork}}),exports.GREP_COLLAPSED_LINES=Y.GREP_COLLAPSED_LINES,Object.defineProperty(exports,"GearIcon",{enumerable:!0,get:function(){return $.Settings}}),exports.HashlineLines=ae.HashlineLines,exports.Input=b.Input,exports.Kbd=T.Kbd,Object.defineProperty(exports,"KebabIcon",{enumerable:!0,get:function(){return $.MoreVertical}}),exports.LINE_TONE_TO_STATUS=Z.LINE_TONE_TO_STATUS,exports.Label=D.Label,Object.defineProperty(exports,"LoaderIcon",{enumerable:!0,get:function(){return $.Loader2}}),exports.MAX_DIGIT_SHORTCUT=x.MAX_DIGIT_SHORTCUT,exports.MEDIA_KINDS=ue.MEDIA_KINDS,exports.MESSAGE_LINE_TONES=Q.MESSAGE_LINE_TONES,exports.Markdown=O.Markdown,exports.McpToolFields=E.McpToolFields,exports.McpToolFrame=E.McpToolFrame,exports.McpToolOutput=E.McpToolOutput,exports.MediaPreview=oe.MediaPreview,Object.defineProperty(exports,"MessageIcon",{enumerable:!0,get:function(){return $.MessageCircle}}),exports.MessageItem=M.MessageItem,exports.MessageItemBody=M.MessageItemBody,exports.MessageItemGroup=M.MessageItemGroup,exports.MessageItemHeader=M.MessageItemHeader,exports.MessageItemStatus=M.MessageItemStatus,exports.MessageLines=N.MessageLines,Object.defineProperty(exports,"MicIcon",{enumerable:!0,get:function(){return $.Mic}}),exports.NavTab=q.NavTab,exports.NavTabBadge=q.NavTabBadge,exports.OptionLabel=S.OptionLabel,exports.OptionList=S.OptionList,exports.OptionRow=S.OptionRow,Object.defineProperty(exports,"PaletteIcon",{enumerable:!0,get:function(){return $.Palette}}),exports.Panel=P.Panel,exports.PanelBody=P.PanelBody,exports.PanelHeader=P.PanelHeader,exports.PdfPreview=A.PdfPreview,Object.defineProperty(exports,"PlusIcon",{enumerable:!0,get:function(){return $.Plus}}),exports.Popover=F.Popover,exports.PopoverAnchor=F.PopoverAnchor,exports.PopoverClose=F.PopoverClose,exports.PopoverContent=F.PopoverContent,exports.PopoverFooter=F.PopoverFooter,exports.PopoverHeader=F.PopoverHeader,exports.PopoverTrigger=F.PopoverTrigger,exports.Progress=I.Progress,Object.defineProperty(exports,"QuoteIcon",{enumerable:!0,get:function(){return $.Quote}}),exports.READ_COLLAPSED_LINES=Y.READ_COLLAPSED_LINES,exports.RadioGroup=L.RadioGroup,exports.RadioGroupCard=L.RadioGroupCard,exports.RadioGroupItem=L.RadioGroupItem,Object.defineProperty(exports,"RefreshIcon",{enumerable:!0,get:function(){return $.RefreshCw}}),exports.ReviewCommentDraft=z.ReviewCommentDraft,Object.defineProperty(exports,"RewindIcon",{enumerable:!0,get:function(){return $.Rewind}}),exports.STATUS_EDGE=j.STATUS_EDGE,exports.STATUS_GLYPH=M.STATUS_GLYPH,exports.STATUS_LABEL=M.STATUS_LABEL,exports.STATUS_TONES=Q.STATUS_TONES,exports.STATUS_TO_CHIP=Z.STATUS_TO_CHIP,exports.STATUS_TO_DOT=Z.STATUS_TO_DOT,exports.ScrollArea=B.ScrollArea,exports.ScrollBar=B.ScrollBar,Object.defineProperty(exports,"SearchIcon",{enumerable:!0,get:function(){return $.Search}}),exports.SectionLabel=V.SectionLabel,exports.Select=H.Select,exports.SelectContent=H.SelectContent,exports.SelectGroup=H.SelectGroup,exports.SelectItem=H.SelectItem,exports.SelectLabel=H.SelectLabel,exports.SelectSeparator=H.SelectSeparator,exports.SelectTrigger=H.SelectTrigger,exports.SelectValue=H.SelectValue,Object.defineProperty(exports,"SendIcon",{enumerable:!0,get:function(){return $.Send}}),exports.Separator=U.Separator,exports.Sheet=W.Sheet,exports.SheetBody=W.SheetBody,exports.SheetClose=W.SheetClose,exports.SheetContent=W.SheetContent,exports.SheetDescription=W.SheetDescription,exports.SheetFooter=W.SheetFooter,exports.SheetHeader=W.SheetHeader,exports.SheetOverlay=W.SheetOverlay,exports.SheetTitle=W.SheetTitle,exports.SheetTrigger=W.SheetTrigger,Object.defineProperty(exports,"ShieldIcon",{enumerable:!0,get:function(){return $.ShieldCheck}}),exports.Skeleton=_.Skeleton,exports.Spinner=ee.Spinner,exports.StatusBadge=j.StatusBadge,Object.defineProperty(exports,"StopIcon",{enumerable:!0,get:function(){return $.Square}}),exports.StreamCursor=G.StreamCursor,exports.Switch=K.Switch,exports.SyntaxLine=h.SyntaxLine,exports.SyntaxText=h.SyntaxText,exports.Tabs=q.Tabs,exports.TabsContent=q.TabsContent,exports.TabsList=q.TabsList,exports.TabsTrigger=q.TabsTrigger,exports.TerminalView=se.TerminalView,exports.Textarea=R.Textarea,exports.Toast=J.Toast,exports.ToastAction=J.ToastAction,exports.ToastClose=J.ToastClose,exports.ToastDescription=J.ToastDescription,exports.ToastProvider=J.ToastProvider,exports.ToastTitle=J.ToastTitle,exports.ToastViewport=J.ToastViewport,exports.ToolPathLink=ce.ToolPathLink,exports.Tooltip=o.Tooltip,exports.TooltipContent=o.TooltipContent,exports.TooltipProvider=o.TooltipProvider,exports.TooltipTrigger=o.TooltipTrigger,Object.defineProperty(exports,"TrashIcon",{enumerable:!0,get:function(){return $.Trash2}}),Object.defineProperty(exports,"UserIcon",{enumerable:!0,get:function(){return $.UserRound}}),Object.defineProperty(exports,"VolumeIcon",{enumerable:!0,get:function(){return $.Volume2}}),exports.ansiSpans=n.ansiSpans,exports.badgeVariants=a.badgeVariants,exports.breadcrumbSegments=s.breadcrumbSegments,exports.buildReviewPrompt=u.buildReviewPrompt,exports.buttonVariants=c.buttonVariants,exports.cn=e.cn,exports.collapseLines=le.collapseLines,exports.compactDetails=Y.compactDetails,exports.defaultReviewHeading=u.defaultReviewHeading,exports.detectGrammar=m.detectGrammar,exports.dialogFooterVariants=l.dialogFooterVariants,exports.diffGutterWidth=u.diffGutterWidth,exports.diffRangeOf=u.diffRangeOf,exports.dotVariants=f.dotVariants,exports.dropdownMenuItemVariants=p.dropdownMenuItemVariants,exports.fieldVariants=b.fieldVariants,exports.grammarKeyOf=re.grammarKeyOf,exports.groupByDirectory=X.groupByDirectory,exports.groupRowLabel=X.groupRowLabel,exports.handleOptionListKey=x.handleOptionListKey,exports.hashlineBody=Y.hashlineBody,exports.hashlineGroups=w.hashlineGroups,exports.hashlineGroupsKey=w.hashlineGroupsKey,exports.highlightToLines=m.highlightToLines,exports.mediaKindOf=k.mediaKindOf,exports.messageItemRowVariants=M.messageItemRowVariants,exports.messageItemStatusVariants=M.messageItemStatusVariants,exports.messageItemVariants=M.messageItemVariants,exports.messageLineVariants=N.messageLineVariants,exports.optionListHint=x.optionListHint,exports.optionListVariants=S.optionListVariants,exports.optionMarker=x.optionMarker,exports.optionMarkerVariants=S.optionMarkerVariants,exports.optionRowVariants=S.optionRowVariants,exports.parseFileHeader=Y.parseFileHeader,exports.parseTaggedLine=Y.parseTaggedLine,exports.presentHashlineLines=Y.presentHashlineLines,exports.resolvePdfViewportRegion=A.resolvePdfViewportRegion,exports.resultTextLines=Y.resultTextLines,exports.reviewCommentAnchor=u.reviewCommentAnchor,exports.statusBadgeVariants=j.statusBadgeVariants,exports.syntaxStyleOf=m.syntaxStyleOf,exports.tabBadgeVariants=q.tabBadgeVariants,exports.tabVariants=q.tabVariants,exports.takeTrailingNotice=Y.takeTrailingNotice,exports.toastVariants=J.toastVariants,exports.toolTone=M.toolTone,exports.trimSnippet=u.trimSnippet,exports.useMessageItem=M.useMessageItem,exports.useSyntaxLines=h.useSyntaxLines;
package/dist/index.d.mts CHANGED
@@ -6,6 +6,8 @@ import { Badge, BadgeProps, BadgeTone, badgeVariants } from "./packages/core/doo
6
6
  import { BREADCRUMB_ELLIPSIS, Breadcrumb, BreadcrumbProps, breadcrumbSegments } from "./packages/core/doompi-web-components/src/components/Breadcrumb.mjs";
7
7
  import { Button, ButtonProps, ButtonSize, ButtonVariant, buttonVariants } from "./packages/core/doompi-web-components/src/components/Button.mjs";
8
8
  import { Dialog, DialogBody, DialogClose, DialogContent, DialogContentProps, DialogDescription, DialogFooter, DialogFooterProps, DialogHeader, DialogHeaderProps, DialogTitle, DialogTrigger, dialogFooterVariants } from "./packages/core/doompi-web-components/src/components/Dialog.mjs";
9
+ import { DiffHunk, DiffMarker, DiffRow, DiffSelection, DiffSide, ReviewComment } from "./packages/core/doompi-web-components/src/types/diff.mjs";
10
+ import { DiffView, DiffViewProps } from "./packages/core/doompi-web-components/src/components/DiffView.mjs";
9
11
  import { Dot, DotProps, DotTone, dotVariants } from "./packages/core/doompi-web-components/src/components/Dot.mjs";
10
12
  import { Drawer, DrawerProps } from "./packages/core/doompi-web-components/src/components/Drawer.mjs";
11
13
  import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuCheckboxItemProps, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuItemProps, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuRadioItemProps, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, dropdownMenuItemVariants } from "./packages/core/doompi-web-components/src/components/DropdownMenu.mjs";
@@ -33,6 +35,7 @@ import { Panel, PanelBody, PanelHeader, PanelProps } from "./packages/core/doomp
33
35
  import { Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverFooter, PopoverHeader, PopoverTrigger } from "./packages/core/doompi-web-components/src/components/Popover.mjs";
34
36
  import { Progress } from "./packages/core/doompi-web-components/src/components/Progress.mjs";
35
37
  import { RadioGroup, RadioGroupCard, RadioGroupItem } from "./packages/core/doompi-web-components/src/components/RadioGroup.mjs";
38
+ import { ReviewCommentDraft, ReviewCommentDraftProps } from "./packages/core/doompi-web-components/src/components/ReviewCommentDraft.mjs";
36
39
  import { ScrollArea, ScrollBar } from "./packages/core/doompi-web-components/src/components/ScrollArea.mjs";
37
40
  import { SectionLabel } from "./packages/core/doompi-web-components/src/components/SectionLabel.mjs";
38
41
  import { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue } from "./packages/core/doompi-web-components/src/components/Select.mjs";
@@ -56,7 +59,9 @@ import { cn } from "./packages/core/doompi-web-components/src/lib/cn.mjs";
56
59
  import { CollapsedLines, collapseLines } from "./packages/core/doompi-web-components/src/lib/collapse.mjs";
57
60
  import { HashlineGroup, hashlineGroups, hashlineGroupsKey } from "./packages/core/doompi-web-components/src/lib/hashlineHighlight.mjs";
58
61
  import { mediaKindOf } from "./packages/core/doompi-web-components/src/lib/media.mjs";
62
+ import { PathGroup, groupByDirectory, groupRowLabel } from "./packages/core/doompi-web-components/src/lib/pathGroups.mjs";
63
+ import { buildReviewPrompt, defaultReviewHeading, diffGutterWidth, diffRangeOf, reviewCommentAnchor, trimSnippet } from "./packages/core/doompi-web-components/src/lib/review.mjs";
59
64
  import { MAX_DIGIT_SHORTCUT, handleOptionListKey, optionListHint, optionMarker } from "./packages/core/doompi-web-components/src/lib/optionList.mjs";
60
65
  import { CHIP_TO_STATUS, LINE_TONE_TO_STATUS, STATUS_TO_CHIP, STATUS_TO_DOT } from "./packages/core/doompi-web-components/src/lib/tone.mjs";
61
66
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "./packages/core/doompi-web-components/src/components/Tooltip.mjs";
62
- export { ACCENT_TONES, type AccentTone, Accordion, AccordionContent, AccordionItem, AccordionTrigger, ActivityIcon, AlertIcon, AnsiLine, type AnsiLineProps, type AnsiSpan, AnsiText, type AnsiTextProps, AudioLinesIcon, Avatar, AvatarFallback, AvatarImage, BREADCRUMB_ELLIPSIS, Badge, type BadgeProps, type BadgeTone, BookmarkPlusIcon, BranchIcon, Breadcrumb, type BreadcrumbProps, Button, type ButtonProps, type ButtonSize, type ButtonVariant, CHIP_TONES, CHIP_TO_STATUS, CheckIcon, Checkbox, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, type ChipTone, CloseIcon, CodeBlock, type CodeBlockProps, CodeEditor, type CodeEditorController, type CodeEditorProps, type CollapsedLines, Collapsible, CollapsibleContent, CollapsibleTrigger, CommandDialog, type CommandDialogProps, CommandEmpty, CommandFooter, CommandGroup, CommandGroupLabel, CommandHeader, CommandInput, CommandItem, CommandItemLabel, CommandList, CopyIcon, DOT_TONES, Dialog, DialogBody, DialogClose, DialogContent, type DialogContentProps, DialogDescription, DialogFooter, type DialogFooterProps, DialogHeader, type DialogHeaderProps, DialogTitle, DialogTrigger, Dot, type DotProps, type DotTone, Drawer, type DrawerProps, DropdownMenu, DropdownMenuCheckboxItem, type DropdownMenuCheckboxItemProps, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, type DropdownMenuItemProps, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, type DropdownMenuRadioItemProps, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EditIcon, type EditorEdit, type EditorMarkedRange, type EditorSelectionRange, type EditorTextRange, type EditorViewportRectangle, EmptyState, type EmptyStateProps, EnterIcon, ExternalLinkIcon, type FieldSize, type FieldVariant, FileIcon, ForkIcon, GREP_COLLAPSED_LINES, GearIcon, type GrammarKey, type GrammarQuery, type HashlineBody, type HashlineGroup, HashlineLines, type HashlineLinesProps, type HashlineResult, type HashlineResultKind, Input, type InputProps, Kbd, KebabIcon, LINE_TONE_TO_STATUS, Label, LoaderIcon, MAX_DIGIT_SHORTCUT, MEDIA_KINDS, MESSAGE_LINE_TONES, Markdown, McpToolFields, McpToolFrame, McpToolOutput, type MediaFrameCapture, type MediaFrameMetadata, type MediaIntrinsicSize, type MediaKind, type MediaPlaybackState, MediaPreview, type MediaPreviewController, type MediaPreviewProps, MessageIcon, MessageItem, MessageItemBody, MessageItemGroup, type MessageItemGroupProps, MessageItemHeader, type MessageItemHeaderProps, type MessageItemProps, type MessageItemState, MessageItemStatus, type MessageItemStatusProps, type MessageLine, type MessageLineTone, MessageLines, type MessageLinesProps, MicIcon, NavTab, NavTabBadge, type NavTabProps, OptionLabel, OptionList, type OptionListProps, OptionRow, type OptionRowProps, PaletteIcon, Panel, PanelBody, PanelHeader, type PanelProps, type PdfNormalizedRectangle, type PdfPageRegion, type PdfPageState, PdfPreview, type PdfPreviewController, type PdfPreviewProps, PlusIcon, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverFooter, PopoverHeader, PopoverTrigger, type PresentedLine, Progress, QuoteIcon, READ_COLLAPSED_LINES, RadioGroup, RadioGroupCard, RadioGroupItem, RefreshIcon, RewindIcon, STATUS_EDGE, STATUS_GLYPH, STATUS_LABEL, STATUS_TONES, STATUS_TO_CHIP, STATUS_TO_DOT, ScrollArea, ScrollBar, SearchIcon, SectionLabel, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, SendIcon, Separator, Sheet, SheetBody, SheetClose, SheetContent, type SheetContentProps, SheetDescription, SheetFooter, SheetHeader, type SheetHeaderProps, SheetOverlay, SheetTitle, SheetTrigger, ShieldIcon, Skeleton, Spinner, type SpinnerProps, StatusBadge, type StatusBadgeProps, type StatusTone, StopIcon, StreamCursor, Switch, SyntaxLine, type SyntaxLineProps, type SyntaxLines, type SyntaxQuery, type SyntaxSpan, SyntaxText, type SyntaxTextProps, type SyntaxToken, Tabs, TabsContent, TabsList, TabsTrigger, type TaggedLine, type TaggedLineMarker, type TerminalHandle, TerminalView, type TerminalViewProps, Textarea, type TextareaProps, Toast, ToastAction, ToastClose, ToastDescription, type ToastProps, ToastProvider, ToastTitle, ToastViewport, ToolPathLink, type ToolPathLinkProps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TrashIcon, UserIcon, VolumeIcon, ansiSpans, badgeVariants, breadcrumbSegments, buttonVariants, cn, collapseLines, compactDetails, detectGrammar, dialogFooterVariants, dotVariants, dropdownMenuItemVariants, fieldVariants, grammarKeyOf, handleOptionListKey, hashlineBody, hashlineGroups, hashlineGroupsKey, highlightToLines, mediaKindOf, messageItemRowVariants, messageItemStatusVariants, messageItemVariants, messageLineVariants, optionListHint, optionListVariants, optionMarker, optionMarkerVariants, optionRowVariants, parseFileHeader, parseTaggedLine, presentHashlineLines, resolvePdfViewportRegion, resultTextLines, statusBadgeVariants, syntaxStyleOf, tabBadgeVariants, tabVariants, takeTrailingNotice, toastVariants, toolTone, useMessageItem, useSyntaxLines };
67
+ export { ACCENT_TONES, type AccentTone, Accordion, AccordionContent, AccordionItem, AccordionTrigger, ActivityIcon, AlertIcon, AnsiLine, type AnsiLineProps, type AnsiSpan, AnsiText, type AnsiTextProps, AudioLinesIcon, Avatar, AvatarFallback, AvatarImage, BREADCRUMB_ELLIPSIS, Badge, type BadgeProps, type BadgeTone, BookmarkPlusIcon, BranchIcon, Breadcrumb, type BreadcrumbProps, Button, type ButtonProps, type ButtonSize, type ButtonVariant, CHIP_TONES, CHIP_TO_STATUS, CheckIcon, Checkbox, ChevronDownIcon, ChevronRightIcon, ChevronUpIcon, type ChipTone, CloseIcon, CodeBlock, type CodeBlockProps, CodeEditor, type CodeEditorController, type CodeEditorProps, type CollapsedLines, Collapsible, CollapsibleContent, CollapsibleTrigger, CommandDialog, type CommandDialogProps, CommandEmpty, CommandFooter, CommandGroup, CommandGroupLabel, CommandHeader, CommandInput, CommandItem, CommandItemLabel, CommandList, CopyIcon, DOT_TONES, Dialog, DialogBody, DialogClose, DialogContent, type DialogContentProps, DialogDescription, DialogFooter, type DialogFooterProps, DialogHeader, type DialogHeaderProps, DialogTitle, DialogTrigger, type DiffHunk, type DiffMarker, type DiffRow, type DiffSelection, type DiffSide, DiffView, type DiffViewProps, Dot, type DotProps, type DotTone, Drawer, type DrawerProps, DropdownMenu, DropdownMenuCheckboxItem, type DropdownMenuCheckboxItemProps, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, type DropdownMenuItemProps, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, type DropdownMenuRadioItemProps, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, EditIcon, type EditorEdit, type EditorMarkedRange, type EditorSelectionRange, type EditorTextRange, type EditorViewportRectangle, EmptyState, type EmptyStateProps, EnterIcon, ExternalLinkIcon, type FieldSize, type FieldVariant, FileIcon, ForkIcon, GREP_COLLAPSED_LINES, GearIcon, type GrammarKey, type GrammarQuery, type HashlineBody, type HashlineGroup, HashlineLines, type HashlineLinesProps, type HashlineResult, type HashlineResultKind, Input, type InputProps, Kbd, KebabIcon, LINE_TONE_TO_STATUS, Label, LoaderIcon, MAX_DIGIT_SHORTCUT, MEDIA_KINDS, MESSAGE_LINE_TONES, Markdown, McpToolFields, McpToolFrame, McpToolOutput, type MediaFrameCapture, type MediaFrameMetadata, type MediaIntrinsicSize, type MediaKind, type MediaPlaybackState, MediaPreview, type MediaPreviewController, type MediaPreviewProps, MessageIcon, MessageItem, MessageItemBody, MessageItemGroup, type MessageItemGroupProps, MessageItemHeader, type MessageItemHeaderProps, type MessageItemProps, type MessageItemState, MessageItemStatus, type MessageItemStatusProps, type MessageLine, type MessageLineTone, MessageLines, type MessageLinesProps, MicIcon, NavTab, NavTabBadge, type NavTabProps, OptionLabel, OptionList, type OptionListProps, OptionRow, type OptionRowProps, PaletteIcon, Panel, PanelBody, PanelHeader, type PanelProps, type PathGroup, type PdfNormalizedRectangle, type PdfPageRegion, type PdfPageState, PdfPreview, type PdfPreviewController, type PdfPreviewProps, PlusIcon, Popover, PopoverAnchor, PopoverClose, PopoverContent, PopoverFooter, PopoverHeader, PopoverTrigger, type PresentedLine, Progress, QuoteIcon, READ_COLLAPSED_LINES, RadioGroup, RadioGroupCard, RadioGroupItem, RefreshIcon, type ReviewComment, ReviewCommentDraft, type ReviewCommentDraftProps, RewindIcon, STATUS_EDGE, STATUS_GLYPH, STATUS_LABEL, STATUS_TONES, STATUS_TO_CHIP, STATUS_TO_DOT, ScrollArea, ScrollBar, SearchIcon, SectionLabel, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectSeparator, SelectTrigger, SelectValue, SendIcon, Separator, Sheet, SheetBody, SheetClose, SheetContent, type SheetContentProps, SheetDescription, SheetFooter, SheetHeader, type SheetHeaderProps, SheetOverlay, SheetTitle, SheetTrigger, ShieldIcon, Skeleton, Spinner, type SpinnerProps, StatusBadge, type StatusBadgeProps, type StatusTone, StopIcon, StreamCursor, Switch, SyntaxLine, type SyntaxLineProps, type SyntaxLines, type SyntaxQuery, type SyntaxSpan, SyntaxText, type SyntaxTextProps, type SyntaxToken, Tabs, TabsContent, TabsList, TabsTrigger, type TaggedLine, type TaggedLineMarker, type TerminalHandle, TerminalView, type TerminalViewProps, Textarea, type TextareaProps, Toast, ToastAction, ToastClose, ToastDescription, type ToastProps, ToastProvider, ToastTitle, ToastViewport, ToolPathLink, type ToolPathLinkProps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TrashIcon, UserIcon, VolumeIcon, ansiSpans, badgeVariants, breadcrumbSegments, buildReviewPrompt, buttonVariants, cn, collapseLines, compactDetails, defaultReviewHeading, detectGrammar, dialogFooterVariants, diffGutterWidth, diffRangeOf, dotVariants, dropdownMenuItemVariants, fieldVariants, grammarKeyOf, groupByDirectory, groupRowLabel, handleOptionListKey, hashlineBody, hashlineGroups, hashlineGroupsKey, highlightToLines, mediaKindOf, messageItemRowVariants, messageItemStatusVariants, messageItemVariants, messageLineVariants, optionListHint, optionListVariants, optionMarker, optionMarkerVariants, optionRowVariants, parseFileHeader, parseTaggedLine, presentHashlineLines, resolvePdfViewportRegion, resultTextLines, reviewCommentAnchor, statusBadgeVariants, syntaxStyleOf, tabBadgeVariants, tabVariants, takeTrailingNotice, toastVariants, toolTone, trimSnippet, useMessageItem, useSyntaxLines };
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{ActivityIcon as e,AlertIcon as t,AudioLinesIcon as n,BookmarkPlusIcon as r,BranchIcon as i,CheckIcon as a,ChevronDownIcon as o,ChevronRightIcon as s,ChevronUpIcon as c,CloseIcon as l,CopyIcon as u,EditIcon as d,EnterIcon as f,ExternalLinkIcon as p,FileIcon as m,ForkIcon as h,GearIcon as g,KebabIcon as _,LoaderIcon as v,MessageIcon as y,MicIcon as b,PaletteIcon as x,PlusIcon as S,QuoteIcon as C,RefreshIcon as w,RewindIcon as T,SearchIcon as E,SendIcon as D,ShieldIcon as O,StopIcon as k,TrashIcon as A,UserIcon as j,VolumeIcon as M}from"./packages/core/doompi-web-components/src/icons/icons.mjs";import{cn as N}from"./packages/core/doompi-web-components/src/lib/cn.mjs";import{Accordion as P,AccordionContent as F,AccordionItem as I,AccordionTrigger as L}from"./packages/core/doompi-web-components/src/components/Accordion.mjs";import{ansiSpans as R}from"./packages/core/doompi-web-components/src/lib/ansiSpans.mjs";import{AnsiLine as z,AnsiText as B}from"./packages/core/doompi-web-components/src/components/AnsiText.mjs";import{Avatar as V,AvatarFallback as H,AvatarImage as U}from"./packages/core/doompi-web-components/src/components/Avatar.mjs";import{Badge as W,badgeVariants as G}from"./packages/core/doompi-web-components/src/components/Badge.mjs";import{Tooltip as K,TooltipContent as q,TooltipProvider as J,TooltipTrigger as Y}from"./packages/core/doompi-web-components/src/components/Tooltip.mjs";import{BREADCRUMB_ELLIPSIS as X,Breadcrumb as Z,breadcrumbSegments as Q}from"./packages/core/doompi-web-components/src/components/Breadcrumb.mjs";import{Spinner as $}from"./packages/core/doompi-web-components/src/components/Spinner.mjs";import{Button as ee,buttonVariants as te}from"./packages/core/doompi-web-components/src/components/Button.mjs";import{Dialog as ne,DialogBody as re,DialogClose as ie,DialogContent as ae,DialogDescription as oe,DialogFooter as se,DialogHeader as ce,DialogTitle as le,DialogTrigger as ue,dialogFooterVariants as de}from"./packages/core/doompi-web-components/src/components/Dialog.mjs";import{Dot as fe,dotVariants as pe}from"./packages/core/doompi-web-components/src/components/Dot.mjs";import{Drawer as me}from"./packages/core/doompi-web-components/src/components/Drawer.mjs";import{DropdownMenu as he,DropdownMenuCheckboxItem as ge,DropdownMenuContent as _e,DropdownMenuGroup as ve,DropdownMenuItem as ye,DropdownMenuLabel as be,DropdownMenuRadioGroup as xe,DropdownMenuRadioItem as Se,DropdownMenuSeparator as Ce,DropdownMenuShortcut as we,DropdownMenuSub as Te,DropdownMenuSubContent as Ee,DropdownMenuSubTrigger as De,DropdownMenuTrigger as Oe,dropdownMenuItemVariants as ke}from"./packages/core/doompi-web-components/src/components/DropdownMenu.mjs";import{Checkbox as Ae}from"./packages/core/doompi-web-components/src/components/Checkbox.mjs";import{grammarKeyOf as je}from"./packages/core/doompi-web-components/src/lib/editorLanguage.mjs";import{detectGrammar as Me,highlightToLines as Ne,syntaxStyleOf as Pe}from"./packages/core/doompi-web-components/src/lib/syntaxHighlight.mjs";import{SyntaxLine as Fe,SyntaxText as Ie,useSyntaxLines as Le}from"./packages/core/doompi-web-components/src/components/SyntaxText.mjs";import{CodeBlock as Re}from"./packages/core/doompi-web-components/src/components/CodeBlock.mjs";import{Skeleton as ze}from"./packages/core/doompi-web-components/src/components/Skeleton.mjs";import{CodeEditor as Be}from"./packages/core/doompi-web-components/src/components/CodeEditor.mjs";import{Collapsible as Ve,CollapsibleContent as He,CollapsibleTrigger as Ue}from"./packages/core/doompi-web-components/src/components/Collapsible.mjs";import{Input as We,fieldVariants as Ge}from"./packages/core/doompi-web-components/src/components/Input.mjs";import{MAX_DIGIT_SHORTCUT as Ke,handleOptionListKey as qe,optionListHint as Je,optionMarker as Ye}from"./packages/core/doompi-web-components/src/lib/optionList.mjs";import{OptionLabel as Xe,OptionList as Ze,OptionRow as Qe,optionListVariants as $e,optionMarkerVariants as et,optionRowVariants as tt}from"./packages/core/doompi-web-components/src/components/OptionList.mjs";import{CommandDialog as nt,CommandEmpty as rt,CommandFooter as it,CommandGroup as at,CommandGroupLabel as ot,CommandHeader as st,CommandInput as ct,CommandItem as lt,CommandItemLabel as ut,CommandList as dt}from"./packages/core/doompi-web-components/src/components/Command.mjs";import{EmptyState as ft}from"./packages/core/doompi-web-components/src/components/EmptyState.mjs";import{hashlineGroups as pt,hashlineGroupsKey as mt}from"./packages/core/doompi-web-components/src/lib/hashlineHighlight.mjs";import{HashlineLines as ht}from"./packages/core/doompi-web-components/src/components/HashlineLines.mjs";import{Kbd as gt}from"./packages/core/doompi-web-components/src/components/Kbd.mjs";import{McpToolFields as _t,McpToolFrame as vt,McpToolOutput as yt}from"./packages/core/doompi-web-components/src/components/McpToolWidget.mjs";import{Label as bt}from"./packages/core/doompi-web-components/src/components/Label.mjs";import{Markdown as xt}from"./packages/core/doompi-web-components/src/components/Markdown.mjs";import{mediaKindOf as St}from"./packages/core/doompi-web-components/src/lib/media.mjs";import{PdfPreview as Ct,resolvePdfViewportRegion as wt}from"./packages/core/doompi-web-components/src/components/PdfPreview.mjs";import{MediaPreview as Tt}from"./packages/core/doompi-web-components/src/components/MediaPreview.mjs";import{STATUS_EDGE as Et,StatusBadge as Dt,statusBadgeVariants as Ot}from"./packages/core/doompi-web-components/src/components/StatusBadge.mjs";import{MessageItem as kt,MessageItemBody as At,MessageItemGroup as jt,MessageItemHeader as Mt,MessageItemStatus as Nt,STATUS_GLYPH as Pt,STATUS_LABEL as Ft,messageItemRowVariants as It,messageItemStatusVariants as Lt,messageItemVariants as Rt,toolTone as zt,useMessageItem as Bt}from"./packages/core/doompi-web-components/src/components/MessageItem.mjs";import{MessageLines as Vt,messageLineVariants as Ht}from"./packages/core/doompi-web-components/src/components/MessageLines.mjs";import{Panel as Ut,PanelBody as Wt,PanelHeader as Gt}from"./packages/core/doompi-web-components/src/components/Panel.mjs";import{Popover as Kt,PopoverAnchor as qt,PopoverClose as Jt,PopoverContent as Yt,PopoverFooter as Xt,PopoverHeader as Zt,PopoverTrigger as Qt}from"./packages/core/doompi-web-components/src/components/Popover.mjs";import{Progress as $t}from"./packages/core/doompi-web-components/src/components/Progress.mjs";import{RadioGroup as en,RadioGroupCard as tn,RadioGroupItem as nn}from"./packages/core/doompi-web-components/src/components/RadioGroup.mjs";import{ScrollArea as rn,ScrollBar as an}from"./packages/core/doompi-web-components/src/components/ScrollArea.mjs";import{SectionLabel as on}from"./packages/core/doompi-web-components/src/components/SectionLabel.mjs";import{Select as sn,SelectContent as cn,SelectGroup as ln,SelectItem as un,SelectLabel as dn,SelectSeparator as fn,SelectTrigger as pn,SelectValue as mn}from"./packages/core/doompi-web-components/src/components/Select.mjs";import{Separator as hn}from"./packages/core/doompi-web-components/src/components/Separator.mjs";import{Sheet as gn,SheetBody as _n,SheetClose as vn,SheetContent as yn,SheetDescription as bn,SheetFooter as xn,SheetHeader as Sn,SheetOverlay as Cn,SheetTitle as wn,SheetTrigger as Tn}from"./packages/core/doompi-web-components/src/components/Sheet.mjs";import{StreamCursor as En}from"./packages/core/doompi-web-components/src/components/StreamCursor.mjs";import{Switch as Dn}from"./packages/core/doompi-web-components/src/components/Switch.mjs";import{NavTab as On,NavTabBadge as kn,Tabs as An,TabsContent as jn,TabsList as Mn,TabsTrigger as Nn,tabBadgeVariants as Pn,tabVariants as Fn}from"./packages/core/doompi-web-components/src/components/Tabs.mjs";import{TerminalView as In}from"./packages/core/doompi-web-components/src/components/TerminalView.mjs";import{Textarea as Ln}from"./packages/core/doompi-web-components/src/components/Textarea.mjs";import{Toast as Rn,ToastAction as zn,ToastClose as Bn,ToastDescription as Vn,ToastProvider as Hn,ToastTitle as Un,ToastViewport as Wn,toastVariants as Gn}from"./packages/core/doompi-web-components/src/components/Toast.mjs";import{ToolPathLink as Kn}from"./packages/core/doompi-web-components/src/components/ToolPathLink.mjs";import{collapseLines as qn}from"./packages/core/doompi-web-components/src/lib/collapse.mjs";import{GREP_COLLAPSED_LINES as Jn,READ_COLLAPSED_LINES as Yn,compactDetails as Xn,hashlineBody as Zn,parseFileHeader as Qn,parseTaggedLine as $n,presentHashlineLines as er,resultTextLines as tr,takeTrailingNotice as nr}from"./packages/core/doompi-web-components/src/lib/hashlineView.mjs";import{CHIP_TO_STATUS as rr,LINE_TONE_TO_STATUS as ir,STATUS_TO_CHIP as ar,STATUS_TO_DOT as or}from"./packages/core/doompi-web-components/src/lib/tone.mjs";import{MEDIA_KINDS as sr}from"./packages/core/doompi-web-components/src/types/editor.mjs";import{ACCENT_TONES as cr,CHIP_TONES as lr,DOT_TONES as ur,MESSAGE_LINE_TONES as dr,STATUS_TONES as fr}from"./packages/core/doompi-web-components/src/types/tone.mjs";export{cr as ACCENT_TONES,P as Accordion,F as AccordionContent,I as AccordionItem,L as AccordionTrigger,e as ActivityIcon,t as AlertIcon,z as AnsiLine,B as AnsiText,n as AudioLinesIcon,V as Avatar,H as AvatarFallback,U as AvatarImage,X as BREADCRUMB_ELLIPSIS,W as Badge,r as BookmarkPlusIcon,i as BranchIcon,Z as Breadcrumb,ee as Button,lr as CHIP_TONES,rr as CHIP_TO_STATUS,a as CheckIcon,Ae as Checkbox,o as ChevronDownIcon,s as ChevronRightIcon,c as ChevronUpIcon,l as CloseIcon,Re as CodeBlock,Be as CodeEditor,Ve as Collapsible,He as CollapsibleContent,Ue as CollapsibleTrigger,nt as CommandDialog,rt as CommandEmpty,it as CommandFooter,at as CommandGroup,ot as CommandGroupLabel,st as CommandHeader,ct as CommandInput,lt as CommandItem,ut as CommandItemLabel,dt as CommandList,u as CopyIcon,ur as DOT_TONES,ne as Dialog,re as DialogBody,ie as DialogClose,ae as DialogContent,oe as DialogDescription,se as DialogFooter,ce as DialogHeader,le as DialogTitle,ue as DialogTrigger,fe as Dot,me as Drawer,he as DropdownMenu,ge as DropdownMenuCheckboxItem,_e as DropdownMenuContent,ve as DropdownMenuGroup,ye as DropdownMenuItem,be as DropdownMenuLabel,xe as DropdownMenuRadioGroup,Se as DropdownMenuRadioItem,Ce as DropdownMenuSeparator,we as DropdownMenuShortcut,Te as DropdownMenuSub,Ee as DropdownMenuSubContent,De as DropdownMenuSubTrigger,Oe as DropdownMenuTrigger,d as EditIcon,ft as EmptyState,f as EnterIcon,p as ExternalLinkIcon,m as FileIcon,h as ForkIcon,Jn as GREP_COLLAPSED_LINES,g as GearIcon,ht as HashlineLines,We as Input,gt as Kbd,_ as KebabIcon,ir as LINE_TONE_TO_STATUS,bt as Label,v as LoaderIcon,Ke as MAX_DIGIT_SHORTCUT,sr as MEDIA_KINDS,dr as MESSAGE_LINE_TONES,xt as Markdown,_t as McpToolFields,vt as McpToolFrame,yt as McpToolOutput,Tt as MediaPreview,y as MessageIcon,kt as MessageItem,At as MessageItemBody,jt as MessageItemGroup,Mt as MessageItemHeader,Nt as MessageItemStatus,Vt as MessageLines,b as MicIcon,On as NavTab,kn as NavTabBadge,Xe as OptionLabel,Ze as OptionList,Qe as OptionRow,x as PaletteIcon,Ut as Panel,Wt as PanelBody,Gt as PanelHeader,Ct as PdfPreview,S as PlusIcon,Kt as Popover,qt as PopoverAnchor,Jt as PopoverClose,Yt as PopoverContent,Xt as PopoverFooter,Zt as PopoverHeader,Qt as PopoverTrigger,$t as Progress,C as QuoteIcon,Yn as READ_COLLAPSED_LINES,en as RadioGroup,tn as RadioGroupCard,nn as RadioGroupItem,w as RefreshIcon,T as RewindIcon,Et as STATUS_EDGE,Pt as STATUS_GLYPH,Ft as STATUS_LABEL,fr as STATUS_TONES,ar as STATUS_TO_CHIP,or as STATUS_TO_DOT,rn as ScrollArea,an as ScrollBar,E as SearchIcon,on as SectionLabel,sn as Select,cn as SelectContent,ln as SelectGroup,un as SelectItem,dn as SelectLabel,fn as SelectSeparator,pn as SelectTrigger,mn as SelectValue,D as SendIcon,hn as Separator,gn as Sheet,_n as SheetBody,vn as SheetClose,yn as SheetContent,bn as SheetDescription,xn as SheetFooter,Sn as SheetHeader,Cn as SheetOverlay,wn as SheetTitle,Tn as SheetTrigger,O as ShieldIcon,ze as Skeleton,$ as Spinner,Dt as StatusBadge,k as StopIcon,En as StreamCursor,Dn as Switch,Fe as SyntaxLine,Ie as SyntaxText,An as Tabs,jn as TabsContent,Mn as TabsList,Nn as TabsTrigger,In as TerminalView,Ln as Textarea,Rn as Toast,zn as ToastAction,Bn as ToastClose,Vn as ToastDescription,Hn as ToastProvider,Un as ToastTitle,Wn as ToastViewport,Kn as ToolPathLink,K as Tooltip,q as TooltipContent,J as TooltipProvider,Y as TooltipTrigger,A as TrashIcon,j as UserIcon,M as VolumeIcon,R as ansiSpans,G as badgeVariants,Q as breadcrumbSegments,te as buttonVariants,N as cn,qn as collapseLines,Xn as compactDetails,Me as detectGrammar,de as dialogFooterVariants,pe as dotVariants,ke as dropdownMenuItemVariants,Ge as fieldVariants,je as grammarKeyOf,qe as handleOptionListKey,Zn as hashlineBody,pt as hashlineGroups,mt as hashlineGroupsKey,Ne as highlightToLines,St as mediaKindOf,It as messageItemRowVariants,Lt as messageItemStatusVariants,Rt as messageItemVariants,Ht as messageLineVariants,Je as optionListHint,$e as optionListVariants,Ye as optionMarker,et as optionMarkerVariants,tt as optionRowVariants,Qn as parseFileHeader,$n as parseTaggedLine,er as presentHashlineLines,wt as resolvePdfViewportRegion,tr as resultTextLines,Ot as statusBadgeVariants,Pe as syntaxStyleOf,Pn as tabBadgeVariants,Fn as tabVariants,nr as takeTrailingNotice,Gn as toastVariants,zt as toolTone,Bt as useMessageItem,Le as useSyntaxLines};
1
+ import{ActivityIcon as e,AlertIcon as t,AudioLinesIcon as n,BookmarkPlusIcon as r,BranchIcon as i,CheckIcon as a,ChevronDownIcon as o,ChevronRightIcon as s,ChevronUpIcon as c,CloseIcon as l,CopyIcon as u,EditIcon as d,EnterIcon as f,ExternalLinkIcon as p,FileIcon as m,ForkIcon as h,GearIcon as g,KebabIcon as _,LoaderIcon as v,MessageIcon as y,MicIcon as b,PaletteIcon as x,PlusIcon as S,QuoteIcon as C,RefreshIcon as w,RewindIcon as T,SearchIcon as E,SendIcon as D,ShieldIcon as O,StopIcon as k,TrashIcon as A,UserIcon as j,VolumeIcon as M}from"./packages/core/doompi-web-components/src/icons/icons.mjs";import{cn as N}from"./packages/core/doompi-web-components/src/lib/cn.mjs";import{Accordion as P,AccordionContent as F,AccordionItem as I,AccordionTrigger as L}from"./packages/core/doompi-web-components/src/components/Accordion.mjs";import{ansiSpans as R}from"./packages/core/doompi-web-components/src/lib/ansiSpans.mjs";import{AnsiLine as z,AnsiText as B}from"./packages/core/doompi-web-components/src/components/AnsiText.mjs";import{Avatar as V,AvatarFallback as H,AvatarImage as U}from"./packages/core/doompi-web-components/src/components/Avatar.mjs";import{Badge as W,badgeVariants as G}from"./packages/core/doompi-web-components/src/components/Badge.mjs";import{Tooltip as K,TooltipContent as q,TooltipProvider as J,TooltipTrigger as Y}from"./packages/core/doompi-web-components/src/components/Tooltip.mjs";import{BREADCRUMB_ELLIPSIS as X,Breadcrumb as Z,breadcrumbSegments as Q}from"./packages/core/doompi-web-components/src/components/Breadcrumb.mjs";import{Spinner as $}from"./packages/core/doompi-web-components/src/components/Spinner.mjs";import{Button as ee,buttonVariants as te}from"./packages/core/doompi-web-components/src/components/Button.mjs";import{Dialog as ne,DialogBody as re,DialogClose as ie,DialogContent as ae,DialogDescription as oe,DialogFooter as se,DialogHeader as ce,DialogTitle as le,DialogTrigger as ue,dialogFooterVariants as de}from"./packages/core/doompi-web-components/src/components/Dialog.mjs";import{buildReviewPrompt as fe,defaultReviewHeading as pe,diffGutterWidth as me,diffRangeOf as he,reviewCommentAnchor as ge,trimSnippet as _e}from"./packages/core/doompi-web-components/src/lib/review.mjs";import{DiffView as ve}from"./packages/core/doompi-web-components/src/components/DiffView.mjs";import{Dot as ye,dotVariants as be}from"./packages/core/doompi-web-components/src/components/Dot.mjs";import{Drawer as xe}from"./packages/core/doompi-web-components/src/components/Drawer.mjs";import{DropdownMenu as Se,DropdownMenuCheckboxItem as Ce,DropdownMenuContent as we,DropdownMenuGroup as Te,DropdownMenuItem as Ee,DropdownMenuLabel as De,DropdownMenuRadioGroup as Oe,DropdownMenuRadioItem as ke,DropdownMenuSeparator as Ae,DropdownMenuShortcut as je,DropdownMenuSub as Me,DropdownMenuSubContent as Ne,DropdownMenuSubTrigger as Pe,DropdownMenuTrigger as Fe,dropdownMenuItemVariants as Ie}from"./packages/core/doompi-web-components/src/components/DropdownMenu.mjs";import{Checkbox as Le}from"./packages/core/doompi-web-components/src/components/Checkbox.mjs";import{grammarKeyOf as Re}from"./packages/core/doompi-web-components/src/lib/editorLanguage.mjs";import{detectGrammar as ze,highlightToLines as Be,syntaxStyleOf as Ve}from"./packages/core/doompi-web-components/src/lib/syntaxHighlight.mjs";import{SyntaxLine as He,SyntaxText as Ue,useSyntaxLines as We}from"./packages/core/doompi-web-components/src/components/SyntaxText.mjs";import{CodeBlock as Ge}from"./packages/core/doompi-web-components/src/components/CodeBlock.mjs";import{Skeleton as Ke}from"./packages/core/doompi-web-components/src/components/Skeleton.mjs";import{CodeEditor as qe}from"./packages/core/doompi-web-components/src/components/CodeEditor.mjs";import{Collapsible as Je,CollapsibleContent as Ye,CollapsibleTrigger as Xe}from"./packages/core/doompi-web-components/src/components/Collapsible.mjs";import{Input as Ze,fieldVariants as Qe}from"./packages/core/doompi-web-components/src/components/Input.mjs";import{MAX_DIGIT_SHORTCUT as $e,handleOptionListKey as et,optionListHint as tt,optionMarker as nt}from"./packages/core/doompi-web-components/src/lib/optionList.mjs";import{OptionLabel as rt,OptionList as it,OptionRow as at,optionListVariants as ot,optionMarkerVariants as st,optionRowVariants as ct}from"./packages/core/doompi-web-components/src/components/OptionList.mjs";import{CommandDialog as lt,CommandEmpty as ut,CommandFooter as dt,CommandGroup as ft,CommandGroupLabel as pt,CommandHeader as mt,CommandInput as ht,CommandItem as gt,CommandItemLabel as _t,CommandList as vt}from"./packages/core/doompi-web-components/src/components/Command.mjs";import{EmptyState as yt}from"./packages/core/doompi-web-components/src/components/EmptyState.mjs";import{hashlineGroups as bt,hashlineGroupsKey as xt}from"./packages/core/doompi-web-components/src/lib/hashlineHighlight.mjs";import{HashlineLines as St}from"./packages/core/doompi-web-components/src/components/HashlineLines.mjs";import{Kbd as Ct}from"./packages/core/doompi-web-components/src/components/Kbd.mjs";import{McpToolFields as wt,McpToolFrame as Tt,McpToolOutput as Et}from"./packages/core/doompi-web-components/src/components/McpToolWidget.mjs";import{Label as Dt}from"./packages/core/doompi-web-components/src/components/Label.mjs";import{Markdown as Ot}from"./packages/core/doompi-web-components/src/components/Markdown.mjs";import{mediaKindOf as kt}from"./packages/core/doompi-web-components/src/lib/media.mjs";import{PdfPreview as At,resolvePdfViewportRegion as jt}from"./packages/core/doompi-web-components/src/components/PdfPreview.mjs";import{MediaPreview as Mt}from"./packages/core/doompi-web-components/src/components/MediaPreview.mjs";import{STATUS_EDGE as Nt,StatusBadge as Pt,statusBadgeVariants as Ft}from"./packages/core/doompi-web-components/src/components/StatusBadge.mjs";import{MessageItem as It,MessageItemBody as Lt,MessageItemGroup as Rt,MessageItemHeader as zt,MessageItemStatus as Bt,STATUS_GLYPH as Vt,STATUS_LABEL as Ht,messageItemRowVariants as Ut,messageItemStatusVariants as Wt,messageItemVariants as Gt,toolTone as Kt,useMessageItem as qt}from"./packages/core/doompi-web-components/src/components/MessageItem.mjs";import{MessageLines as Jt,messageLineVariants as Yt}from"./packages/core/doompi-web-components/src/components/MessageLines.mjs";import{Panel as Xt,PanelBody as Zt,PanelHeader as Qt}from"./packages/core/doompi-web-components/src/components/Panel.mjs";import{Popover as $t,PopoverAnchor as en,PopoverClose as tn,PopoverContent as nn,PopoverFooter as rn,PopoverHeader as an,PopoverTrigger as on}from"./packages/core/doompi-web-components/src/components/Popover.mjs";import{Progress as sn}from"./packages/core/doompi-web-components/src/components/Progress.mjs";import{RadioGroup as cn,RadioGroupCard as ln,RadioGroupItem as un}from"./packages/core/doompi-web-components/src/components/RadioGroup.mjs";import{Textarea as dn}from"./packages/core/doompi-web-components/src/components/Textarea.mjs";import{ReviewCommentDraft as fn}from"./packages/core/doompi-web-components/src/components/ReviewCommentDraft.mjs";import{ScrollArea as pn,ScrollBar as mn}from"./packages/core/doompi-web-components/src/components/ScrollArea.mjs";import{SectionLabel as hn}from"./packages/core/doompi-web-components/src/components/SectionLabel.mjs";import{Select as gn,SelectContent as _n,SelectGroup as vn,SelectItem as yn,SelectLabel as bn,SelectSeparator as xn,SelectTrigger as Sn,SelectValue as Cn}from"./packages/core/doompi-web-components/src/components/Select.mjs";import{Separator as wn}from"./packages/core/doompi-web-components/src/components/Separator.mjs";import{Sheet as Tn,SheetBody as En,SheetClose as Dn,SheetContent as On,SheetDescription as kn,SheetFooter as An,SheetHeader as jn,SheetOverlay as Mn,SheetTitle as Nn,SheetTrigger as Pn}from"./packages/core/doompi-web-components/src/components/Sheet.mjs";import{StreamCursor as Fn}from"./packages/core/doompi-web-components/src/components/StreamCursor.mjs";import{Switch as In}from"./packages/core/doompi-web-components/src/components/Switch.mjs";import{NavTab as Ln,NavTabBadge as Rn,Tabs as zn,TabsContent as Bn,TabsList as Vn,TabsTrigger as Hn,tabBadgeVariants as Un,tabVariants as Wn}from"./packages/core/doompi-web-components/src/components/Tabs.mjs";import{TerminalView as Gn}from"./packages/core/doompi-web-components/src/components/TerminalView.mjs";import{Toast as Kn,ToastAction as qn,ToastClose as Jn,ToastDescription as Yn,ToastProvider as Xn,ToastTitle as Zn,ToastViewport as Qn,toastVariants as $n}from"./packages/core/doompi-web-components/src/components/Toast.mjs";import{ToolPathLink as er}from"./packages/core/doompi-web-components/src/components/ToolPathLink.mjs";import{collapseLines as tr}from"./packages/core/doompi-web-components/src/lib/collapse.mjs";import{GREP_COLLAPSED_LINES as nr,READ_COLLAPSED_LINES as rr,compactDetails as ir,hashlineBody as ar,parseFileHeader as or,parseTaggedLine as sr,presentHashlineLines as cr,resultTextLines as lr,takeTrailingNotice as ur}from"./packages/core/doompi-web-components/src/lib/hashlineView.mjs";import{groupByDirectory as dr,groupRowLabel as fr}from"./packages/core/doompi-web-components/src/lib/pathGroups.mjs";import{CHIP_TO_STATUS as pr,LINE_TONE_TO_STATUS as mr,STATUS_TO_CHIP as hr,STATUS_TO_DOT as gr}from"./packages/core/doompi-web-components/src/lib/tone.mjs";import{MEDIA_KINDS as _r}from"./packages/core/doompi-web-components/src/types/editor.mjs";import{ACCENT_TONES as vr,CHIP_TONES as yr,DOT_TONES as br,MESSAGE_LINE_TONES as xr,STATUS_TONES as Sr}from"./packages/core/doompi-web-components/src/types/tone.mjs";export{vr as ACCENT_TONES,P as Accordion,F as AccordionContent,I as AccordionItem,L as AccordionTrigger,e as ActivityIcon,t as AlertIcon,z as AnsiLine,B as AnsiText,n as AudioLinesIcon,V as Avatar,H as AvatarFallback,U as AvatarImage,X as BREADCRUMB_ELLIPSIS,W as Badge,r as BookmarkPlusIcon,i as BranchIcon,Z as Breadcrumb,ee as Button,yr as CHIP_TONES,pr as CHIP_TO_STATUS,a as CheckIcon,Le as Checkbox,o as ChevronDownIcon,s as ChevronRightIcon,c as ChevronUpIcon,l as CloseIcon,Ge as CodeBlock,qe as CodeEditor,Je as Collapsible,Ye as CollapsibleContent,Xe as CollapsibleTrigger,lt as CommandDialog,ut as CommandEmpty,dt as CommandFooter,ft as CommandGroup,pt as CommandGroupLabel,mt as CommandHeader,ht as CommandInput,gt as CommandItem,_t as CommandItemLabel,vt as CommandList,u as CopyIcon,br as DOT_TONES,ne as Dialog,re as DialogBody,ie as DialogClose,ae as DialogContent,oe as DialogDescription,se as DialogFooter,ce as DialogHeader,le as DialogTitle,ue as DialogTrigger,ve as DiffView,ye as Dot,xe as Drawer,Se as DropdownMenu,Ce as DropdownMenuCheckboxItem,we as DropdownMenuContent,Te as DropdownMenuGroup,Ee as DropdownMenuItem,De as DropdownMenuLabel,Oe as DropdownMenuRadioGroup,ke as DropdownMenuRadioItem,Ae as DropdownMenuSeparator,je as DropdownMenuShortcut,Me as DropdownMenuSub,Ne as DropdownMenuSubContent,Pe as DropdownMenuSubTrigger,Fe as DropdownMenuTrigger,d as EditIcon,yt as EmptyState,f as EnterIcon,p as ExternalLinkIcon,m as FileIcon,h as ForkIcon,nr as GREP_COLLAPSED_LINES,g as GearIcon,St as HashlineLines,Ze as Input,Ct as Kbd,_ as KebabIcon,mr as LINE_TONE_TO_STATUS,Dt as Label,v as LoaderIcon,$e as MAX_DIGIT_SHORTCUT,_r as MEDIA_KINDS,xr as MESSAGE_LINE_TONES,Ot as Markdown,wt as McpToolFields,Tt as McpToolFrame,Et as McpToolOutput,Mt as MediaPreview,y as MessageIcon,It as MessageItem,Lt as MessageItemBody,Rt as MessageItemGroup,zt as MessageItemHeader,Bt as MessageItemStatus,Jt as MessageLines,b as MicIcon,Ln as NavTab,Rn as NavTabBadge,rt as OptionLabel,it as OptionList,at as OptionRow,x as PaletteIcon,Xt as Panel,Zt as PanelBody,Qt as PanelHeader,At as PdfPreview,S as PlusIcon,$t as Popover,en as PopoverAnchor,tn as PopoverClose,nn as PopoverContent,rn as PopoverFooter,an as PopoverHeader,on as PopoverTrigger,sn as Progress,C as QuoteIcon,rr as READ_COLLAPSED_LINES,cn as RadioGroup,ln as RadioGroupCard,un as RadioGroupItem,w as RefreshIcon,fn as ReviewCommentDraft,T as RewindIcon,Nt as STATUS_EDGE,Vt as STATUS_GLYPH,Ht as STATUS_LABEL,Sr as STATUS_TONES,hr as STATUS_TO_CHIP,gr as STATUS_TO_DOT,pn as ScrollArea,mn as ScrollBar,E as SearchIcon,hn as SectionLabel,gn as Select,_n as SelectContent,vn as SelectGroup,yn as SelectItem,bn as SelectLabel,xn as SelectSeparator,Sn as SelectTrigger,Cn as SelectValue,D as SendIcon,wn as Separator,Tn as Sheet,En as SheetBody,Dn as SheetClose,On as SheetContent,kn as SheetDescription,An as SheetFooter,jn as SheetHeader,Mn as SheetOverlay,Nn as SheetTitle,Pn as SheetTrigger,O as ShieldIcon,Ke as Skeleton,$ as Spinner,Pt as StatusBadge,k as StopIcon,Fn as StreamCursor,In as Switch,He as SyntaxLine,Ue as SyntaxText,zn as Tabs,Bn as TabsContent,Vn as TabsList,Hn as TabsTrigger,Gn as TerminalView,dn as Textarea,Kn as Toast,qn as ToastAction,Jn as ToastClose,Yn as ToastDescription,Xn as ToastProvider,Zn as ToastTitle,Qn as ToastViewport,er as ToolPathLink,K as Tooltip,q as TooltipContent,J as TooltipProvider,Y as TooltipTrigger,A as TrashIcon,j as UserIcon,M as VolumeIcon,R as ansiSpans,G as badgeVariants,Q as breadcrumbSegments,fe as buildReviewPrompt,te as buttonVariants,N as cn,tr as collapseLines,ir as compactDetails,pe as defaultReviewHeading,ze as detectGrammar,de as dialogFooterVariants,me as diffGutterWidth,he as diffRangeOf,be as dotVariants,Ie as dropdownMenuItemVariants,Qe as fieldVariants,Re as grammarKeyOf,dr as groupByDirectory,fr as groupRowLabel,et as handleOptionListKey,ar as hashlineBody,bt as hashlineGroups,xt as hashlineGroupsKey,Be as highlightToLines,kt as mediaKindOf,Ut as messageItemRowVariants,Wt as messageItemStatusVariants,Gt as messageItemVariants,Yt as messageLineVariants,tt as optionListHint,ot as optionListVariants,nt as optionMarker,st as optionMarkerVariants,ct as optionRowVariants,or as parseFileHeader,sr as parseTaggedLine,cr as presentHashlineLines,jt as resolvePdfViewportRegion,lr as resultTextLines,ge as reviewCommentAnchor,Ft as statusBadgeVariants,Ve as syntaxStyleOf,Un as tabBadgeVariants,Wn as tabVariants,ur as takeTrailingNotice,$n as toastVariants,Kt as toolTone,_e as trimSnippet,qt as useMessageItem,We as useSyntaxLines};
@@ -0,0 +1,16 @@
1
+ import { DiffHunk, DiffRow, DiffSelection } from "../types/diff.mjs";
2
+ import { ReactNode } from "react";
3
+ //#region src/components/DiffView.d.ts
4
+ export interface DiffViewProps {
5
+ hunks: readonly DiffHunk[];
6
+ /** Marks the surface so a test and a selection handler can find it. Unique per diff on a page. */
7
+ testId: string;
8
+ /** Called with the selected text, the lines it covers, and their side. Enables line-number clicks. */
9
+ onSelect?: (selection: DiffSelection) => void;
10
+ /** Drawn under one row, full width: inline comments and an open draft go here. */
11
+ renderAfterRow?: (row: DiffRow) => ReactNode;
12
+ className?: string;
13
+ }
14
+ export declare function DiffView({ hunks, testId, onSelect, renderAfterRow, className }: DiffViewProps): import("react").JSX.Element;
15
+ //#endregion
16
+ //# sourceMappingURL=DiffView.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DiffView.d.mts","names":[],"sources":["../../../../../../src/components/DiffView.tsx"],"mappings":";;;iBA4BiB;EACf,gBAAgB;;EAEhB;;EAEA,YAAY,WAAW;;EAEvB,kBAAkB,KAAK,YAAY;EACnC;;wBAOc,WAAW,OAAO,QAAQ,UAAU,gBAAgB,aAAa,gCAAa,IAAA"}
@@ -0,0 +1,2 @@
1
+ import{cn as e}from"../lib/cn.mjs";import{Button as t}from"./Button.mjs";import{diffGutterWidth as n,diffRangeOf as r}from"../lib/review.mjs";import{jsx as i,jsxs as a}from"react/jsx-runtime";import{Fragment as o}from"react";const s={"+":`bg-doom-tint-green text-doom-green`,"-":`bg-doom-tint-red text-doom-red`," ":`text-doom-dim`};function c(e){return e===`+`||e===`-`||e===` `}function l({hunks:l,testId:u,onSelect:d,renderAfterRow:f,className:p}){let m=n(l);return l.length===0?/* @__PURE__ */ i(`p`,{"data-testid":`${u}-empty`,className:`px-2 py-1 text-xs text-doom-faint`,children:`no lines changed`}):/* @__PURE__ */ i(`div`,{"data-testid":u,"data-diff-surface":u,onMouseUp:()=>{if(d===void 0)return;let e=globalThis.getSelection?.(),t=e?.toString()??``;if(t.trim()===``)return;let n=[...document.querySelectorAll(`[data-diff-surface="${u}"] [data-diff-line]`)].filter(t=>e?.containsNode(t,!0)===!0).map(e=>({marker:e.dataset.diffMarker,line:Number(e.dataset.diffLine)})).filter(e=>c(e.marker)),i=r(n);i!==void 0&&d({...i,snippet:t})},className:e(`overflow-x-auto font-mono text-sm leading-normal`,p),children:l.map((n,r)=>/* @__PURE__ */ a(`div`,{children:[r>0?/* @__PURE__ */ a(`div`,{className:`flex items-center gap-2 px-2 py-0.5 text-2xs text-doom-faint`,children:[/* @__PURE__ */ i(`span`,{className:`h-px flex-1 bg-doom-border-soft`}),/* @__PURE__ */ i(`span`,{children:`⋯`}),/* @__PURE__ */ i(`span`,{className:`h-px flex-1 bg-doom-border-soft`})]}):null,n.rows.map((n,r)=>/* @__PURE__ */ a(o,{children:[/* @__PURE__ */ a(`div`,{"data-diff-line":n.line,"data-diff-marker":n.marker,className:e(`flex whitespace-pre`,s[n.marker]),children:[d===void 0?/* @__PURE__ */ i(`span`,{"aria-hidden":!0,className:`shrink-0 select-none pr-2 pl-2 text-right text-doom-faint`,style:{width:`${m+2}ch`},children:n.line}):/* @__PURE__ */ i(t,{variant:`ghost`,size:`xs`,"data-diff-gutter":n.line,"aria-label":`comment on ${n.marker===`-`?`removed `:``}line ${n.line}`,onClick:()=>d({side:n.marker===`-`?`old`:`new`,startLine:n.line,endLine:n.line,snippet:n.content}),className:`h-auto min-h-0 min-w-0 shrink-0 select-none justify-end rounded-none py-0 pr-2 pl-2 font-normal text-sm text-doom-faint hover:bg-transparent hover:text-doom-blue`,style:{width:`${m+2}ch`},children:n.line}),/* @__PURE__ */ i(`span`,{className:`shrink-0 select-none pr-1`,children:n.marker}),/* @__PURE__ */ i(`span`,{className:`min-w-0`,children:n.content})]}),f?.(n)]},`${n.marker}-${n.line}-${r}`))]},`${n.start}-${r}`))})}export{l as DiffView};
2
+ //# sourceMappingURL=DiffView.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DiffView.mjs","names":["Fragment"],"sources":["../../../../../../src/components/DiffView.tsx"],"sourcesContent":["import { Fragment, type ReactNode } from 'react';\n\nimport { cn } from '../lib/cn';\nimport { diffGutterWidth, diffRangeOf } from '../lib/review';\nimport type { DiffHunk, DiffMarker, DiffRow, DiffSelection } from '../types/diff';\nimport { Button } from './Button';\n\n/**\n * A diff, drawn the way this cockpit draws every other one: a numbered gutter\n * and a background wash per row, so a change reads at a glance rather than by\n * hunting for leading punctuation.\n *\n * Hunks arrive apart rather than joined by an elision marker, so the gap\n * between two of them is a rule the component draws, not a line it has to\n * recognise in a string.\n *\n * A reader comments two ways: by highlighting text, which reports the lines the\n * highlight touches, or by clicking a line number, which reports that one line.\n * Either way the selection names its side, so a note on a removed line points\n * at the old file rather than at whatever the new file has on that number.\n */\n\nconst ROW_TONE: Readonly<Record<DiffMarker, string>> = {\n '+': 'bg-doom-tint-green text-doom-green',\n '-': 'bg-doom-tint-red text-doom-red',\n ' ': 'text-doom-dim',\n};\n\nexport interface DiffViewProps {\n hunks: readonly DiffHunk[];\n /** Marks the surface so a test and a selection handler can find it. Unique per diff on a page. */\n testId: string;\n /** Called with the selected text, the lines it covers, and their side. Enables line-number clicks. */\n onSelect?: (selection: DiffSelection) => void;\n /** Drawn under one row, full width: inline comments and an open draft go here. */\n renderAfterRow?: (row: DiffRow) => ReactNode;\n className?: string;\n}\n\nfunction isMarker(value: string | undefined): value is DiffMarker {\n return value === '+' || value === '-' || value === ' ';\n}\n\nexport function DiffView({ hunks, testId, onSelect, renderAfterRow, className }: DiffViewProps) {\n const gutter = diffGutterWidth(hunks);\n\n /**\n * Turns whatever the reader highlighted into a line range. The rows carry\n * their own numbers and markers, so the range comes from the rows the\n * selection touches rather than from counting newlines in the rendered text.\n */\n const handleSelect = (): void => {\n if (onSelect === undefined) return;\n const selection = globalThis.getSelection?.();\n const text = selection?.toString() ?? '';\n if (text.trim() === '') return;\n const rows = [...document.querySelectorAll<HTMLElement>(`[data-diff-surface=\"${testId}\"] [data-diff-line]`)];\n const touched = rows\n .filter((row) => selection?.containsNode(row, true) === true)\n .map((row) => ({ marker: row.dataset.diffMarker, line: Number(row.dataset.diffLine) }))\n .filter((row): row is { marker: DiffMarker; line: number } => isMarker(row.marker));\n const range = diffRangeOf(touched);\n if (range !== undefined) onSelect({ ...range, snippet: text });\n };\n\n if (hunks.length === 0) {\n return (\n <p data-testid={`${testId}-empty`} className=\"px-2 py-1 text-xs text-doom-faint\">\n no lines changed\n </p>\n );\n }\n\n return (\n <div\n data-testid={testId}\n data-diff-surface={testId}\n onMouseUp={handleSelect}\n className={cn('overflow-x-auto font-mono text-sm leading-normal', className)}\n >\n {hunks.map((hunk, position) => (\n <div key={`${hunk.start}-${position}`}>\n {position > 0 ? (\n <div className=\"flex items-center gap-2 px-2 py-0.5 text-2xs text-doom-faint\">\n <span className=\"h-px flex-1 bg-doom-border-soft\" />\n <span>⋯</span>\n <span className=\"h-px flex-1 bg-doom-border-soft\" />\n </div>\n ) : null}\n {hunk.rows.map((row, offset) => (\n <Fragment key={`${row.marker}-${row.line}-${offset}`}>\n <div\n data-diff-line={row.line}\n data-diff-marker={row.marker}\n className={cn('flex whitespace-pre', ROW_TONE[row.marker])}\n >\n {onSelect === undefined ? (\n <span\n aria-hidden\n className=\"shrink-0 select-none pr-2 pl-2 text-right text-doom-faint\"\n style={{ width: `${gutter + 2}ch` }}\n >\n {row.line}\n </span>\n ) : (\n <Button\n variant=\"ghost\"\n size=\"xs\"\n data-diff-gutter={row.line}\n aria-label={`comment on ${row.marker === '-' ? 'removed ' : ''}line ${row.line}`}\n onClick={() =>\n onSelect({\n side: row.marker === '-' ? 'old' : 'new',\n startLine: row.line,\n endLine: row.line,\n snippet: row.content,\n })\n }\n className=\"h-auto min-h-0 min-w-0 shrink-0 select-none justify-end rounded-none py-0 pr-2 pl-2 font-normal text-sm text-doom-faint hover:bg-transparent hover:text-doom-blue\"\n style={{ width: `${gutter + 2}ch` }}\n >\n {row.line}\n </Button>\n )}\n <span className=\"shrink-0 select-none pr-1\">{row.marker}</span>\n <span className=\"min-w-0\">{row.content}</span>\n </div>\n {renderAfterRow?.(row)}\n </Fragment>\n ))}\n </div>\n ))}\n </div>\n );\n}\n"],"mappings":"iOAsBA,MAAM,EAAiD,CACrD,IAAK,qCACL,IAAK,iCACL,IAAK,eACP,EAaA,SAAS,EAAS,EAAgD,CAChE,OAAO,IAAU,KAAO,IAAU,KAAO,IAAU,GACrD,CAEA,SAAgB,EAAS,CAAE,QAAO,SAAQ,WAAU,iBAAgB,aAA4B,CAC9F,IAAM,EAAS,EAAgB,CAAK,EA6BpC,OARI,EAAM,SAAW,EAEjB,kBAAC,IAAD,CAAG,cAAa,GAAG,EAAO,QAAS,UAAU,oCAAoC,SAAA,kBAE9E,CAAA,EAKL,kBAAC,MAAD,CACE,cAAa,EACb,oBAAmB,EACnB,cA1B6B,CAC/B,GAAI,IAAa,IAAA,GAAW,OAC5B,IAAM,EAAY,WAAW,eAAe,EACtC,EAAO,GAAW,SAAS,GAAK,GACtC,GAAI,EAAK,KAAK,IAAM,GAAI,OAExB,IAAM,EAAU,CADF,GAAG,SAAS,iBAA8B,uBAAuB,EAAO,oBAAoB,CACvF,CAAC,CACjB,OAAQ,GAAQ,GAAW,aAAa,EAAK,EAAI,IAAM,EAAI,CAAC,CAC5D,IAAK,IAAS,CAAE,OAAQ,EAAI,QAAQ,WAAY,KAAM,OAAO,EAAI,QAAQ,QAAQ,CAAE,EAAE,CAAC,CACtF,OAAQ,GAAqD,EAAS,EAAI,MAAM,CAAC,EAC9E,EAAQ,EAAY,CAAO,EAC7B,IAAU,IAAA,IAAW,EAAS,CAAE,GAAG,EAAO,QAAS,CAAK,CAAC,CAC/D,EAeI,UAAW,EAAG,mDAAoD,CAAS,EAE1E,SAAA,EAAM,KAAK,EAAM,IAChB,kBAAC,MAAD,CAAA,SAAA,CACG,EAAW,EACV,kBAAC,MAAD,CAAK,UAAU,+DAAf,SAAA,CACE,kBAAC,OAAD,CAAM,UAAU,iCAAmC,CAAA,EACnD,kBAAC,OAAD,CAAA,SAAM,GAAO,CAAA,EACb,kBAAC,OAAD,CAAM,UAAU,iCAAmC,CAAA,CAChD,CACH,CAAA,EAAA,KACH,EAAK,KAAK,KAAK,EAAK,IACnB,kBAACA,EAAD,CAAA,SAAA,CACE,kBAAC,MAAD,CACE,iBAAgB,EAAI,KACpB,mBAAkB,EAAI,OACtB,UAAW,EAAG,sBAAuB,EAAS,EAAI,OAAO,EAH3D,SAAA,CAKG,IAAa,IAAA,GACZ,kBAAC,OAAD,CACE,cAAA,GACA,UAAU,4DACV,MAAO,CAAE,MAAO,GAAG,EAAS,EAAE,GAAI,EAEjC,SAAA,EAAI,IACD,CAAA,EAEN,kBAAC,EAAD,CACE,QAAQ,QACR,KAAK,KACL,mBAAkB,EAAI,KACtB,aAAY,cAAc,EAAI,SAAW,IAAM,WAAa,GAAG,OAAO,EAAI,OAC1E,YACE,EAAS,CACP,KAAM,EAAI,SAAW,IAAM,MAAQ,MACnC,UAAW,EAAI,KACf,QAAS,EAAI,KACb,QAAS,EAAI,OACf,CAAC,EAEH,UAAU,oKACV,MAAO,CAAE,MAAO,GAAG,EAAS,EAAE,GAAI,EAEjC,SAAA,EAAI,IACC,CAAA,EAEV,kBAAC,OAAD,CAAM,UAAU,4BAA6B,SAAA,EAAI,MAAa,CAAA,EAC9D,kBAAC,OAAD,CAAM,UAAU,UAAW,SAAA,EAAI,OAAc,CAAA,CAC1C,CACJ,CAAA,EAAA,IAAiB,CAAG,CACb,CAAA,EAtCK,GAAG,EAAI,OAAO,GAAG,EAAI,KAAK,GAAG,GAsClC,CACX,CACE,CAAA,EAjDK,GAAG,EAAK,MAAM,GAAG,GAiDtB,CACN,CACE,CAAA,CAET"}
@@ -0,0 +1,24 @@
1
+ import { DiffSide } from "../types/diff.mjs";
2
+ //#region src/components/ReviewCommentDraft.d.ts
3
+ /**
4
+ * The box a selection raises: what was highlighted, and a note about it.
5
+ *
6
+ * The note is held here rather than in a store because it belongs to one open
7
+ * box and dies with it; only a submitted comment is worth keeping, and the
8
+ * owner decides where that goes.
9
+ */
10
+ export interface ReviewCommentDraftProps {
11
+ snippet: string;
12
+ /** Absent when the selection came from somewhere lines cannot be recovered, such as a rendered preview. */
13
+ startLine?: number;
14
+ endLine?: number;
15
+ /** Absent means the new side. */
16
+ side?: DiffSide;
17
+ onSubmit: (body: string) => void;
18
+ onCancel: () => void;
19
+ /** Prefix for the test ids: `<prefix>-draft`, `-body`, `-add`, `-cancel`. */
20
+ testIdPrefix?: string;
21
+ }
22
+ export declare function ReviewCommentDraft({ snippet, startLine, endLine, side, onSubmit, onCancel, testIdPrefix }: ReviewCommentDraftProps): import("react").JSX.Element;
23
+ //#endregion
24
+ //# sourceMappingURL=ReviewCommentDraft.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReviewCommentDraft.d.mts","names":[],"sources":["../../../../../../src/components/ReviewCommentDraft.tsx"],"mappings":";;;;;;;;;iBAciB;EACf;;EAEA;EACA;;EAEA,OAAO;EACP,WAAW;EACX;;EAEA;;wBAWc,qBACd,SACA,WACA,SACA,MACA,UACA,UACA,gBACC,0CAAuB,IAAA"}
@@ -0,0 +1,2 @@
1
+ import{Button as e}from"./Button.mjs";import{trimSnippet as t}from"../lib/review.mjs";import{Textarea as n}from"./Textarea.mjs";import{jsx as r,jsxs as i}from"react/jsx-runtime";import{useState as a}from"react";function o(e,t,n){if(e===void 0)return`no line anchor: this selection came from the rendered preview`;let r=n===`old`?`removed `:``;return t===void 0||t===e?`${r}line ${e}`:`${r}lines ${e} to ${t}`}function s({snippet:s,startLine:c,endLine:l,side:u,onSubmit:d,onCancel:f,testIdPrefix:p=`review-comment`}){let[m,h]=a(``);return/* @__PURE__ */ i(`div`,{"data-testid":`${p}-draft`,className:`flex flex-col gap-1.5 border-t border-doom-border p-2`,children:[/* @__PURE__ */ r(`p`,{className:`text-2xs text-doom-faint`,children:o(c,l,u)}),/* @__PURE__ */ r(`pre`,{className:`max-h-24 overflow-y-auto whitespace-pre-wrap break-words rounded border border-doom-border-soft bg-doom-deep p-1.5 font-mono text-xs text-doom-dim`,children:t(s,8,600)}),/* @__PURE__ */ r(n,{"data-testid":`${p}-body`,value:m,rows:3,autoFocus:!0,placeholder:`what should change here?`,onChange:e=>h(e.target.value),onKeyDown:e=>{e.key===`Escape`&&f(),e.key===`Enter`&&(e.metaKey||e.ctrlKey)&&(e.preventDefault(),m.trim()!==``&&d(m))},className:`text-sm`}),/* @__PURE__ */ i(`div`,{className:`flex items-center gap-1.5`,children:[/* @__PURE__ */ r(e,{variant:`outline`,size:`xs`,"data-testid":`${p}-add`,disabled:m.trim()===``,onClick:()=>d(m),className:`text-2xs`,children:`add comment`}),/* @__PURE__ */ r(e,{variant:`ghost`,size:`xs`,"data-testid":`${p}-cancel`,onClick:f,className:`text-2xs`,children:`cancel`}),/* @__PURE__ */ r(`span`,{className:`text-2xs text-doom-faint`,children:`⌘⏎ to add`})]})]})}export{s as ReviewCommentDraft};
2
+ //# sourceMappingURL=ReviewCommentDraft.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReviewCommentDraft.mjs","names":[],"sources":["../../../../../../src/components/ReviewCommentDraft.tsx"],"sourcesContent":["import { useState } from 'react';\n\nimport { trimSnippet } from '../lib/review';\nimport type { DiffSide } from '../types/diff';\nimport { Button } from './Button';\nimport { Textarea } from './Textarea';\n\n/**\n * The box a selection raises: what was highlighted, and a note about it.\n *\n * The note is held here rather than in a store because it belongs to one open\n * box and dies with it; only a submitted comment is worth keeping, and the\n * owner decides where that goes.\n */\nexport interface ReviewCommentDraftProps {\n snippet: string;\n /** Absent when the selection came from somewhere lines cannot be recovered, such as a rendered preview. */\n startLine?: number;\n endLine?: number;\n /** Absent means the new side. */\n side?: DiffSide;\n onSubmit: (body: string) => void;\n onCancel: () => void;\n /** Prefix for the test ids: `<prefix>-draft`, `-body`, `-add`, `-cancel`. */\n testIdPrefix?: string;\n}\n\nfunction rangeLabel(startLine: number | undefined, endLine: number | undefined, side: DiffSide | undefined): string {\n if (startLine === undefined) return 'no line anchor: this selection came from the rendered preview';\n const removed = side === 'old' ? 'removed ' : '';\n return endLine === undefined || endLine === startLine\n ? `${removed}line ${startLine}`\n : `${removed}lines ${startLine} to ${endLine}`;\n}\n\nexport function ReviewCommentDraft({\n snippet,\n startLine,\n endLine,\n side,\n onSubmit,\n onCancel,\n testIdPrefix = 'review-comment',\n}: ReviewCommentDraftProps) {\n const [body, setBody] = useState('');\n\n return (\n <div data-testid={`${testIdPrefix}-draft`} className=\"flex flex-col gap-1.5 border-t border-doom-border p-2\">\n <p className=\"text-2xs text-doom-faint\">{rangeLabel(startLine, endLine, side)}</p>\n <pre className=\"max-h-24 overflow-y-auto whitespace-pre-wrap break-words rounded border border-doom-border-soft bg-doom-deep p-1.5 font-mono text-xs text-doom-dim\">\n {trimSnippet(snippet, 8, 600)}\n </pre>\n <Textarea\n data-testid={`${testIdPrefix}-body`}\n value={body}\n rows={3}\n autoFocus\n placeholder=\"what should change here?\"\n onChange={(event) => setBody(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Escape') onCancel();\n if (event.key !== 'Enter' || !(event.metaKey || event.ctrlKey)) return;\n event.preventDefault();\n if (body.trim() !== '') onSubmit(body);\n }}\n className=\"text-sm\"\n />\n <div className=\"flex items-center gap-1.5\">\n <Button\n variant=\"outline\"\n size=\"xs\"\n data-testid={`${testIdPrefix}-add`}\n disabled={body.trim() === ''}\n onClick={() => onSubmit(body)}\n className=\"text-2xs\"\n >\n add comment\n </Button>\n <Button\n variant=\"ghost\"\n size=\"xs\"\n data-testid={`${testIdPrefix}-cancel`}\n onClick={onCancel}\n className=\"text-2xs\"\n >\n cancel\n </Button>\n <span className=\"text-2xs text-doom-faint\">⌘⏎ to add</span>\n </div>\n </div>\n );\n}\n"],"mappings":"mNA2BA,SAAS,EAAW,EAA+B,EAA6B,EAAoC,CAClH,GAAI,IAAc,IAAA,GAAW,MAAO,gEACpC,IAAM,EAAU,IAAS,MAAQ,WAAa,GAC9C,OAAO,IAAY,IAAA,IAAa,IAAY,EACxC,GAAG,EAAQ,OAAO,IAClB,GAAG,EAAQ,QAAQ,EAAU,MAAM,GACzC,CAEA,SAAgB,EAAmB,CACjC,UACA,YACA,UACA,OACA,WACA,WACA,eAAe,kBACW,CAC1B,GAAM,CAAC,EAAM,GAAW,EAAS,EAAE,EAEnC,MACE,kBAAC,MAAD,CAAK,cAAa,GAAG,EAAa,QAAS,UAAU,wDAArD,SAAA,CACE,kBAAC,IAAD,CAAG,UAAU,2BAA4B,SAAA,EAAW,EAAW,EAAS,CAAI,CAAK,CAAA,EACjF,kBAAC,MAAD,CAAK,UAAU,qJACZ,SAAA,EAAY,EAAS,EAAG,GAAG,CACzB,CAAA,EACL,kBAAC,EAAD,CACE,cAAa,GAAG,EAAa,OAC7B,MAAO,EACP,KAAM,EACN,UAAA,GACA,YAAY,2BACZ,SAAW,GAAU,EAAQ,EAAM,OAAO,KAAK,EAC/C,UAAY,GAAU,CAChB,EAAM,MAAQ,UAAU,EAAS,EACjC,EAAM,MAAQ,UAAa,EAAM,SAAW,EAAM,WACtD,EAAM,eAAe,EACjB,EAAK,KAAK,IAAM,IAAI,EAAS,CAAI,EACvC,EACA,UAAU,SACX,CAAA,EACD,kBAAC,MAAD,CAAK,UAAU,4BAAf,SAAA,CACE,kBAAC,EAAD,CACE,QAAQ,UACR,KAAK,KACL,cAAa,GAAG,EAAa,MAC7B,SAAU,EAAK,KAAK,IAAM,GAC1B,YAAe,EAAS,CAAI,EAC5B,UAAU,WACX,SAAA,aAEO,CAAA,EACR,kBAAC,EAAD,CACE,QAAQ,QACR,KAAK,KACL,cAAa,GAAG,EAAa,SAC7B,QAAS,EACT,UAAU,WACX,SAAA,QAEO,CAAA,EACR,kBAAC,OAAD,CAAM,UAAU,2BAA2B,SAAA,WAAe,CAAA,CACvD,GACF,GAET"}
@@ -0,0 +1,23 @@
1
+ //#region src/lib/pathGroups.d.ts
2
+ /**
3
+ * The two-level grouping a changed-file list uses: one header per top-level
4
+ * segment, each naming the deepest directory its files share.
5
+ *
6
+ * Two levels rather than a full tree: paths here run five and six segments
7
+ * deep, so a node per segment spends more rows on directories than on the files
8
+ * someone came to find. The header carries the shared run of directories and
9
+ * each row carries what is left, so a file stays one row and the part that
10
+ * distinguishes it stays readable.
11
+ */
12
+ /** One header row and the items under it. */
13
+ export interface PathGroup<T> {
14
+ /** The shared directory the header names, or empty for files at the root. */
15
+ prefix: string;
16
+ items: T[];
17
+ }
18
+ /** Groups by top-level segment, ordered by path so a header's files sit together under it. */
19
+ export declare function groupByDirectory<T>(items: readonly T[], pathOf: (item: T) => string): PathGroup<T>[];
20
+ /** What one row shows once its group's header has already said the shared part. */
21
+ export declare function groupRowLabel(prefix: string, relPath: string): string;
22
+ //#endregion
23
+ //# sourceMappingURL=pathGroups.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pathGroups.d.mts","names":[],"sources":["../../../../../../src/lib/pathGroups.ts"],"mappings":";;;;;;;;;;;;iBAYiB,UAAU;;EAEzB;EACA,OAAO;;;wBAsBO,iBAAiB,GAAG,gBAAgB,KAAK,SAAS,MAAM,eAAe,UAAU;;wBAsBjF,cAAc,gBAAgB"}
@@ -0,0 +1,2 @@
1
+ function e(e){let t=e.lastIndexOf(`/`);return t===-1?``:e.slice(0,t)}function t(e,t){let n=e.split(`/`),r=t.split(`/`),i=[];for(let e=0;e<Math.min(n.length,r.length)&&n[e]===r[e];e+=1)i.push(n[e]);return i.join(`/`)}function n(n,r){let i=/* @__PURE__ */ new Map;for(let e of n){let t=r(e),n=t.indexOf(`/`),a=n===-1?``:t.slice(0,n),o=i.get(a);o===void 0?i.set(a,[e]):o.push(e)}let a=[];for(let[n,o]of i){let i=[...o].sort((e,t)=>r(e).localeCompare(r(t))),s=n===``?``:i.map(t=>e(r(t))).reduce(t);a.push({prefix:s,items:i})}return a.sort((e,t)=>e.prefix.localeCompare(t.prefix))}function r(e,t){return e===``?t:t.slice(e.length+1)}export{n as groupByDirectory,r as groupRowLabel};
2
+ //# sourceMappingURL=pathGroups.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pathGroups.mjs","names":[],"sources":["../../../../../../src/lib/pathGroups.ts"],"sourcesContent":["/**\n * The two-level grouping a changed-file list uses: one header per top-level\n * segment, each naming the deepest directory its files share.\n *\n * Two levels rather than a full tree: paths here run five and six segments\n * deep, so a node per segment spends more rows on directories than on the files\n * someone came to find. The header carries the shared run of directories and\n * each row carries what is left, so a file stays one row and the part that\n * distinguishes it stays readable.\n */\n\n/** One header row and the items under it. */\nexport interface PathGroup<T> {\n /** The shared directory the header names, or empty for files at the root. */\n prefix: string;\n items: T[];\n}\n\n/** The directory part of a relative path, or empty for a file at the root. */\nfunction parentDir(relPath: string): string {\n const cut = relPath.lastIndexOf('/');\n return cut === -1 ? '' : relPath.slice(0, cut);\n}\n\n/** The longest directory two paths share, compared segment by segment rather than character by character. */\nfunction commonDir(left: string, right: string): string {\n const leftParts = left.split('/');\n const rightParts = right.split('/');\n const shared: string[] = [];\n for (let index = 0; index < Math.min(leftParts.length, rightParts.length); index += 1) {\n if (leftParts[index] !== rightParts[index]) break;\n shared.push(leftParts[index]);\n }\n return shared.join('/');\n}\n\n/** Groups by top-level segment, ordered by path so a header's files sit together under it. */\nexport function groupByDirectory<T>(items: readonly T[], pathOf: (item: T) => string): PathGroup<T>[] {\n const buckets = new Map<string, T[]>();\n for (const item of items) {\n const relPath = pathOf(item);\n const cut = relPath.indexOf('/');\n const key = cut === -1 ? '' : relPath.slice(0, cut);\n const bucket = buckets.get(key);\n if (bucket === undefined) buckets.set(key, [item]);\n else bucket.push(item);\n }\n const groups: PathGroup<T>[] = [];\n for (const [key, bucket] of buckets) {\n const sorted = [...bucket].sort((left, right) => pathOf(left).localeCompare(pathOf(right)));\n // Root files have no directory to name, so they keep an empty header and\n // render their own paths in full.\n const prefix = key === '' ? '' : sorted.map((item) => parentDir(pathOf(item))).reduce(commonDir);\n groups.push({ prefix, items: sorted });\n }\n return groups.sort((left, right) => left.prefix.localeCompare(right.prefix));\n}\n\n/** What one row shows once its group's header has already said the shared part. */\nexport function groupRowLabel(prefix: string, relPath: string): string {\n return prefix === '' ? relPath : relPath.slice(prefix.length + 1);\n}\n"],"mappings":"AAmBA,SAAS,EAAU,EAAyB,CAC1C,IAAM,EAAM,EAAQ,YAAY,GAAG,EACnC,OAAO,IAAQ,GAAK,GAAK,EAAQ,MAAM,EAAG,CAAG,CAC/C,CAGA,SAAS,EAAU,EAAc,EAAuB,CACtD,IAAM,EAAY,EAAK,MAAM,GAAG,EAC1B,EAAa,EAAM,MAAM,GAAG,EAC5B,EAAmB,CAAC,EAC1B,IAAK,IAAI,EAAQ,EAAG,EAAQ,KAAK,IAAI,EAAU,OAAQ,EAAW,MAAM,GAClE,EAAU,KAAW,EAAW,GADqC,GAAS,EAElF,EAAO,KAAK,EAAU,EAAM,EAE9B,OAAO,EAAO,KAAK,GAAG,CACxB,CAGA,SAAgB,EAAoB,EAAqB,EAA6C,CACpG,IAAM,kBAAU,IAAI,IACpB,IAAK,IAAM,KAAQ,EAAO,CACxB,IAAM,EAAU,EAAO,CAAI,EACrB,EAAM,EAAQ,QAAQ,GAAG,EACzB,EAAM,IAAQ,GAAK,GAAK,EAAQ,MAAM,EAAG,CAAG,EAC5C,EAAS,EAAQ,IAAI,CAAG,EAC1B,IAAW,IAAA,GAAW,EAAQ,IAAI,EAAK,CAAC,CAAI,CAAC,EAC5C,EAAO,KAAK,CAAI,CACvB,CACA,IAAM,EAAyB,CAAC,EAChC,IAAK,GAAM,CAAC,EAAK,KAAW,EAAS,CACnC,IAAM,EAAS,CAAC,GAAG,CAAM,CAAC,CAAC,MAAM,EAAM,IAAU,EAAO,CAAI,CAAC,CAAC,cAAc,EAAO,CAAK,CAAC,CAAC,EAGpF,EAAS,IAAQ,GAAK,GAAK,EAAO,IAAK,GAAS,EAAU,EAAO,CAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAS,EAC/F,EAAO,KAAK,CAAE,SAAQ,MAAO,CAAO,CAAC,CACvC,CACA,OAAO,EAAO,MAAM,EAAM,IAAU,EAAK,OAAO,cAAc,EAAM,MAAM,CAAC,CAC7E,CAGA,SAAgB,EAAc,EAAgB,EAAyB,CACrE,OAAO,IAAW,GAAK,EAAU,EAAQ,MAAM,EAAO,OAAS,CAAC,CAClE"}
@@ -0,0 +1,40 @@
1
+ import { DiffHunk, DiffMarker, DiffSide, ReviewComment } from "../types/diff.mjs";
2
+ //#region src/lib/review.d.ts
3
+ /**
4
+ * Pure review logic shared by every surface that comments on a diff: sizing a
5
+ * gutter, deciding which side a selection is on, naming an anchor, and folding
6
+ * a set of notes into one message.
7
+ */
8
+ /** The widest line number in a diff, in characters, which sizes the gutter. */
9
+ export declare function diffGutterWidth(hunks: readonly DiffHunk[]): number;
10
+ /**
11
+ * The line range a set of touched rows covers, and the side it is on.
12
+ *
13
+ * Any context or added row puts the selection on the new side, and then the
14
+ * removed rows in it are ignored: their numbers belong to the other file and
15
+ * would stretch the range over lines that have nothing to do with it. Only a
16
+ * selection made entirely of removed rows lands on the old side.
17
+ */
18
+ export declare function diffRangeOf(rows: readonly {
19
+ marker: DiffMarker;
20
+ line: number;
21
+ }[]): {
22
+ side: DiffSide;
23
+ startLine: number;
24
+ endLine: number;
25
+ } | undefined;
26
+ /** Trims a quoted snippet to something a prompt can carry without drowning it. */
27
+ export declare function trimSnippet(snippet: string, maxLines?: number, maxChars?: number): string;
28
+ /** How a comment names the place it is about. New-side anchors keep the `path:line` form. */
29
+ export declare function reviewCommentAnchor(comment: ReviewComment): string;
30
+ /** The opening line of a review when the caller names no context of its own. */
31
+ export declare function defaultReviewHeading(count: number): string;
32
+ /**
33
+ * The one message a review sends.
34
+ *
35
+ * Every note goes in a single message rather than one each: N notes then cost
36
+ * one turn, and the agent sees the whole review before it changes anything.
37
+ */
38
+ export declare function buildReviewPrompt(comments: readonly ReviewComment[], heading?: string): string;
39
+ //#endregion
40
+ //# sourceMappingURL=review.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.d.mts","names":[],"sources":["../../../../../../src/lib/review.ts"],"mappings":";;;;;;;;wBASgB,gBAAgB,gBAAgB;;;;;;;;;wBAgBhC,YACd;EAAiB,QAAQ;EAAY;;EAClC,MAAM;EAAU;EAAmB;;;wBAUxB,YAAY,iBAAiB,mBAAe;;wBAQ5C,oBAAoB,SAAS;;wBAc7B,qBAAqB;;;;;;;wBAYrB,kBAAkB,mBAAmB,iBAAiB"}
@@ -0,0 +1,8 @@
1
+ function e(e){let t=1;for(let n of e)for(let e of n.rows)t=Math.max(t,String(e.line).length);return t}function t(e){let t=e.filter(e=>Number.isFinite(e.line)&&e.line>0),n=t.filter(e=>e.marker!==`-`),r=n.length>0?`new`:`old`,i=(n.length>0?n:t).map(e=>e.line);if(i.length!==0)return{side:r,startLine:Math.min(...i),endLine:Math.max(...i)}}function n(e,t=20,n=2e3){let r=e.split(`
2
+ `),i=(r.length>t?[...r.slice(0,t),`…`]:r).join(`
3
+ `);return i.length>n?`${i.slice(0,n)}…`:i}function r(e){if(e.startLine===void 0)return e.relPath;let t=e.endLine===void 0||e.endLine===e.startLine;return e.side===`old`?t?`${e.relPath} (removed line ${e.startLine})`:`${e.relPath} (removed lines ${e.startLine}-${e.endLine})`:t?`${e.relPath}:${e.startLine}`:`${e.relPath}:${e.startLine}-${e.endLine}`}function i(e){return e===1?`I left one review comment on a file you changed. Please address it.`:`I left ${e} review comments on files you changed. Please address them.`}function a(e,t){if(e.length===0)return``;let a=e.map(e=>{let t=n(e.snippet).split(`
4
+ `).map(e=>`> ${e}`).join(`
5
+ `);return`### ${r(e)}\n\n${t}\n\n${e.body.trim()}`}).join(`
6
+
7
+ `);return`${t??i(e.length)}\n\n${a}`}export{a as buildReviewPrompt,i as defaultReviewHeading,e as diffGutterWidth,t as diffRangeOf,r as reviewCommentAnchor,n as trimSnippet};
8
+ //# sourceMappingURL=review.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.mjs","names":[],"sources":["../../../../../../src/lib/review.ts"],"sourcesContent":["import type { DiffHunk, DiffMarker, DiffSide, ReviewComment } from '../types/diff';\n\n/**\n * Pure review logic shared by every surface that comments on a diff: sizing a\n * gutter, deciding which side a selection is on, naming an anchor, and folding\n * a set of notes into one message.\n */\n\n/** The widest line number in a diff, in characters, which sizes the gutter. */\nexport function diffGutterWidth(hunks: readonly DiffHunk[]): number {\n let widest = 1;\n for (const hunk of hunks) {\n for (const row of hunk.rows) widest = Math.max(widest, String(row.line).length);\n }\n return widest;\n}\n\n/**\n * The line range a set of touched rows covers, and the side it is on.\n *\n * Any context or added row puts the selection on the new side, and then the\n * removed rows in it are ignored: their numbers belong to the other file and\n * would stretch the range over lines that have nothing to do with it. Only a\n * selection made entirely of removed rows lands on the old side.\n */\nexport function diffRangeOf(\n rows: readonly { marker: DiffMarker; line: number }[],\n): { side: DiffSide; startLine: number; endLine: number } | undefined {\n const numbered = rows.filter((row) => Number.isFinite(row.line) && row.line > 0);\n const kept = numbered.filter((row) => row.marker !== '-');\n const side: DiffSide = kept.length > 0 ? 'new' : 'old';\n const lines = (kept.length > 0 ? kept : numbered).map((row) => row.line);\n if (lines.length === 0) return undefined;\n return { side, startLine: Math.min(...lines), endLine: Math.max(...lines) };\n}\n\n/** Trims a quoted snippet to something a prompt can carry without drowning it. */\nexport function trimSnippet(snippet: string, maxLines = 20, maxChars = 2000): string {\n const lines = snippet.split('\\n');\n const clipped = lines.length > maxLines ? [...lines.slice(0, maxLines), '…'] : lines;\n const text = clipped.join('\\n');\n return text.length > maxChars ? `${text.slice(0, maxChars)}…` : text;\n}\n\n/** How a comment names the place it is about. New-side anchors keep the `path:line` form. */\nexport function reviewCommentAnchor(comment: ReviewComment): string {\n if (comment.startLine === undefined) return comment.relPath;\n const single = comment.endLine === undefined || comment.endLine === comment.startLine;\n if (comment.side === 'old') {\n return single\n ? `${comment.relPath} (removed line ${comment.startLine})`\n : `${comment.relPath} (removed lines ${comment.startLine}-${comment.endLine})`;\n }\n return single\n ? `${comment.relPath}:${comment.startLine}`\n : `${comment.relPath}:${comment.startLine}-${comment.endLine}`;\n}\n\n/** The opening line of a review when the caller names no context of its own. */\nexport function defaultReviewHeading(count: number): string {\n return count === 1\n ? 'I left one review comment on a file you changed. Please address it.'\n : `I left ${count} review comments on files you changed. Please address them.`;\n}\n\n/**\n * The one message a review sends.\n *\n * Every note goes in a single message rather than one each: N notes then cost\n * one turn, and the agent sees the whole review before it changes anything.\n */\nexport function buildReviewPrompt(comments: readonly ReviewComment[], heading?: string): string {\n if (comments.length === 0) return '';\n const body = comments\n .map((comment) => {\n const quoted = trimSnippet(comment.snippet)\n .split('\\n')\n .map((line) => `> ${line}`)\n .join('\\n');\n return `### ${reviewCommentAnchor(comment)}\\n\\n${quoted}\\n\\n${comment.body.trim()}`;\n })\n .join('\\n\\n');\n return `${heading ?? defaultReviewHeading(comments.length)}\\n\\n${body}`;\n}\n"],"mappings":"AASA,SAAgB,EAAgB,EAAoC,CAClE,IAAI,EAAS,EACb,IAAK,IAAM,KAAQ,EACjB,IAAK,IAAM,KAAO,EAAK,KAAM,EAAS,KAAK,IAAI,EAAQ,OAAO,EAAI,IAAI,CAAC,CAAC,MAAM,EAEhF,OAAO,CACT,CAUA,SAAgB,EACd,EACoE,CACpE,IAAM,EAAW,EAAK,OAAQ,GAAQ,OAAO,SAAS,EAAI,IAAI,GAAK,EAAI,KAAO,CAAC,EACzE,EAAO,EAAS,OAAQ,GAAQ,EAAI,SAAW,GAAG,EAClD,EAAiB,EAAK,OAAS,EAAI,MAAQ,MAC3C,GAAS,EAAK,OAAS,EAAI,EAAO,EAAA,CAAU,IAAK,GAAQ,EAAI,IAAI,EACnE,KAAM,SAAW,EACrB,MAAO,CAAE,OAAM,UAAW,KAAK,IAAI,GAAG,CAAK,EAAG,QAAS,KAAK,IAAI,GAAG,CAAK,CAAE,CAC5E,CAGA,SAAgB,EAAY,EAAiB,EAAW,GAAI,EAAW,IAAc,CACnF,IAAM,EAAQ,EAAQ,MAAM;CAAI,EAE1B,GADU,EAAM,OAAS,EAAW,CAAC,GAAG,EAAM,MAAM,EAAG,CAAQ,EAAG,GAAG,EAAI,EAAA,CAC1D,KAAK;CAAI,EAC9B,OAAO,EAAK,OAAS,EAAW,GAAG,EAAK,MAAM,EAAG,CAAQ,EAAE,GAAK,CAClE,CAGA,SAAgB,EAAoB,EAAgC,CAClE,GAAI,EAAQ,YAAc,IAAA,GAAW,OAAO,EAAQ,QACpD,IAAM,EAAS,EAAQ,UAAY,IAAA,IAAa,EAAQ,UAAY,EAAQ,UAM5E,OALI,EAAQ,OAAS,MACZ,EACH,GAAG,EAAQ,QAAQ,iBAAiB,EAAQ,UAAU,GACtD,GAAG,EAAQ,QAAQ,kBAAkB,EAAQ,UAAU,GAAG,EAAQ,QAAQ,GAEzE,EACH,GAAG,EAAQ,QAAQ,GAAG,EAAQ,YAC9B,GAAG,EAAQ,QAAQ,GAAG,EAAQ,UAAU,GAAG,EAAQ,SACzD,CAGA,SAAgB,EAAqB,EAAuB,CAC1D,OAAO,IAAU,EACb,sEACA,UAAU,EAAM,4DACtB,CAQA,SAAgB,EAAkB,EAAoC,EAA0B,CAC9F,GAAI,EAAS,SAAW,EAAG,MAAO,GAClC,IAAM,EAAO,EACV,IAAK,GAAY,CAChB,IAAM,EAAS,EAAY,EAAQ,OAAO,CAAC,CACxC,MAAM;CAAI,CAAC,CACX,IAAK,GAAS,KAAK,GAAM,CAAC,CAC1B,KAAK;CAAI,EACZ,MAAO,OAAO,EAAoB,CAAO,EAAE,MAAM,EAAO,MAAM,EAAQ,KAAK,KAAK,GAClF,CAAC,CAAC,CACD,KAAK;;CAAM,EACd,MAAO,GAAG,GAAW,EAAqB,EAAS,MAAM,EAAE,MAAM,GACnE"}
@@ -0,0 +1,46 @@
1
+ //#region src/types/diff.d.ts
2
+ /**
3
+ * The shapes a diff and a review comment take on screen.
4
+ *
5
+ * A row carries one line number, and which file it belongs to follows from the
6
+ * marker: the new file's for context and additions, the old file's for
7
+ * removals. That is what lets a comment on a removed line point at the old
8
+ * file instead of at an unrelated line of the new one.
9
+ */
10
+ /** Which file a line number belongs to. */
11
+ export type DiffSide = 'old' | 'new';
12
+ export type DiffMarker = '+' | '-' | ' ';
13
+ /** One line of a diff: new-side number for context and additions, old-side for removals. */
14
+ export interface DiffRow {
15
+ marker: DiffMarker;
16
+ line: number;
17
+ content: string;
18
+ }
19
+ /** A run of changed lines with its context. Hunks arrive apart; the view draws the gap. */
20
+ export interface DiffHunk {
21
+ start: number;
22
+ rows: readonly DiffRow[];
23
+ }
24
+ /** What a reader picked: a line range on one side, and the text they highlighted. */
25
+ export interface DiffSelection {
26
+ side: DiffSide;
27
+ startLine: number;
28
+ endLine: number;
29
+ snippet: string;
30
+ }
31
+ /** One review note, anchored to lines on one side, or to a quoted selection with no lines. */
32
+ export interface ReviewComment {
33
+ id: string;
34
+ /** The file's identity for the owner: an absolute path, or the repository-relative one. */
35
+ path: string;
36
+ /** What the message names the file by. */
37
+ relPath: string;
38
+ /** Absent means the new side, which is what every anchor meant before sides existed. */
39
+ side?: DiffSide;
40
+ startLine?: number;
41
+ endLine?: number;
42
+ snippet: string;
43
+ body: string;
44
+ }
45
+ //#endregion
46
+ //# sourceMappingURL=diff.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff.d.mts","names":[],"sources":["../../../../../../src/types/diff.ts"],"mappings":";;;;;;;;;;YAUY;YAEA;;iBAGK;EACf,QAAQ;EACR;EACA;;;iBAIe;EACf;EACA,eAAe;;;iBAIA;EACf,MAAM;EACN;EACA;EACA;;;iBAIe;EACf;;EAEA;;EAEA;;EAEA,OAAO;EACP;EACA;EACA;EACA"}
@@ -0,0 +1,2 @@
1
+ const e=require("../lib/cn.cjs"),t=require("./Button.cjs"),n=require("../lib/review.cjs");let r=require("react/jsx-runtime"),i=require("react");const a={"+":`bg-doom-tint-green text-doom-green`,"-":`bg-doom-tint-red text-doom-red`," ":`text-doom-dim`};function o(e){return e===`+`||e===`-`||e===` `}function s({hunks:s,testId:c,onSelect:l,renderAfterRow:u,className:d}){let f=n.diffGutterWidth(s);return s.length===0?/* @__PURE__ */ (0,r.jsx)(`p`,{"data-testid":`${c}-empty`,className:`px-2 py-1 text-xs text-doom-faint`,children:`no lines changed`}):/* @__PURE__ */ (0,r.jsx)(`div`,{"data-testid":c,"data-diff-surface":c,onMouseUp:()=>{if(l===void 0)return;let e=globalThis.getSelection?.(),t=e?.toString()??``;if(t.trim()===``)return;let r=[...document.querySelectorAll(`[data-diff-surface="${c}"] [data-diff-line]`)].filter(t=>e?.containsNode(t,!0)===!0).map(e=>({marker:e.dataset.diffMarker,line:Number(e.dataset.diffLine)})).filter(e=>o(e.marker)),i=n.diffRangeOf(r);i!==void 0&&l({...i,snippet:t})},className:e.cn(`overflow-x-auto font-mono text-sm leading-normal`,d),children:s.map((n,o)=>/* @__PURE__ */ (0,r.jsxs)(`div`,{children:[o>0?/* @__PURE__ */ (0,r.jsxs)(`div`,{className:`flex items-center gap-2 px-2 py-0.5 text-2xs text-doom-faint`,children:[/* @__PURE__ */ (0,r.jsx)(`span`,{className:`h-px flex-1 bg-doom-border-soft`}),/* @__PURE__ */ (0,r.jsx)(`span`,{children:`⋯`}),/* @__PURE__ */ (0,r.jsx)(`span`,{className:`h-px flex-1 bg-doom-border-soft`})]}):null,n.rows.map((n,o)=>/* @__PURE__ */ (0,r.jsxs)(i.Fragment,{children:[/* @__PURE__ */ (0,r.jsxs)(`div`,{"data-diff-line":n.line,"data-diff-marker":n.marker,className:e.cn(`flex whitespace-pre`,a[n.marker]),children:[l===void 0?/* @__PURE__ */ (0,r.jsx)(`span`,{"aria-hidden":!0,className:`shrink-0 select-none pr-2 pl-2 text-right text-doom-faint`,style:{width:`${f+2}ch`},children:n.line}):/* @__PURE__ */ (0,r.jsx)(t.Button,{variant:`ghost`,size:`xs`,"data-diff-gutter":n.line,"aria-label":`comment on ${n.marker===`-`?`removed `:``}line ${n.line}`,onClick:()=>l({side:n.marker===`-`?`old`:`new`,startLine:n.line,endLine:n.line,snippet:n.content}),className:`h-auto min-h-0 min-w-0 shrink-0 select-none justify-end rounded-none py-0 pr-2 pl-2 font-normal text-sm text-doom-faint hover:bg-transparent hover:text-doom-blue`,style:{width:`${f+2}ch`},children:n.line}),/* @__PURE__ */ (0,r.jsx)(`span`,{className:`shrink-0 select-none pr-1`,children:n.marker}),/* @__PURE__ */ (0,r.jsx)(`span`,{className:`min-w-0`,children:n.content})]}),u?.(n)]},`${n.marker}-${n.line}-${o}`))]},`${n.start}-${o}`))})}exports.DiffView=s;
2
+ //# sourceMappingURL=DiffView.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DiffView.cjs","names":["diffGutterWidth","diffRangeOf","cn","Fragment","Button"],"sources":["../../../src/components/DiffView.tsx"],"sourcesContent":["import { Fragment, type ReactNode } from 'react';\n\nimport { cn } from '../lib/cn';\nimport { diffGutterWidth, diffRangeOf } from '../lib/review';\nimport type { DiffHunk, DiffMarker, DiffRow, DiffSelection } from '../types/diff';\nimport { Button } from './Button';\n\n/**\n * A diff, drawn the way this cockpit draws every other one: a numbered gutter\n * and a background wash per row, so a change reads at a glance rather than by\n * hunting for leading punctuation.\n *\n * Hunks arrive apart rather than joined by an elision marker, so the gap\n * between two of them is a rule the component draws, not a line it has to\n * recognise in a string.\n *\n * A reader comments two ways: by highlighting text, which reports the lines the\n * highlight touches, or by clicking a line number, which reports that one line.\n * Either way the selection names its side, so a note on a removed line points\n * at the old file rather than at whatever the new file has on that number.\n */\n\nconst ROW_TONE: Readonly<Record<DiffMarker, string>> = {\n '+': 'bg-doom-tint-green text-doom-green',\n '-': 'bg-doom-tint-red text-doom-red',\n ' ': 'text-doom-dim',\n};\n\nexport interface DiffViewProps {\n hunks: readonly DiffHunk[];\n /** Marks the surface so a test and a selection handler can find it. Unique per diff on a page. */\n testId: string;\n /** Called with the selected text, the lines it covers, and their side. Enables line-number clicks. */\n onSelect?: (selection: DiffSelection) => void;\n /** Drawn under one row, full width: inline comments and an open draft go here. */\n renderAfterRow?: (row: DiffRow) => ReactNode;\n className?: string;\n}\n\nfunction isMarker(value: string | undefined): value is DiffMarker {\n return value === '+' || value === '-' || value === ' ';\n}\n\nexport function DiffView({ hunks, testId, onSelect, renderAfterRow, className }: DiffViewProps) {\n const gutter = diffGutterWidth(hunks);\n\n /**\n * Turns whatever the reader highlighted into a line range. The rows carry\n * their own numbers and markers, so the range comes from the rows the\n * selection touches rather than from counting newlines in the rendered text.\n */\n const handleSelect = (): void => {\n if (onSelect === undefined) return;\n const selection = globalThis.getSelection?.();\n const text = selection?.toString() ?? '';\n if (text.trim() === '') return;\n const rows = [...document.querySelectorAll<HTMLElement>(`[data-diff-surface=\"${testId}\"] [data-diff-line]`)];\n const touched = rows\n .filter((row) => selection?.containsNode(row, true) === true)\n .map((row) => ({ marker: row.dataset.diffMarker, line: Number(row.dataset.diffLine) }))\n .filter((row): row is { marker: DiffMarker; line: number } => isMarker(row.marker));\n const range = diffRangeOf(touched);\n if (range !== undefined) onSelect({ ...range, snippet: text });\n };\n\n if (hunks.length === 0) {\n return (\n <p data-testid={`${testId}-empty`} className=\"px-2 py-1 text-xs text-doom-faint\">\n no lines changed\n </p>\n );\n }\n\n return (\n <div\n data-testid={testId}\n data-diff-surface={testId}\n onMouseUp={handleSelect}\n className={cn('overflow-x-auto font-mono text-sm leading-normal', className)}\n >\n {hunks.map((hunk, position) => (\n <div key={`${hunk.start}-${position}`}>\n {position > 0 ? (\n <div className=\"flex items-center gap-2 px-2 py-0.5 text-2xs text-doom-faint\">\n <span className=\"h-px flex-1 bg-doom-border-soft\" />\n <span>⋯</span>\n <span className=\"h-px flex-1 bg-doom-border-soft\" />\n </div>\n ) : null}\n {hunk.rows.map((row, offset) => (\n <Fragment key={`${row.marker}-${row.line}-${offset}`}>\n <div\n data-diff-line={row.line}\n data-diff-marker={row.marker}\n className={cn('flex whitespace-pre', ROW_TONE[row.marker])}\n >\n {onSelect === undefined ? (\n <span\n aria-hidden\n className=\"shrink-0 select-none pr-2 pl-2 text-right text-doom-faint\"\n style={{ width: `${gutter + 2}ch` }}\n >\n {row.line}\n </span>\n ) : (\n <Button\n variant=\"ghost\"\n size=\"xs\"\n data-diff-gutter={row.line}\n aria-label={`comment on ${row.marker === '-' ? 'removed ' : ''}line ${row.line}`}\n onClick={() =>\n onSelect({\n side: row.marker === '-' ? 'old' : 'new',\n startLine: row.line,\n endLine: row.line,\n snippet: row.content,\n })\n }\n className=\"h-auto min-h-0 min-w-0 shrink-0 select-none justify-end rounded-none py-0 pr-2 pl-2 font-normal text-sm text-doom-faint hover:bg-transparent hover:text-doom-blue\"\n style={{ width: `${gutter + 2}ch` }}\n >\n {row.line}\n </Button>\n )}\n <span className=\"shrink-0 select-none pr-1\">{row.marker}</span>\n <span className=\"min-w-0\">{row.content}</span>\n </div>\n {renderAfterRow?.(row)}\n </Fragment>\n ))}\n </div>\n ))}\n </div>\n );\n}\n"],"mappings":"gJAsBA,MAAM,EAAiD,CACrD,IAAK,qCACL,IAAK,iCACL,IAAK,eACP,EAaA,SAAS,EAAS,EAAgD,CAChE,OAAO,IAAU,KAAO,IAAU,KAAO,IAAU,GACrD,CAEA,SAAgB,EAAS,CAAE,QAAO,SAAQ,WAAU,iBAAgB,aAA4B,CAC9F,IAAM,EAASA,EAAAA,gBAAgB,CAAK,EA6BpC,OARI,EAAM,SAAW,EAEjB,iBAAA,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,cAAa,GAAG,EAAO,QAAS,UAAU,oCAAoC,SAAA,kBAE9E,CAAA,EAKL,iBAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CACE,cAAa,EACb,oBAAmB,EACnB,cA1B6B,CAC/B,GAAI,IAAa,IAAA,GAAW,OAC5B,IAAM,EAAY,WAAW,eAAe,EACtC,EAAO,GAAW,SAAS,GAAK,GACtC,GAAI,EAAK,KAAK,IAAM,GAAI,OAExB,IAAM,EAAU,CADF,GAAG,SAAS,iBAA8B,uBAAuB,EAAO,oBAAoB,CACvF,CAAC,CACjB,OAAQ,GAAQ,GAAW,aAAa,EAAK,EAAI,IAAM,EAAI,CAAC,CAC5D,IAAK,IAAS,CAAE,OAAQ,EAAI,QAAQ,WAAY,KAAM,OAAO,EAAI,QAAQ,QAAQ,CAAE,EAAE,CAAC,CACtF,OAAQ,GAAqD,EAAS,EAAI,MAAM,CAAC,EAC9E,EAAQC,EAAAA,YAAY,CAAO,EAC7B,IAAU,IAAA,IAAW,EAAS,CAAE,GAAG,EAAO,QAAS,CAAK,CAAC,CAC/D,EAeI,UAAWC,EAAAA,GAAG,mDAAoD,CAAS,EAE1E,SAAA,EAAM,KAAK,EAAM,IAChB,iBAAA,EAAA,EAAA,KAAA,CAAC,MAAD,CAAA,SAAA,CACG,EAAW,EACV,iBAAA,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,+DAAf,SAAA,CACE,iBAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,iCAAmC,CAAA,EACnD,iBAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CAAA,SAAM,GAAO,CAAA,EACb,iBAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,iCAAmC,CAAA,CAChD,CACH,CAAA,EAAA,KACH,EAAK,KAAK,KAAK,EAAK,IACnB,iBAAA,EAAA,EAAA,KAAA,CAACC,EAAAA,SAAD,CAAA,SAAA,CACE,iBAAA,EAAA,EAAA,KAAA,CAAC,MAAD,CACE,iBAAgB,EAAI,KACpB,mBAAkB,EAAI,OACtB,UAAWD,EAAAA,GAAG,sBAAuB,EAAS,EAAI,OAAO,EAH3D,SAAA,CAKG,IAAa,IAAA,GACZ,iBAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CACE,cAAA,GACA,UAAU,4DACV,MAAO,CAAE,MAAO,GAAG,EAAS,EAAE,GAAI,EAEjC,SAAA,EAAI,IACD,CAAA,EAEN,iBAAA,EAAA,EAAA,IAAA,CAACE,EAAAA,OAAD,CACE,QAAQ,QACR,KAAK,KACL,mBAAkB,EAAI,KACtB,aAAY,cAAc,EAAI,SAAW,IAAM,WAAa,GAAG,OAAO,EAAI,OAC1E,YACE,EAAS,CACP,KAAM,EAAI,SAAW,IAAM,MAAQ,MACnC,UAAW,EAAI,KACf,QAAS,EAAI,KACb,QAAS,EAAI,OACf,CAAC,EAEH,UAAU,oKACV,MAAO,CAAE,MAAO,GAAG,EAAS,EAAE,GAAI,EAEjC,SAAA,EAAI,IACC,CAAA,EAEV,iBAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,4BAA6B,SAAA,EAAI,MAAa,CAAA,EAC9D,iBAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,UAAW,SAAA,EAAI,OAAc,CAAA,CAC1C,CACJ,CAAA,EAAA,IAAiB,CAAG,CACb,CAAA,EAtCK,GAAG,EAAI,OAAO,GAAG,EAAI,KAAK,GAAG,GAsClC,CACX,CACE,CAAA,EAjDK,GAAG,EAAK,MAAM,GAAG,GAiDtB,CACN,CACE,CAAA,CAET"}
@@ -0,0 +1,2 @@
1
+ const e=require("./Button.cjs"),t=require("../lib/review.cjs"),n=require("./Textarea.cjs");let r=require("react/jsx-runtime"),i=require("react");function a(e,t,n){if(e===void 0)return`no line anchor: this selection came from the rendered preview`;let r=n===`old`?`removed `:``;return t===void 0||t===e?`${r}line ${e}`:`${r}lines ${e} to ${t}`}function o({snippet:o,startLine:s,endLine:c,side:l,onSubmit:u,onCancel:d,testIdPrefix:f=`review-comment`}){let[p,m]=(0,i.useState)(``);return/* @__PURE__ */ (0,r.jsxs)(`div`,{"data-testid":`${f}-draft`,className:`flex flex-col gap-1.5 border-t border-doom-border p-2`,children:[/* @__PURE__ */ (0,r.jsx)(`p`,{className:`text-2xs text-doom-faint`,children:a(s,c,l)}),/* @__PURE__ */ (0,r.jsx)(`pre`,{className:`max-h-24 overflow-y-auto whitespace-pre-wrap break-words rounded border border-doom-border-soft bg-doom-deep p-1.5 font-mono text-xs text-doom-dim`,children:t.trimSnippet(o,8,600)}),/* @__PURE__ */ (0,r.jsx)(n.Textarea,{"data-testid":`${f}-body`,value:p,rows:3,autoFocus:!0,placeholder:`what should change here?`,onChange:e=>m(e.target.value),onKeyDown:e=>{e.key===`Escape`&&d(),e.key===`Enter`&&(e.metaKey||e.ctrlKey)&&(e.preventDefault(),p.trim()!==``&&u(p))},className:`text-sm`}),/* @__PURE__ */ (0,r.jsxs)(`div`,{className:`flex items-center gap-1.5`,children:[/* @__PURE__ */ (0,r.jsx)(e.Button,{variant:`outline`,size:`xs`,"data-testid":`${f}-add`,disabled:p.trim()===``,onClick:()=>u(p),className:`text-2xs`,children:`add comment`}),/* @__PURE__ */ (0,r.jsx)(e.Button,{variant:`ghost`,size:`xs`,"data-testid":`${f}-cancel`,onClick:d,className:`text-2xs`,children:`cancel`}),/* @__PURE__ */ (0,r.jsx)(`span`,{className:`text-2xs text-doom-faint`,children:`⌘⏎ to add`})]})]})}exports.ReviewCommentDraft=o;
2
+ //# sourceMappingURL=ReviewCommentDraft.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReviewCommentDraft.cjs","names":["useState","trimSnippet","Textarea","Button"],"sources":["../../../src/components/ReviewCommentDraft.tsx"],"sourcesContent":["import { useState } from 'react';\n\nimport { trimSnippet } from '../lib/review';\nimport type { DiffSide } from '../types/diff';\nimport { Button } from './Button';\nimport { Textarea } from './Textarea';\n\n/**\n * The box a selection raises: what was highlighted, and a note about it.\n *\n * The note is held here rather than in a store because it belongs to one open\n * box and dies with it; only a submitted comment is worth keeping, and the\n * owner decides where that goes.\n */\nexport interface ReviewCommentDraftProps {\n snippet: string;\n /** Absent when the selection came from somewhere lines cannot be recovered, such as a rendered preview. */\n startLine?: number;\n endLine?: number;\n /** Absent means the new side. */\n side?: DiffSide;\n onSubmit: (body: string) => void;\n onCancel: () => void;\n /** Prefix for the test ids: `<prefix>-draft`, `-body`, `-add`, `-cancel`. */\n testIdPrefix?: string;\n}\n\nfunction rangeLabel(startLine: number | undefined, endLine: number | undefined, side: DiffSide | undefined): string {\n if (startLine === undefined) return 'no line anchor: this selection came from the rendered preview';\n const removed = side === 'old' ? 'removed ' : '';\n return endLine === undefined || endLine === startLine\n ? `${removed}line ${startLine}`\n : `${removed}lines ${startLine} to ${endLine}`;\n}\n\nexport function ReviewCommentDraft({\n snippet,\n startLine,\n endLine,\n side,\n onSubmit,\n onCancel,\n testIdPrefix = 'review-comment',\n}: ReviewCommentDraftProps) {\n const [body, setBody] = useState('');\n\n return (\n <div data-testid={`${testIdPrefix}-draft`} className=\"flex flex-col gap-1.5 border-t border-doom-border p-2\">\n <p className=\"text-2xs text-doom-faint\">{rangeLabel(startLine, endLine, side)}</p>\n <pre className=\"max-h-24 overflow-y-auto whitespace-pre-wrap break-words rounded border border-doom-border-soft bg-doom-deep p-1.5 font-mono text-xs text-doom-dim\">\n {trimSnippet(snippet, 8, 600)}\n </pre>\n <Textarea\n data-testid={`${testIdPrefix}-body`}\n value={body}\n rows={3}\n autoFocus\n placeholder=\"what should change here?\"\n onChange={(event) => setBody(event.target.value)}\n onKeyDown={(event) => {\n if (event.key === 'Escape') onCancel();\n if (event.key !== 'Enter' || !(event.metaKey || event.ctrlKey)) return;\n event.preventDefault();\n if (body.trim() !== '') onSubmit(body);\n }}\n className=\"text-sm\"\n />\n <div className=\"flex items-center gap-1.5\">\n <Button\n variant=\"outline\"\n size=\"xs\"\n data-testid={`${testIdPrefix}-add`}\n disabled={body.trim() === ''}\n onClick={() => onSubmit(body)}\n className=\"text-2xs\"\n >\n add comment\n </Button>\n <Button\n variant=\"ghost\"\n size=\"xs\"\n data-testid={`${testIdPrefix}-cancel`}\n onClick={onCancel}\n className=\"text-2xs\"\n >\n cancel\n </Button>\n <span className=\"text-2xs text-doom-faint\">⌘⏎ to add</span>\n </div>\n </div>\n );\n}\n"],"mappings":"iJA2BA,SAAS,EAAW,EAA+B,EAA6B,EAAoC,CAClH,GAAI,IAAc,IAAA,GAAW,MAAO,gEACpC,IAAM,EAAU,IAAS,MAAQ,WAAa,GAC9C,OAAO,IAAY,IAAA,IAAa,IAAY,EACxC,GAAG,EAAQ,OAAO,IAClB,GAAG,EAAQ,QAAQ,EAAU,MAAM,GACzC,CAEA,SAAgB,EAAmB,CACjC,UACA,YACA,UACA,OACA,WACA,WACA,eAAe,kBACW,CAC1B,GAAM,CAAC,EAAM,IAAA,EAAWA,EAAAA,SAAAA,CAAS,EAAE,EAEnC,MACE,iBAAA,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,cAAa,GAAG,EAAa,QAAS,UAAU,wDAArD,SAAA,CACE,iBAAA,EAAA,EAAA,IAAA,CAAC,IAAD,CAAG,UAAU,2BAA4B,SAAA,EAAW,EAAW,EAAS,CAAI,CAAK,CAAA,EACjF,iBAAA,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,UAAU,qJACZC,SAAAA,EAAAA,YAAY,EAAS,EAAG,GAAG,CACzB,CAAA,EACL,iBAAA,EAAA,EAAA,IAAA,CAACC,EAAAA,SAAD,CACE,cAAa,GAAG,EAAa,OAC7B,MAAO,EACP,KAAM,EACN,UAAA,GACA,YAAY,2BACZ,SAAW,GAAU,EAAQ,EAAM,OAAO,KAAK,EAC/C,UAAY,GAAU,CAChB,EAAM,MAAQ,UAAU,EAAS,EACjC,EAAM,MAAQ,UAAa,EAAM,SAAW,EAAM,WACtD,EAAM,eAAe,EACjB,EAAK,KAAK,IAAM,IAAI,EAAS,CAAI,EACvC,EACA,UAAU,SACX,CAAA,EACD,iBAAA,EAAA,EAAA,KAAA,CAAC,MAAD,CAAK,UAAU,4BAAf,SAAA,CACE,iBAAA,EAAA,EAAA,IAAA,CAACC,EAAAA,OAAD,CACE,QAAQ,UACR,KAAK,KACL,cAAa,GAAG,EAAa,MAC7B,SAAU,EAAK,KAAK,IAAM,GAC1B,YAAe,EAAS,CAAI,EAC5B,UAAU,WACX,SAAA,aAEO,CAAA,EACR,iBAAA,EAAA,EAAA,IAAA,CAACA,EAAAA,OAAD,CACE,QAAQ,QACR,KAAK,KACL,cAAa,GAAG,EAAa,SAC7B,QAAS,EACT,UAAU,WACX,SAAA,QAEO,CAAA,EACR,iBAAA,EAAA,EAAA,IAAA,CAAC,OAAD,CAAM,UAAU,2BAA2B,SAAA,WAAe,CAAA,CACvD,GACF,GAET"}
@@ -0,0 +1,2 @@
1
+ function e(e){let t=e.lastIndexOf(`/`);return t===-1?``:e.slice(0,t)}function t(e,t){let n=e.split(`/`),r=t.split(`/`),i=[];for(let e=0;e<Math.min(n.length,r.length)&&n[e]===r[e];e+=1)i.push(n[e]);return i.join(`/`)}function n(n,r){let i=/* @__PURE__ */ new Map;for(let e of n){let t=r(e),n=t.indexOf(`/`),a=n===-1?``:t.slice(0,n),o=i.get(a);o===void 0?i.set(a,[e]):o.push(e)}let a=[];for(let[n,o]of i){let i=[...o].sort((e,t)=>r(e).localeCompare(r(t))),s=n===``?``:i.map(t=>e(r(t))).reduce(t);a.push({prefix:s,items:i})}return a.sort((e,t)=>e.prefix.localeCompare(t.prefix))}function r(e,t){return e===``?t:t.slice(e.length+1)}exports.groupByDirectory=n,exports.groupRowLabel=r;
2
+ //# sourceMappingURL=pathGroups.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pathGroups.cjs","names":[],"sources":["../../../src/lib/pathGroups.ts"],"sourcesContent":["/**\n * The two-level grouping a changed-file list uses: one header per top-level\n * segment, each naming the deepest directory its files share.\n *\n * Two levels rather than a full tree: paths here run five and six segments\n * deep, so a node per segment spends more rows on directories than on the files\n * someone came to find. The header carries the shared run of directories and\n * each row carries what is left, so a file stays one row and the part that\n * distinguishes it stays readable.\n */\n\n/** One header row and the items under it. */\nexport interface PathGroup<T> {\n /** The shared directory the header names, or empty for files at the root. */\n prefix: string;\n items: T[];\n}\n\n/** The directory part of a relative path, or empty for a file at the root. */\nfunction parentDir(relPath: string): string {\n const cut = relPath.lastIndexOf('/');\n return cut === -1 ? '' : relPath.slice(0, cut);\n}\n\n/** The longest directory two paths share, compared segment by segment rather than character by character. */\nfunction commonDir(left: string, right: string): string {\n const leftParts = left.split('/');\n const rightParts = right.split('/');\n const shared: string[] = [];\n for (let index = 0; index < Math.min(leftParts.length, rightParts.length); index += 1) {\n if (leftParts[index] !== rightParts[index]) break;\n shared.push(leftParts[index]);\n }\n return shared.join('/');\n}\n\n/** Groups by top-level segment, ordered by path so a header's files sit together under it. */\nexport function groupByDirectory<T>(items: readonly T[], pathOf: (item: T) => string): PathGroup<T>[] {\n const buckets = new Map<string, T[]>();\n for (const item of items) {\n const relPath = pathOf(item);\n const cut = relPath.indexOf('/');\n const key = cut === -1 ? '' : relPath.slice(0, cut);\n const bucket = buckets.get(key);\n if (bucket === undefined) buckets.set(key, [item]);\n else bucket.push(item);\n }\n const groups: PathGroup<T>[] = [];\n for (const [key, bucket] of buckets) {\n const sorted = [...bucket].sort((left, right) => pathOf(left).localeCompare(pathOf(right)));\n // Root files have no directory to name, so they keep an empty header and\n // render their own paths in full.\n const prefix = key === '' ? '' : sorted.map((item) => parentDir(pathOf(item))).reduce(commonDir);\n groups.push({ prefix, items: sorted });\n }\n return groups.sort((left, right) => left.prefix.localeCompare(right.prefix));\n}\n\n/** What one row shows once its group's header has already said the shared part. */\nexport function groupRowLabel(prefix: string, relPath: string): string {\n return prefix === '' ? relPath : relPath.slice(prefix.length + 1);\n}\n"],"mappings":"AAmBA,SAAS,EAAU,EAAyB,CAC1C,IAAM,EAAM,EAAQ,YAAY,GAAG,EACnC,OAAO,IAAQ,GAAK,GAAK,EAAQ,MAAM,EAAG,CAAG,CAC/C,CAGA,SAAS,EAAU,EAAc,EAAuB,CACtD,IAAM,EAAY,EAAK,MAAM,GAAG,EAC1B,EAAa,EAAM,MAAM,GAAG,EAC5B,EAAmB,CAAC,EAC1B,IAAK,IAAI,EAAQ,EAAG,EAAQ,KAAK,IAAI,EAAU,OAAQ,EAAW,MAAM,GAClE,EAAU,KAAW,EAAW,GADqC,GAAS,EAElF,EAAO,KAAK,EAAU,EAAM,EAE9B,OAAO,EAAO,KAAK,GAAG,CACxB,CAGA,SAAgB,EAAoB,EAAqB,EAA6C,CACpG,IAAM,kBAAU,IAAI,IACpB,IAAK,IAAM,KAAQ,EAAO,CACxB,IAAM,EAAU,EAAO,CAAI,EACrB,EAAM,EAAQ,QAAQ,GAAG,EACzB,EAAM,IAAQ,GAAK,GAAK,EAAQ,MAAM,EAAG,CAAG,EAC5C,EAAS,EAAQ,IAAI,CAAG,EAC1B,IAAW,IAAA,GAAW,EAAQ,IAAI,EAAK,CAAC,CAAI,CAAC,EAC5C,EAAO,KAAK,CAAI,CACvB,CACA,IAAM,EAAyB,CAAC,EAChC,IAAK,GAAM,CAAC,EAAK,KAAW,EAAS,CACnC,IAAM,EAAS,CAAC,GAAG,CAAM,CAAC,CAAC,MAAM,EAAM,IAAU,EAAO,CAAI,CAAC,CAAC,cAAc,EAAO,CAAK,CAAC,CAAC,EAGpF,EAAS,IAAQ,GAAK,GAAK,EAAO,IAAK,GAAS,EAAU,EAAO,CAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAS,EAC/F,EAAO,KAAK,CAAE,SAAQ,MAAO,CAAO,CAAC,CACvC,CACA,OAAO,EAAO,MAAM,EAAM,IAAU,EAAK,OAAO,cAAc,EAAM,MAAM,CAAC,CAC7E,CAGA,SAAgB,EAAc,EAAgB,EAAyB,CACrE,OAAO,IAAW,GAAK,EAAU,EAAQ,MAAM,EAAO,OAAS,CAAC,CAClE"}
@@ -0,0 +1,8 @@
1
+ function e(e){let t=1;for(let n of e)for(let e of n.rows)t=Math.max(t,String(e.line).length);return t}function t(e){let t=e.filter(e=>Number.isFinite(e.line)&&e.line>0),n=t.filter(e=>e.marker!==`-`),r=n.length>0?`new`:`old`,i=(n.length>0?n:t).map(e=>e.line);if(i.length!==0)return{side:r,startLine:Math.min(...i),endLine:Math.max(...i)}}function n(e,t=20,n=2e3){let r=e.split(`
2
+ `),i=(r.length>t?[...r.slice(0,t),`…`]:r).join(`
3
+ `);return i.length>n?`${i.slice(0,n)}…`:i}function r(e){if(e.startLine===void 0)return e.relPath;let t=e.endLine===void 0||e.endLine===e.startLine;return e.side===`old`?t?`${e.relPath} (removed line ${e.startLine})`:`${e.relPath} (removed lines ${e.startLine}-${e.endLine})`:t?`${e.relPath}:${e.startLine}`:`${e.relPath}:${e.startLine}-${e.endLine}`}function i(e){return e===1?`I left one review comment on a file you changed. Please address it.`:`I left ${e} review comments on files you changed. Please address them.`}function a(e,t){if(e.length===0)return``;let a=e.map(e=>{let t=n(e.snippet).split(`
4
+ `).map(e=>`> ${e}`).join(`
5
+ `);return`### ${r(e)}\n\n${t}\n\n${e.body.trim()}`}).join(`
6
+
7
+ `);return`${t??i(e.length)}\n\n${a}`}exports.buildReviewPrompt=a,exports.defaultReviewHeading=i,exports.diffGutterWidth=e,exports.diffRangeOf=t,exports.reviewCommentAnchor=r,exports.trimSnippet=n;
8
+ //# sourceMappingURL=review.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"review.cjs","names":[],"sources":["../../../src/lib/review.ts"],"sourcesContent":["import type { DiffHunk, DiffMarker, DiffSide, ReviewComment } from '../types/diff';\n\n/**\n * Pure review logic shared by every surface that comments on a diff: sizing a\n * gutter, deciding which side a selection is on, naming an anchor, and folding\n * a set of notes into one message.\n */\n\n/** The widest line number in a diff, in characters, which sizes the gutter. */\nexport function diffGutterWidth(hunks: readonly DiffHunk[]): number {\n let widest = 1;\n for (const hunk of hunks) {\n for (const row of hunk.rows) widest = Math.max(widest, String(row.line).length);\n }\n return widest;\n}\n\n/**\n * The line range a set of touched rows covers, and the side it is on.\n *\n * Any context or added row puts the selection on the new side, and then the\n * removed rows in it are ignored: their numbers belong to the other file and\n * would stretch the range over lines that have nothing to do with it. Only a\n * selection made entirely of removed rows lands on the old side.\n */\nexport function diffRangeOf(\n rows: readonly { marker: DiffMarker; line: number }[],\n): { side: DiffSide; startLine: number; endLine: number } | undefined {\n const numbered = rows.filter((row) => Number.isFinite(row.line) && row.line > 0);\n const kept = numbered.filter((row) => row.marker !== '-');\n const side: DiffSide = kept.length > 0 ? 'new' : 'old';\n const lines = (kept.length > 0 ? kept : numbered).map((row) => row.line);\n if (lines.length === 0) return undefined;\n return { side, startLine: Math.min(...lines), endLine: Math.max(...lines) };\n}\n\n/** Trims a quoted snippet to something a prompt can carry without drowning it. */\nexport function trimSnippet(snippet: string, maxLines = 20, maxChars = 2000): string {\n const lines = snippet.split('\\n');\n const clipped = lines.length > maxLines ? [...lines.slice(0, maxLines), '…'] : lines;\n const text = clipped.join('\\n');\n return text.length > maxChars ? `${text.slice(0, maxChars)}…` : text;\n}\n\n/** How a comment names the place it is about. New-side anchors keep the `path:line` form. */\nexport function reviewCommentAnchor(comment: ReviewComment): string {\n if (comment.startLine === undefined) return comment.relPath;\n const single = comment.endLine === undefined || comment.endLine === comment.startLine;\n if (comment.side === 'old') {\n return single\n ? `${comment.relPath} (removed line ${comment.startLine})`\n : `${comment.relPath} (removed lines ${comment.startLine}-${comment.endLine})`;\n }\n return single\n ? `${comment.relPath}:${comment.startLine}`\n : `${comment.relPath}:${comment.startLine}-${comment.endLine}`;\n}\n\n/** The opening line of a review when the caller names no context of its own. */\nexport function defaultReviewHeading(count: number): string {\n return count === 1\n ? 'I left one review comment on a file you changed. Please address it.'\n : `I left ${count} review comments on files you changed. Please address them.`;\n}\n\n/**\n * The one message a review sends.\n *\n * Every note goes in a single message rather than one each: N notes then cost\n * one turn, and the agent sees the whole review before it changes anything.\n */\nexport function buildReviewPrompt(comments: readonly ReviewComment[], heading?: string): string {\n if (comments.length === 0) return '';\n const body = comments\n .map((comment) => {\n const quoted = trimSnippet(comment.snippet)\n .split('\\n')\n .map((line) => `> ${line}`)\n .join('\\n');\n return `### ${reviewCommentAnchor(comment)}\\n\\n${quoted}\\n\\n${comment.body.trim()}`;\n })\n .join('\\n\\n');\n return `${heading ?? defaultReviewHeading(comments.length)}\\n\\n${body}`;\n}\n"],"mappings":"AASA,SAAgB,EAAgB,EAAoC,CAClE,IAAI,EAAS,EACb,IAAK,IAAM,KAAQ,EACjB,IAAK,IAAM,KAAO,EAAK,KAAM,EAAS,KAAK,IAAI,EAAQ,OAAO,EAAI,IAAI,CAAC,CAAC,MAAM,EAEhF,OAAO,CACT,CAUA,SAAgB,EACd,EACoE,CACpE,IAAM,EAAW,EAAK,OAAQ,GAAQ,OAAO,SAAS,EAAI,IAAI,GAAK,EAAI,KAAO,CAAC,EACzE,EAAO,EAAS,OAAQ,GAAQ,EAAI,SAAW,GAAG,EAClD,EAAiB,EAAK,OAAS,EAAI,MAAQ,MAC3C,GAAS,EAAK,OAAS,EAAI,EAAO,EAAA,CAAU,IAAK,GAAQ,EAAI,IAAI,EACnE,KAAM,SAAW,EACrB,MAAO,CAAE,OAAM,UAAW,KAAK,IAAI,GAAG,CAAK,EAAG,QAAS,KAAK,IAAI,GAAG,CAAK,CAAE,CAC5E,CAGA,SAAgB,EAAY,EAAiB,EAAW,GAAI,EAAW,IAAc,CACnF,IAAM,EAAQ,EAAQ,MAAM;CAAI,EAE1B,GADU,EAAM,OAAS,EAAW,CAAC,GAAG,EAAM,MAAM,EAAG,CAAQ,EAAG,GAAG,EAAI,EAAA,CAC1D,KAAK;CAAI,EAC9B,OAAO,EAAK,OAAS,EAAW,GAAG,EAAK,MAAM,EAAG,CAAQ,EAAE,GAAK,CAClE,CAGA,SAAgB,EAAoB,EAAgC,CAClE,GAAI,EAAQ,YAAc,IAAA,GAAW,OAAO,EAAQ,QACpD,IAAM,EAAS,EAAQ,UAAY,IAAA,IAAa,EAAQ,UAAY,EAAQ,UAM5E,OALI,EAAQ,OAAS,MACZ,EACH,GAAG,EAAQ,QAAQ,iBAAiB,EAAQ,UAAU,GACtD,GAAG,EAAQ,QAAQ,kBAAkB,EAAQ,UAAU,GAAG,EAAQ,QAAQ,GAEzE,EACH,GAAG,EAAQ,QAAQ,GAAG,EAAQ,YAC9B,GAAG,EAAQ,QAAQ,GAAG,EAAQ,UAAU,GAAG,EAAQ,SACzD,CAGA,SAAgB,EAAqB,EAAuB,CAC1D,OAAO,IAAU,EACb,sEACA,UAAU,EAAM,4DACtB,CAQA,SAAgB,EAAkB,EAAoC,EAA0B,CAC9F,GAAI,EAAS,SAAW,EAAG,MAAO,GAClC,IAAM,EAAO,EACV,IAAK,GAAY,CAChB,IAAM,EAAS,EAAY,EAAQ,OAAO,CAAC,CACxC,MAAM;CAAI,CAAC,CACX,IAAK,GAAS,KAAK,GAAM,CAAC,CAC1B,KAAK;CAAI,EACZ,MAAO,OAAO,EAAoB,CAAO,EAAE,MAAM,EAAO,MAAM,EAAQ,KAAK,KAAK,GAClF,CAAC,CAAC,CACD,KAAK;;CAAM,EACd,MAAO,GAAG,GAAW,EAAqB,EAAS,MAAM,EAAE,MAAM,GACnE"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agimon-ai/doompi-web-components",
3
- "version": "0.0.1-alpha.58",
3
+ "version": "0.0.1-alpha.60",
4
4
  "description": "Shared web components and theme tokens for the DoomPi cockpit and its web plugins: shadcn-style primitives on Radix, tuned to the Doom palette, with runtime theme configs.",
5
5
  "keywords": [
6
6
  "ai",
@@ -91,8 +91,8 @@
91
91
  "tailwind-merge": "3.7.0"
92
92
  },
93
93
  "devDependencies": {
94
- "@agimon-ai/doompi-core": "0.0.1-alpha.100",
95
- "@agimon-ai/vibe-lint-plugin-doom-web": "0.0.1-alpha.87",
94
+ "@agimon-ai/doompi-core": "0.0.1-alpha.102",
95
+ "@agimon-ai/vibe-lint-plugin-doom-web": "0.0.1-alpha.89",
96
96
  "@types/node": "26.6.2",
97
97
  "@types/react": "19.3.0",
98
98
  "@types/react-dom": "19.3.0",