mirror of
https://github.com/anotherhadi/ilovetui.git
synced 2026-10-05 10:58:26 +02:00
Vendored
-168
@@ -1,168 +0,0 @@
|
||||
// @bun
|
||||
import {
|
||||
theme
|
||||
} from "./chunk-x7m82z3z.js";
|
||||
|
||||
// src/components/Tabs.tsx
|
||||
import { effect as _$effect } from "@opentui/solid";
|
||||
import { insertNode as _$insertNode } from "@opentui/solid";
|
||||
import { createComponent as _$createComponent } from "@opentui/solid";
|
||||
import { insert as _$insert } from "@opentui/solid";
|
||||
import { use as _$use } from "@opentui/solid";
|
||||
import { setProp as _$setProp } from "@opentui/solid";
|
||||
import { createElement as _$createElement } from "@opentui/solid";
|
||||
import { BorderChars, CliRenderEvents, TextAttributes } from "@opentui/core";
|
||||
import { onResize, useRenderer } from "@opentui/solid";
|
||||
import { createMemo, createSignal, Index } from "solid-js";
|
||||
function stepTabValue(items, value, delta) {
|
||||
const index = items.findIndex((t) => t.value === value);
|
||||
if (index === -1)
|
||||
return value;
|
||||
return items[(index + delta + items.length) % items.length].value;
|
||||
}
|
||||
function innerWidth(label) {
|
||||
return [...label].length + 2;
|
||||
}
|
||||
function segmentWidth(label) {
|
||||
return innerWidth(label) + 2;
|
||||
}
|
||||
function topEdge(chars, label) {
|
||||
return `${chars.topLeft}${chars.horizontal.repeat(innerWidth(label))}${chars.topRight}`;
|
||||
}
|
||||
function bottomEdge(chars, label, isFirst, isLast, isActive) {
|
||||
const left = isFirst ? isActive ? chars.vertical : chars.leftT : isActive ? chars.bottomRight : chars.bottomT;
|
||||
const right = isLast ? isActive ? chars.vertical : chars.rightT : isActive ? chars.bottomLeft : chars.bottomT;
|
||||
const fill = isActive ? " " : chars.horizontal;
|
||||
return left + fill.repeat(innerWidth(label)) + right;
|
||||
}
|
||||
function buildBottomRow(chars, segments, available) {
|
||||
const tabsWidth = segments.reduce((sum, s) => sum + segmentWidth(s.label), 0);
|
||||
const remainder = available - tabsWidth;
|
||||
const extending = remainder > 0;
|
||||
const tabs = segments.map((s, i) => bottomEdge(chars, s.label, i === 0, i === segments.length - 1 && !extending, s.isActive)).join("");
|
||||
return extending ? tabs + chars.horizontal.repeat(remainder - 1) + chars.topRight : tabs;
|
||||
}
|
||||
function fitCount(items, start, available) {
|
||||
const hiddenBefore = start;
|
||||
let used = 0;
|
||||
let count = 0;
|
||||
for (let i = start;i < items.length; i++) {
|
||||
const width = segmentWidth(items[i].label);
|
||||
const hiddenAfter = items.length - start - count - 1;
|
||||
const totalHidden = hiddenBefore + hiddenAfter;
|
||||
const reserve = totalHidden > 0 ? segmentWidth(`+${totalHidden}`) : 0;
|
||||
if (used + width + reserve > available)
|
||||
break;
|
||||
used += width;
|
||||
count++;
|
||||
}
|
||||
return Math.max(count, 1);
|
||||
}
|
||||
function Tabs(props) {
|
||||
const renderer = useRenderer();
|
||||
const [width, setWidth] = createSignal(0);
|
||||
let container;
|
||||
const measure = () => {
|
||||
if (!container)
|
||||
return;
|
||||
setWidth(container.width);
|
||||
};
|
||||
const remeasureNextFrame = () => renderer.once(CliRenderEvents.FRAME, measure);
|
||||
onResize(remeasureNextFrame);
|
||||
const segments = createMemo(() => {
|
||||
const items = props.items;
|
||||
const activeIndex = Math.max(0, items.findIndex((t) => t.value === props.value));
|
||||
let start = 0;
|
||||
let count = fitCount(items, start, width());
|
||||
if (activeIndex >= start + count) {
|
||||
start = activeIndex;
|
||||
count = fitCount(items, start, width());
|
||||
}
|
||||
const shownItems = items.slice(start, start + count);
|
||||
const shown = shownItems.map((item) => ({
|
||||
value: item.value,
|
||||
label: item.label,
|
||||
isActive: item.value === props.value
|
||||
}));
|
||||
const hidden = items.length - count;
|
||||
if (hidden > 0) {
|
||||
const used = shownItems.reduce((sum, item) => sum + segmentWidth(item.label), 0);
|
||||
const tag = `+${hidden}`;
|
||||
if (shown.length === 0 || used + segmentWidth(tag) <= width()) {
|
||||
shown.push({
|
||||
value: undefined,
|
||||
label: tag,
|
||||
isActive: false
|
||||
});
|
||||
}
|
||||
}
|
||||
return shown;
|
||||
});
|
||||
const accent = () => props.accentColor ?? theme.primary;
|
||||
const muted = () => props.mutedColor ?? theme.muted;
|
||||
const borderColor = () => props.focused ? accent() : muted();
|
||||
const chars = BorderChars[theme.borderStyle];
|
||||
return (() => {
|
||||
var _el$ = _$createElement("box"), _el$2 = _$createElement("text"), _el$3 = _$createElement("box"), _el$4 = _$createElement("text");
|
||||
_$insertNode(_el$, _el$2);
|
||||
_$insertNode(_el$, _el$3);
|
||||
_$insertNode(_el$, _el$4);
|
||||
_$use((el) => {
|
||||
container = el;
|
||||
remeasureNextFrame();
|
||||
}, _el$);
|
||||
_$setProp(_el$, "flexDirection", "column");
|
||||
_$setProp(_el$, "height", 3);
|
||||
_$setProp(_el$2, "selectable", false);
|
||||
_$insert(_el$2, () => segments().map((s) => topEdge(chars, s.label)).join(""));
|
||||
_$setProp(_el$3, "flexDirection", "row");
|
||||
_$insert(_el$3, _$createComponent(Index, {
|
||||
get each() {
|
||||
return segments();
|
||||
},
|
||||
children: (s) => [(() => {
|
||||
var _el$5 = _$createElement("text");
|
||||
_$setProp(_el$5, "selectable", false);
|
||||
_$insert(_el$5, () => chars.vertical);
|
||||
_$effect((_$p) => _$setProp(_el$5, "fg", borderColor(), _$p));
|
||||
return _el$5;
|
||||
})(), (() => {
|
||||
var _el$6 = _$createElement("text");
|
||||
_$setProp(_el$6, "selectable", false);
|
||||
_$insert(_el$6, () => ` ${s().label} `);
|
||||
_$effect((_p$) => {
|
||||
var _v$3 = s().isActive ? accent() : muted(), _v$4 = s().isActive ? TextAttributes.BOLD : undefined, _v$5 = theme.mouse && s().value !== undefined ? () => props.onChange(s().value) : undefined;
|
||||
_v$3 !== _p$.e && (_p$.e = _$setProp(_el$6, "fg", _v$3, _p$.e));
|
||||
_v$4 !== _p$.t && (_p$.t = _$setProp(_el$6, "attributes", _v$4, _p$.t));
|
||||
_v$5 !== _p$.a && (_p$.a = _$setProp(_el$6, "onMouseDown", _v$5, _p$.a));
|
||||
return _p$;
|
||||
}, {
|
||||
e: undefined,
|
||||
t: undefined,
|
||||
a: undefined
|
||||
});
|
||||
return _el$6;
|
||||
})(), (() => {
|
||||
var _el$7 = _$createElement("text");
|
||||
_$setProp(_el$7, "selectable", false);
|
||||
_$insert(_el$7, () => chars.vertical);
|
||||
_$effect((_$p) => _$setProp(_el$7, "fg", borderColor(), _$p));
|
||||
return _el$7;
|
||||
})()]
|
||||
}));
|
||||
_$setProp(_el$4, "selectable", false);
|
||||
_$insert(_el$4, () => buildBottomRow(chars, segments(), width()));
|
||||
_$effect((_p$) => {
|
||||
var _v$ = borderColor(), _v$2 = borderColor();
|
||||
_v$ !== _p$.e && (_p$.e = _$setProp(_el$2, "fg", _v$, _p$.e));
|
||||
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$4, "fg", _v$2, _p$.t));
|
||||
return _p$;
|
||||
}, {
|
||||
e: undefined,
|
||||
t: undefined
|
||||
});
|
||||
return _el$;
|
||||
})();
|
||||
}
|
||||
|
||||
export { stepTabValue, Tabs };
|
||||
Reference in New Issue
Block a user