prompt-area 0.1.0

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 (41) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +120 -0
  3. package/dist/action-bar/index.d.ts +60 -0
  4. package/dist/action-bar/index.js +5 -0
  5. package/dist/action-bar/index.js.map +1 -0
  6. package/dist/chat-prompt-layout/index.d.ts +53 -0
  7. package/dist/chat-prompt-layout/index.js +5 -0
  8. package/dist/chat-prompt-layout/index.js.map +1 -0
  9. package/dist/chunk-ANZZEZP2.js +38 -0
  10. package/dist/chunk-ANZZEZP2.js.map +1 -0
  11. package/dist/chunk-BPJO4DGM.js +198 -0
  12. package/dist/chunk-BPJO4DGM.js.map +1 -0
  13. package/dist/chunk-BWVBDP7C.js +38 -0
  14. package/dist/chunk-BWVBDP7C.js.map +1 -0
  15. package/dist/chunk-E7HUXORB.js +2692 -0
  16. package/dist/chunk-E7HUXORB.js.map +1 -0
  17. package/dist/chunk-NF2LHZIE.js +12 -0
  18. package/dist/chunk-NF2LHZIE.js.map +1 -0
  19. package/dist/chunk-UBBCAMJA.js +116 -0
  20. package/dist/chunk-UBBCAMJA.js.map +1 -0
  21. package/dist/chunk-XDKRP7UE.js +125 -0
  22. package/dist/chunk-XDKRP7UE.js.map +1 -0
  23. package/dist/compact-prompt-area/index.d.ts +86 -0
  24. package/dist/compact-prompt-area/index.js +6 -0
  25. package/dist/compact-prompt-area/index.js.map +1 -0
  26. package/dist/helpers/index.d.ts +374 -0
  27. package/dist/helpers/index.js +291 -0
  28. package/dist/helpers/index.js.map +1 -0
  29. package/dist/index.d.ts +7 -0
  30. package/dist/index.js +10 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/prompt-area/index.d.ts +327 -0
  33. package/dist/prompt-area/index.js +6 -0
  34. package/dist/prompt-area/index.js.map +1 -0
  35. package/dist/status-bar/index.d.ts +50 -0
  36. package/dist/status-bar/index.js +5 -0
  37. package/dist/status-bar/index.js.map +1 -0
  38. package/dist/styles.css +2 -0
  39. package/dist/tailwind.css +181 -0
  40. package/dist/types-C4BgDEpe.d.ts +271 -0
  41. package/package.json +102 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/prompt-area/prompt-area-engine.ts","../../src/prompt-area/segment-helpers.ts","../../src/prompt-area/trigger-presets.ts"],"names":["text","matchingTrigger","chip"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Pure logic engine for the PromptArea component.\n * No DOM dependencies - fully testable in Node.\n */\nimport type { Segment, ChipSegment, TriggerConfig, TriggerPosition, ActiveTrigger } from './types'\n\n// ---------------------------------------------------------------------------\n// Serialization\n// ---------------------------------------------------------------------------\n\n/**\n * Converts an array of segments to a plain text string.\n * Chips are represented as `{trigger}{displayText}` (e.g., \"@Alice\").\n */\nexport function segmentsToPlainText(segments: Segment[]): string {\n return segments\n .map((seg) => {\n if (seg.type === 'text') return seg.text\n return `${seg.trigger}${seg.displayText}`\n })\n .join('')\n}\n\n/**\n * Converts plain text into a single text segment.\n * Used for initial value conversion from plain strings.\n */\nexport function plainTextToSegments(text: string): Segment[] {\n if (!text) return []\n return [{ type: 'text', text }]\n}\n\n// ---------------------------------------------------------------------------\n// Trigger position validation\n// ---------------------------------------------------------------------------\n\n/**\n * Checks whether a trigger character at the given position in text\n * is valid according to the position rule.\n *\n * @param text - The full text content\n * @param charIndex - The index of the trigger character in the text\n * @param position - The position rule to validate against\n */\nexport function isValidTriggerPosition(\n text: string,\n charIndex: number,\n position: TriggerPosition,\n): boolean {\n if (charIndex === 0) return true\n\n const prevChar = text[charIndex - 1]\n\n if (position === 'start') {\n return prevChar === '\\n'\n }\n\n // position === 'any': valid after any whitespace\n return prevChar === ' ' || prevChar === '\\n' || prevChar === '\\t'\n}\n\n// ---------------------------------------------------------------------------\n// Trigger detection\n// ---------------------------------------------------------------------------\n\n/**\n * Scans backwards from the cursor position to detect if the user is\n * currently typing a trigger word.\n *\n * Returns the active trigger info, or null if no trigger is active.\n *\n * @param text - The full plain text content\n * @param cursorPos - The cursor position (character offset from start)\n * @param triggers - Available trigger configurations\n */\nexport function detectActiveTrigger(\n text: string,\n cursorPos: number,\n triggers: TriggerConfig[],\n): ActiveTrigger | null {\n if (!text || cursorPos === 0 || triggers.length === 0) return null\n\n // Scan backwards from cursor to find the nearest trigger character.\n // Stop at whitespace (trigger word has ended) or start of text.\n for (let i = cursorPos - 1; i >= 0; i--) {\n const char = text[i]\n\n // If we hit whitespace before finding a trigger, check if this whitespace\n // is immediately followed by a trigger character\n if (char === ' ' || char === '\\n' || char === '\\t') {\n // The character after this whitespace could be a trigger\n if (i + 1 < cursorPos) {\n const nextChar = text[i + 1]\n const matchingTrigger = triggers.find((t) => t.char === nextChar)\n if (matchingTrigger && isValidTriggerPosition(text, i + 1, matchingTrigger.position)) {\n return {\n config: matchingTrigger,\n startOffset: i + 1,\n query: text.slice(i + 2, cursorPos),\n }\n }\n }\n // No trigger found after this whitespace, stop searching\n return null\n }\n\n // Check if this character is a trigger character\n const matchingTrigger = triggers.find((t) => t.char === char)\n if (matchingTrigger && isValidTriggerPosition(text, i, matchingTrigger.position)) {\n return {\n config: matchingTrigger,\n startOffset: i,\n query: text.slice(i + 1, cursorPos),\n }\n }\n }\n\n return null\n}\n\n// ---------------------------------------------------------------------------\n// Chip resolution\n// ---------------------------------------------------------------------------\n\n/**\n * Resolves an active trigger into a chip within the segments array.\n * Replaces the trigger text (trigger char + query) with a chip segment.\n *\n * @param segments - Current document segments\n * @param activeTrigger - The active trigger to resolve\n * @param chip - The chip data (value, displayText, optional data)\n * @returns New segments array with the chip inserted, and the new cursor position\n */\nexport function resolveChip(\n segments: Segment[],\n activeTrigger: ActiveTrigger,\n chip: { value: string; displayText: string; data?: unknown; autoResolved?: boolean },\n): { segments: Segment[]; cursorOffset: number } {\n const triggerStart = activeTrigger.startOffset\n const triggerEnd = triggerStart + 1 + activeTrigger.query.length // +1 for trigger char\n\n // Build the new segments by mapping plain text positions back to segment boundaries\n const newSegments: Segment[] = []\n let offset = 0\n\n for (const seg of segments) {\n if (seg.type === 'chip') {\n const chipText = `${seg.trigger}${seg.displayText}`\n const chipStart = offset\n const chipEnd = offset + chipText.length\n\n // If the trigger range overlaps with this chip, something is wrong.\n // Chips should not be partially replaced.\n if (chipEnd <= triggerStart || chipStart >= triggerEnd) {\n newSegments.push(seg)\n }\n offset = chipEnd\n } else {\n const textStart = offset\n const textEnd = offset + seg.text.length\n\n if (textEnd <= triggerStart) {\n // Entirely before the trigger - keep as-is\n newSegments.push(seg)\n } else if (textStart >= triggerEnd) {\n // Entirely after the trigger - keep as-is\n newSegments.push(seg)\n } else {\n // This text segment contains (part of) the trigger range\n const beforeText = seg.text.slice(0, Math.max(0, triggerStart - textStart))\n const afterText = seg.text.slice(Math.min(seg.text.length, triggerEnd - textStart))\n\n if (beforeText) {\n newSegments.push({ type: 'text', text: beforeText })\n }\n\n const newChip: ChipSegment = {\n type: 'chip',\n trigger: activeTrigger.config.char,\n value: chip.value,\n displayText: chip.displayText,\n ...(chip.data !== undefined ? { data: chip.data } : {}),\n ...(chip.autoResolved ? { autoResolved: true } : {}),\n }\n newSegments.push(newChip)\n\n // Add trailing space after chip, then any remaining text\n if (afterText) {\n newSegments.push({ type: 'text', text: ' ' + afterText.replace(/^\\s/, '') })\n } else {\n newSegments.push({ type: 'text', text: ' ' })\n }\n }\n\n offset = textEnd\n }\n }\n\n // Merge adjacent text segments\n const merged = mergeAdjacentTextSegments(newSegments)\n\n // Cursor should be placed after the chip + trailing space.\n // Find the *last* matching chip so duplicates resolve correctly.\n let lastChipEndOffset = -1\n let runningOffset = 0\n for (const seg of merged) {\n if (seg.type === 'text') {\n runningOffset += seg.text.length\n } else {\n runningOffset += seg.trigger.length + seg.displayText.length\n if (\n seg.value === chip.value &&\n seg.displayText === chip.displayText &&\n seg.trigger === activeTrigger.config.char\n ) {\n lastChipEndOffset = runningOffset\n }\n }\n }\n // +1 accounts for the trailing space after the chip\n const cursorOffset = lastChipEndOffset === -1 ? runningOffset : lastChipEndOffset + 1\n\n return { segments: merged, cursorOffset }\n}\n\n// ---------------------------------------------------------------------------\n// Chip removal\n// ---------------------------------------------------------------------------\n\n/**\n * Removes a chip at the given segment index and merges adjacent text segments.\n *\n * @param segments - Current document segments\n * @param index - The segment index to remove\n * @returns New segments array with the chip removed\n */\nexport function removeChipAtIndex(segments: Segment[], index: number): Segment[] {\n if (index < 0 || index >= segments.length) return segments\n if (segments[index].type !== 'chip') return segments\n\n const result = [...segments.slice(0, index), ...segments.slice(index + 1)]\n return mergeAdjacentTextSegments(result)\n}\n\n/**\n * Reverts an auto-resolved chip at the given segment index back to plain text.\n * The text includes the trigger character + display text (e.g., \"#readme\").\n *\n * @param segments - Current document segments\n * @param index - The segment index to revert\n * @returns New segments with the chip replaced by text, or null if not applicable\n */\nexport function revertChipAtIndex(\n segments: Segment[],\n index: number,\n): { segments: Segment[]; revertedText: string } | null {\n if (index < 0 || index >= segments.length) return null\n const seg = segments[index]\n if (seg.type !== 'chip' || !seg.autoResolved) return null\n\n const revertedText = `${seg.trigger}${seg.displayText}`\n const result = [\n ...segments.slice(0, index),\n { type: 'text' as const, text: revertedText },\n ...segments.slice(index + 1),\n ]\n return { segments: mergeAdjacentTextSegments(result), revertedText }\n}\n\n// ---------------------------------------------------------------------------\n// Paste: resolve trigger patterns in segments\n// ---------------------------------------------------------------------------\n\n/**\n * Scans text segments for trigger patterns and auto-resolves them into chips.\n * Only resolves triggers that have `resolveOnSpace: true`.\n *\n * Trigger patterns must appear at word boundaries: start of text, after\n * whitespace, or after a newline. This avoids false positives like email\n * addresses (user@example.com).\n */\nexport function resolveTriggersInSegments(\n segments: Segment[],\n triggers: TriggerConfig[],\n): Segment[] {\n const autoResolveTriggers = triggers.filter((t) => t.resolveOnSpace)\n if (autoResolveTriggers.length === 0) return segments\n\n const triggerChars = new Set(autoResolveTriggers.map((t) => t.char))\n const result: Segment[] = []\n\n for (const seg of segments) {\n if (seg.type === 'chip') {\n result.push(seg)\n continue\n }\n\n const parts = splitTextByTriggerPatterns(seg.text, autoResolveTriggers, triggerChars)\n result.push(...parts)\n }\n\n return mergeAdjacentTextSegments(result)\n}\n\n/**\n * Splits a text string into text and chip segments based on trigger patterns.\n * A trigger pattern is: (start-of-string | whitespace) + trigger_char + word_chars\n * followed by whitespace or end-of-string.\n */\nfunction splitTextByTriggerPatterns(\n text: string,\n triggers: TriggerConfig[],\n triggerChars: Set<string>,\n): Segment[] {\n if (!text) return []\n\n const segments: Segment[] = []\n let i = 0\n\n while (i < text.length) {\n const char = text[i]\n\n if (triggerChars.has(char)) {\n const isAtBoundary =\n i === 0 || text[i - 1] === ' ' || text[i - 1] === '\\n' || text[i - 1] === '\\t'\n\n if (isAtBoundary) {\n const trigger = triggers.find((t) => t.char === char)\n if (trigger && isValidTriggerPosition(text, i, trigger.position)) {\n let end = i + 1\n while (\n end < text.length &&\n text[end] !== ' ' &&\n text[end] !== '\\n' &&\n text[end] !== '\\t'\n ) {\n end++\n }\n\n const query = text.slice(i + 1, end)\n if (query.length > 0) {\n // Treat both undefined and '' from onSelect as \"no custom label\"\n // and fall back to the query — an empty displayText would render\n // a blank chip.\n const displayText = trigger.onSelect?.({ value: query, label: query }) || query\n segments.push({\n type: 'chip',\n trigger: char,\n value: query,\n displayText,\n autoResolved: true,\n })\n i = end\n continue\n }\n }\n }\n }\n\n const start = i\n i++\n while (\n i < text.length &&\n !(\n triggerChars.has(text[i]) &&\n (text[i - 1] === ' ' || text[i - 1] === '\\n' || text[i - 1] === '\\t')\n )\n ) {\n i++\n }\n segments.push({ type: 'text', text: text.slice(start, i) })\n }\n\n return segments\n}\n\n// ---------------------------------------------------------------------------\n// Text range replacement\n// ---------------------------------------------------------------------------\n\n/**\n * Replaces a range of plain text within the segments array.\n * Handles segment boundaries correctly, preserving chip segments.\n *\n * @param segments - Current document segments\n * @param start - Start offset in plain text\n * @param end - End offset in plain text\n * @param replacement - The replacement text\n * @returns New segments array with the replacement applied\n */\nexport function replaceTextRange(\n segments: Segment[],\n start: number,\n end: number,\n replacement: string,\n): Segment[] {\n const newSegments: Segment[] = []\n let offset = 0\n let inserted = false\n\n for (const seg of segments) {\n if (seg.type === 'chip') {\n const chipText = `${seg.trigger}${seg.displayText}`\n const chipStart = offset\n const chipEnd = offset + chipText.length\n\n // For insertion (start === end), insert before this chip if position matches\n if (!inserted && start === end && chipStart === start) {\n newSegments.push({ type: 'text', text: replacement })\n inserted = true\n }\n\n if (chipEnd <= start || chipStart >= end) {\n newSegments.push(seg)\n }\n // Chips within the range are removed\n offset = chipEnd\n } else {\n const textStart = offset\n const textEnd = offset + seg.text.length\n\n // Check if this segment contains the insertion/replacement point\n const isBefore = start === end ? textEnd < start : textEnd <= start\n const isAfter = start === end ? textStart > end : textStart >= end\n\n if (isBefore) {\n // Entirely before the range\n newSegments.push(seg)\n } else if (isAfter) {\n // Entirely after the range\n newSegments.push(seg)\n } else {\n // Overlaps with the range (or contains the insertion point)\n const beforeText = seg.text.slice(0, Math.max(0, start - textStart))\n const afterText = seg.text.slice(Math.min(seg.text.length, end - textStart))\n\n if (beforeText) {\n newSegments.push({ type: 'text', text: beforeText })\n }\n // Insert replacement only once (when we first enter the range)\n if (!inserted && textStart <= start) {\n newSegments.push({ type: 'text', text: replacement })\n inserted = true\n }\n if (afterText) {\n newSegments.push({ type: 'text', text: afterText })\n }\n }\n\n offset = textEnd\n }\n }\n\n // Fallback: if replacement wasn't inserted (e.g., insertion at very end)\n if (!inserted && replacement) {\n newSegments.push({ type: 'text', text: replacement })\n }\n\n return mergeAdjacentTextSegments(newSegments)\n}\n\n// ---------------------------------------------------------------------------\n// Markdown formatting shortcuts\n// ---------------------------------------------------------------------------\n\n/**\n * Toggles markdown wrap markers around a selected text range.\n * If the selection is already wrapped with the marker, unwraps it.\n * If not wrapped, wraps it.\n *\n * @param segments - Current document segments\n * @param selectionStart - Start offset in plain text\n * @param selectionEnd - End offset in plain text\n * @param marker - The markdown marker (e.g., '**' for bold, '*' for italic)\n * @returns New segments and selection offsets, or null if selection is collapsed\n */\nexport function toggleMarkdownWrap(\n segments: Segment[],\n selectionStart: number,\n selectionEnd: number,\n marker: string,\n): { segments: Segment[]; selectionStart: number; selectionEnd: number } | null {\n if (selectionStart === selectionEnd) return null\n\n const plainText = segmentsToPlainText(segments)\n const markerLen = marker.length\n\n // Check if already wrapped\n const hasOpeningMarker =\n selectionStart >= markerLen &&\n plainText.slice(selectionStart - markerLen, selectionStart) === marker\n const hasClosingMarker =\n selectionEnd + markerLen <= plainText.length &&\n plainText.slice(selectionEnd, selectionEnd + markerLen) === marker\n\n let isWrapped = hasOpeningMarker && hasClosingMarker\n\n // For single-char markers (e.g., '*'), ensure we're not matching\n // inside a multi-char marker (e.g., '**')\n if (isWrapped && markerLen === 1) {\n const charBeforeOpening =\n selectionStart > markerLen ? plainText[selectionStart - markerLen - 1] : ''\n const charAfterClosing =\n selectionEnd + markerLen < plainText.length ? plainText[selectionEnd + markerLen] : ''\n if (charBeforeOpening === marker || charAfterClosing === marker) {\n isWrapped = false\n }\n }\n\n if (isWrapped) {\n // Unwrap: remove closing marker first (preserves start offsets), then opening\n const afterClosing = replaceTextRange(segments, selectionEnd, selectionEnd + markerLen, '')\n const afterOpening = replaceTextRange(\n afterClosing,\n selectionStart - markerLen,\n selectionStart,\n '',\n )\n return {\n segments: afterOpening,\n selectionStart: selectionStart - markerLen,\n selectionEnd: selectionEnd - markerLen,\n }\n }\n\n // Wrap: insert closing marker first (preserves start offsets), then opening\n const afterClosing = replaceTextRange(segments, selectionEnd, selectionEnd, marker)\n const afterOpening = replaceTextRange(afterClosing, selectionStart, selectionStart, marker)\n return {\n segments: afterOpening,\n selectionStart: selectionStart + markerLen,\n selectionEnd: selectionEnd + markerLen,\n }\n}\n\n// ---------------------------------------------------------------------------\n// Inline markdown parsing\n// ---------------------------------------------------------------------------\n\nexport type MarkdownToken =\n | { type: 'plain'; text: string }\n | { type: 'bold'; text: string }\n | { type: 'italic'; text: string }\n | { type: 'bold-italic'; text: string }\n | { type: 'url'; text: string }\n\n/**\n * Parses text for simple inline markdown: bold, italic, bold-italic, and URLs.\n * Does NOT handle block-level markdown (lists, headings, etc.).\n */\nexport function parseInlineMarkdown(text: string): MarkdownToken[] {\n if (!text) return []\n\n const tokens: MarkdownToken[] = []\n // Regex patterns for inline markdown elements:\n // 1. ***text*** or ___text___ -> bold-italic\n // 2. **text** or __text__ -> bold\n // 3. *text* or _text_ -> italic\n // 4. https://... or http://... -> URL\n const pattern = /(\\*{3}(.+?)\\*{3})|(\\*{2}(.+?)\\*{2})|(\\*(.+?)\\*)|(https?:\\/\\/[^\\s),]+)/g\n\n let lastIndex = 0\n let match: RegExpExecArray | null\n\n while ((match = pattern.exec(text)) !== null) {\n // Add any plain text before this match\n if (match.index > lastIndex) {\n tokens.push({ type: 'plain', text: text.slice(lastIndex, match.index) })\n }\n\n if (match[1] && match[2]) {\n // ***bold-italic***\n tokens.push({ type: 'bold-italic', text: match[2] })\n } else if (match[3] && match[4]) {\n // **bold**\n tokens.push({ type: 'bold', text: match[4] })\n } else if (match[5] && match[6]) {\n // *italic*\n tokens.push({ type: 'italic', text: match[6] })\n } else if (match[7]) {\n // URL\n tokens.push({ type: 'url', text: match[7] })\n }\n\n lastIndex = match.index + match[0].length\n }\n\n // Add any remaining plain text\n if (lastIndex < text.length) {\n tokens.push({ type: 'plain', text: text.slice(lastIndex) })\n }\n\n return tokens\n}\n\n// ---------------------------------------------------------------------------\n// Segment comparison\n// ---------------------------------------------------------------------------\n\n/**\n * Shallow equality check for two segment arrays.\n * Compares type, text, trigger, value, displayText, and autoResolved fields.\n * Avoids JSON.stringify overhead for the common case.\n */\nexport function segmentsEqual(a: Segment[], b: Segment[]): boolean {\n if (a === b) return true\n if (a.length !== b.length) return false\n\n for (let i = 0; i < a.length; i++) {\n const sa = a[i]\n const sb = b[i]\n if (sa.type !== sb.type) return false\n if (sa.type === 'text') {\n if (sb.type !== 'text' || sa.text !== sb.text) return false\n } else {\n if (\n sb.type !== 'chip' ||\n sa.trigger !== sb.trigger ||\n sa.value !== sb.value ||\n sa.displayText !== sb.displayText ||\n sa.autoResolved !== sb.autoResolved\n )\n return false\n }\n }\n return true\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Merges adjacent text segments into single text segments.\n * Also removes empty text segments.\n */\nexport function mergeAdjacentTextSegments(segments: Segment[]): Segment[] {\n const result: Segment[] = []\n\n for (const seg of segments) {\n if (seg.type === 'text' && seg.text === '') continue\n\n const last = result[result.length - 1]\n if (seg.type === 'text' && last?.type === 'text') {\n // Merge with previous text segment\n result[result.length - 1] = { type: 'text', text: last.text + seg.text }\n } else {\n result.push(seg)\n }\n }\n\n return result\n}\n","/**\n * Convenience helpers for creating and inspecting Segments.\n *\n * These reduce boilerplate when building AI chat UIs that work with the\n * PromptArea document model.\n *\n * @example\n * ```ts\n * import { text, chip, isSegmentsEmpty, segmentsToPlainText } from './segment-helpers'\n *\n * const greeting = [text('Hello '), chip({ trigger: '@', value: 'u1', displayText: 'Alice' })]\n * isSegmentsEmpty(greeting) // false\n * segmentsToPlainText(greeting) // \"Hello @Alice\"\n * ```\n */\n\nimport type { Segment, TextSegment, ChipSegment } from './types'\nimport { segmentsToPlainText, plainTextToSegments } from './prompt-area-engine'\n\n// Re-export serialization utilities so consumers have a single import.\nexport { segmentsToPlainText, plainTextToSegments }\n\n// ---------------------------------------------------------------------------\n// Factories\n// ---------------------------------------------------------------------------\n\n/** Create a text segment. */\nexport function text(value: string): TextSegment {\n return { type: 'text', text: value }\n}\n\n/** Create a chip segment. */\nexport function chip(opts: Omit<ChipSegment, 'type'>): ChipSegment {\n return { type: 'chip', ...opts }\n}\n\n// ---------------------------------------------------------------------------\n// Predicates\n// ---------------------------------------------------------------------------\n\n/** Returns `true` when the segment array is empty or contains only whitespace text. */\nexport function isSegmentsEmpty(segments: Segment[]): boolean {\n if (segments.length === 0) return true\n return segments.every((seg) => seg.type === 'text' && seg.text.trim() === '')\n}\n\n/** Returns `true` when the segment array contains at least one chip. */\nexport function hasChips(segments: Segment[]): boolean {\n return segments.some((seg) => seg.type === 'chip')\n}\n\n/** Extracts all chip segments from a segment array. */\nexport function getChips(segments: Segment[]): ChipSegment[] {\n return segments.filter((seg): seg is ChipSegment => seg.type === 'chip')\n}\n\n/** Extracts chips matching a specific trigger character. */\nexport function getChipsByTrigger(segments: Segment[], trigger: string): ChipSegment[] {\n return segments.filter(\n (seg): seg is ChipSegment => seg.type === 'chip' && seg.trigger === trigger,\n )\n}\n","/**\n * Pre-built trigger configuration factories for common AI chat patterns.\n *\n * Each factory returns a full `TriggerConfig` with sensible defaults.\n * Pass only what you need to override.\n *\n * @example\n * ```tsx\n * <PromptArea\n * triggers={[\n * mentionTrigger({ onSearch: searchUsers }),\n * commandTrigger({ onSearch: searchCommands }),\n * hashtagTrigger(),\n * ]}\n * />\n * ```\n */\n\nimport type { TriggerConfig } from './types'\n\n// ---------------------------------------------------------------------------\n// Shared option type — everything in TriggerConfig except the keys each\n// factory sets by default.\n// ---------------------------------------------------------------------------\n\ntype TriggerPresetOptions = Omit<Partial<TriggerConfig>, 'char' | 'position' | 'mode'>\n\n// ---------------------------------------------------------------------------\n// @mention — dropdown at any position\n// ---------------------------------------------------------------------------\n\nexport type MentionTriggerOptions = TriggerPresetOptions & {\n /** Override the trigger character. Defaults to `'@'`. */\n char?: string\n}\n\n/**\n * Creates a **mention** trigger (`@`).\n *\n * Defaults: `position: 'any'`, `mode: 'dropdown'`, `chipStyle: 'pill'`,\n * accessible label `\"mention\"`.\n */\nexport function mentionTrigger(opts: MentionTriggerOptions = {}): TriggerConfig {\n const { char = '@', ...rest } = opts\n return {\n char,\n position: 'any',\n mode: 'dropdown',\n chipStyle: 'pill',\n accessibilityLabel: 'mention',\n ...rest,\n }\n}\n\n// ---------------------------------------------------------------------------\n// /command — dropdown only at line start\n// ---------------------------------------------------------------------------\n\nexport type CommandTriggerOptions = TriggerPresetOptions & {\n /** Override the trigger character. Defaults to `'/'`. */\n char?: string\n}\n\n/**\n * Creates a **command** trigger (`/`).\n *\n * Defaults: `position: 'start'`, `mode: 'dropdown'`, `chipStyle: 'inline'`,\n * accessible label `\"command\"`.\n */\nexport function commandTrigger(opts: CommandTriggerOptions = {}): TriggerConfig {\n const { char = '/', ...rest } = opts\n return {\n char,\n position: 'start',\n mode: 'dropdown',\n chipStyle: 'inline',\n accessibilityLabel: 'command',\n ...rest,\n }\n}\n\n// ---------------------------------------------------------------------------\n// #hashtag — dropdown at any position, auto-resolve on space\n// ---------------------------------------------------------------------------\n\nexport type HashtagTriggerOptions = TriggerPresetOptions & {\n /** Override the trigger character. Defaults to `'#'`. */\n char?: string\n}\n\n/**\n * Creates a **hashtag / tag** trigger (`#`).\n *\n * Defaults: `position: 'any'`, `mode: 'dropdown'`, `chipStyle: 'pill'`,\n * `resolveOnSpace: true`, accessible label `\"tag\"`.\n */\nexport function hashtagTrigger(opts: HashtagTriggerOptions = {}): TriggerConfig {\n const { char = '#', ...rest } = opts\n return {\n char,\n position: 'any',\n mode: 'dropdown',\n chipStyle: 'pill',\n resolveOnSpace: true,\n accessibilityLabel: 'tag',\n ...rest,\n }\n}\n\n// ---------------------------------------------------------------------------\n// Generic callback trigger (e.g., for file pickers, model selectors)\n// ---------------------------------------------------------------------------\n\nexport type CallbackTriggerOptions = Omit<Partial<TriggerConfig>, 'mode'> & {\n /** The trigger character. Required. */\n char: string\n}\n\n/**\n * Creates a **callback** trigger that fires `onActivate` instead of showing\n * a dropdown. Useful for opening file pickers, model selectors, etc.\n *\n * Defaults: `position: 'start'`, `mode: 'callback'`.\n */\nexport function callbackTrigger(opts: CallbackTriggerOptions): TriggerConfig {\n const { char, ...rest } = opts\n return {\n char,\n position: 'start',\n mode: 'callback',\n ...rest,\n }\n}\n"]}
