@react-spot/plugin-comments 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +91 -0
- package/dist/index.cjs +717 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +8 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +716 -0
- package/dist/index.js.map +1 -0
- package/dist/index.prod.cjs +11 -0
- package/dist/index.prod.cjs.map +1 -0
- package/dist/index.prod.d.cts +12 -0
- package/dist/index.prod.d.cts.map +1 -0
- package/dist/index.prod.d.ts +12 -0
- package/dist/index.prod.d.ts.map +1 -0
- package/dist/index.prod.js +9 -0
- package/dist/index.prod.js.map +1 -0
- package/dist/store-BLnDRt21.d.ts +11 -0
- package/dist/store-BLnDRt21.d.ts.map +1 -0
- package/dist/store-BQEfjyfd.d.cts +11 -0
- package/dist/store-BQEfjyfd.d.cts.map +1 -0
- package/package.json +89 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/store.ts","../src/CommentEditor.tsx","../src/utils.ts","../src/SendToOpencode.tsx","../src/CommentsMenu.tsx","../src/index.tsx"],"sourcesContent":["import { atom, createStore, useAtomValue, useSetAtom } from 'jotai'\n\nexport interface CommentEntry {\n id: string\n filePath: string\n lineNumber: number\n comment: string\n createdAt: number\n}\n\nexport interface PendingComment {\n filePath: string\n lineNumber: number\n anchorEl: HTMLElement\n}\n\ninterface CommentsSnapshot {\n comments: CommentEntry[]\n pending: PendingComment | null\n}\n\ntype NewCommentEntry = Omit<CommentEntry, 'id' | 'createdAt'>\n\ninterface CommentsStore {\n getSnapshot(): CommentsSnapshot\n addComment(entry: NewCommentEntry): string\n updateComment(id: string, text: string): void\n removeComment(id: string): void\n clearAllComments(): void\n setPending(value: PendingComment | null): void\n}\n\nconst commentEntriesAtom = atom<CommentEntry[]>([])\nconst pendingCommentAtom = atom<PendingComment | null>(null)\n\nconst commentsSnapshotAtom = atom<CommentsSnapshot>((get) => ({\n comments: get(commentEntriesAtom),\n pending: get(pendingCommentAtom),\n}))\n\nconst addCommentAtom = atom(null, (get, set, entry: NewCommentEntry) => {\n const id = crypto.randomUUID()\n const comment: CommentEntry = { ...entry, id, createdAt: Date.now() }\n\n set(commentEntriesAtom, [...get(commentEntriesAtom), comment])\n\n return id\n})\n\nconst updateCommentAtom = atom(\n null,\n (get, set, payload: { id: string; text: string }) => {\n set(\n commentEntriesAtom,\n get(commentEntriesAtom).map((comment) =>\n comment.id === payload.id\n ? { ...comment, comment: payload.text }\n : comment,\n ),\n )\n },\n)\n\nconst removeCommentAtom = atom(null, (get, set, id: string) => {\n set(\n commentEntriesAtom,\n get(commentEntriesAtom).filter((comment) => comment.id !== id),\n )\n})\n\nconst clearAllCommentsAtom = atom(null, (_get, set) => {\n set(commentEntriesAtom, [])\n})\n\nexport function createCommentsStore(\n jotaiStore: ReturnType<typeof createStore> = createStore(),\n): CommentsStore {\n return {\n getSnapshot: () => jotaiStore.get(commentsSnapshotAtom),\n addComment: (entry) => jotaiStore.set(addCommentAtom, entry),\n updateComment: (id, text) => {\n jotaiStore.set(updateCommentAtom, { id, text })\n },\n removeComment: (id) => {\n jotaiStore.set(removeCommentAtom, id)\n },\n clearAllComments: () => {\n jotaiStore.set(clearAllCommentsAtom)\n },\n setPending: (value) => {\n jotaiStore.set(pendingCommentAtom, value)\n },\n }\n}\n\nfunction useCommentsSnapshot() {\n return useAtomValue(commentsSnapshotAtom)\n}\n\nexport function useCommentEntries() {\n return useCommentsSnapshot().comments\n}\n\nexport function usePendingComment() {\n return useCommentsSnapshot().pending\n}\n\nexport function useCommentsActions() {\n const addComment = useSetAtom(addCommentAtom)\n const updateComment = useSetAtom(updateCommentAtom)\n const removeComment = useSetAtom(removeCommentAtom)\n const clearAllComments = useSetAtom(clearAllCommentsAtom)\n const setPending = useSetAtom(pendingCommentAtom)\n\n return {\n addComment,\n updateComment,\n removeComment,\n clearAllComments,\n setPending,\n }\n}\n","import { useWidgetPortalContainer } from '@react-spot/core'\nimport {\n Button,\n Popover,\n Separator,\n Textarea,\n} from '@react-spot/ui-components'\nimport { useEffect, useRef, useState } from 'react'\n\nimport { useCommentsActions, usePendingComment } from './store'\n\nexport function CommentEditorOverlay() {\n const portalContainer = useWidgetPortalContainer()\n const pending = usePendingComment()\n const { addComment, setPending } = useCommentsActions()\n const [text, setText] = useState('')\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n\n useEffect(() => {\n if (pending) {\n setText('')\n requestAnimationFrame(() => {\n textareaRef.current?.focus()\n })\n }\n }, [pending])\n\n const handleCancel = () => {\n setPending(null)\n }\n\n const handleSubmit = () => {\n if (!pending || !text.trim()) return\n addComment({\n filePath: pending.filePath,\n lineNumber: pending.lineNumber,\n comment: text.trim(),\n })\n setPending(null)\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Escape') {\n e.preventDefault()\n handleCancel()\n } else if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n handleSubmit()\n }\n }\n\n if (!pending) return null\n\n return (\n <Popover.Root\n open\n onOpenChange={(open: boolean) => {\n if (!open) setPending(null)\n }}\n >\n <Popover.Portal container={portalContainer}>\n <Popover.Positioner\n anchor={pending.anchorEl}\n side=\"bottom\"\n align=\"start\"\n sideOffset={8}\n collisionPadding={8}\n positionMethod=\"fixed\"\n style={{\n zIndex: 9999999,\n pointerEvents: 'auto',\n }}\n >\n <Popover.Popup\n initialFocus={false}\n style={{\n width: 480,\n border: '1px solid #3b82f6',\n padding: 8,\n fontFamily: 'system-ui, sans-serif',\n boxSizing: 'border-box',\n }}\n onClick={(e) => e.stopPropagation()}\n onKeyDown={(e) => e.stopPropagation()}\n >\n <Textarea\n ref={textareaRef}\n value={text}\n onChange={(e) => setText(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"Add comment\"\n rows={3}\n />\n\n <Separator style={{ margin: '4px 0' }} />\n\n <div\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n paddingTop: 4,\n }}\n >\n <span\n style={{\n fontSize: 11,\n color: '#71717a',\n fontFamily: 'ui-monospace, monospace',\n }}\n >\n Commenting on line {pending.lineNumber}\n </span>\n <div style={{ display: 'flex', gap: 6 }}>\n <Button variant=\"secondary\" onClick={handleCancel}>\n Cancel\n </Button>\n <Button\n variant=\"primary\"\n onClick={handleSubmit}\n disabled={!text.trim()}\n >\n Comment\n </Button>\n </div>\n </div>\n </Popover.Popup>\n </Popover.Positioner>\n </Popover.Portal>\n </Popover.Root>\n )\n}\n","/**\n * Formats a comment as a compact `file:line: comment` string.\n * Used for both copy-to-clipboard and the synthetic text part sent to OpenCode.\n */\nexport function formatCommentNote(\n filePath: string,\n lineNumber: number,\n comment: string,\n): string {\n return `${filePath}:${lineNumber}: ${comment}`\n}\n","import { createOpencodeClient } from '@opencode-ai/sdk'\nimport type { Session } from '@opencode-ai/sdk'\nimport { useWidgetPortalContainer } from '@react-spot/core'\nimport { Button, Select, Textarea } from '@react-spot/ui-components'\nimport { useEffect, useRef, useState } from 'react'\n\nimport type { CommentEntry } from './store'\nimport { formatCommentNote } from './utils'\n\n// ---------------------------------------------------------------------------\n// SendToOpencodeForm\n// ---------------------------------------------------------------------------\n\ntype Status =\n | 'idle'\n | 'loading-sessions'\n | 'ready'\n | 'sending'\n | 'sent'\n | 'error'\n\nexport function SendToOpencodeForm({\n root,\n comments,\n onClearComments,\n onDone,\n}: {\n root: string | undefined\n comments: CommentEntry[]\n onClearComments(): void\n onDone(): void\n}) {\n const portalContainer = useWidgetPortalContainer()\n const [sessions, setSessions] = useState<Session[]>([])\n const [selectedId, setSelectedId] = useState<string>('__new__')\n const [generalComment, setGeneralComment] = useState('')\n const [status, setStatus] = useState<Status>('loading-sessions')\n const [errorMsg, setErrorMsg] = useState('')\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n\n // Lazily create the client — only when the form mounts\n const [client] = useState(() =>\n createOpencodeClient({\n baseUrl: 'http://localhost:4096',\n ...(root ? { directory: root } : {}),\n }),\n )\n\n useEffect(() => {\n client.session\n .list()\n .then((res) => {\n // Sort most-recently-updated first and filter out child sessions\n const list = (res.data ?? [])\n .filter((s) => !s.parentID)\n .toSorted((a, b) => (b.time?.updated ?? 0) - (a.time?.updated ?? 0))\n setSessions(list)\n setStatus('ready')\n // Pre-select the most recent session if one exists\n if (list.length > 0) setSelectedId(list[0]!.id)\n requestAnimationFrame(() => textareaRef.current?.focus())\n })\n .catch(() => {\n setStatus('error')\n setErrorMsg('Could not connect to OpenCode. Is it running?')\n })\n }, [client])\n\n const handleSend = async () => {\n if (!comments.length) return\n\n setStatus('sending')\n setErrorMsg('')\n\n try {\n // Fetch line previews for all comments in parallel\n const previews = await Promise.all(\n comments.map(async (c) => {\n try {\n const res = await client.file.read({ query: { path: c.filePath } })\n const lines = (res.data?.content ?? '').split('\\n')\n return lines[c.lineNumber - 1] ?? ''\n } catch {\n return ''\n }\n }),\n )\n\n // Build structured parts\n type Part =\n | {\n type: 'text'\n text: string\n synthetic?: boolean\n metadata?: Record<string, unknown>\n }\n | { type: 'file'; mime: string; filename: string; url: string }\n\n const parts: Part[] = []\n\n // Optional general comment — omit entirely if empty\n const trimmed = generalComment.trim()\n if (trimmed) parts.push({ type: 'text', text: trimmed })\n\n // One synthetic text + one file part per comment\n for (let i = 0; i < comments.length; i++) {\n const c = comments[i]!\n const preview = previews[i]!\n const absUrl = root\n ? `file://${root.replace(/\\/$/, '')}/${c.filePath}?start=${c.lineNumber}&end=${c.lineNumber}`\n : `file:///${c.filePath}?start=${c.lineNumber}&end=${c.lineNumber}`\n const filename = c.filePath.split('/').pop() ?? c.filePath\n\n parts.push({\n type: 'text',\n text: formatCommentNote(c.filePath, c.lineNumber, c.comment),\n synthetic: true,\n metadata: {\n opencodeComment: {\n path: c.filePath,\n selection: {\n startLine: c.lineNumber,\n endLine: c.lineNumber,\n startChar: 0,\n endChar: 0,\n },\n comment: c.comment,\n preview,\n origin: 'file',\n },\n },\n })\n\n parts.push({ type: 'file', mime: 'text/plain', filename, url: absUrl })\n }\n\n // Resolve the target session ID\n let sessionId = selectedId\n if (sessionId === '__new__') {\n const res = await client.session.create({ body: {} })\n if (!res.data?.id) throw new Error('Failed to create session')\n sessionId = res.data.id\n }\n\n await client.session.promptAsync({\n path: { id: sessionId },\n body: { parts },\n })\n\n onClearComments()\n setStatus('sent')\n setTimeout(onDone, 1200)\n } catch (e) {\n setStatus('error')\n setErrorMsg(e instanceof Error ? e.message : 'Failed to send to OpenCode')\n }\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Escape') {\n e.preventDefault()\n onDone()\n } else if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {\n e.preventDefault()\n handleSend()\n }\n }\n\n if (status === 'sent') {\n return (\n <div\n style={{\n padding: '12px',\n textAlign: 'center',\n fontSize: 12,\n color: '#4ade80',\n fontFamily: 'system-ui, sans-serif',\n }}\n >\n Sent to OpenCode!\n </div>\n )\n }\n\n const loading = status === 'loading-sessions'\n const sending = status === 'sending'\n const disabled = loading || sending\n\n return (\n <div\n style={{\n padding: '10px 12px 8px',\n display: 'flex',\n flexDirection: 'column',\n gap: 8,\n }}\n onKeyDown={(e) => e.stopPropagation()}\n >\n {/* Session selector */}\n <div>\n <label\n style={{\n display: 'block',\n fontSize: 11,\n color: '#71717a',\n fontFamily: 'system-ui, sans-serif',\n marginBottom: 4,\n }}\n >\n Session\n </label>\n <Select.Root\n value={selectedId}\n onValueChange={(v) => v && setSelectedId(v)}\n disabled={disabled}\n >\n <Select.Trigger style={{ borderRadius: 4 }}>\n <Select.Value placeholder=\"Select a session…\">\n {(value) => sessions.find((s) => s.id === value)?.title ?? value}\n </Select.Value>\n </Select.Trigger>\n <Select.Portal container={portalContainer}>\n <Select.Positioner\n style={{ zIndex: 9999999, pointerEvents: 'auto' }}\n >\n <Select.Popup>\n <Select.List>\n <Select.Item value=\"__new__\">\n <Select.ItemText>+ New session</Select.ItemText>\n </Select.Item>\n {loading ? (\n <Select.Item value=\"__loading__\" disabled>\n <Select.ItemText>Loading sessions…</Select.ItemText>\n </Select.Item>\n ) : (\n sessions.map((s) => (\n <Select.Item key={s.id} value={s.id}>\n <Select.ItemText>\n {s.title || `Session ${s.id.slice(0, 8)}`}\n </Select.ItemText>\n </Select.Item>\n ))\n )}\n </Select.List>\n </Select.Popup>\n </Select.Positioner>\n </Select.Portal>\n </Select.Root>\n </div>\n\n {/* General comment */}\n <div>\n <label\n style={{\n display: 'block',\n fontSize: 11,\n color: '#71717a',\n fontFamily: 'system-ui, sans-serif',\n marginBottom: 4,\n }}\n >\n Message <span style={{ color: '#52525b' }}>(optional)</span>\n </label>\n <Textarea\n ref={textareaRef}\n value={generalComment}\n onChange={(e) => setGeneralComment(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder=\"e.g. Left the comments below, please address\"\n rows={2}\n disabled={disabled}\n />\n </div>\n\n {/* Error */}\n {status === 'error' && errorMsg && (\n <p\n style={{\n margin: 0,\n fontSize: 11,\n color: '#f87171',\n fontFamily: 'system-ui, sans-serif',\n }}\n >\n {errorMsg}\n </p>\n )}\n\n {/* Actions */}\n <div style={{ display: 'flex', justifyContent: 'flex-end', gap: 6 }}>\n <Button variant=\"secondary\" onClick={onDone} disabled={sending}>\n Cancel\n </Button>\n <Button variant=\"primary\" onClick={handleSend} disabled={disabled}>\n {sending ? 'Sending…' : 'Send'}\n </Button>\n </div>\n </div>\n )\n}\n","import { useProjectRoot } from '@react-spot/core'\nimport {\n Button,\n ClipboardIcon,\n DropdownMenu,\n IconButton,\n OpencodeIcon,\n PanelHeader,\n Textarea,\n TrashIcon,\n XIcon,\n} from '@react-spot/ui-components'\nimport { useEffect, useRef, useState } from 'react'\n\nimport { SendToOpencodeForm } from './SendToOpencode'\nimport {\n type CommentEntry,\n useCommentEntries,\n useCommentsActions,\n} from './store'\nimport { formatCommentNote } from './utils'\n\nfunction CommentRow({\n comment,\n onDelete,\n onUpdate,\n}: {\n comment: CommentEntry\n onDelete(): void\n onUpdate(text: string): void\n}) {\n const [hovered, setHovered] = useState(false)\n const [editing, setEditing] = useState(false)\n const [draft, setDraft] = useState(comment.comment)\n const textareaRef = useRef<HTMLTextAreaElement>(null)\n\n useEffect(() => {\n if (!editing) setDraft(comment.comment)\n }, [comment.comment, editing])\n\n const startEditing = () => {\n setDraft(comment.comment)\n setEditing(true)\n requestAnimationFrame(() => {\n const el = textareaRef.current\n if (!el) return\n el.focus()\n el.selectionStart = el.selectionEnd = el.value.length\n })\n }\n\n const handleSave = () => {\n const trimmed = draft.trim()\n if (trimmed && trimmed !== comment.comment) onUpdate(trimmed)\n setEditing(false)\n }\n\n const handleCancel = () => {\n setDraft(comment.comment)\n setEditing(false)\n }\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === 'Escape') {\n e.preventDefault()\n handleCancel()\n } else if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n handleSave()\n }\n }\n\n return (\n <div\n style={{\n padding: '6px 12px',\n background: hovered ? 'rgba(255,255,255,0.03)' : 'transparent',\n transition: 'background 0.1s',\n }}\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n >\n <div\n style={{\n display: 'flex',\n alignItems: 'flex-start',\n justifyContent: 'space-between',\n gap: 8,\n }}\n >\n <span\n style={{\n fontSize: 11,\n fontFamily: 'ui-monospace, monospace',\n color: '#3b82f6',\n flexShrink: 0,\n }}\n >\n {comment.filePath}:{comment.lineNumber}\n </span>\n {hovered && !editing && (\n <IconButton\n onClick={onDelete}\n title=\"Remove comment\"\n style={{ padding: 0, flexShrink: 0 }}\n >\n <XIcon size={12} />\n </IconButton>\n )}\n </div>\n\n {editing ? (\n <div style={{ marginTop: 4 }}>\n <Textarea\n ref={textareaRef}\n value={draft}\n onChange={(e) => setDraft(e.target.value)}\n onKeyDown={handleKeyDown}\n rows={3}\n />\n <div\n style={{\n display: 'flex',\n justifyContent: 'flex-end',\n gap: 6,\n marginTop: 4,\n }}\n >\n <Button\n variant=\"secondary\"\n onClick={handleCancel}\n style={{ height: 24, fontSize: 11 }}\n >\n Cancel\n </Button>\n <Button\n variant=\"primary\"\n onClick={handleSave}\n disabled={!draft.trim()}\n style={{ height: 24, fontSize: 11 }}\n >\n Save\n </Button>\n </div>\n </div>\n ) : (\n <p\n onClick={startEditing}\n title=\"Click to edit\"\n style={{\n margin: '3px 0 0',\n fontSize: 12,\n color: '#d4d4d8',\n fontFamily: 'system-ui, sans-serif',\n lineHeight: 1.4,\n whiteSpace: 'pre-wrap',\n wordBreak: 'break-word',\n cursor: 'text',\n }}\n >\n {comment.comment}\n </p>\n )}\n </div>\n )\n}\n\nexport function CommentsMenu({ onClose }: { onClose(): void }) {\n const root = useProjectRoot()\n const comments = useCommentEntries()\n const { clearAllComments, removeComment, updateComment } =\n useCommentsActions()\n const [copyFeedback, setCopyFeedback] = useState(false)\n const [showSendForm, setShowSendForm] = useState(false)\n\n useEffect(() => {\n if (!comments.length) setShowSendForm(false)\n }, [comments.length])\n\n const handleCopy = () => {\n if (!comments.length) return\n const text = comments\n .map((c) => formatCommentNote(c.filePath, c.lineNumber, c.comment))\n .join('\\n\\n')\n\n navigator.clipboard\n .writeText(text)\n .then(() => {\n setCopyFeedback(true)\n setTimeout(() => setCopyFeedback(false), 1500)\n })\n .catch(() => {})\n }\n\n const handleClear = () => {\n clearAllComments()\n onClose()\n }\n\n return (\n <div\n style={{\n width: 320,\n overflow: 'hidden',\n }}\n onClick={(e) => e.stopPropagation()}\n >\n <PanelHeader\n title={\n <>\n Comments\n {comments.length > 0 && (\n <span\n style={{\n marginLeft: 6,\n fontSize: 11,\n color: '#71717a',\n fontWeight: 400,\n }}\n >\n ({comments.length})\n </span>\n )}\n </>\n }\n actionsRender={\n <IconButton onClick={onClose} title=\"Close\">\n <XIcon />\n </IconButton>\n }\n />\n\n {comments.length === 0 ? (\n <div\n style={{\n padding: '16px 12px',\n fontSize: 12,\n lineHeight: 1.5,\n color: '#97979b',\n fontFamily: 'system-ui, sans-serif',\n textAlign: 'center',\n textWrap: 'balance',\n }}\n >\n No comments yet. Inspect an element and click "Add comment".\n </div>\n ) : (\n <div\n style={{ maxHeight: 280, overflowY: 'auto', paddingBlock: 6 }}\n onKeyDown={(e) => e.stopPropagation()}\n >\n {comments.map((c) => (\n <CommentRow\n key={c.id}\n comment={c}\n onDelete={() => removeComment(c.id)}\n onUpdate={(text) => updateComment({ id: c.id, text })}\n />\n ))}\n </div>\n )}\n\n {comments.length > 0 && (\n <>\n <div style={{ borderTop: '1px solid #27272a', margin: '4px 0 0' }} />\n {showSendForm ? (\n <SendToOpencodeForm\n root={root}\n comments={comments}\n onClearComments={clearAllComments}\n onDone={() => {\n setShowSendForm(false)\n onClose()\n }}\n />\n ) : (\n <div style={{ padding: '4px 6px' }}>\n <DropdownMenu.Item\n closeOnClick={false}\n onClick={() => setShowSendForm(true)}\n >\n <OpencodeIcon size={13} />\n Send to OpenCode\n </DropdownMenu.Item>\n <DropdownMenu.Item closeOnClick={false} onClick={handleCopy}>\n <ClipboardIcon />\n {copyFeedback ? 'Copied!' : 'Copy to clipboard'}\n </DropdownMenu.Item>\n <DropdownMenu.Item\n style={{ color: '#ef4444' }}\n onClick={handleClear}\n >\n <TrashIcon />\n Clear all\n </DropdownMenu.Item>\n </div>\n )}\n </>\n )}\n </div>\n )\n}\n","import type { TracePlugin } from '@react-spot/core'\nimport {\n useDeactivateInspector,\n useWidgetPortalContainer,\n} from '@react-spot/core'\nimport {\n ChatBubbleIcon,\n DropdownMenu,\n ToolbarButton,\n Tooltip,\n} from '@react-spot/ui-components'\nimport { useRef, useState } from 'react'\n\nimport { CommentEditorOverlay } from './CommentEditor'\nimport { CommentsMenu } from './CommentsMenu'\nimport { useCommentEntries } from './store'\n\nexport type { CommentEntry } from './store'\n\nfunction CommentsToolbarIcon({ count }: { count: number }) {\n return (\n <span\n style={{\n position: 'relative',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <ChatBubbleIcon />\n {count > 0 && (\n <span\n style={{\n position: 'absolute',\n top: -6,\n right: -6,\n background: '#ef4444',\n color: '#fff',\n fontSize: 9,\n fontWeight: 700,\n fontFamily: 'system-ui, sans-serif',\n lineHeight: 1,\n minWidth: 14,\n height: 14,\n borderRadius: 7,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '0 3px',\n boxSizing: 'border-box',\n pointerEvents: 'none',\n }}\n >\n {count > 99 ? '99+' : count}\n </span>\n )}\n </span>\n )\n}\n\nfunction CommentsToolbar() {\n const comments = useCommentEntries()\n const portalContainer = useWidgetPortalContainer()\n const deactivateInspector = useDeactivateInspector()\n const buttonRef = useRef<HTMLButtonElement>(null)\n const [isOpen, setIsOpen] = useState(false)\n const count = comments.length\n\n return (\n <>\n <Tooltip\n label=\"Comments\"\n container={portalContainer}\n render={<ToolbarButton ref={buttonRef} />}\n aria-label=\"Comments\"\n onClick={() => {\n deactivateInspector()\n setIsOpen((open) => !open)\n }}\n >\n <CommentsToolbarIcon count={count} />\n </Tooltip>\n\n <DropdownMenu.Root open={isOpen} onOpenChange={setIsOpen}>\n <DropdownMenu.Portal container={portalContainer}>\n <DropdownMenu.Positioner\n anchor={buttonRef.current}\n side=\"top\"\n align=\"end\"\n sideOffset={8}\n collisionPadding={8}\n positionMethod=\"fixed\"\n style={{ zIndex: 9999999, pointerEvents: 'auto' }}\n >\n <DropdownMenu.Popup>\n <CommentsMenu onClose={() => setIsOpen(false)} />\n </DropdownMenu.Popup>\n </DropdownMenu.Positioner>\n </DropdownMenu.Portal>\n </DropdownMenu.Root>\n\n <CommentEditorOverlay />\n </>\n )\n}\n\nexport function CommentsPlugin(): TracePlugin {\n return {\n name: 'comments',\n toolbar: CommentsToolbar,\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
//#region src/index.prod.ts
|
|
4
|
+
/**
|
|
5
|
+
* Production stub for @react-spot/plugin-comments.
|
|
6
|
+
*/
|
|
7
|
+
const CommentsPlugin = () => ({ name: "comments" });
|
|
8
|
+
|
|
9
|
+
//#endregion
|
|
10
|
+
exports.CommentsPlugin = CommentsPlugin;
|
|
11
|
+
//# sourceMappingURL=index.prod.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.prod.cjs","names":[],"sources":["../src/index.prod.ts"],"sourcesContent":["/**\n * Production stub for @react-spot/plugin-comments.\n */\nexport const CommentsPlugin = () => ({ name: 'comments' as const })\n\nexport type { CommentEntry } from './store'\n"],"mappings":";;;;;;AAGA,MAAa,wBAAwB,EAAE,MAAM,YAAqB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { t as CommentEntry } from "./store-BQEfjyfd.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/index.prod.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Production stub for @react-spot/plugin-comments.
|
|
6
|
+
*/
|
|
7
|
+
declare const CommentsPlugin: () => {
|
|
8
|
+
name: "comments";
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
|
11
|
+
export { type CommentEntry, CommentsPlugin };
|
|
12
|
+
//# sourceMappingURL=index.prod.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.prod.d.cts","names":[],"sources":["../src/index.prod.ts"],"mappings":";;;;;;cAGa,cAAA;EAAsD,IAAA;AAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { t as CommentEntry } from "./store-BLnDRt21.js";
|
|
2
|
+
|
|
3
|
+
//#region src/index.prod.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Production stub for @react-spot/plugin-comments.
|
|
6
|
+
*/
|
|
7
|
+
declare const CommentsPlugin: () => {
|
|
8
|
+
name: "comments";
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
|
11
|
+
export { type CommentEntry, CommentsPlugin };
|
|
12
|
+
//# sourceMappingURL=index.prod.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.prod.d.ts","names":[],"sources":["../src/index.prod.ts"],"mappings":";;;;;;cAGa,cAAA;EAAsD,IAAA;AAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.prod.js","names":[],"sources":["../src/index.prod.ts"],"sourcesContent":["/**\n * Production stub for @react-spot/plugin-comments.\n */\nexport const CommentsPlugin = () => ({ name: 'comments' as const })\n\nexport type { CommentEntry } from './store'\n"],"mappings":";;;;AAGA,MAAa,wBAAwB,EAAE,MAAM,YAAqB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-BLnDRt21.d.ts","names":[],"sources":["../src/store.ts"],"mappings":";UAEiB,YAAA;EACf,EAAA;EACA,QAAA;EACA,UAAA;EACA,OAAA;EACA,SAAA;AAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store-BQEfjyfd.d.cts","names":[],"sources":["../src/store.ts"],"mappings":";UAEiB,YAAA;EACf,EAAA;EACA,QAAA;EACA,UAAA;EACA,OAAA;EACA,SAAA;AAAA"}
|
package/package.json
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@react-spot/plugin-comments",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "react-trace plugin: inline code comments with OpenCode AI integration",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"react-trace",
|
|
7
|
+
"react-trace-agents",
|
|
8
|
+
"react-trace-ai",
|
|
9
|
+
"react-trace-comments",
|
|
10
|
+
"react-trace-plugin"
|
|
11
|
+
],
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"author": "Vitor Buzinaro",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/buzinas/react-trace",
|
|
17
|
+
"directory": "packages/plugin-comments"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist"
|
|
21
|
+
],
|
|
22
|
+
"type": "module",
|
|
23
|
+
"main": "./dist/index.cjs",
|
|
24
|
+
"module": "./dist/index.js",
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"development": {
|
|
29
|
+
"import": {
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"default": "./dist/index.js"
|
|
32
|
+
},
|
|
33
|
+
"require": {
|
|
34
|
+
"types": "./dist/index.d.cts",
|
|
35
|
+
"default": "./dist/index.cjs"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"production": {
|
|
39
|
+
"import": {
|
|
40
|
+
"types": "./dist/index.d.ts",
|
|
41
|
+
"default": "./dist/index.prod.js"
|
|
42
|
+
},
|
|
43
|
+
"require": {
|
|
44
|
+
"types": "./dist/index.d.cts",
|
|
45
|
+
"default": "./dist/index.prod.cjs"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"default": {
|
|
49
|
+
"import": {
|
|
50
|
+
"types": "./dist/index.d.ts",
|
|
51
|
+
"default": "./dist/index.js"
|
|
52
|
+
},
|
|
53
|
+
"require": {
|
|
54
|
+
"types": "./dist/index.d.cts",
|
|
55
|
+
"default": "./dist/index.cjs"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
"publishConfig": {
|
|
61
|
+
"access": "public"
|
|
62
|
+
},
|
|
63
|
+
"scripts": {
|
|
64
|
+
"build": "tsdown",
|
|
65
|
+
"dev": "tsdown --watch --no-clean",
|
|
66
|
+
"typecheck": "tsc --noEmit",
|
|
67
|
+
"lint": "oxlint src",
|
|
68
|
+
"prepublishOnly": "pnpm build"
|
|
69
|
+
},
|
|
70
|
+
"dependencies": {
|
|
71
|
+
"@opencode-ai/sdk": "^1.2.16",
|
|
72
|
+
"jotai": "^2.18.0"
|
|
73
|
+
},
|
|
74
|
+
"devDependencies": {
|
|
75
|
+
"@types/react": "^19",
|
|
76
|
+
"@types/react-dom": "^19",
|
|
77
|
+
"oxlint": "latest",
|
|
78
|
+
"react": "^19",
|
|
79
|
+
"react-dom": "^19",
|
|
80
|
+
"tsdown": "^0.21.0-beta.2",
|
|
81
|
+
"typescript": "^5"
|
|
82
|
+
},
|
|
83
|
+
"peerDependencies": {
|
|
84
|
+
"@react-spot/core": "^0.0.1",
|
|
85
|
+
"@react-spot/ui-components": "^0.0.1",
|
|
86
|
+
"react": ">=18",
|
|
87
|
+
"react-dom": ">=18"
|
|
88
|
+
}
|
|
89
|
+
}
|