@adea-ai/ui 0.68.2 → 0.69.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 +79 -15
- package/dist/NOTICE +55 -24
- package/dist/components/conversation/atomic/chat-composer.d.ts +20 -0
- package/dist/components/conversation/atomic/chat-composer.d.ts.map +1 -0
- package/dist/components/conversation/atomic/chat-composer.js +69 -0
- package/dist/components/conversation/atomic/chat-composer.js.map +1 -0
- package/dist/components/conversation/atomic/index.d.ts +3 -0
- package/dist/components/conversation/atomic/index.d.ts.map +1 -0
- package/dist/components/conversation/atomic/index.js +2 -0
- package/dist/components/conversation/chat-composer.d.ts +12 -21
- package/dist/components/conversation/chat-composer.d.ts.map +1 -1
- package/dist/components/conversation/chat-composer.js +33 -403
- package/dist/components/conversation/chat-composer.js.map +1 -1
- package/dist/components/conversation/internal/chat-composer-shell.d.ts +38 -0
- package/dist/components/conversation/internal/chat-composer-shell.d.ts.map +1 -0
- package/dist/components/conversation/internal/chat-composer-shell.js +423 -0
- package/dist/components/conversation/internal/chat-composer-shell.js.map +1 -0
- package/dist/components/conversation/paste-preview.d.ts +11 -0
- package/dist/components/conversation/paste-preview.d.ts.map +1 -0
- package/dist/components/conversation/paste-preview.js +28 -0
- package/dist/components/conversation/paste-preview.js.map +1 -0
- package/dist/components/conversation/paste-token-editor.d.ts +26 -0
- package/dist/components/conversation/paste-token-editor.d.ts.map +1 -0
- package/dist/components/conversation/paste-token-editor.js +570 -0
- package/dist/components/conversation/paste-token-editor.js.map +1 -0
- package/dist/components/conversation/paste-tokens.d.ts.map +1 -1
- package/dist/components/conversation/paste-tokens.js +11 -2
- package/dist/components/conversation/paste-tokens.js.map +1 -1
- package/dist/r/conversation.json +26 -0
- package/dist/r/registry.json +26 -0
- package/dist/r/src/components/conversation/atomic/chat-composer.tsx +57 -0
- package/dist/r/src/components/conversation/atomic/index.ts +6 -0
- package/dist/r/src/components/conversation/chat-composer.tsx +39 -331
- package/dist/r/src/components/conversation/internal/chat-composer-shell.tsx +390 -0
- package/dist/r/src/components/conversation/paste-preview.ts +35 -0
- package/dist/r/src/components/conversation/paste-token-editor.tsx +672 -0
- package/dist/r/src/components/conversation/paste-tokens.ts +15 -2
- package/package.json +1 -1
- package/registry.json +26 -0
- package/src/components/conversation/atomic/chat-composer.tsx +57 -0
- package/src/components/conversation/atomic/index.ts +6 -0
- package/src/components/conversation/chat-composer.tsx +39 -331
- package/src/components/conversation/internal/chat-composer-shell.tsx +390 -0
- package/src/components/conversation/paste-preview.ts +35 -0
- package/src/components/conversation/paste-token-editor.tsx +672 -0
- package/src/components/conversation/paste-tokens.ts +15 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paste-token-editor.js","names":["For","Show","createEffect","createMemo","createSignal","createUniqueId","on","onCleanup","onMount","countLines","findTokenRanges","formatToken","isPasteBlock","nextSeq","pruneBlocks","shouldCollapse","stripTrailingBlankLines","tokenRangeAt","PasteBlock","summarizePastePreview","Tooltip","KobalteTooltip","PasteTokenDraft","text","blocks","TokenRange","start","end","block","Segment","PasteTokenEditorProps","value","resetKey","ref","element","HTMLTextAreaElement","createBlockId","onChange","draft","inputLabel","placeholder","disabled","readOnly","composing","onCompositionStart","onCompositionEnd","onFocus","onBlur","onKeyDown","event","KeyboardEvent","PREVIEW_OPEN_DELAY_MS","isTouchDevice","window","matchMedia","matches","isBlockquotePrefix","linePrefix","sawMarker","index","length","code","charCodeAt","PasteTokenEditor","props","preview","setPreview","previewSummary","content","lines","descriptionId","keyboardHintId","field","mirror","HTMLDivElement","previewTimer","ReturnType","setTimeout","scheduledBlockId","rawPasteNext","suppressPasteInput","nativePasteInputSeen","keyboardNavigationPending","acceptingTextDrop","snappedCaretPreview","blockId","position","ranges","clearTimer","clearTimeout","undefined","closePreview","schedulePreview","id","current","find","range","change","snapToTokenEdge","tokenRanges","edge","setCaret","focus","requestAnimationFrame","setSelectionRange","replaceRange","removed","filter","nextStart","Math","min","map","nextEnd","max","next","slice","some","expandToken","segments","result","cursor","push","scheduleCaretPreview","selectionStart","selectionEnd","caret","candidate","snappedRange","openKeyboardPreview","schedulePointerPreview","MouseEvent","buttons","span","querySelectorAll","HTMLElement","rect","getBoundingClientRect","clientX","left","right","clientY","top","bottom","sequence","Number","dataset","pasteSeq","seq","snapSelection","direction","selectionDirection","handleKeyDown","metaKey","ctrlKey","shiftKey","altKey","key","toLowerCase","isComposing","keyCode","preventDefault","collapsed","plainModifier","backspace","deletion","remove","adjacent","boundary","lastIndexOf","indexOf","from","to","active","navigation","leftward","nextRanges","expandSelectionForClipboard","covered","handlePaste","ClipboardEvent","forceRaw","pasted","clipboardData","getData","cleaned","before","after","leading","endsWith","trailing","startsWith","insert","inserted","document","execCommand","handleDragOver","DragEvent","dataTransfer","types","includes","handleDragLeave","handleDrop","dropped","handleClipboard","expanded","setData","type","handleClick","detail","addEventListener","removeEventListener","_$createComponent","open","onOpenChange","openDelay","children","Trigger","as","_el$","_tmpl$","_$use","_$insert","each","segment","_el$4","_tmpl$4","_$effect","_$setAttribute","_el$5","_tmpl$5","_el$2","_tmpl$2","$$keydown","_$addEventListener","scrollTop","currentTarget","scrollLeft","$$mousemove","$$click","$$input","_p$","_v$","_v$2","_v$3","_v$4","_v$5","e","t","a","o","i","_el$3","_tmpl$3","when","summary","Portal","Content","_el$6","_tmpl$6","hiddenLines","_el$7","_tmpl$7","_el$8","firstChild","_el$0","nextSibling","_el$9","_$memo","hiddenCharacters","_el$1","_tmpl$8","_el$10","_el$12","_el$11","Arrow","_$delegateEvents","_$createComponent","KobalteTooltip","_$setAttribute","_$memo","_$delegateEvents"],"sources":["../../../src/components/conversation/paste-token-editor.tsx"],"sourcesContent":["/*\n * Substantially translated from KiroCrew website/src/components/ChatInput.tsx\n * and PasteHighlightLayer.tsx at 283e136c0f902e965a535a7c9548c57c7504fed0.\n * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n * Licensed under Apache-2.0; see LICENSE and NOTICE.\n */\nimport {\n For,\n Show,\n createEffect,\n createMemo,\n createSignal,\n createUniqueId,\n on,\n onCleanup,\n onMount,\n} from 'solid-js'\nimport {\n countLines,\n findTokenRanges,\n formatToken,\n isPasteBlock,\n nextSeq,\n pruneBlocks,\n shouldCollapse,\n stripTrailingBlankLines,\n tokenRangeAt,\n type PasteBlock,\n} from './paste-tokens'\nimport { summarizePastePreview } from './paste-preview'\nimport { Tooltip as KobalteTooltip } from '@kobalte/core/tooltip'\n\nexport type PasteTokenDraft = { text: string; blocks: PasteBlock[] }\ntype TokenRange = { start: number; end: number; block: PasteBlock }\ntype Segment = { text: string; block?: PasteBlock }\n\nexport type PasteTokenEditorProps = {\n value: string\n resetKey?: unknown\n blocks: readonly PasteBlock[]\n ref: (element: HTMLTextAreaElement | undefined) => void\n createBlockId: () => string\n onChange: (draft: PasteTokenDraft) => void\n inputLabel: string\n placeholder: string\n disabled?: boolean\n readOnly?: boolean\n composing: () => boolean\n onCompositionStart: () => void\n onCompositionEnd: () => void\n onFocus: () => void\n onBlur: () => void\n onKeyDown: (event: KeyboardEvent) => void\n}\n\nconst PREVIEW_OPEN_DELAY_MS = 300\n\nfunction isTouchDevice(): boolean {\n return (\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n (window.matchMedia('(pointer: coarse)').matches || window.matchMedia('(hover: none)').matches)\n )\n}\n\nfunction isBlockquotePrefix(linePrefix: string): boolean {\n let sawMarker = false\n for (let index = 0; index < linePrefix.length; index += 1) {\n const code = linePrefix.charCodeAt(index)\n if (code === 62) sawMarker = true\n else if (code !== 32 && code !== 9) return false\n }\n return sawMarker\n}\n\n/** Controlled plain-text editor that treats known paste markers as atomic ranges. */\nexport function PasteTokenEditor(props: PasteTokenEditorProps) {\n const [preview, setPreview] = createSignal<PasteBlock | null>(null)\n const previewSummary = createMemo(() => {\n const block = preview()\n return block ? summarizePastePreview(block.content, block.lines) : null\n })\n const descriptionId = `paste-preview-${createUniqueId()}`\n const keyboardHintId = `paste-keyboard-hint-${createUniqueId()}`\n let field: HTMLTextAreaElement | undefined\n let mirror: HTMLDivElement | undefined\n let previewTimer: ReturnType<typeof setTimeout> | undefined\n let scheduledBlockId: string | null = null\n let rawPasteNext = false\n let suppressPasteInput = false\n let nativePasteInputSeen = false\n let keyboardNavigationPending = false\n let acceptingTextDrop = false\n let snappedCaretPreview: { blockId: string; position: number } | null = null\n\n const ranges = () => findTokenRanges(props.value, props.blocks)\n const clearTimer = () => {\n clearTimeout(previewTimer)\n previewTimer = undefined\n }\n const closePreview = () => {\n clearTimer()\n scheduledBlockId = null\n snappedCaretPreview = null\n setPreview(null)\n }\n const schedulePreview = (block: PasteBlock) => {\n if (scheduledBlockId === block.id) return\n clearTimer()\n scheduledBlockId = block.id\n setPreview(null)\n previewTimer = setTimeout(() => {\n previewTimer = undefined\n const current = ranges().find((range) => range.block.id === block.id)\n if (current) setPreview(current.block)\n else closePreview()\n }, PREVIEW_OPEN_DELAY_MS)\n }\n const change = (text: string, blocks: readonly PasteBlock[] = props.blocks) => {\n props.onChange({ text, blocks: pruneBlocks(text, [...blocks]) })\n }\n const snapToTokenEdge = (\n position: number,\n tokenRanges: readonly TokenRange[] = ranges(),\n edge?: 'start' | 'end'\n ) => {\n for (const range of tokenRanges) {\n if (position > range.start && position < range.end) {\n if (edge === 'start') return range.start\n if (edge === 'end') return range.end\n return position - range.start <= range.end - position ? range.start : range.end\n }\n }\n return position\n }\n const setCaret = (position: number, focus = false) => {\n requestAnimationFrame(() => {\n if (!field) return\n if (focus) field.focus()\n field.setSelectionRange(position, position)\n })\n }\n const replaceRange = (start: number, end: number) => {\n if (!field) return\n const removed = ranges().filter((range) => range.start < end && range.end > start)\n if (!removed.length) return\n const nextStart = Math.min(start, ...removed.map((range) => range.start))\n const nextEnd = Math.max(end, ...removed.map((range) => range.end))\n const next = props.value.slice(0, nextStart) + props.value.slice(nextEnd)\n change(\n next,\n props.blocks.filter((block) => !removed.some((range) => range.block.id === block.id))\n )\n setCaret(nextStart)\n }\n const expandToken = (range: TokenRange) => {\n const next =\n props.value.slice(0, range.start) + range.block.content + props.value.slice(range.end)\n change(\n next,\n props.blocks.filter((block) => block.id !== range.block.id)\n )\n closePreview()\n setCaret(range.start + range.block.content.length, true)\n }\n\n const segments = (): Segment[] => {\n const result: Segment[] = []\n let cursor = 0\n for (const range of ranges()) {\n if (range.start > cursor) result.push({ text: props.value.slice(cursor, range.start) })\n result.push({ text: props.value.slice(range.start, range.end), block: range.block })\n cursor = range.end\n }\n if (cursor < props.value.length) result.push({ text: props.value.slice(cursor) })\n if (!result.length) result.push({ text: props.value })\n return result\n }\n\n const scheduleCaretPreview = () => {\n if (isTouchDevice() || props.composing() || !field) {\n closePreview()\n return\n }\n if (field.selectionStart !== field.selectionEnd) {\n closePreview()\n return\n }\n const caret = field.selectionStart\n const range = ranges().find((candidate) => caret > candidate.start && caret < candidate.end)\n if (range) {\n schedulePreview(range.block)\n return\n }\n const snappedRange =\n snappedCaretPreview?.position === caret\n ? ranges().find((candidate) => candidate.block.id === snappedCaretPreview?.blockId)\n : undefined\n if (snappedRange) schedulePreview(snappedRange.block)\n else closePreview()\n }\n\n const openKeyboardPreview = (): boolean => {\n if (!field) return false\n const start = field.selectionStart\n const end = field.selectionEnd\n const range = ranges().find((candidate) =>\n start === end\n ? start >= candidate.start && start <= candidate.end\n : candidate.start < end && candidate.end > start\n )\n if (!range) return false\n clearTimer()\n scheduledBlockId = range.block.id\n setPreview(range.block)\n return true\n }\n\n const schedulePointerPreview = (event: MouseEvent) => {\n if (isTouchDevice() || props.composing() || event.buttons !== 0 || !mirror) {\n closePreview()\n return\n }\n for (const span of mirror.querySelectorAll<HTMLElement>('[data-paste-seq]')) {\n const rect = span.getBoundingClientRect()\n if (\n event.clientX >= rect.left &&\n event.clientX <= rect.right &&\n event.clientY >= rect.top &&\n event.clientY <= rect.bottom\n ) {\n const sequence = Number(span.dataset.pasteSeq)\n const range = ranges().find((candidate) => candidate.block.seq === sequence)\n if (range) schedulePreview(range.block)\n else closePreview()\n return\n }\n }\n closePreview()\n }\n\n const snapSelection = () => {\n if (!field || props.composing() || acceptingTextDrop) return\n const start = field.selectionStart\n const end = field.selectionEnd\n const direction = field.selectionDirection\n const tokenRanges = ranges()\n if (start === end) {\n if (keyboardNavigationPending) return\n scheduleCaretPreview()\n const next = snapToTokenEdge(start, tokenRanges)\n if (next !== start) {\n const range = tokenRanges.find(\n (candidate) => start > candidate.start && start < candidate.end\n )\n if (range) snappedCaretPreview = { blockId: range.block.id, position: next }\n field.setSelectionRange(next, next, direction)\n }\n return\n }\n scheduleCaretPreview()\n const nextStart = snapToTokenEdge(start, tokenRanges)\n const nextEnd = snapToTokenEdge(end, tokenRanges)\n if (nextStart !== start || nextEnd !== end) {\n field.setSelectionRange(Math.min(nextStart, nextEnd), Math.max(nextStart, nextEnd), direction)\n }\n }\n\n const handleKeyDown = (event: KeyboardEvent) => {\n snappedCaretPreview = null\n rawPasteNext =\n (event.metaKey || event.ctrlKey) &&\n event.shiftKey &&\n !event.altKey &&\n event.key.toLowerCase() === 'v'\n if (props.composing() || event.isComposing || event.keyCode === 229 || !field) {\n props.onKeyDown(event)\n return\n }\n if (\n event.key === 'ArrowDown' &&\n event.altKey &&\n !event.metaKey &&\n !event.ctrlKey &&\n !event.shiftKey &&\n openKeyboardPreview()\n ) {\n event.preventDefault()\n props.onKeyDown(event)\n return\n }\n if (event.key === 'Escape' && preview()) closePreview()\n\n const value = props.value\n const start = field.selectionStart\n const end = field.selectionEnd\n const collapsed = start === end\n const tokenRanges = ranges()\n const plainModifier = !event.metaKey && !event.ctrlKey && !event.altKey\n const backspace = event.key === 'Backspace'\n const deletion = backspace || event.key === 'Delete'\n let remove: readonly [number, number] | undefined\n\n if (deletion && !collapsed) {\n if (tokenRanges.some((range) => range.start < end && range.end > start)) remove = [start, end]\n } else if (deletion) {\n const adjacent = tokenRanges.find((range) =>\n backspace ? range.end === start : range.start === start\n )\n if (adjacent && (plainModifier || event.altKey || event.ctrlKey)) {\n remove = [adjacent.start, adjacent.end]\n } else if (event.metaKey) {\n const boundary = backspace\n ? value.lastIndexOf('\\n', start - 1) + 1\n : value.indexOf('\\n', start)\n const from = backspace ? boundary : start\n const to = backspace ? start : boundary < 0 ? value.length : boundary\n if (tokenRanges.some((range) => range.start < to && range.end > from)) remove = [from, to]\n }\n }\n if (remove) {\n event.preventDefault()\n replaceRange(remove[0], remove[1])\n props.onKeyDown(event)\n return\n }\n\n if (plainModifier && collapsed && !event.shiftKey) {\n const left = event.key === 'ArrowLeft'\n const right = event.key === 'ArrowRight'\n const adjacent = left\n ? tokenRanges.find((range) => range.end === start)\n : right\n ? tokenRanges.find((range) => range.start === start)\n : undefined\n if (adjacent) {\n event.preventDefault()\n setCaret(left ? adjacent.start : adjacent.end)\n props.onKeyDown(event)\n return\n }\n }\n if (!event.metaKey && !event.ctrlKey && !event.altKey && event.shiftKey) {\n const direction = field.selectionDirection === 'backward' ? 'backward' : 'forward'\n const active = direction === 'backward' ? start : end\n const adjacent =\n event.key === 'ArrowLeft'\n ? tokenRanges.find((range) => range.end === active)\n : event.key === 'ArrowRight'\n ? tokenRanges.find((range) => range.start === active)\n : undefined\n if (adjacent) {\n event.preventDefault()\n requestAnimationFrame(() => {\n if (!field) return\n if (event.key === 'ArrowLeft' && direction === 'backward')\n field.setSelectionRange(adjacent.start, end, 'backward')\n else if (event.key === 'ArrowLeft')\n field.setSelectionRange(\n start,\n adjacent.start,\n start <= adjacent.start ? 'forward' : 'backward'\n )\n else if (direction === 'backward')\n field.setSelectionRange(adjacent.end, end, adjacent.end <= end ? 'backward' : 'forward')\n else field.setSelectionRange(start, adjacent.end, 'forward')\n })\n props.onKeyDown(event)\n return\n }\n }\n\n const navigation =\n event.key === 'Home' ||\n event.key === 'End' ||\n ((event.key === 'ArrowLeft' || event.key === 'ArrowRight') &&\n (event.metaKey || event.ctrlKey || event.altKey))\n if (navigation) {\n const leftward = event.key === 'ArrowLeft' || event.key === 'Home'\n keyboardNavigationPending = true\n requestAnimationFrame(() => {\n if (field) {\n const nextRanges = findTokenRanges(field.value, props.blocks)\n const edge = leftward ? 'start' : 'end'\n const nextStart = snapToTokenEdge(field.selectionStart, nextRanges, edge)\n const nextEnd = snapToTokenEdge(field.selectionEnd, nextRanges, edge)\n if (nextStart !== field.selectionStart || nextEnd !== field.selectionEnd) {\n field.setSelectionRange(\n Math.min(nextStart, nextEnd),\n Math.max(nextStart, nextEnd),\n field.selectionDirection\n )\n }\n }\n keyboardNavigationPending = false\n })\n }\n props.onKeyDown(event)\n }\n\n const expandSelectionForClipboard = (start: number, end: number): string | null => {\n if (start === end) return null\n const covered = ranges().filter((range) => range.start >= start && range.end <= end)\n if (!covered.length) return null\n let result = ''\n let cursor = start\n for (const range of covered) {\n result += props.value.slice(cursor, range.start) + range.block.content\n cursor = range.end\n }\n return result + props.value.slice(cursor, end)\n }\n\n const handlePaste = (event: ClipboardEvent) => {\n const forceRaw = rawPasteNext\n rawPasteNext = false\n const pasted = event.clipboardData?.getData('text/plain') ?? ''\n if (!pasted || !field || props.readOnly || props.disabled) return\n const cleaned = forceRaw ? pasted : stripTrailingBlankLines(pasted)\n const start = field.selectionStart\n const end = field.selectionEnd\n const before = props.value.slice(0, start)\n const after = props.value.slice(end)\n\n if (!forceRaw && shouldCollapse(cleaned)) {\n const id = props.createBlockId()\n if (props.blocks.some((block) => block.id === id)) return\n const block: PasteBlock = {\n id,\n seq: nextSeq([...props.blocks]),\n lines: countLines(cleaned),\n content: cleaned,\n }\n if (!isPasteBlock(block)) return\n const linePrefix = before.slice(before.lastIndexOf('\\n') + 1)\n const leading =\n before && !before.endsWith('\\n') && !isBlockquotePrefix(linePrefix) ? '\\n' : ''\n const trailing = after && !after.startsWith('\\n') ? '\\n' : ''\n const insert = leading + formatToken(block) + trailing\n event.preventDefault()\n change(before + insert + after, [...props.blocks, block])\n closePreview()\n setCaret(before.length + insert.length)\n return\n }\n if (forceRaw) return\n if (cleaned !== pasted && cleaned !== '') {\n event.preventDefault()\n const next = before + cleaned + after\n nativePasteInputSeen = false\n suppressPasteInput = true\n let inserted = false\n try {\n inserted =\n typeof document.execCommand === 'function' &&\n document.execCommand('insertText', false, cleaned)\n } catch {\n inserted = false\n }\n if (!nativePasteInputSeen) suppressPasteInput = false\n change(next)\n if (inserted && field.value === next) return\n setCaret(before.length + cleaned.length)\n }\n }\n\n const handleDragOver = (event: DragEvent) => {\n if (!field || props.readOnly || props.disabled || props.composing()) return\n if (event.dataTransfer?.types.includes('text/plain')) {\n acceptingTextDrop = true\n closePreview()\n event.preventDefault()\n }\n }\n\n const handleDragLeave = () => {\n acceptingTextDrop = false\n }\n\n const handleDrop = (event: DragEvent) => {\n if (!field || props.readOnly || props.disabled || props.composing()) {\n acceptingTextDrop = false\n return\n }\n if (!event.dataTransfer?.types.includes('text/plain')) {\n acceptingTextDrop = false\n return\n }\n const dropped = event.dataTransfer.getData('text/plain')\n event.preventDefault()\n acceptingTextDrop = false\n if (!dropped) return\n\n const tokenRanges = ranges()\n let start = field.selectionStart\n let end = field.selectionEnd\n const removed = tokenRanges.filter((range) =>\n start === end\n ? start > range.start && start < range.end\n : range.start < end && range.end > start\n )\n if (removed.length) {\n start = Math.min(start, ...removed.map((range) => range.start))\n end = Math.max(end, ...removed.map((range) => range.end))\n }\n\n change(props.value.slice(0, start) + dropped + props.value.slice(end))\n closePreview()\n setCaret(start + dropped.length)\n }\n\n const handleClipboard = (event: ClipboardEvent) => {\n if (!field || !event.clipboardData) return\n const start = field.selectionStart\n const end = field.selectionEnd\n const expanded = expandSelectionForClipboard(start, end)\n if (expanded === null) return\n event.clipboardData.setData('text/plain', expanded)\n event.preventDefault()\n if (event.type === 'cut') {\n change(props.value.slice(0, start) + props.value.slice(end))\n setCaret(start)\n }\n }\n\n const handleClick = (event: MouseEvent) => {\n if (!field || !props.blocks.length) return\n const range = tokenRangeAt(props.value, props.blocks, field.selectionStart)\n if (!range) return\n if (isTouchDevice() || event.detail >= 2) expandToken(range)\n else {\n requestAnimationFrame(() => field?.setSelectionRange(range.start, range.end))\n }\n }\n\n createEffect(on(() => props.value, closePreview))\n createEffect(on(() => props.blocks, closePreview))\n createEffect(\n on(\n () => props.resetKey,\n () => {\n rawPasteNext = false\n closePreview()\n }\n )\n )\n onMount(() => {\n window.addEventListener('scroll', closePreview, true)\n window.addEventListener('resize', closePreview)\n onCleanup(() => {\n window.removeEventListener('scroll', closePreview, true)\n window.removeEventListener('resize', closePreview)\n })\n })\n onCleanup(() => clearTimer())\n\n return (\n <KobalteTooltip\n open={!!preview()}\n onOpenChange={(open) => {\n if (!open) closePreview()\n }}\n openDelay={PREVIEW_OPEN_DELAY_MS}\n >\n <KobalteTooltip.Trigger as=\"div\" class=\"relative\">\n <div\n ref={(element) => (mirror = element)}\n data-slot=\"paste-token-mirror\"\n aria-hidden=\"true\"\n class=\"pointer-events-none absolute inset-0 overflow-hidden select-none whitespace-pre-wrap break-words px-4 py-3 text-sm text-transparent\"\n >\n <For each={segments()}>\n {(segment) =>\n segment.block ? (\n <span\n class=\"box-decoration-clone rounded-md bg-primary-subtle\"\n data-paste-seq={segment.block.seq}\n >\n {segment.text}\n </span>\n ) : (\n <span>{segment.text}</span>\n )\n }\n </For>\n {props.value.endsWith('\\n') ? '\\u200b' : ''}\n </div>\n <textarea\n ref={(element) => {\n field = element\n props.ref(element)\n onCleanup(() => {\n if (field === element) field = undefined\n props.ref(undefined)\n })\n }}\n data-slot=\"composer-input\"\n aria-label={props.inputLabel}\n aria-describedby={preview() ? `${keyboardHintId} ${descriptionId}` : keyboardHintId}\n aria-keyshortcuts=\"Alt+ArrowDown\"\n class=\"relative field-sizing-content text-foreground placeholder:text-muted-foreground min-h-11 max-h-36 w-full resize-none border-0 bg-transparent px-4 py-3 text-sm outline-none disabled:opacity-50\"\n value={props.value}\n disabled={props.disabled}\n readOnly={props.readOnly}\n placeholder={props.placeholder}\n rows={1}\n onInput={(event) => {\n if (suppressPasteInput) {\n suppressPasteInput = false\n nativePasteInputSeen = true\n return\n }\n change(event.currentTarget.value)\n }}\n onPaste={handlePaste}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n onCopy={handleClipboard}\n onCut={handleClipboard}\n onClick={handleClick}\n onSelect={snapSelection}\n onMouseMove={schedulePointerPreview}\n onMouseLeave={closePreview}\n onScroll={(event) => {\n if (mirror) {\n mirror.scrollTop = event.currentTarget.scrollTop\n mirror.scrollLeft = event.currentTarget.scrollLeft\n }\n closePreview()\n }}\n onCompositionStart={props.onCompositionStart}\n onCompositionEnd={props.onCompositionEnd}\n onFocus={props.onFocus}\n onBlur={() => {\n rawPasteNext = false\n acceptingTextDrop = false\n props.onBlur()\n closePreview()\n }}\n onKeyDown={handleKeyDown}\n />\n <span id={keyboardHintId} class=\"visually-hidden\">\n When the caret is next to a paste token or a token is selected, press Alt+Down Arrow to\n preview its text. Press Escape to close the preview.\n </span>\n </KobalteTooltip.Trigger>\n <Show when={previewSummary()}>\n {(summary) => (\n <KobalteTooltip.Portal>\n <KobalteTooltip.Content\n id={descriptionId}\n data-slot=\"paste-token-preview\"\n class=\"bg-scrim text-scrim-foreground z-(--z-tooltip) w-fit max-w-64 rounded-md px-2 py-1 text-xs origin-(--kb-tooltip-content-transform-origin) text-balance data-expanded:animate-in data-expanded:fade-in-0 data-expanded:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 data-expanded:duration-150 data-closed:duration-100\"\n >\n <pre class=\"m-0 max-h-48 max-w-64 overflow-y-auto whitespace-pre-wrap break-words font-mono\">\n {summary().text}\n </pre>\n <Show when={summary().hiddenLines > 0}>\n <span>+{summary().hiddenLines} more lines</span>\n </Show>\n <Show when={summary().hiddenLines === 0 && summary().hiddenCharacters > 0}>\n <span>+{summary().hiddenCharacters} more characters</span>\n </Show>\n <KobalteTooltip.Arrow aria-hidden=\"true\" />\n </KobalteTooltip.Content>\n </KobalteTooltip.Portal>\n )}\n </Show>\n </KobalteTooltip>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paste-tokens.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/paste-tokens.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,mEAAmE;AACnE,MAAM,WAAW,UAAU;IACzB,qFAAqF;IACrF,EAAE,EAAE,MAAM,CAAA;IACV,yEAAyE;IACzE,GAAG,EAAE,MAAM,CAAA;IACX,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAA;IACb,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,eAAO,MAAM,qBAAqB,IAAI,CAAA;AACtC,eAAO,MAAM,qBAAqB,MAAM,CAAA;AAMxC,kFAAkF;AAClF,eAAO,MAAM,iBAAiB,QAAsC,CAAA;AAMpE,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAUhE;AAaD,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAGrD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"paste-tokens.d.ts","sourceRoot":"","sources":["../../../src/components/conversation/paste-tokens.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,mEAAmE;AACnE,MAAM,WAAW,UAAU;IACzB,qFAAqF;IACrF,EAAE,EAAE,MAAM,CAAA;IACV,yEAAyE;IACzE,GAAG,EAAE,MAAM,CAAA;IACX,oDAAoD;IACpD,KAAK,EAAE,MAAM,CAAA;IACb,+CAA+C;IAC/C,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,eAAO,MAAM,qBAAqB,IAAI,CAAA;AACtC,eAAO,MAAM,qBAAqB,MAAM,CAAA;AAMxC,kFAAkF;AAClF,eAAO,MAAM,iBAAiB,QAAsC,CAAA;AAMpE,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,UAAU,CAUhE;AAaD,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAGrD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAWpD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQ/C;AAED,uEAAuE;AACvE,wBAAgB,OAAO,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,GAAG,MAAM,CAO7D;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,SAAS,UAAU,EAAE,EAC9B,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,GAChB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,UAAU,EAAE,CAAA;CAAE,CAiDxC;AAED,iFAAiF;AACjF,wBAAgB,eAAe,CAC7B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,SAAS,UAAU,EAAE,GAC5B,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,CAAC,CAkB1D;AAED,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,SAAS,UAAU,EAAE,EAC7B,KAAK,EAAE,MAAM,GACZ;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,GAAG,IAAI,CAM1D;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAQ5E;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,UAAU,EAAE,GAAG,MAAM,CAU7E;AAED,iFAAiF;AACjF,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,UAAU,EAAE,GAAG,MAAM,CAgDvF;AAED,6EAA6E;AAC7E,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAiB7D"}
|
|
@@ -31,11 +31,20 @@ function formatToken(block) {
|
|
|
31
31
|
}
|
|
32
32
|
function shouldCollapse(text) {
|
|
33
33
|
if (!text) return false;
|
|
34
|
-
|
|
34
|
+
if (text.length >= 200) return true;
|
|
35
|
+
let lines = 1;
|
|
36
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
37
|
+
if (text.charCodeAt(index) !== 10) continue;
|
|
38
|
+
lines += 1;
|
|
39
|
+
if (lines >= 3) return true;
|
|
40
|
+
}
|
|
41
|
+
return false;
|
|
35
42
|
}
|
|
36
43
|
function countLines(text) {
|
|
37
44
|
if (!text) return 0;
|
|
38
|
-
|
|
45
|
+
let lines = 1;
|
|
46
|
+
for (let index = 0; index < text.length; index += 1) if (text.charCodeAt(index) === 10) lines += 1;
|
|
47
|
+
return lines;
|
|
39
48
|
}
|
|
40
49
|
/** Next sequence for a new paste = max existing + 1, starting at 1. */
|
|
41
50
|
function nextSeq(blocks) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paste-tokens.js","names":[],"sources":["../../../src/components/conversation/paste-tokens.ts"],"sourcesContent":["/**\n * Pure paste-token transformations translated and hardened from KiroCrew's\n * `website/src/utils/pasteTokens.ts` at revision\n * `283e136c0f902e965a535a7c9548c57c7504fed0` (Apache-2.0). See the #532 entry\n * in the repository NOTICE. Paste identity is supplied by the host; this module\n * does not access storage, clipboard APIs, message services, or editor state.\n */\n\n/** A collapsed paste block stored alongside input or a message. */\nexport interface PasteBlock {\n /** A stable host-provided ASCII identifier; never included in visible token text. */\n id: string\n /** Positive safe integer, unique among blocks in the same text value. */\n seq: number\n /** Positive safe integer displayed in the token. */\n lines: number\n /** Original pasted text, retained verbatim. */\n content: string\n}\n\nexport const PASTE_THRESHOLD_LINES = 3\nexport const PASTE_THRESHOLD_CHARS = 200\n\nconst PASTE_ID_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/\nconst MAX_SAFE_SEQUENCE_TEXT_LENGTH = String(Number.MAX_SAFE_INTEGER).length\nconst PASTE_TOKEN_SOURCE = String.raw`\\[ Paste #([1-9]\\d{0,${MAX_SAFE_SEQUENCE_TEXT_LENGTH - 1}}) · ([1-9]\\d{0,${MAX_SAFE_SEQUENCE_TEXT_LENGTH - 1}}) lines \\]`\n\n/** Canonical token pattern. Internal scans always use a fresh RegExp instance. */\nexport const PASTE_TOKEN_REGEX = new RegExp(PASTE_TOKEN_SOURCE, 'g')\n\nfunction isPositiveSafeInteger(value: unknown): value is number {\n return Number.isSafeInteger(value) && (value as number) > 0\n}\n\n/** Check data received from a host before using it as a paste-token block. */\nexport function isPasteBlock(value: unknown): value is PasteBlock {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false\n const candidate = value as Record<string, unknown>\n return (\n typeof candidate.id === 'string' &&\n PASTE_ID_PATTERN.test(candidate.id) &&\n isPositiveSafeInteger(candidate.seq) &&\n isPositiveSafeInteger(candidate.lines) &&\n typeof candidate.content === 'string'\n )\n}\n\nfunction unambiguousBlocks(blocks: readonly PasteBlock[]): PasteBlock[] {\n const valid = blocks.filter(isPasteBlock)\n const seqCounts = new Map<number, number>()\n const idCounts = new Map<string, number>()\n for (const block of valid) {\n seqCounts.set(block.seq, (seqCounts.get(block.seq) ?? 0) + 1)\n idCounts.set(block.id, (idCounts.get(block.id) ?? 0) + 1)\n }\n return valid.filter((block) => seqCounts.get(block.seq) === 1 && idCounts.get(block.id) === 1)\n}\n\nexport function formatToken(block: PasteBlock): string {\n if (!isPasteBlock(block)) throw new TypeError('Cannot format an invalid paste block')\n return `[ Paste #${block.seq} · ${block.lines} lines ]`\n}\n\nexport function shouldCollapse(text: string): boolean {\n if (!text) return false\n return countLines(text) >= PASTE_THRESHOLD_LINES || text.length >= PASTE_THRESHOLD_CHARS\n}\n\nexport function countLines(text: string): number {\n if (!text) return 0\n return text.split('\\n').length\n}\n\n/** Next sequence for a new paste = max existing + 1, starting at 1. */\nexport function nextSeq(blocks: readonly PasteBlock[]): number {\n let max = 0\n for (const block of blocks) {\n if (isPasteBlock(block) && block.seq > max) max = block.seq\n }\n if (max === Number.MAX_SAFE_INTEGER) throw new RangeError('Paste sequence space is exhausted')\n return max + 1\n}\n\n/**\n * Re-sequence `carried` blocks whose sequence is already taken by `used`, and\n * rewrite their markers in one right-to-left pass. Carried block IDs and\n * sequences must be unique so a visible marker always has one backing block.\n * `used` is mutated to include the assigned sequences.\n */\nexport function remapCarriedBlocks(\n text: string,\n carried: readonly PasteBlock[],\n used: Set<number>\n): { text: string; blocks: PasteBlock[] } {\n const seenSeqs = new Set<number>()\n const seenIds = new Set<string>()\n for (const block of carried) {\n if (!isPasteBlock(block)) throw new TypeError('Cannot remap an invalid paste block')\n if (seenSeqs.has(block.seq) || seenIds.has(block.id)) {\n throw new TypeError('Carried paste block IDs and sequences must be unique')\n }\n seenSeqs.add(block.seq)\n seenIds.add(block.id)\n }\n\n let maxUsed = 0\n for (const value of used) {\n if (isPositiveSafeInteger(value) && value > maxUsed) maxUsed = value\n }\n let free = maxUsed < Number.MAX_SAFE_INTEGER ? maxUsed + 1 : 1\n const allocateFree = (): number => {\n while (used.has(free)) {\n free = free < Number.MAX_SAFE_INTEGER ? free + 1 : 1\n }\n const assigned = free\n used.add(assigned)\n free = assigned < Number.MAX_SAFE_INTEGER ? assigned + 1 : 1\n return assigned\n }\n\n const remap = new Map<number, number>()\n const blocks = carried.map((block) => {\n if (!used.has(block.seq)) {\n used.add(block.seq)\n return block\n }\n const seq = allocateFree()\n remap.set(block.seq, seq)\n return { ...block, seq }\n })\n\n if (!remap.size) return { text, blocks }\n\n let out = text\n const ranges = findTokenRanges(text, carried)\n for (let index = ranges.length - 1; index >= 0; index -= 1) {\n const { start, end, block } = ranges[index]!\n const mapped = remap.get(block.seq)\n if (mapped === undefined) continue\n out = out.slice(0, start) + formatToken({ ...block, seq: mapped }) + out.slice(end)\n }\n return { text: out, blocks }\n}\n\n/** Ranges for canonical tokens whose sequence and line count match one block. */\nexport function findTokenRanges(\n text: string,\n blocks: readonly PasteBlock[]\n): Array<{ start: number; end: number; block: PasteBlock }> {\n if (!text || !blocks.length) return []\n const bySeq = new Map(unambiguousBlocks(blocks).map((block) => [block.seq, block]))\n if (!bySeq.size) return []\n\n const tokenRegex = new RegExp(PASTE_TOKEN_SOURCE, 'g')\n const ranges: Array<{ start: number; end: number; block: PasteBlock }> = []\n let match: RegExpExecArray | null\n while ((match = tokenRegex.exec(text)) !== null) {\n const seq = Number(match[1])\n const lines = Number(match[2])\n if (!isPositiveSafeInteger(seq) || !isPositiveSafeInteger(lines)) continue\n const block = bySeq.get(seq)\n if (block && block.lines === lines) {\n ranges.push({ start: match.index, end: match.index + match[0].length, block })\n }\n }\n return ranges\n}\n\nexport function tokenRangeAt(\n text: string,\n blocks: readonly PasteBlock[],\n caret: number\n): { start: number; end: number; block: PasteBlock } | null {\n if (!Number.isSafeInteger(caret) || caret < 0 || caret > text.length) return null\n for (const range of findTokenRanges(text, blocks)) {\n if (caret >= range.start && caret <= range.end) return range\n }\n return null\n}\n\nexport function pruneBlocks(text: string, blocks: PasteBlock[]): PasteBlock[] {\n if (!blocks.length) return blocks\n const usable = unambiguousBlocks(blocks)\n const survivors = new Set(findTokenRanges(text, usable).map((range) => range.block.id))\n const next = usable.filter((block) => survivors.has(block.id))\n return next.length === blocks.length && next.every((block, index) => block === blocks[index])\n ? blocks\n : next\n}\n\nexport function expandAll(text: string, blocks: readonly PasteBlock[]): string {\n if (!text || !blocks.length) return text\n const ranges = findTokenRanges(text, blocks)\n if (!ranges.length) return text\n let out = text\n for (let index = ranges.length - 1; index >= 0; index -= 1) {\n const range = ranges[index]!\n out = out.slice(0, range.start) + range.block.content + out.slice(range.end)\n }\n return out\n}\n\n/** Inverse of `expandAll`: replace each first non-overlapping verbatim block. */\nexport function recollapsePastes(content: string, blocks: readonly PasteBlock[]): string {\n if (!content || !blocks.length) return content\n\n interface Hit {\n start: number\n end: number\n block: PasteBlock\n }\n const hits: Hit[] = []\n const claimed: Array<[number, number]> = []\n const firstUnclaimed = (needle: string): number => {\n if (!needle) return -1\n let from = 0\n while (from <= content.length) {\n const index = content.indexOf(needle, from)\n if (index < 0) return -1\n if (!claimed.some(([start, end]) => index < end && index + needle.length > start))\n return index\n from = index + 1\n }\n return -1\n }\n\n for (const block of unambiguousBlocks(blocks)) {\n if (!block.content) continue\n const trimmed = block.content.trimEnd()\n let needle = block.content\n let index = firstUnclaimed(needle)\n if (index < 0 && trimmed && trimmed !== block.content) {\n needle = trimmed\n index = firstUnclaimed(needle)\n }\n if (index < 0) continue\n const end = index + needle.length\n hits.push({ start: index, end, block })\n claimed.push([index, end])\n }\n\n if (!hits.length) return content\n hits.sort((left, right) => left.start - right.start)\n let out = ''\n let position = 0\n for (const hit of hits) {\n if (hit.start < position) continue\n out += content.slice(position, hit.start) + formatToken(hit.block)\n position = hit.end\n }\n return out + content.slice(position)\n}\n\n/** Strip a trailing whitespace run only when that run contains a newline. */\nexport function stripTrailingBlankLines(value: string): string {\n let index = value.length - 1\n let sawNewline = false\n while (index >= 0) {\n const code = value.charCodeAt(index)\n if (code === 10 || code === 13) {\n sawNewline = true\n index -= 1\n continue\n }\n if (code === 32 || code === 9) {\n index -= 1\n continue\n }\n break\n }\n return sawNewline ? value.slice(0, index + 1) : value\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"paste-tokens.js","names":[],"sources":["../../../src/components/conversation/paste-tokens.ts"],"sourcesContent":["/**\n * Pure paste-token transformations translated and hardened from KiroCrew's\n * `website/src/utils/pasteTokens.ts` at revision\n * `283e136c0f902e965a535a7c9548c57c7504fed0` (Apache-2.0). See the #532 entry\n * in the repository NOTICE. Paste identity is supplied by the host; this module\n * does not access storage, clipboard APIs, message services, or editor state.\n */\n\n/** A collapsed paste block stored alongside input or a message. */\nexport interface PasteBlock {\n /** A stable host-provided ASCII identifier; never included in visible token text. */\n id: string\n /** Positive safe integer, unique among blocks in the same text value. */\n seq: number\n /** Positive safe integer displayed in the token. */\n lines: number\n /** Original pasted text, retained verbatim. */\n content: string\n}\n\nexport const PASTE_THRESHOLD_LINES = 3\nexport const PASTE_THRESHOLD_CHARS = 200\n\nconst PASTE_ID_PATTERN = /^[A-Za-z0-9._:-]{1,128}$/\nconst MAX_SAFE_SEQUENCE_TEXT_LENGTH = String(Number.MAX_SAFE_INTEGER).length\nconst PASTE_TOKEN_SOURCE = String.raw`\\[ Paste #([1-9]\\d{0,${MAX_SAFE_SEQUENCE_TEXT_LENGTH - 1}}) · ([1-9]\\d{0,${MAX_SAFE_SEQUENCE_TEXT_LENGTH - 1}}) lines \\]`\n\n/** Canonical token pattern. Internal scans always use a fresh RegExp instance. */\nexport const PASTE_TOKEN_REGEX = new RegExp(PASTE_TOKEN_SOURCE, 'g')\n\nfunction isPositiveSafeInteger(value: unknown): value is number {\n return Number.isSafeInteger(value) && (value as number) > 0\n}\n\n/** Check data received from a host before using it as a paste-token block. */\nexport function isPasteBlock(value: unknown): value is PasteBlock {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) return false\n const candidate = value as Record<string, unknown>\n return (\n typeof candidate.id === 'string' &&\n PASTE_ID_PATTERN.test(candidate.id) &&\n isPositiveSafeInteger(candidate.seq) &&\n isPositiveSafeInteger(candidate.lines) &&\n typeof candidate.content === 'string'\n )\n}\n\nfunction unambiguousBlocks(blocks: readonly PasteBlock[]): PasteBlock[] {\n const valid = blocks.filter(isPasteBlock)\n const seqCounts = new Map<number, number>()\n const idCounts = new Map<string, number>()\n for (const block of valid) {\n seqCounts.set(block.seq, (seqCounts.get(block.seq) ?? 0) + 1)\n idCounts.set(block.id, (idCounts.get(block.id) ?? 0) + 1)\n }\n return valid.filter((block) => seqCounts.get(block.seq) === 1 && idCounts.get(block.id) === 1)\n}\n\nexport function formatToken(block: PasteBlock): string {\n if (!isPasteBlock(block)) throw new TypeError('Cannot format an invalid paste block')\n return `[ Paste #${block.seq} · ${block.lines} lines ]`\n}\n\nexport function shouldCollapse(text: string): boolean {\n if (!text) return false\n if (text.length >= PASTE_THRESHOLD_CHARS) return true\n\n let lines = 1\n for (let index = 0; index < text.length; index += 1) {\n if (text.charCodeAt(index) !== 10) continue\n lines += 1\n if (lines >= PASTE_THRESHOLD_LINES) return true\n }\n return false\n}\n\nexport function countLines(text: string): number {\n if (!text) return 0\n\n let lines = 1\n for (let index = 0; index < text.length; index += 1) {\n if (text.charCodeAt(index) === 10) lines += 1\n }\n return lines\n}\n\n/** Next sequence for a new paste = max existing + 1, starting at 1. */\nexport function nextSeq(blocks: readonly PasteBlock[]): number {\n let max = 0\n for (const block of blocks) {\n if (isPasteBlock(block) && block.seq > max) max = block.seq\n }\n if (max === Number.MAX_SAFE_INTEGER) throw new RangeError('Paste sequence space is exhausted')\n return max + 1\n}\n\n/**\n * Re-sequence `carried` blocks whose sequence is already taken by `used`, and\n * rewrite their markers in one right-to-left pass. Carried block IDs and\n * sequences must be unique so a visible marker always has one backing block.\n * `used` is mutated to include the assigned sequences.\n */\nexport function remapCarriedBlocks(\n text: string,\n carried: readonly PasteBlock[],\n used: Set<number>\n): { text: string; blocks: PasteBlock[] } {\n const seenSeqs = new Set<number>()\n const seenIds = new Set<string>()\n for (const block of carried) {\n if (!isPasteBlock(block)) throw new TypeError('Cannot remap an invalid paste block')\n if (seenSeqs.has(block.seq) || seenIds.has(block.id)) {\n throw new TypeError('Carried paste block IDs and sequences must be unique')\n }\n seenSeqs.add(block.seq)\n seenIds.add(block.id)\n }\n\n let maxUsed = 0\n for (const value of used) {\n if (isPositiveSafeInteger(value) && value > maxUsed) maxUsed = value\n }\n let free = maxUsed < Number.MAX_SAFE_INTEGER ? maxUsed + 1 : 1\n const allocateFree = (): number => {\n while (used.has(free)) {\n free = free < Number.MAX_SAFE_INTEGER ? free + 1 : 1\n }\n const assigned = free\n used.add(assigned)\n free = assigned < Number.MAX_SAFE_INTEGER ? assigned + 1 : 1\n return assigned\n }\n\n const remap = new Map<number, number>()\n const blocks = carried.map((block) => {\n if (!used.has(block.seq)) {\n used.add(block.seq)\n return block\n }\n const seq = allocateFree()\n remap.set(block.seq, seq)\n return { ...block, seq }\n })\n\n if (!remap.size) return { text, blocks }\n\n let out = text\n const ranges = findTokenRanges(text, carried)\n for (let index = ranges.length - 1; index >= 0; index -= 1) {\n const { start, end, block } = ranges[index]!\n const mapped = remap.get(block.seq)\n if (mapped === undefined) continue\n out = out.slice(0, start) + formatToken({ ...block, seq: mapped }) + out.slice(end)\n }\n return { text: out, blocks }\n}\n\n/** Ranges for canonical tokens whose sequence and line count match one block. */\nexport function findTokenRanges(\n text: string,\n blocks: readonly PasteBlock[]\n): Array<{ start: number; end: number; block: PasteBlock }> {\n if (!text || !blocks.length) return []\n const bySeq = new Map(unambiguousBlocks(blocks).map((block) => [block.seq, block]))\n if (!bySeq.size) return []\n\n const tokenRegex = new RegExp(PASTE_TOKEN_SOURCE, 'g')\n const ranges: Array<{ start: number; end: number; block: PasteBlock }> = []\n let match: RegExpExecArray | null\n while ((match = tokenRegex.exec(text)) !== null) {\n const seq = Number(match[1])\n const lines = Number(match[2])\n if (!isPositiveSafeInteger(seq) || !isPositiveSafeInteger(lines)) continue\n const block = bySeq.get(seq)\n if (block && block.lines === lines) {\n ranges.push({ start: match.index, end: match.index + match[0].length, block })\n }\n }\n return ranges\n}\n\nexport function tokenRangeAt(\n text: string,\n blocks: readonly PasteBlock[],\n caret: number\n): { start: number; end: number; block: PasteBlock } | null {\n if (!Number.isSafeInteger(caret) || caret < 0 || caret > text.length) return null\n for (const range of findTokenRanges(text, blocks)) {\n if (caret >= range.start && caret <= range.end) return range\n }\n return null\n}\n\nexport function pruneBlocks(text: string, blocks: PasteBlock[]): PasteBlock[] {\n if (!blocks.length) return blocks\n const usable = unambiguousBlocks(blocks)\n const survivors = new Set(findTokenRanges(text, usable).map((range) => range.block.id))\n const next = usable.filter((block) => survivors.has(block.id))\n return next.length === blocks.length && next.every((block, index) => block === blocks[index])\n ? blocks\n : next\n}\n\nexport function expandAll(text: string, blocks: readonly PasteBlock[]): string {\n if (!text || !blocks.length) return text\n const ranges = findTokenRanges(text, blocks)\n if (!ranges.length) return text\n let out = text\n for (let index = ranges.length - 1; index >= 0; index -= 1) {\n const range = ranges[index]!\n out = out.slice(0, range.start) + range.block.content + out.slice(range.end)\n }\n return out\n}\n\n/** Inverse of `expandAll`: replace each first non-overlapping verbatim block. */\nexport function recollapsePastes(content: string, blocks: readonly PasteBlock[]): string {\n if (!content || !blocks.length) return content\n\n interface Hit {\n start: number\n end: number\n block: PasteBlock\n }\n const hits: Hit[] = []\n const claimed: Array<[number, number]> = []\n const firstUnclaimed = (needle: string): number => {\n if (!needle) return -1\n let from = 0\n while (from <= content.length) {\n const index = content.indexOf(needle, from)\n if (index < 0) return -1\n if (!claimed.some(([start, end]) => index < end && index + needle.length > start))\n return index\n from = index + 1\n }\n return -1\n }\n\n for (const block of unambiguousBlocks(blocks)) {\n if (!block.content) continue\n const trimmed = block.content.trimEnd()\n let needle = block.content\n let index = firstUnclaimed(needle)\n if (index < 0 && trimmed && trimmed !== block.content) {\n needle = trimmed\n index = firstUnclaimed(needle)\n }\n if (index < 0) continue\n const end = index + needle.length\n hits.push({ start: index, end, block })\n claimed.push([index, end])\n }\n\n if (!hits.length) return content\n hits.sort((left, right) => left.start - right.start)\n let out = ''\n let position = 0\n for (const hit of hits) {\n if (hit.start < position) continue\n out += content.slice(position, hit.start) + formatToken(hit.block)\n position = hit.end\n }\n return out + content.slice(position)\n}\n\n/** Strip a trailing whitespace run only when that run contains a newline. */\nexport function stripTrailingBlankLines(value: string): string {\n let index = value.length - 1\n let sawNewline = false\n while (index >= 0) {\n const code = value.charCodeAt(index)\n if (code === 10 || code === 13) {\n sawNewline = true\n index -= 1\n continue\n }\n if (code === 32 || code === 9) {\n index -= 1\n continue\n }\n break\n }\n return sawNewline ? value.slice(0, index + 1) : value\n}\n"],"mappings":"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"}
|
package/dist/r/conversation.json
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
"title": "Conversation",
|
|
5
5
|
"description": "",
|
|
6
6
|
"dependencies": [
|
|
7
|
+
"@kobalte/core@^0.13.14",
|
|
7
8
|
"lucide-solid@^1.48.0"
|
|
8
9
|
],
|
|
9
10
|
"registryDependencies": [
|
|
@@ -17,6 +18,16 @@
|
|
|
17
18
|
"lib"
|
|
18
19
|
],
|
|
19
20
|
"files": [
|
|
21
|
+
{
|
|
22
|
+
"path": "src/components/conversation/atomic/chat-composer.tsx",
|
|
23
|
+
"type": "registry:ui",
|
|
24
|
+
"target": "components/conversation/atomic/chat-composer.tsx"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"path": "src/components/conversation/atomic/index.ts",
|
|
28
|
+
"type": "registry:ui",
|
|
29
|
+
"target": "components/conversation/atomic/index.ts"
|
|
30
|
+
},
|
|
20
31
|
{
|
|
21
32
|
"path": "src/components/conversation/busy-send-button.tsx",
|
|
22
33
|
"type": "registry:ui",
|
|
@@ -47,6 +58,11 @@
|
|
|
47
58
|
"type": "registry:ui",
|
|
48
59
|
"target": "components/conversation/index.ts"
|
|
49
60
|
},
|
|
61
|
+
{
|
|
62
|
+
"path": "src/components/conversation/internal/chat-composer-shell.tsx",
|
|
63
|
+
"type": "registry:ui",
|
|
64
|
+
"target": "components/conversation/internal/chat-composer-shell.tsx"
|
|
65
|
+
},
|
|
50
66
|
{
|
|
51
67
|
"path": "src/components/conversation/message-composer.tsx",
|
|
52
68
|
"type": "registry:ui",
|
|
@@ -57,6 +73,16 @@
|
|
|
57
73
|
"type": "registry:ui",
|
|
58
74
|
"target": "components/conversation/message-row.tsx"
|
|
59
75
|
},
|
|
76
|
+
{
|
|
77
|
+
"path": "src/components/conversation/paste-preview.ts",
|
|
78
|
+
"type": "registry:ui",
|
|
79
|
+
"target": "components/conversation/paste-preview.ts"
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"path": "src/components/conversation/paste-token-editor.tsx",
|
|
83
|
+
"type": "registry:ui",
|
|
84
|
+
"target": "components/conversation/paste-token-editor.tsx"
|
|
85
|
+
},
|
|
60
86
|
{
|
|
61
87
|
"path": "src/components/conversation/paste-tokens.ts",
|
|
62
88
|
"type": "registry:ui",
|
package/dist/r/registry.json
CHANGED
|
@@ -1818,6 +1818,7 @@
|
|
|
1818
1818
|
"title": "Conversation",
|
|
1819
1819
|
"description": "",
|
|
1820
1820
|
"dependencies": [
|
|
1821
|
+
"@kobalte/core@^0.13.14",
|
|
1821
1822
|
"lucide-solid@^1.48.0"
|
|
1822
1823
|
],
|
|
1823
1824
|
"registryDependencies": [
|
|
@@ -1831,6 +1832,16 @@
|
|
|
1831
1832
|
"lib"
|
|
1832
1833
|
],
|
|
1833
1834
|
"files": [
|
|
1835
|
+
{
|
|
1836
|
+
"path": "src/components/conversation/atomic/chat-composer.tsx",
|
|
1837
|
+
"type": "registry:ui",
|
|
1838
|
+
"target": "components/conversation/atomic/chat-composer.tsx"
|
|
1839
|
+
},
|
|
1840
|
+
{
|
|
1841
|
+
"path": "src/components/conversation/atomic/index.ts",
|
|
1842
|
+
"type": "registry:ui",
|
|
1843
|
+
"target": "components/conversation/atomic/index.ts"
|
|
1844
|
+
},
|
|
1834
1845
|
{
|
|
1835
1846
|
"path": "src/components/conversation/busy-send-button.tsx",
|
|
1836
1847
|
"type": "registry:ui",
|
|
@@ -1861,6 +1872,11 @@
|
|
|
1861
1872
|
"type": "registry:ui",
|
|
1862
1873
|
"target": "components/conversation/index.ts"
|
|
1863
1874
|
},
|
|
1875
|
+
{
|
|
1876
|
+
"path": "src/components/conversation/internal/chat-composer-shell.tsx",
|
|
1877
|
+
"type": "registry:ui",
|
|
1878
|
+
"target": "components/conversation/internal/chat-composer-shell.tsx"
|
|
1879
|
+
},
|
|
1864
1880
|
{
|
|
1865
1881
|
"path": "src/components/conversation/message-composer.tsx",
|
|
1866
1882
|
"type": "registry:ui",
|
|
@@ -1871,6 +1887,16 @@
|
|
|
1871
1887
|
"type": "registry:ui",
|
|
1872
1888
|
"target": "components/conversation/message-row.tsx"
|
|
1873
1889
|
},
|
|
1890
|
+
{
|
|
1891
|
+
"path": "src/components/conversation/paste-preview.ts",
|
|
1892
|
+
"type": "registry:ui",
|
|
1893
|
+
"target": "components/conversation/paste-preview.ts"
|
|
1894
|
+
},
|
|
1895
|
+
{
|
|
1896
|
+
"path": "src/components/conversation/paste-token-editor.tsx",
|
|
1897
|
+
"type": "registry:ui",
|
|
1898
|
+
"target": "components/conversation/paste-token-editor.tsx"
|
|
1899
|
+
},
|
|
1874
1900
|
{
|
|
1875
1901
|
"path": "src/components/conversation/paste-tokens.ts",
|
|
1876
1902
|
"type": "registry:ui",
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Controlled atomic token composer translated from KiroCrew ChatInput.tsx and
|
|
3
|
+
* PasteHighlightLayer.tsx at 283e136c0f902e965a535a7c9548c57c7504fed0.
|
|
4
|
+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
5
|
+
* Licensed under Apache-2.0; see LICENSE and NOTICE.
|
|
6
|
+
*/
|
|
7
|
+
import { type ChatComposerSharedProps, type ChatComposerSubmitInput } from '../chat-composer'
|
|
8
|
+
import { ChatComposerShell } from '../internal/chat-composer-shell'
|
|
9
|
+
import { PasteTokenEditor, type PasteTokenDraft } from '../paste-token-editor'
|
|
10
|
+
import { pruneBlocks, type PasteBlock } from '../paste-tokens'
|
|
11
|
+
|
|
12
|
+
export type ChatComposerPasteTokens = {
|
|
13
|
+
/** Current host-owned backing blocks, paired with `value`. */
|
|
14
|
+
blocks: readonly PasteBlock[]
|
|
15
|
+
/** Synchronous host identity allocation; the UI owns no persistent identity. */
|
|
16
|
+
createBlockId: () => string
|
|
17
|
+
/** One synchronous update for the complete text and surviving blocks. */
|
|
18
|
+
onChange: (draft: PasteTokenDraft) => void
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type AtomicChatComposerProps = ChatComposerSharedProps & {
|
|
22
|
+
pasteTokens: ChatComposerPasteTokens
|
|
23
|
+
onSubmit: (input: ChatComposerSubmitInput & { blocks: PasteBlock[] }) => void | Promise<void>
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Atomic editor entry, sharing the plain composer's private composition shell. */
|
|
27
|
+
export function AtomicChatComposer(props: AtomicChatComposerProps) {
|
|
28
|
+
return (
|
|
29
|
+
<ChatComposerShell
|
|
30
|
+
{...props}
|
|
31
|
+
createSubmitExtra={({ text }) => ({
|
|
32
|
+
blocks: pruneBlocks(text, [...props.pasteTokens.blocks]).map((block) => ({ ...block })),
|
|
33
|
+
})}
|
|
34
|
+
onSubmit={props.onSubmit}
|
|
35
|
+
renderInput={(input) => (
|
|
36
|
+
<PasteTokenEditor
|
|
37
|
+
ref={input.ref}
|
|
38
|
+
value={input.value()}
|
|
39
|
+
resetKey={input.resetKey()}
|
|
40
|
+
blocks={props.pasteTokens.blocks}
|
|
41
|
+
createBlockId={props.pasteTokens.createBlockId}
|
|
42
|
+
onChange={props.pasteTokens.onChange}
|
|
43
|
+
inputLabel={input.inputLabel()}
|
|
44
|
+
placeholder={input.placeholder()}
|
|
45
|
+
disabled={input.disabled()}
|
|
46
|
+
readOnly={input.readOnly()}
|
|
47
|
+
composing={input.composing}
|
|
48
|
+
onCompositionStart={input.onCompositionStart}
|
|
49
|
+
onCompositionEnd={input.onCompositionEnd}
|
|
50
|
+
onFocus={input.onFocus}
|
|
51
|
+
onBlur={input.onBlur}
|
|
52
|
+
onKeyDown={input.onKeyDown}
|
|
53
|
+
/>
|
|
54
|
+
)}
|
|
55
|
+
/>
|
|
56
|
+
)
|
|
57
|
+
}
|