All files / core/blong-browser/src/components/Commander PathBar.tsx

79.16% Statements 19/24
75% Branches 12/16
75% Functions 6/8
86.36% Lines 19/22

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124                                                                  69x 69x   69x 2x 2x     69x                                 2x 2x   2x 2x                               1x   2x 1x 1x 1x 1x 1x 1x                         29x                                                
import React, {useState, type ReactNode} from 'react';
import {Button, InputText} from '../../primereact/index.js';
 
export interface IPathSegment {
    key: string;
    label: string;
}
 
/**
 * PathBar — the commander navigation bar: navigation buttons (back/forward/up/
 * refresh) on the left, a combined breadcrumb / "jump to path" widget that
 * fills the remaining space, and an optional search box — Windows-Explorer
 * style.
 *
 * The crumb/jump widget renders the breadcrumb; clicking a crumb navigates,
 * while clicking the empty space switches it into an editable "jump to path"
 * input (Enter navigates, Esc/Blur exits back to breadcrumbs).
 */
export function PathBar({
    segments,
    onNavigate,
    onJump,
    nav,
    search,
}: {
    segments: IPathSegment[];
    onNavigate?: (index: number) => void;
    onJump?: (path: string) => void;
    /** Navigation buttons rendered at the far left (back/forward/up/refresh). */
    nav?: ReactNode;
    /** Search input rendered at the far right. */
    search?: ReactNode;
}) {
    const [editing, setEditing] = useState(false);
    const [jump, setJump] = useState('');
 
    const startJump = () => {
        setJump('');
        setEditing(true);
    };
 
    return (
        <div
            className="blong-commander-path-bar"
            style={{
                display: 'flex',
                alignItems: 'center',
                gap: '0.25rem',
                padding: '0.2rem 0.4rem',
                borderBottom: '1px solid var(--surface-border)',
                minHeight: '2.1rem',
            }}
        >
            {nav}
            <div
                className="blong-commander-crumb-jump"
                title="Click a crumb to navigate · click empty space to jump to path"
                onClick={e => {
                    Iif (editing) return;
                    const target = e.target as HTMLElement;
                    // Clicks on breadcrumb buttons navigate via their own onClick.
                    Iif (target.closest('.p-button')) return;
                    startJump();
                }}
                style={{
                    flex: 1,
                    minWidth: 0,
                    display: 'flex',
                    alignItems: 'center',
                    overflow: 'hidden',
                    whiteSpace: 'nowrap',
                    cursor: editing ? 'text' : 'default',
                }}
            >
                {editing ? (
                    <InputText
                        autoFocus
                        value={jump}
                        onChange={e => setJump(e.target.value)}
                        onKeyDown={e => {
                            if (e.key === 'Enter') {
                                onJump?.(jump.trim());
                                setJump('');
                                setEditing(false);
                            } else Eif (e.key === 'Escape') {
                                setJump('');
                                setEditing(false);
                            }
                        }}
                        onBlur={() => {
                            setJump('');
                            setEditing(false);
                        }}
                        placeholder="Jump to path…"
                        style={{width: '100%', fontSize: '0.8rem', padding: '0.2rem 0.4rem'}}
                    />
                ) : (
                    <>
                        {segments.map((segment, index) => (
                            <React.Fragment key={segment.key}>
                                {index > 0 && (
                                    <span style={{color: 'var(--text-color-secondary)', margin: '0 0.1rem'}}>/</span>
                                )}
                                <Button
                                    label={segment.label}
                                    className="p-button-text p-button-sm"
                                    style={{padding: '0.1rem 0.35rem'}}
                                    onClick={() => onNavigate?.(index)}
                                />
                            </React.Fragment>
                        ))}
                        {segments.length === 0 && (
                            <span style={{color: 'var(--text-color-secondary)', fontSize: '0.8rem'}}>
                                Home · click here to jump…
                            </span>
                        )}
                    </>
                )}
            </div>
            {search}
        </div>
    );
}