import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { Box, Text } from '../../ink.js';
import { themeToInkHex } from '../ink-theme.js';
import { truncate } from './text.js';
const ACCENT_BAR = '\u258E'; // ▎
const SEPARATOR = '\u2500'; // ─
// Custom border with only the left edge populated. All other chars are
// empty strings — combined with borderTop/borderRight/borderBottom set
// to false, Ink paints only the left column with our ▎ on every row.
const LEFT_ACCENT_BORDER = {
    topLeft: '',
    top: '',
    topRight: '',
    left: ACCENT_BAR,
    right: '',
    bottomLeft: '',
    bottom: '',
    bottomRight: '',
};
export function ComposerInputChrome({ mode, queued, columns, attachments, children, }) {
    // The `mode` prop intentionally stays in the type — slash commands,
    // permission flows, and the rail coordinate by it — but the composer
    // does NOT paint it next to `›`. The bottom rail's MODE cell is the
    // single source of truth for that signal; duplicating it here just
    // creates two labels that have to agree at render time.
    void mode;
    const accentHex = themeToInkHex('owl');
    const warnHex = themeToInkHex('warning');
    const dimHex = themeToInkHex('textDim');
    const muteHex = themeToInkHex('textMute');
    const inkHex = themeToInkHex('text');
    const hairFaintHex = themeToInkHex('hairFaint');
    const bgInputHex = themeToInkHex('bgInput');
    const width = Math.max(20, columns ?? process.stdout.columns ?? 80);
    const queuedRaw = queued
        ? truncate(queued, Math.max(10, width - 24))
        : null;
    return (_jsxs(Box, { flexDirection: "column", children: [attachments && attachments.length > 0 ? (_jsxs(Box, { flexDirection: "row", flexWrap: "wrap", children: [attachments.slice(0, 4).map((att, i) => (_jsxs(Box, { flexDirection: "row", marginRight: 1, borderStyle: "round", borderColor: hairFaintHex, paddingX: 1, children: [_jsx(Box, { marginRight: 1, backgroundColor: bgInputHex, paddingX: 1, children: _jsx(Text, { color: att.kind === 'img' ? accentHex : muteHex, children: att.kind === 'img' ? '🖼' : att.kind === 'dir' ? '▸' : '◰' }) }), _jsx(Text, { color: inkHex, children: truncate(att.name, 32) }), att.size ? _jsxs(Text, { color: dimHex, children: [' ', att.size] }) : null, _jsx(Text, { color: muteHex, children: '  ×' })] }, `${att.kind}:${att.name}:${i}`))), attachments.length > 4 ? (_jsx(Box, { paddingX: 1, children: _jsxs(Text, { color: muteHex, children: ["+", attachments.length - 4, " more"] }) })) : null] })) : null, queuedRaw ? (_jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: warnHex, bold: true, children: "QUEUED NEXT" }), _jsx(Text, { children: '  ' }), _jsx(Text, { color: dimHex, wrap: "truncate-end", children: queuedRaw }), _jsx(Text, { children: '  ' }), _jsx(Text, { color: muteHex, children: "esc to cancel" })] })) : null, _jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: accentHex, children: "\u203A " }), _jsx(Box, { flexGrow: 1, flexDirection: "column", children: children })] })] }));
}
/**
 * Parse an input string for `@path` attachment references and classify
 * each by file extension. The product wires `@` as a file picker prefix
 * (see ink-repl.tsx file-picker overlay), so this is the natural source
 * of attachment chips: they preview what's bundled with the next message.
 */
const ATTACHMENT_REF_RE = /(?:^|[\s])@([^\s]+)/g;
const IMG_EXT_RE = /\.(png|jpe?g|gif|webp|svg|bmp|ico)$/i;
export function parseInputAttachments(input) {
    if (!input || !input.includes('@'))
        return [];
    const seen = new Set();
    const out = [];
    for (const match of input.matchAll(ATTACHMENT_REF_RE)) {
        const raw = match[1];
        if (!raw)
            continue;
        // Strip trailing punctuation that's likely sentence chrome, not part
        // of the path (e.g. "@src/foo.ts," → "src/foo.ts").
        const path = raw.replace(/[,.;:)\]]+$/, '');
        if (!path || seen.has(path))
            continue;
        seen.add(path);
        const isDir = path.endsWith('/');
        const isImg = !isDir && IMG_EXT_RE.test(path);
        out.push({
            kind: isImg ? 'img' : isDir ? 'dir' : 'file',
            name: path,
        });
    }
    return out;
}
export function ComposerPanel({ children, rail, bodyLines }) {
    // minHeight is only applied when the caller opts in via bodyLines.
    // undefined → no minimum, body sizes to children (correct for overlay
    // / permission-prompt modes). number → follow the actual draft height.
    // Keeping a single-line draft in a forced 3-row band makes every keystroke
    // repaint/cursor-park across unnecessary empty rows in real terminals.
    const minHeightProp = bodyLines === undefined ? undefined : Math.max(1, bodyLines);
    // Accent ▎ uses the owl brand token (teal-blue-green). Pulled from the
    // active theme at render time so /theme swaps follow through. No bg
    // tint — design feedback: keep the authoring surface "light", just
    // the left accent plus the state rail below.
    const accentHex = themeToInkHex('owl');
    const hairFaintHex = themeToInkHex('hairFaint');
    const cols = Math.max(10, process.stdout.columns || 80);
    return (_jsxs(Box, { flexDirection: "column", flexShrink: 0, children: [_jsx(Box, { children: _jsx(Text, { color: hairFaintHex, children: SEPARATOR.repeat(cols) }) }), _jsx(Box, { borderStyle: LEFT_ACCENT_BORDER, borderTop: false, borderRight: false, borderBottom: false, borderLeftColor: accentHex, paddingLeft: 1, minHeight: minHeightProp, flexDirection: "column", children: children }), _jsx(Box, { children: _jsx(Text, { color: hairFaintHex, children: SEPARATOR.repeat(cols) }) }), _jsx(Box, { children: _jsx(Text, { children: rail }) })] }));
}
//# sourceMappingURL=composer.js.map