@@ -0,0 +1,7 @@
1
+ export { CallbackTriggerOptions, CommandTriggerOptions, HashtagTriggerOptions, MarkdownToken, MentionTriggerOptions, PromptArea, PromptAreaBind, PromptAreaState, UsePromptAreaStateOptions, callbackTrigger, chip, commandTrigger, detectActiveTrigger, getChips, getChipsByTrigger, hasChips, hashtagTrigger, isSegmentsEmpty, isValidTriggerPosition, mentionTrigger, mergeAdjacentTextSegments, parseInlineMarkdown, plainTextToSegments, resolveChip, resolveTriggersInSegments, segmentsEqual, segmentsToPlainText, text, usePromptArea, usePromptAreaState } from './prompt-area/index.js';
2
+ export { A as ActiveTrigger, C as ChipSegment, a as ChipStyle, P as PromptAreaFile, b as PromptAreaHandle, c as PromptAreaImage, d as PromptAreaProps, S as Segment, T as TextSegment, e as TriggerActivateContext, f as TriggerConfig, g as TriggerMode, h as TriggerPosition, i as TriggerSuggestion } from './types-C4BgDEpe.js';
3
+ export { ActionBar, ActionBarProps } from './action-bar/index.js';
4
+ export { StatusBar, StatusBarProps } from './status-bar/index.js';
5
+ export { CompactPromptArea, CompactPromptAreaProps } from './compact-prompt-area/index.js';
6
+ export { ChatPromptLayout, ChatPromptLayoutProps } from './chat-prompt-layout/index.js';
7
+ import 'react';
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ 'use client';
2
+ export { callbackTrigger, chip, commandTrigger, getChips, getChipsByTrigger, hasChips, hashtagTrigger, isSegmentsEmpty, mentionTrigger, text, usePromptAreaState } from './chunk-UBBCAMJA.js';
3
+ export { ActionBar } from './chunk-BWVBDP7C.js';
4
+ export { StatusBar } from './chunk-ANZZEZP2.js';
5
+ export { CompactPromptArea } from './chunk-BPJO4DGM.js';
6
+ export { PromptArea, detectActiveTrigger, isValidTriggerPosition, mergeAdjacentTextSegments, parseInlineMarkdown, plainTextToSegments, resolveChip, resolveTriggersInSegments, segmentsEqual, segmentsToPlainText, usePromptArea } from './chunk-E7HUXORB.js';
7
+ export { ChatPromptLayout } from './chunk-XDKRP7UE.js';
8
+ import './chunk-NF2LHZIE.js';
9
+ //# sourceMappingURL=index.js.map
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,327 @@
1
+ import * as react from 'react';
2
+ import { d as PromptAreaProps, b as PromptAreaHandle, S as Segment, f as TriggerConfig, C as ChipSegment, A as ActiveTrigger, i as TriggerSuggestion, h as TriggerPosition, T as TextSegment } from '../types-C4BgDEpe.js';
3
+ export { a as ChipStyle, P as PromptAreaFile, c as PromptAreaImage, e as TriggerActivateContext, g as TriggerMode } from '../types-C4BgDEpe.js';
4
+
5
+ /**
6
+ * PromptArea - A lightweight rich text input with trigger support.
7
+ *
8
+ * Uses contentEditable to support inline chips (immutable pills) for
9
+ * mentions, commands, and other triggered tokens. Each trigger character
10
+ * can be configured to show a dropdown or fire a callback.
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * const [segments, setSegments] = useState<Segment[]>([])
15
+ *
16
+ * <PromptArea
17
+ * value={segments}
18
+ * onChange={setSegments}
19
+ * triggers={[
20
+ * { char: '@', position: 'any', mode: 'dropdown', onSearch: searchUsers },
21
+ * { char: '/', position: 'start', mode: 'dropdown', onSearch: searchCommands },
22
+ * { char: '#', position: 'any', mode: 'dropdown', onSearch: searchTags },
23
+ * ]}
24
+ * placeholder="Type a message..."
25
+ * onSubmit={handleSubmit}
26
+ * autoGrow
27
+ * />
28
+ * ```
29
+ */
30
+ declare function PromptArea({ value, onChange, triggers, placeholder, className, disabled, markdown, onSubmit, onEscape, onChipClick, onChipAdd, onChipDelete, onLinkClick, onPaste, onUndo, onRedo, minHeight, maxHeight, autoFocus, autoGrow, 'aria-label': ariaLabel, 'data-test-id': dataTestId, images, imagePosition, onImagePaste, onImageRemove, onImageClick, files, filePosition, onFileRemove, onFileClick, ref, }: PromptAreaProps & {
31
+ ref?: React.Ref<PromptAreaHandle>;
32
+ }): react.JSX.Element;
33
+
34
+ type UsePromptAreaOptions = {
35
+ value: Segment[];
36
+ onChange: (segments: Segment[]) => void;
37
+ triggers?: TriggerConfig[];
38
+ onSubmit?: (segments: Segment[]) => void;
39
+ onEscape?: () => void;
40
+ onChipClick?: (chip: ChipSegment) => void;
41
+ onChipAdd?: (chip: ChipSegment) => void;
42
+ onChipDelete?: (chip: ChipSegment) => void;
43
+ onLinkClick?: (url: string) => void;
44
+ onPaste?: (data: {
45
+ segments: Segment[];
46
+ source: 'internal' | 'external';
47
+ }) => void;
48
+ onUndo?: (segments: Segment[]) => void;
49
+ onRedo?: (segments: Segment[]) => void;
50
+ onImagePaste?: (file: File) => void;
51
+ markdown?: boolean;
52
+ };
53
+ type UsePromptAreaReturn = {
54
+ editorRef: React.RefObject<HTMLDivElement | null>;
55
+ activeTrigger: ActiveTrigger | null;
56
+ suggestions: TriggerSuggestion[];
57
+ suggestionsLoading: boolean;
58
+ suggestionsError: string | null;
59
+ selectedSuggestionIndex: number;
60
+ handleInput: () => void;
61
+ handleKeyDown: (e: React.KeyboardEvent<HTMLDivElement>) => void;
62
+ handleClick: (e: React.MouseEvent<HTMLDivElement>) => void;
63
+ selectSuggestion: (suggestion: TriggerSuggestion) => void;
64
+ dismissTrigger: () => void;
65
+ handle: PromptAreaHandle;
66
+ triggerRect: DOMRect | null;
67
+ eventHandlers: {
68
+ onPaste: (e: React.ClipboardEvent<HTMLDivElement>) => void;
69
+ onCopy: (e: React.ClipboardEvent<HTMLDivElement>) => void;
70
+ onCut: (e: React.ClipboardEvent<HTMLDivElement>) => void;
71
+ onDrop: (e: React.DragEvent<HTMLDivElement>) => void;
72
+ onDragOver: (e: React.DragEvent<HTMLDivElement>) => void;
73
+ onCompositionStart: () => void;
74
+ onCompositionEnd: () => void;
75
+ onBlur: () => void;
76
+ };
77
+ };
78
+ declare function usePromptArea({ value, onChange, triggers, onSubmit, onEscape, onChipClick, onChipAdd, onChipDelete, onLinkClick, onPaste, onUndo, onRedo, onImagePaste, markdown: markdownEnabled, }: UsePromptAreaOptions): UsePromptAreaReturn;
79
+
80
+ /**
81
+ * Convenience hook that wires up all the boilerplate state for a PromptArea.
82
+ *
83
+ * Instead of manually managing `useState<Segment[]>`, `useRef<PromptAreaHandle>`,
84
+ * and computing derived values, call `usePromptAreaState()` once and spread
85
+ * `bind` into your `<PromptArea>`.
86
+ *
87
+ * @example
88
+ * ```tsx
89
+ * function ChatInput() {
90
+ * const { bind, plainText, isEmpty, chips, clear, focus } = usePromptAreaState()
91
+ *
92
+ * return (
93
+ * <PromptArea
94
+ * {...bind}
95
+ * onSubmit={() => {
96
+ * sendMessage(plainText)
97
+ * clear()
98
+ * }}
99
+ * />
100
+ * )
101
+ * }
102
+ * ```
103
+ */
104
+
105
+ type UsePromptAreaStateOptions = {
106
+ /** Initial segment value. Defaults to `[]`. */
107
+ initialValue?: Segment[];
108
+ };
109
+ type PromptAreaBind = {
110
+ /** Ref to attach to PromptArea — gives access to imperative methods. */
111
+ ref: React.RefObject<PromptAreaHandle | null>;
112
+ /** Current segment array — pass as `value` prop. */
113
+ value: Segment[];
114
+ /** Setter — pass as `onChange` prop. */
115
+ onChange: (segments: Segment[]) => void;
116
+ };
117
+ type PromptAreaState = {
118
+ /** Props to spread directly onto `<PromptArea {...bind} />`. Contains ref, value, and onChange. */
119
+ bind: PromptAreaBind;
120
+ /** Derived plain text representation of the current value. */
121
+ plainText: string;
122
+ /** `true` when the value is empty or whitespace-only. */
123
+ isEmpty: boolean;
124
+ /** `true` when the value contains at least one chip. */
125
+ hasChips: boolean;
126
+ /** All chip segments in the current value. */
127
+ chips: ChipSegment[];
128
+ /** Clear all content (both state and the editor DOM). */
129
+ clear: () => void;
130
+ /** Focus the editor. */
131
+ focus: () => void;
132
+ /** Blur the editor. */
133
+ blur: () => void;
134
+ /** Insert a chip at the current cursor position. */
135
+ insertChip: (chip: Omit<ChipSegment, 'type'>) => void;
136
+ };
137
+ declare function usePromptAreaState(options?: UsePromptAreaStateOptions): PromptAreaState;
138
+
139
+ /**
140
+ * Pure logic engine for the PromptArea component.
141
+ * No DOM dependencies - fully testable in Node.
142
+ */
143
+
144
+ /**
145
+ * Converts an array of segments to a plain text string.
146
+ * Chips are represented as `{trigger}{displayText}` (e.g., "@Alice").
147
+ */
148
+ declare function segmentsToPlainText(segments: Segment[]): string;
149
+ /**
150
+ * Converts plain text into a single text segment.
151
+ * Used for initial value conversion from plain strings.
152
+ */
153
+ declare function plainTextToSegments(text: string): Segment[];
154
+ /**
155
+ * Checks whether a trigger character at the given position in text
156
+ * is valid according to the position rule.
157
+ *
158
+ * @param text - The full text content
159
+ * @param charIndex - The index of the trigger character in the text
160
+ * @param position - The position rule to validate against
161
+ */
162
+ declare function isValidTriggerPosition(text: string, charIndex: number, position: TriggerPosition): boolean;
163
+ /**
164
+ * Scans backwards from the cursor position to detect if the user is
165
+ * currently typing a trigger word.
166
+ *
167
+ * Returns the active trigger info, or null if no trigger is active.
168
+ *
169
+ * @param text - The full plain text content
170
+ * @param cursorPos - The cursor position (character offset from start)
171
+ * @param triggers - Available trigger configurations
172
+ */
173
+ declare function detectActiveTrigger(text: string, cursorPos: number, triggers: TriggerConfig[]): ActiveTrigger | null;
174
+ /**
175
+ * Resolves an active trigger into a chip within the segments array.
176
+ * Replaces the trigger text (trigger char + query) with a chip segment.
177
+ *
178
+ * @param segments - Current document segments
179
+ * @param activeTrigger - The active trigger to resolve
180
+ * @param chip - The chip data (value, displayText, optional data)
181
+ * @returns New segments array with the chip inserted, and the new cursor position
182
+ */
183
+ declare function resolveChip(segments: Segment[], activeTrigger: ActiveTrigger, chip: {
184
+ value: string;
185
+ displayText: string;
186
+ data?: unknown;
187
+ autoResolved?: boolean;
188
+ }): {
189
+ segments: Segment[];
190
+ cursorOffset: number;
191
+ };
192
+ /**
193
+ * Scans text segments for trigger patterns and auto-resolves them into chips.
194
+ * Only resolves triggers that have `resolveOnSpace: true`.
195
+ *
196
+ * Trigger patterns must appear at word boundaries: start of text, after
197
+ * whitespace, or after a newline. This avoids false positives like email
198
+ * addresses (user@example.com).
199
+ */
200
+ declare function resolveTriggersInSegments(segments: Segment[], triggers: TriggerConfig[]): Segment[];
201
+ type MarkdownToken = {
202
+ type: 'plain';
203
+ text: string;
204
+ } | {
205
+ type: 'bold';
206
+ text: string;
207
+ } | {
208
+ type: 'italic';
209
+ text: string;
210
+ } | {
211
+ type: 'bold-italic';
212
+ text: string;
213
+ } | {
214
+ type: 'url';
215
+ text: string;
216
+ };
217
+ /**
218
+ * Parses text for simple inline markdown: bold, italic, bold-italic, and URLs.
219
+ * Does NOT handle block-level markdown (lists, headings, etc.).
220
+ */
221
+ declare function parseInlineMarkdown(text: string): MarkdownToken[];
222
+ /**
223
+ * Shallow equality check for two segment arrays.
224
+ * Compares type, text, trigger, value, displayText, and autoResolved fields.
225
+ * Avoids JSON.stringify overhead for the common case.
226
+ */
227
+ declare function segmentsEqual(a: Segment[], b: Segment[]): boolean;
228
+ /**
229
+ * Merges adjacent text segments into single text segments.
230
+ * Also removes empty text segments.
231
+ */
232
+ declare function mergeAdjacentTextSegments(segments: Segment[]): Segment[];
233
+
234
+ /**
235
+ * Convenience helpers for creating and inspecting Segments.
236
+ *
237
+ * These reduce boilerplate when building AI chat UIs that work with the
238
+ * PromptArea document model.
239
+ *
240
+ * @example
241
+ * ```ts
242
+ * import { text, chip, isSegmentsEmpty, segmentsToPlainText } from './segment-helpers'
243
+ *
244
+ * const greeting = [text('Hello '), chip({ trigger: '@', value: 'u1', displayText: 'Alice' })]
245
+ * isSegmentsEmpty(greeting) // false
246
+ * segmentsToPlainText(greeting) // "Hello @Alice"
247
+ * ```
248
+ */
249
+
250
+ /** Create a text segment. */
251
+ declare function text(value: string): TextSegment;
252
+ /** Create a chip segment. */
253
+ declare function chip(opts: Omit<ChipSegment, 'type'>): ChipSegment;
254
+ /** Returns `true` when the segment array is empty or contains only whitespace text. */
255
+ declare function isSegmentsEmpty(segments: Segment[]): boolean;
256
+ /** Returns `true` when the segment array contains at least one chip. */
257
+ declare function hasChips(segments: Segment[]): boolean;
258
+ /** Extracts all chip segments from a segment array. */
259
+ declare function getChips(segments: Segment[]): ChipSegment[];
260
+ /** Extracts chips matching a specific trigger character. */
261
+ declare function getChipsByTrigger(segments: Segment[], trigger: string): ChipSegment[];
262
+
263
+ /**
264
+ * Pre-built trigger configuration factories for common AI chat patterns.
265
+ *
266
+ * Each factory returns a full `TriggerConfig` with sensible defaults.
267
+ * Pass only what you need to override.
268
+ *
269
+ * @example
270
+ * ```tsx
271
+ * <PromptArea
272
+ * triggers={[
273
+ * mentionTrigger({ onSearch: searchUsers }),
274
+ * commandTrigger({ onSearch: searchCommands }),
275
+ * hashtagTrigger(),
276
+ * ]}
277
+ * />
278
+ * ```
279
+ */
280
+
281
+ type TriggerPresetOptions = Omit<Partial<TriggerConfig>, 'char' | 'position' | 'mode'>;
282
+ type MentionTriggerOptions = TriggerPresetOptions & {
283
+ /** Override the trigger character. Defaults to `'@'`. */
284
+ char?: string;
285
+ };
286
+ /**
287
+ * Creates a **mention** trigger (`@`).
288
+ *
289
+ * Defaults: `position: 'any'`, `mode: 'dropdown'`, `chipStyle: 'pill'`,
290
+ * accessible label `"mention"`.
291
+ */
292
+ declare function mentionTrigger(opts?: MentionTriggerOptions): TriggerConfig;
293
+ type CommandTriggerOptions = TriggerPresetOptions & {
294
+ /** Override the trigger character. Defaults to `'/'`. */
295
+ char?: string;
296
+ };
297
+ /**
298
+ * Creates a **command** trigger (`/`).
299
+ *
300
+ * Defaults: `position: 'start'`, `mode: 'dropdown'`, `chipStyle: 'inline'`,
301
+ * accessible label `"command"`.
302
+ */
303
+ declare function commandTrigger(opts?: CommandTriggerOptions): TriggerConfig;
304
+ type HashtagTriggerOptions = TriggerPresetOptions & {
305
+ /** Override the trigger character. Defaults to `'#'`. */
306
+ char?: string;
307
+ };
308
+ /**
309
+ * Creates a **hashtag / tag** trigger (`#`).
310
+ *
311
+ * Defaults: `position: 'any'`, `mode: 'dropdown'`, `chipStyle: 'pill'`,
312
+ * `resolveOnSpace: true`, accessible label `"tag"`.
313
+ */
314
+ declare function hashtagTrigger(opts?: HashtagTriggerOptions): TriggerConfig;
315
+ type CallbackTriggerOptions = Omit<Partial<TriggerConfig>, 'mode'> & {
316
+ /** The trigger character. Required. */
317
+ char: string;
318
+ };
319
+ /**
320
+ * Creates a **callback** trigger that fires `onActivate` instead of showing
321
+ * a dropdown. Useful for opening file pickers, model selectors, etc.
322
+ *
323
+ * Defaults: `position: 'start'`, `mode: 'callback'`.
324
+ */
325
+ declare function callbackTrigger(opts: CallbackTriggerOptions): TriggerConfig;
326
+
327
+ export { ActiveTrigger, type CallbackTriggerOptions, ChipSegment, type CommandTriggerOptions, type HashtagTriggerOptions, type MarkdownToken, type MentionTriggerOptions, PromptArea, type PromptAreaBind, PromptAreaHandle, PromptAreaProps, type PromptAreaState, Segment, TextSegment, TriggerConfig, TriggerPosition, TriggerSuggestion, type UsePromptAreaStateOptions, callbackTrigger, chip, commandTrigger, detectActiveTrigger, getChips, getChipsByTrigger, hasChips, hashtagTrigger, isSegmentsEmpty, isValidTriggerPosition, mentionTrigger, mergeAdjacentTextSegments, parseInlineMarkdown, plainTextToSegments, resolveChip, resolveTriggersInSegments, segmentsEqual, segmentsToPlainText, text, usePromptArea, usePromptAreaState };
@@ -0,0 +1,6 @@
1
+ 'use client';
2
+ export { callbackTrigger, chip, commandTrigger, getChips, getChipsByTrigger, hasChips, hashtagTrigger, isSegmentsEmpty, mentionTrigger, text, usePromptAreaState } from '../chunk-UBBCAMJA.js';
3
+ export { PromptArea, detectActiveTrigger, isValidTriggerPosition, mergeAdjacentTextSegments, parseInlineMarkdown, plainTextToSegments, resolveChip, resolveTriggersInSegments, segmentsEqual, segmentsToPlainText, usePromptArea } from '../chunk-E7HUXORB.js';
4
+ import '../chunk-NF2LHZIE.js';
5
+ //# sourceMappingURL=index.js.map
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,50 @@
1
+ import * as react from 'react';
2
+
3
+ /**
4
+ * StatusBar component types
5
+ *
6
+ * A horizontal bar with left and right slots, designed to sit
7
+ * above or below a text input (e.g., PromptArea) to display
8
+ * contextual information such as branch name, model selector, etc.
9
+ */
10
+ /**
11
+ * Props for the StatusBar component.
12
+ */
13
+ type StatusBarProps = {
14
+ /** Content rendered on the left side of the bar */
15
+ left?: React.ReactNode;
16
+ /** Content rendered on the right side of the bar */
17
+ right?: React.ReactNode;
18
+ /** Additional CSS class for the root element */
19
+ className?: string;
20
+ /** Whether the status bar is disabled (visually dims and disables pointer events) */
21
+ disabled?: boolean;
22
+ /** Accessible label for the status bar */
23
+ 'aria-label'?: string;
24
+ /** data-test-id for e2e testing */
25
+ 'data-test-id'?: string;
26
+ };
27
+
28
+ /**
29
+ * StatusBar - A horizontal bar with left and right slots.
30
+ *
31
+ * Designed to sit above or below a text input (e.g., PromptArea) to
32
+ * display contextual information. Place it as a sibling before or
33
+ * after the input inside a shared wrapper.
34
+ *
35
+ * @example
36
+ * ```tsx
37
+ * <div className="rounded-lg border">
38
+ * <StatusBar
39
+ * left={<span>prompt-area</span>}
40
+ * right={<span>Default</span>}
41
+ * />
42
+ * <PromptArea value={segments} onChange={setSegments} ... />
43
+ * </div>
44
+ * ```
45
+ */
46
+ declare function StatusBar({ left, right, className, disabled, 'aria-label': ariaLabel, 'data-test-id': dataTestId, ref, }: StatusBarProps & {
47
+ ref?: React.Ref<HTMLDivElement>;
48
+ }): react.JSX.Element;
49
+
50
+ export { StatusBar, type StatusBarProps };
@@ -0,0 +1,5 @@
1
+ 'use client';
2
+ export { StatusBar } from '../chunk-ANZZEZP2.js';
3
+ import '../chunk-NF2LHZIE.js';
4
+ //# sourceMappingURL=index.js.map
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
@@ -0,0 +1,2 @@
1
+ /*! tailwindcss v4.3.1 | MIT License | https://tailwindcss.com */
2
+ @layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-duration:initial;--tw-ease:initial;--tw-animation-delay:0s;--tw-animation-direction:normal;--tw-animation-duration:initial;--tw-animation-fill-mode:none;--tw-animation-iteration-count:1;--tw-enter-blur:0;--tw-enter-opacity:1;--tw-enter-rotate:0;--tw-enter-scale:1;--tw-enter-translate-x:0;--tw-enter-translate-y:0;--tw-exit-blur:0;--tw-exit-opacity:1;--tw-exit-rotate:0;--tw-exit-scale:1;--tw-exit-translate-x:0;--tw-exit-translate-y:0}}}@layer theme{:root,:host{--color-blue-100:oklch(93.2% .032 255.585);--color-black:#000;--color-white:#fff;--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--font-weight-medium:500;--font-weight-bold:700;--leading-relaxed:1.625;--radius-2xl:1rem;--ease-out:cubic-bezier(0, 0, .2, 1);--ease-in-out:cubic-bezier(.4, 0, .2, 1);--animate-spin:spin 1s linear infinite;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}}@layer base;@layer components{.prompt-area-chip{cursor:pointer;-webkit-user-select:none;user-select:none;vertical-align:baseline;background-color:var(--secondary);color:var(--foreground);border-radius:4px;align-items:center;margin:0 1px;padding:1px 6px;font-size:.875rem;font-weight:500;transition:background-color .2s,transform .15s cubic-bezier(.4,0,.2,1),box-shadow .2s;display:inline-flex;position:relative;overflow:hidden}.prompt-area-chip:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.prompt-area-chip:hover{background-color:color-mix(in srgb, var(--secondary) 80%, var(--foreground) 20%)}}.prompt-area-chip:hover{box-shadow:0 1px 4px var(--foreground)}@supports (color:color-mix(in lab, red, red)){.prompt-area-chip:hover{box-shadow:0 1px 4px color-mix(in srgb, var(--foreground) 10%, transparent)}}.prompt-area-chip:active{background-color:var(--secondary);transform:scale(.93)}@supports (color:color-mix(in lab, red, red)){.prompt-area-chip:active{background-color:color-mix(in srgb, var(--secondary) 70%, var(--foreground) 30%)}}.prompt-area-chip:active{transition:background-color 50ms,transform 80ms cubic-bezier(.4,0,.2,1),box-shadow 50ms;box-shadow:0 0 #0000}@keyframes prompt-area-chip-ripple{0%{opacity:.4;transform:scale(0)}to{opacity:0;transform:scale(2.5)}}.prompt-area-chip-ripple{aspect-ratio:1;background:var(--foreground);border-radius:50%;width:100%;position:absolute}@supports (color:color-mix(in lab, red, red)){.prompt-area-chip-ripple{background:color-mix(in srgb, var(--foreground) 15%, transparent)}}.prompt-area-chip-ripple{pointer-events:none;animation:.45s ease-out forwards prompt-area-chip-ripple}.prompt-area-md-marker{font-size:0;display:inline}.prompt-area-chip--inline{border-radius:0;margin:0;padding:0;font-weight:700}}@layer utilities{.pointer-events-auto{pointer-events:auto}.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.visible{visibility:visible}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:0}.top-0{top:0}.top-0\.5{top:calc(var(--spacing) * .5)}.right-0{right:0}.right-0\.5{right:calc(var(--spacing) * .5)}.bottom-0{bottom:0}.bottom-4{bottom:calc(var(--spacing) * 4)}.bottom-full{bottom:100%}.left-0{left:0}.z-10{z-index:10}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.mt-0\.5{margin-top:calc(var(--spacing) * .5)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.size-9{width:calc(var(--spacing) * 9);height:calc(var(--spacing) * 9)}.h-3\.5{height:calc(var(--spacing) * 3.5)}.h-4{height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-10{height:calc(var(--spacing) * 10)}.h-14{height:calc(var(--spacing) * 14)}.h-16{height:calc(var(--spacing) * 16)}.h-\[600px\]{height:600px}.h-full{height:100%}.max-h-48{max-height:calc(var(--spacing) * 48)}.max-h-\[240px\]{max-height:240px}.w-3\.5{width:calc(var(--spacing) * 3.5)}.w-4{width:calc(var(--spacing) * 4)}.w-5{width:calc(var(--spacing) * 5)}.w-16{width:calc(var(--spacing) * 16)}.w-36{width:calc(var(--spacing) * 36)}.w-48{width:calc(var(--spacing) * 48)}.w-full{width:100%}.min-w-0{min-width:0}.min-w-\[200px\]{min-width:200px}.flex-1{flex:1}.flex-shrink-0{flex-shrink:0}.shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.animate-in{animation:enter var(--tw-animation-duration,var(--tw-duration,.15s))var(--tw-ease,ease)var(--tw-animation-delay,0s)var(--tw-animation-iteration-count,1)var(--tw-animation-direction,normal)var(--tw-animation-fill-mode,none)}.animate-spin{animation:var(--animate-spin)}.cursor-not-allowed{cursor:not-allowed}.cursor-pointer{cursor:pointer}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.place-items-center{place-items:center}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.gap-1{gap:var(--spacing)}.gap-1\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-xl{border-radius:calc(var(--radius) + 4px)}.border{border-style:var(--tw-border-style);border-width:1px}.border-2{border-style:var(--tw-border-style);border-width:2px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-border{border-color:var(--border)}.border-white{border-color:var(--color-white)}.border-t-transparent{border-top-color:#0000}.bg-accent{background-color:var(--accent)}.bg-background{background-color:var(--background)}.bg-black\/40{background-color:#0006}@supports (color:color-mix(in lab, red, red)){.bg-black\/40{background-color:color-mix(in oklab, var(--color-black) 40%, transparent)}}.bg-black\/60{background-color:#0009}@supports (color:color-mix(in lab, red, red)){.bg-black\/60{background-color:color-mix(in oklab, var(--color-black) 60%, transparent)}}.bg-blue-100{background-color:var(--color-blue-100)}.bg-muted{background-color:var(--muted)}.bg-popover{background-color:var(--popover)}.bg-primary{background-color:var(--primary)}.object-cover{object-fit:cover}.p-1\.5{padding:calc(var(--spacing) * 1.5)}.p-2{padding:calc(var(--spacing) * 2)}.p-4{padding:calc(var(--spacing) * 4)}.px-2{padding-inline:calc(var(--spacing) * 2)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.px-5{padding-inline:calc(var(--spacing) * 5)}.py-1\.5{padding-block:calc(var(--spacing) * 1.5)}.py-2{padding-block:calc(var(--spacing) * 2)}.pt-1{padding-top:var(--spacing)}.pt-2{padding-top:calc(var(--spacing) * 2)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pb-2{padding-bottom:calc(var(--spacing) * 2)}.pb-3{padding-bottom:calc(var(--spacing) * 3)}.text-left{text-align:left}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.break-words{overflow-wrap:break-word}.whitespace-pre-wrap{white-space:pre-wrap}.text-destructive{color:var(--destructive)}.text-foreground{color:var(--foreground)}.text-muted-foreground{color:var(--muted-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-white{color:var(--color-white)}.italic{font-style:italic}.underline{text-decoration-line:underline}.opacity-50{opacity:.5}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a), 0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a), 0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.blur{--tw-blur:blur(8px);filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.ease-out{--tw-ease:var(--ease-out);transition-timing-function:var(--ease-out)}.fade-in-0{--tw-enter-opacity:0}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.zoom-in-95{--tw-enter-scale:.95}.slide-in-from-top-4{--tw-enter-translate-y:calc(4*var(--spacing)*-1)}@media (hover:hover){.hover\:bg-accent:hover{background-color:var(--accent)}.hover\:bg-black\/80:hover{background-color:#000c}@supports (color:color-mix(in lab, red, red)){.hover\:bg-black\/80:hover{background-color:color-mix(in oklab, var(--color-black) 80%, transparent)}}.hover\:bg-primary\/90:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.hover\:bg-primary\/90:hover{background-color:color-mix(in oklab, var(--primary) 90%, transparent)}}.hover\:text-foreground:hover{color:var(--foreground)}.hover\:text-primary\/80:hover{color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.hover\:text-primary\/80:hover{color:color-mix(in oklab, var(--primary) 80%, transparent)}}}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{opacity:.5}.dark\:bg-white\/60:is(.dark *){background-color:#fff9}@supports (color:color-mix(in lab, red, red)){.dark\:bg-white\/60:is(.dark *){background-color:color-mix(in oklab, var(--color-white) 60%, transparent)}}.dark\:text-black:is(.dark *){color:var(--color-black)}@media (hover:hover){.dark\:hover\:bg-white\/80:is(.dark *):hover{background-color:#fffc}@supports (color:color-mix(in lab, red, red)){.dark\:hover\:bg-white\/80:is(.dark *):hover{background-color:color-mix(in oklab, var(--color-white) 80%, transparent)}}}}@property --tw-animation-delay{syntax:"*";inherits:false;initial-value:0s}@property --tw-animation-direction{syntax:"*";inherits:false;initial-value:normal}@property --tw-animation-duration{syntax:"*";inherits:false}@property --tw-animation-fill-mode{syntax:"*";inherits:false;initial-value:none}@property --tw-animation-iteration-count{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-enter-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-enter-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-blur{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-opacity{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-rotate{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-scale{syntax:"*";inherits:false;initial-value:1}@property --tw-exit-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-exit-translate-y{syntax:"*";inherits:false;initial-value:0}:root{--radius:.625rem;--background:oklch(100% 0 0);--foreground:oklch(14.5% 0 0);--card:oklch(100% 0 0);--card-foreground:oklch(14.5% 0 0);--popover:oklch(100% 0 0);--popover-foreground:oklch(14.5% 0 0);--primary:oklch(20.5% 0 0);--primary-foreground:oklch(98.5% 0 0);--secondary:oklch(97% 0 0);--secondary-foreground:oklch(20.5% 0 0);--muted:oklch(97% 0 0);--muted-foreground:oklch(55.6% 0 0);--accent:oklch(97% 0 0);--accent-foreground:oklch(20.5% 0 0);--destructive:oklch(57.7% .245 27.325);--border:oklch(92.2% 0 0);--input:oklch(92.2% 0 0);--ring:oklch(70.8% 0 0)}.dark{--background:oklch(14.5% 0 0);--foreground:oklch(98.5% 0 0);--card:oklch(20.5% 0 0);--card-foreground:oklch(98.5% 0 0);--popover:oklch(20.5% 0 0);--popover-foreground:oklch(98.5% 0 0);--primary:oklch(92.2% 0 0);--primary-foreground:oklch(20.5% 0 0);--secondary:oklch(26.9% 0 0);--secondary-foreground:oklch(98.5% 0 0);--muted:oklch(26.9% 0 0);--muted-foreground:oklch(70.8% 0 0);--accent:oklch(26.9% 0 0);--accent-foreground:oklch(98.5% 0 0);--destructive:oklch(70.4% .191 22.216);--border:oklch(100% 0 0/.14);--input:oklch(100% 0 0/.2);--ring:oklch(55.6% 0 0)}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-ease{syntax:"*";inherits:false}@keyframes spin{to{transform:rotate(360deg)}}@keyframes enter{0%{opacity:var(--tw-enter-opacity,1);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0)scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1))rotate(var(--tw-enter-rotate,0));filter:blur(var(--tw-enter-blur,0))}}