precompile

Signed-off-by: Hadi <[email protected]>
This commit is contained in:
Hadi
2026-09-01 10:57:30 +02:00
parent 12305ba1f2
commit 038842878a
46 changed files with 1602 additions and 2 deletions
-1
View File
@@ -1,2 +1 @@
node_modules/
dist/
+26
View File
@@ -0,0 +1,26 @@
// @bun
// src/context/helper.tsx
import { createComponent as _$createComponent } from "@opentui/solid";
import { createContext, useContext } from "solid-js";
function createSimpleContext(input) {
const ctx = createContext();
return {
provider: (props) => {
const value = input.init(props);
return _$createComponent(ctx.Provider, {
value,
get children() {
return props.children;
}
});
},
use() {
const value = useContext(ctx);
if (!value)
throw new Error(`${input.name} context must be used within its provider`);
return value;
}
};
}
export { createSimpleContext };
+45
View File
@@ -0,0 +1,45 @@
// @bun
import {
buildPresets
} from "./chunk-ergc99dh.js";
import {
configPath,
readYamlFile
} from "./chunk-7f8jagy5.js";
import {
mergeConfig,
normalizeColors,
resolveBorderStyle
} from "./chunk-hcq62p48.js";
// src/index.ts
import { join } from "path";
function buildTheme() {
const defaultConfigPath = join(import.meta.dir, "default.yaml");
const base = readYamlFile(defaultConfigPath) ?? {};
const user = readYamlFile(configPath()) ?? {};
const merged = mergeConfig(base, user);
const colors = normalizeColors(merged.colors);
return {
...colors,
background: colors.base00,
subtleBg: colors.base01,
selection: colors.base02,
subtle: colors.base03,
muted: colors.base04,
text: colors.base05,
primary: colors.base0d,
success: colors.base0b,
warning: colors.base09,
error: colors.base08,
nerdFonts: merged.nerdFonts,
emojiFonts: merged.emojiFonts,
reducedMotion: merged.reducedMotion,
mouse: merged.mouse,
borderStyle: resolveBorderStyle(merged.border)
};
}
var theme = buildTheme();
var presets = buildPresets(theme);
export { theme, presets };
+22
View File
@@ -0,0 +1,22 @@
// @bun
// src/yaml.ts
import { existsSync, readFileSync } from "fs";
import { homedir } from "os";
import { join } from "path";
import { parse as parseYAML } from "yaml";
function configPath() {
const configDir = process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
return join(configDir, "ilovetui", "config.yaml");
}
function readYamlFile(path) {
if (!existsSync(path))
return;
try {
return parseYAML(readFileSync(path, "utf8")) ?? undefined;
} catch (err) {
console.error(`ilovetui: failed to parse ${path}, ignoring it.`, err);
return;
}
}
export { configPath, readYamlFile };
+69
View File
@@ -0,0 +1,69 @@
// @bun
import {
theme
} from "./chunk-57mam43k.js";
// src/components/Modal.tsx
import { createComponent as _$createComponent } from "@opentui/solid";
import { effect as _$effect } from "@opentui/solid";
import { insertNode as _$insertNode } from "@opentui/solid";
import { insert as _$insert } from "@opentui/solid";
import { setProp as _$setProp } from "@opentui/solid";
import { createElement as _$createElement } from "@opentui/solid";
import { RGBA } from "@opentui/core";
import { Portal, useTerminalDimensions } from "@opentui/solid";
import { Show } from "solid-js";
function Modal(props) {
const dimensions = useTerminalDimensions();
return _$createComponent(Portal, {
get children() {
return _$createComponent(Show, {
get when() {
return props.open;
},
get children() {
var _el$ = _$createElement("box"), _el$2 = _$createElement("box");
_$insertNode(_el$, _el$2);
_$setProp(_el$, "position", "absolute");
_$setProp(_el$, "top", 0);
_$setProp(_el$, "left", 0);
_$setProp(_el$, "alignItems", "center");
_$setProp(_el$, "zIndex", 2000);
_$setProp(_el$2, "border", true);
_$setProp(_el$2, "flexDirection", "column");
_$setProp(_el$2, "paddingLeft", 2);
_$setProp(_el$2, "paddingRight", 2);
_$setProp(_el$2, "paddingTop", 1);
_$setProp(_el$2, "paddingBottom", 1);
_$insert(_el$2, () => props.children);
_$effect((_p$) => {
var _v$ = dimensions().width, _v$2 = dimensions().height, _v$3 = Math.floor(dimensions().height / 4), _v$4 = props.backdropColor ?? RGBA.fromInts(0, 0, 0, 150), _v$5 = theme.mouse ? props.onDismiss : undefined, _v$6 = props.width ?? 50, _v$7 = theme.borderStyle, _v$8 = props.accentColor ?? theme.primary, _v$9 = props.backgroundColor ?? theme.background;
_v$ !== _p$.e && (_p$.e = _$setProp(_el$, "width", _v$, _p$.e));
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$, "height", _v$2, _p$.t));
_v$3 !== _p$.a && (_p$.a = _$setProp(_el$, "paddingTop", _v$3, _p$.a));
_v$4 !== _p$.o && (_p$.o = _$setProp(_el$, "backgroundColor", _v$4, _p$.o));
_v$5 !== _p$.i && (_p$.i = _$setProp(_el$, "onMouseDown", _v$5, _p$.i));
_v$6 !== _p$.n && (_p$.n = _$setProp(_el$2, "width", _v$6, _p$.n));
_v$7 !== _p$.s && (_p$.s = _$setProp(_el$2, "borderStyle", _v$7, _p$.s));
_v$8 !== _p$.h && (_p$.h = _$setProp(_el$2, "borderColor", _v$8, _p$.h));
_v$9 !== _p$.r && (_p$.r = _$setProp(_el$2, "backgroundColor", _v$9, _p$.r));
return _p$;
}, {
e: undefined,
t: undefined,
a: undefined,
o: undefined,
i: undefined,
n: undefined,
s: undefined,
h: undefined,
r: undefined
});
return _el$;
}
});
}
});
}
export { Modal };
+58
View File
@@ -0,0 +1,58 @@
// @bun
import {
theme
} from "./chunk-57mam43k.js";
// src/components/ProgressBar.tsx
import { effect as _$effect } from "@opentui/solid";
import { memo as _$memo } from "@opentui/solid";
import { insert as _$insert } from "@opentui/solid";
import { createComponent as _$createComponent } from "@opentui/solid";
import { setProp as _$setProp } from "@opentui/solid";
import { createElement as _$createElement } from "@opentui/solid";
import { parseColor, RGBA } from "@opentui/core";
import { createMemo, For } from "solid-js";
function sampleGradient(stops, t) {
if (stops.length === 1)
return stops[0];
const clamped = Math.min(Math.max(t, 0), 1);
const segment = clamped * (stops.length - 1);
const i = Math.min(Math.floor(segment), stops.length - 2);
const localT = segment - i;
const [ar, ag, ab, aa] = parseColor(stops[i]).toInts();
const [br, bg, bb, ba] = parseColor(stops[i + 1]).toInts();
return RGBA.fromInts(Math.round(ar + (br - ar) * localT), Math.round(ag + (bg - ag) * localT), Math.round(ab + (bb - ab) * localT), Math.round(aa + (ba - aa) * localT));
}
function ProgressBar(props) {
const width = () => props.width ?? 20;
const stops = createMemo(() => Array.isArray(props.color) ? props.color : [props.color ?? theme.primary]);
const filled = createMemo(() => Math.round(width() * Math.min(Math.max(props.value, 0), 100) / 100));
const cells = createMemo(() => Array.from({
length: width()
}, (_, i) => i));
return (() => {
var _el$ = _$createElement("box");
_$setProp(_el$, "flexDirection", "row");
_$insert(_el$, _$createComponent(For, {
get each() {
return cells();
},
children: (i) => {
const isFilled = () => i < filled();
const t = width() > 1 ? i / (width() - 1) : 0;
return (() => {
var _el$2 = _$createElement("text");
_$insert(_el$2, (() => {
var _c$ = _$memo(() => !!isFilled());
return () => _c$() ? props.fillChar ?? "\u2588" : props.trackChar ?? "\u2591";
})());
_$effect((_$p) => _$setProp(_el$2, "fg", isFilled() ? sampleGradient(stops(), t) : props.trackColor ?? theme.muted, _$p));
return _el$2;
})();
}
}));
return _el$;
})();
}
export { ProgressBar };
+9
View File
@@ -0,0 +1,9 @@
// @bun
// src/context/help.ts
import { createSignal } from "solid-js";
var [helpOpen, setHelpOpen] = createSignal(false);
function toggleHelp() {
setHelpOpen((open) => !open);
}
export { helpOpen, toggleHelp };
+162
View File
@@ -0,0 +1,162 @@
// @bun
import {
theme
} from "./chunk-57mam43k.js";
// src/components/Tabs.tsx
import { createTextNode as _$createTextNode } from "@opentui/solid";
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 { CliRenderEvents, TextAttributes } from "@opentui/core";
import { onResize, useRenderer } from "@opentui/solid";
import { createMemo, createSignal, For } 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(label) {
return `\u256D${"\u2500".repeat(innerWidth(label))}\u256E`;
}
function bottomEdge(label, isFirst, isLast, isActive) {
const left = isFirst ? isActive ? "\u2502" : "\u251C" : isActive ? "\u256F" : "\u2534";
const right = isLast ? isActive ? "\u2502" : "\u2524" : isActive ? "\u2570" : "\u2534";
const fill = isActive ? " " : "\u2500";
return left + fill.repeat(innerWidth(label)) + right;
}
function buildBottomRow(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(s.label, i === 0, i === segments.length - 1 && !extending, s.isActive)).join("");
return extending ? tabs + "\u2500".repeat(remainder - 1) + "\u256E" : 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();
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");
_$insert(_el$2, () => segments().map((s) => topEdge(s.label)).join(""));
_$setProp(_el$3, "flexDirection", "row");
_$insert(_el$3, _$createComponent(For, {
get each() {
return segments();
},
children: (s) => [(() => {
var _el$5 = _$createElement("text");
_$insertNode(_el$5, _$createTextNode(`\u2502`));
_$effect((_$p) => _$setProp(_el$5, "fg", borderColor(), _$p));
return _el$5;
})(), (() => {
var _el$7 = _$createElement("text");
_$insert(_el$7, () => ` ${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$7, "fg", _v$3, _p$.e));
_v$4 !== _p$.t && (_p$.t = _$setProp(_el$7, "attributes", _v$4, _p$.t));
_v$5 !== _p$.a && (_p$.a = _$setProp(_el$7, "onMouseDown", _v$5, _p$.a));
return _p$;
}, {
e: undefined,
t: undefined,
a: undefined
});
return _el$7;
})(), (() => {
var _el$8 = _$createElement("text");
_$insertNode(_el$8, _$createTextNode(`\u2502`));
_$effect((_$p) => _$setProp(_el$8, "fg", borderColor(), _$p));
return _el$8;
})()]
}));
_$insert(_el$4, () => buildBottomRow(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 };
+121
View File
@@ -0,0 +1,121 @@
// @bun
import {
theme
} from "./chunk-57mam43k.js";
// src/components/HelpBar.tsx
import { createTextNode as _$createTextNode } from "@opentui/solid";
import { insertNode as _$insertNode } from "@opentui/solid";
import { effect as _$effect } from "@opentui/solid";
import { memo as _$memo } from "@opentui/solid";
import { insert as _$insert } from "@opentui/solid";
import { createComponent as _$createComponent } 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 { CliRenderEvents, TextAttributes } from "@opentui/core";
import { onResize, useRenderer } from "@opentui/solid";
import { formatCommandBindings } from "@opentui/keymap/extras";
import { useKeymapSelector } from "@opentui/keymap/solid";
import { createMemo, createSignal, For } from "solid-js";
var KEY_DISPLAY = {
up: "\u2191",
down: "\u2193",
left: "\u2190",
right: "\u2192",
enter: "Enter",
escape: "Esc"
};
var SEPARATOR = " ";
var ELLIPSIS = "\u2026";
function HelpBar(props = {}) {
const accent = () => props.accentColor ?? theme.primary;
const muted = () => props.mutedColor ?? theme.muted;
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 entries = useKeymapSelector((keymap) => keymap.getCommandEntries({
visibility: "active"
}).filter((entry) => entry.command.shortHelp === true).map((entry) => ({
command: entry.command.name,
keys: formatCommandBindings(entry.bindings, {
keyNameAliases: KEY_DISPLAY
}) ?? "",
label: typeof entry.command.desc === "string" ? entry.command.desc : entry.command.name
})));
const visible = createMemo(() => {
const available = width() - 2;
const shown = [];
let used = 0;
for (const entry of entries()) {
const sepWidth = shown.length > 0 ? SEPARATOR.length : 0;
const entryWidth = entry.keys.length + 1 + entry.label.length;
if (used + sepWidth + entryWidth <= available) {
used += sepWidth + entryWidth;
shown.push(entry);
continue;
}
const remaining = available - used - sepWidth;
const prefix = `${entry.keys} `;
if (remaining > prefix.length + ELLIPSIS.length) {
const labelBudget = remaining - prefix.length - ELLIPSIS.length;
shown.push({
...entry,
label: `${entry.label.slice(0, labelBudget)}${ELLIPSIS}`
});
}
break;
}
return shown;
});
return (() => {
var _el$ = _$createElement("box");
_$use((el) => {
container = el;
remeasureNextFrame();
}, _el$);
_$setProp(_el$, "flexDirection", "row");
_$setProp(_el$, "paddingLeft", 1);
_$setProp(_el$, "paddingRight", 1);
_$setProp(_el$, "overflow", "hidden");
_$insert(_el$, _$createComponent(For, {
get each() {
return visible();
},
children: (entry, i) => [_$memo(() => _$memo(() => i() > 0)() && (() => {
var _el$4 = _$createElement("text");
_$insertNode(_el$4, _$createTextNode(` `));
_$effect((_$p) => _$setProp(_el$4, "fg", muted(), _$p));
return _el$4;
})()), (() => {
var _el$2 = _$createElement("text");
_$insert(_el$2, () => entry.keys);
_$effect((_p$) => {
var _v$ = accent(), _v$2 = TextAttributes.BOLD;
_v$ !== _p$.e && (_p$.e = _$setProp(_el$2, "fg", _v$, _p$.e));
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$2, "attributes", _v$2, _p$.t));
return _p$;
}, {
e: undefined,
t: undefined
});
return _el$2;
})(), (() => {
var _el$3 = _$createElement("text");
_$insert(_el$3, () => ` ${entry.label}`);
_$effect((_$p) => _$setProp(_el$3, "fg", muted(), _$p));
return _el$3;
})()]
}));
return _el$;
})();
}
export { HelpBar };
+40
View File
@@ -0,0 +1,40 @@
// @bun
// src/presets.ts
function buildPresets(theme) {
const select = {
backgroundColor: theme.background,
textColor: theme.text,
focusedBackgroundColor: theme.subtleBg,
focusedTextColor: theme.text,
selectedBackgroundColor: theme.selection,
selectedTextColor: theme.primary,
descriptionColor: theme.muted,
selectedDescriptionColor: theme.text
};
const tabSelect = {
backgroundColor: theme.background,
textColor: theme.text,
focusedBackgroundColor: theme.subtleBg,
focusedTextColor: theme.text,
selectedBackgroundColor: theme.selection,
selectedTextColor: theme.primary,
selectedDescriptionColor: theme.text
};
const input = {
backgroundColor: theme.background,
textColor: theme.text,
focusedBackgroundColor: theme.subtleBg,
focusedTextColor: theme.text,
placeholderColor: theme.muted
};
const box = {
border: true,
borderStyle: theme.borderStyle,
borderColor: theme.subtle,
focusedBorderColor: theme.primary,
backgroundColor: theme.background
};
return { select, tabSelect, input, textarea: input, box };
}
export { buildPresets };
+77
View File
@@ -0,0 +1,77 @@
// @bun
import {
theme
} from "./chunk-57mam43k.js";
import {
dismiss,
notifications
} from "./chunk-y6txxzxk.js";
// src/components/NotificationHost.tsx
import { effect as _$effect } from "@opentui/solid";
import { insertNode as _$insertNode } from "@opentui/solid";
import { memo as _$memo } from "@opentui/solid";
import { insert as _$insert } from "@opentui/solid";
import { createComponent as _$createComponent } from "@opentui/solid";
import { setProp as _$setProp } from "@opentui/solid";
import { createElement as _$createElement } from "@opentui/solid";
import { Portal } from "@opentui/solid";
import { For } from "solid-js";
var KIND_LABEL = {
info: "Info",
success: "Success",
warning: "Warning",
error: "Error"
};
function NotificationHost(props = {}) {
const defaultColor = () => ({
info: theme.primary,
success: theme.success,
warning: theme.warning,
error: theme.error
});
const colorFor = (kind) => props.colors?.[kind] ?? defaultColor()[kind];
return _$createComponent(Portal, {
get children() {
var _el$ = _$createElement("box");
_$setProp(_el$, "position", "absolute");
_$setProp(_el$, "top", 1);
_$setProp(_el$, "right", 1);
_$setProp(_el$, "flexDirection", "column");
_$setProp(_el$, "zIndex", 1000);
_$insert(_el$, _$createComponent(For, {
get each() {
return notifications();
},
children: (toast) => (() => {
var _el$2 = _$createElement("box"), _el$3 = _$createElement("text"), _el$4 = _$createElement("text");
_$insertNode(_el$2, _el$3);
_$insertNode(_el$2, _el$4);
_$setProp(_el$2, "border", true);
_$setProp(_el$2, "marginBottom", 1);
_$insert(_el$3, () => toast.title ?? KIND_LABEL[toast.kind]);
_$insert(_el$4, () => toast.message);
_$effect((_p$) => {
var _v$ = theme.borderStyle, _v$2 = colorFor(toast.kind), _v$3 = props.width ?? 32, _v$4 = theme.mouse ? () => dismiss(toast.id) : undefined, _v$5 = colorFor(toast.kind);
_v$ !== _p$.e && (_p$.e = _$setProp(_el$2, "borderStyle", _v$, _p$.e));
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$2, "borderColor", _v$2, _p$.t));
_v$3 !== _p$.a && (_p$.a = _$setProp(_el$2, "width", _v$3, _p$.a));
_v$4 !== _p$.o && (_p$.o = _$setProp(_el$2, "onMouseDown", _v$4, _p$.o));
_v$5 !== _p$.i && (_p$.i = _$setProp(_el$3, "fg", _v$5, _p$.i));
return _p$;
}, {
e: undefined,
t: undefined,
a: undefined,
o: undefined,
i: undefined
});
return _el$2;
})()
}));
return _el$;
}
});
}
export { NotificationHost };
+60
View File
@@ -0,0 +1,60 @@
// @bun
// src/config.ts
var COLOR_KEYS = [
"base00",
"base01",
"base02",
"base03",
"base04",
"base05",
"base06",
"base07",
"base08",
"base09",
"base0a",
"base0b",
"base0c",
"base0d",
"base0e",
"base0f"
];
function mergeColors(base, user) {
const merged = {};
for (const key of COLOR_KEYS) {
merged[key] = user[key] || base[key] || "";
}
return merged;
}
function mergeConfig(base, user) {
return {
nerdFonts: user.nerd_fonts ?? base.nerd_fonts ?? false,
emojiFonts: user.emoji_fonts ?? base.emoji_fonts ?? false,
reducedMotion: user.reduced_motion ?? base.reduced_motion ?? false,
mouse: user.mouse ?? base.mouse ?? true,
border: user.border || base.border || "rounded",
colors: mergeColors(base.colors ?? {}, user.colors ?? {})
};
}
function normalizeColor(hex) {
const trimmed = hex.trim();
if (trimmed && !trimmed.startsWith("#"))
return `#${trimmed}`;
return trimmed;
}
function normalizeColors(colors) {
const out = {};
for (const key of COLOR_KEYS)
out[key] = normalizeColor(colors[key]);
return out;
}
var OPENTUI_BORDER_STYLES = [
"single",
"double",
"rounded",
"heavy"
];
function resolveBorderStyle(name) {
return OPENTUI_BORDER_STYLES.includes(name) ? name : "rounded";
}
export { COLOR_KEYS, mergeColors, mergeConfig, normalizeColor, normalizeColors, resolveBorderStyle };
+80
View File
@@ -0,0 +1,80 @@
// @bun
import {
theme
} from "./chunk-57mam43k.js";
// src/components/Badge.tsx
import { insertNode as _$insertNode } from "@opentui/solid";
import { insert as _$insert } from "@opentui/solid";
import { memo as _$memo } from "@opentui/solid";
import { createComponent as _$createComponent } from "@opentui/solid";
import { effect as _$effect } from "@opentui/solid";
import { setProp as _$setProp } from "@opentui/solid";
import { createElement as _$createElement } from "@opentui/solid";
import { TextAttributes } from "@opentui/core";
import { Show } from "solid-js";
function Badge(props) {
const textColor = () => props.textColor ?? theme.background;
const backgroundColor = () => props.backgroundColor ?? theme.background;
const attributes = () => props.bold === false ? undefined : TextAttributes.BOLD;
const nerdFonts = () => props.withNerdfont ?? theme.nerdFonts;
return (() => {
var _el$ = _$createElement("box"), _el$3 = _$createElement("text");
_$insertNode(_el$, _el$3);
_$setProp(_el$, "flexDirection", "row");
_$insert(_el$, _$createComponent(Show, {
get when() {
return nerdFonts();
},
get children() {
var _el$2 = _$createElement("text");
_$effect((_p$) => {
var _v$ = props.color, _v$2 = backgroundColor();
_v$ !== _p$.e && (_p$.e = _$setProp(_el$2, "fg", _v$, _p$.e));
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$2, "bg", _v$2, _p$.t));
return _p$;
}, {
e: undefined,
t: undefined
});
return _el$2;
}
}), _el$3);
_$insert(_el$3, (() => {
var _c$ = _$memo(() => !!nerdFonts());
return () => _c$() ? props.label : ` ${props.label} `;
})());
_$insert(_el$, _$createComponent(Show, {
get when() {
return nerdFonts();
},
get children() {
var _el$4 = _$createElement("text");
_$effect((_p$) => {
var _v$3 = props.color, _v$4 = backgroundColor();
_v$3 !== _p$.e && (_p$.e = _$setProp(_el$4, "fg", _v$3, _p$.e));
_v$4 !== _p$.t && (_p$.t = _$setProp(_el$4, "bg", _v$4, _p$.t));
return _p$;
}, {
e: undefined,
t: undefined
});
return _el$4;
}
}), null);
_$effect((_p$) => {
var _v$5 = textColor(), _v$6 = props.color, _v$7 = attributes();
_v$5 !== _p$.e && (_p$.e = _$setProp(_el$3, "fg", _v$5, _p$.e));
_v$6 !== _p$.t && (_p$.t = _$setProp(_el$3, "bg", _v$6, _p$.t));
_v$7 !== _p$.a && (_p$.a = _$setProp(_el$3, "attributes", _v$7, _p$.a));
return _p$;
}, {
e: undefined,
t: undefined,
a: undefined
});
return _el$;
})();
}
export { Badge };
+60
View File
@@ -0,0 +1,60 @@
// @bun
import {
theme
} from "./chunk-57mam43k.js";
// src/components/MinSizeGuard.tsx
import { createComponent as _$createComponent } from "@opentui/solid";
import { effect as _$effect } from "@opentui/solid";
import { insertNode as _$insertNode } from "@opentui/solid";
import { insert as _$insert } from "@opentui/solid";
import { setProp as _$setProp } from "@opentui/solid";
import { createElement as _$createElement } from "@opentui/solid";
import { useTerminalDimensions } from "@opentui/solid";
import { Match, Switch } from "solid-js";
function MinSizeGuard(props) {
const dimensions = useTerminalDimensions();
const minWidth = () => props.minWidth ?? 80;
const minHeight = () => props.minHeight ?? 24;
const tooSmall = () => dimensions().width < minWidth() || dimensions().height < minHeight();
return _$createComponent(Switch, {
get children() {
return [_$createComponent(Match, {
get when() {
return tooSmall();
},
get children() {
var _el$ = _$createElement("box"), _el$2 = _$createElement("text");
_$insertNode(_el$, _el$2);
_$setProp(_el$, "alignItems", "center");
_$setProp(_el$, "justifyContent", "center");
_$insert(_el$2, () => `Terminal too small
Minimum size: ${minWidth()}x${minHeight()} \u2014 current: ${dimensions().width}x${dimensions().height}`);
_$effect((_p$) => {
var _v$ = dimensions().width, _v$2 = dimensions().height, _v$3 = props.backgroundColor ?? theme.background, _v$4 = props.textColor ?? theme.muted;
_v$ !== _p$.e && (_p$.e = _$setProp(_el$, "width", _v$, _p$.e));
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$, "height", _v$2, _p$.t));
_v$3 !== _p$.a && (_p$.a = _$setProp(_el$, "backgroundColor", _v$3, _p$.a));
_v$4 !== _p$.o && (_p$.o = _$setProp(_el$2, "fg", _v$4, _p$.o));
return _p$;
}, {
e: undefined,
t: undefined,
a: undefined,
o: undefined
});
return _el$;
}
}), _$createComponent(Match, {
get when() {
return !tooSmall();
},
get children() {
return props.children;
}
})];
}
});
}
export { MinSizeGuard };
+78
View File
@@ -0,0 +1,78 @@
// @bun
import {
theme
} from "./chunk-57mam43k.js";
// src/components/Sidebar.tsx
import { effect as _$effect } from "@opentui/solid";
import { insertNode as _$insertNode } from "@opentui/solid";
import { use as _$use } from "@opentui/solid";
import { insert as _$insert } from "@opentui/solid";
import { setProp as _$setProp } from "@opentui/solid";
import { createElement as _$createElement } from "@opentui/solid";
import { TextAttributes } from "@opentui/core";
function Sidebar(props) {
return (() => {
var _el$ = _$createElement("box"), _el$2 = _$createElement("text"), _el$3 = _$createElement("select");
_$insertNode(_el$, _el$2);
_$insertNode(_el$, _el$3);
_$setProp(_el$, "border", true);
_$setProp(_el$, "flexDirection", "column");
_$insert(_el$2, () => props.title);
_$use((el) => {
props.ref?.(el && {
moveUp: () => el.moveUp(),
moveDown: () => el.moveDown(),
selectCurrent: () => el.selectCurrent()
});
}, _el$3);
_$setProp(_el$3, "flexGrow", 1);
_$setProp(_el$3, "showScrollIndicator", true);
_$setProp(_el$3, "onChange", (_index, option) => {
if (!option)
return;
props.onSelect(option);
});
_$setProp(_el$3, "onSelect", (_index, option) => {
if (!option)
return;
props.onConfirm?.(option);
});
_$effect((_p$) => {
var _v$ = props.width ?? 24, _v$2 = theme.borderStyle, _v$3 = props.focused ? props.accentColor ?? theme.primary : props.mutedColor ?? theme.muted, _v$4 = TextAttributes.BOLD, _v$5 = props.focused, _v$6 = props.items, _v$7 = props.backgroundColor, _v$8 = props.textColor, _v$9 = props.focusedBackgroundColor, _v$0 = props.focusedTextColor, _v$1 = props.selectedBackgroundColor, _v$10 = props.selectedTextColor, _v$11 = props.descriptionColor, _v$12 = props.selectedDescriptionColor;
_v$ !== _p$.e && (_p$.e = _$setProp(_el$, "width", _v$, _p$.e));
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$, "borderStyle", _v$2, _p$.t));
_v$3 !== _p$.a && (_p$.a = _$setProp(_el$, "borderColor", _v$3, _p$.a));
_v$4 !== _p$.o && (_p$.o = _$setProp(_el$2, "attributes", _v$4, _p$.o));
_v$5 !== _p$.i && (_p$.i = _$setProp(_el$3, "focused", _v$5, _p$.i));
_v$6 !== _p$.n && (_p$.n = _$setProp(_el$3, "options", _v$6, _p$.n));
_v$7 !== _p$.s && (_p$.s = _$setProp(_el$3, "backgroundColor", _v$7, _p$.s));
_v$8 !== _p$.h && (_p$.h = _$setProp(_el$3, "textColor", _v$8, _p$.h));
_v$9 !== _p$.r && (_p$.r = _$setProp(_el$3, "focusedBackgroundColor", _v$9, _p$.r));
_v$0 !== _p$.d && (_p$.d = _$setProp(_el$3, "focusedTextColor", _v$0, _p$.d));
_v$1 !== _p$.l && (_p$.l = _$setProp(_el$3, "selectedBackgroundColor", _v$1, _p$.l));
_v$10 !== _p$.u && (_p$.u = _$setProp(_el$3, "selectedTextColor", _v$10, _p$.u));
_v$11 !== _p$.c && (_p$.c = _$setProp(_el$3, "descriptionColor", _v$11, _p$.c));
_v$12 !== _p$.w && (_p$.w = _$setProp(_el$3, "selectedDescriptionColor", _v$12, _p$.w));
return _p$;
}, {
e: undefined,
t: undefined,
a: undefined,
o: undefined,
i: undefined,
n: undefined,
s: undefined,
h: undefined,
r: undefined,
d: undefined,
l: undefined,
u: undefined,
c: undefined,
w: undefined
});
return _el$;
})();
}
export { Sidebar };
+32
View File
@@ -0,0 +1,32 @@
// @bun
import {
theme
} from "./chunk-57mam43k.js";
// src/components/SignalBars.tsx
import { effect as _$effect } from "@opentui/solid";
import { insert as _$insert } from "@opentui/solid";
import { createComponent as _$createComponent } from "@opentui/solid";
import { setProp as _$setProp } from "@opentui/solid";
import { createElement as _$createElement } from "@opentui/solid";
import { For } from "solid-js";
var BARS = ["\u2581", "\u2583", "\u2585", "\u2587"];
function SignalBars(props) {
const level = () => Math.floor(props.signal * BARS.length / 100);
return (() => {
var _el$ = _$createElement("box");
_$setProp(_el$, "flexDirection", "row");
_$insert(_el$, _$createComponent(For, {
each: BARS,
children: (bar, i) => (() => {
var _el$2 = _$createElement("text");
_$insert(_el$2, bar);
_$effect((_$p) => _$setProp(_el$2, "fg", i() < level() ? props.filledColor : props.emptyColor ?? theme.muted, _$p));
return _el$2;
})()
}));
return _el$;
})();
}
export { SignalBars };
+21
View File
@@ -0,0 +1,21 @@
// @bun
// src/context/notifications.ts
import { createSignal } from "solid-js";
var DEFAULT_DURATION = 3000;
var [notifications, setNotifications] = createSignal([]);
var nextId = 0;
function notify(message, options = {}) {
const id = options.id ?? `toast-${nextId++}`;
const toast = { id, title: options.title, message, kind: options.kind ?? "info" };
setNotifications((prev) => [...prev.filter((n) => n.id !== id), toast]);
const duration = options.duration ?? DEFAULT_DURATION;
if (duration > 0) {
setTimeout(() => dismiss(id), duration);
}
return id;
}
function dismiss(id) {
setNotifications((prev) => prev.filter((n) => n.id !== id));
}
export { notifications, notify, dismiss };
+76
View File
@@ -0,0 +1,76 @@
// @bun
import {
Modal
} from "./chunk-840y6ygm.js";
import {
helpOpen,
toggleHelp
} from "./chunk-cyvpvpws.js";
// src/components/HelpModal.tsx
import { createComponent as _$createComponent } from "@opentui/solid";
import { insert as _$insert } from "@opentui/solid";
import { setProp as _$setProp } from "@opentui/solid";
import { effect as _$effect } from "@opentui/solid";
import { createTextNode as _$createTextNode } from "@opentui/solid";
import { insertNode as _$insertNode } from "@opentui/solid";
import { createElement as _$createElement } from "@opentui/solid";
import { TextAttributes } from "@opentui/core";
import { formatCommandBindings } from "@opentui/keymap/extras";
import { useKeymapSelector } from "@opentui/keymap/solid";
var KEY_DISPLAY = {
up: "\u2191",
down: "\u2193",
left: "\u2190",
right: "\u2192",
enter: "Enter",
escape: "Esc"
};
function HelpModal(props = {}) {
const entries = useKeymapSelector((keymap) => keymap.getCommandEntries({
visibility: "active"
}).map((entry) => ({
command: entry.command.name,
keys: formatCommandBindings(entry.bindings, {
keyNameAliases: KEY_DISPLAY
}) ?? "",
label: typeof entry.command.desc === "string" ? entry.command.desc : entry.command.name
})));
return _$createComponent(Modal, {
get open() {
return helpOpen();
},
onDismiss: toggleHelp,
get accentColor() {
return props.accentColor;
},
get backgroundColor() {
return props.backgroundColor;
},
get backdropColor() {
return props.backdropColor;
},
get width() {
return props.width;
},
get children() {
return [(() => {
var _el$ = _$createElement("text");
_$insertNode(_el$, _$createTextNode(`Keybindings`));
_$effect((_$p) => _$setProp(_el$, "attributes", TextAttributes.BOLD, _$p));
return _el$;
})(), (() => {
var _el$3 = _$createElement("text");
_$insertNode(_el$3, _$createTextNode(` `));
return _el$3;
})(), (() => {
var _el$5 = _$createElement("text");
_$insert(_el$5, () => entries().map((entry) => `${entry.keys.padEnd(10)}${entry.label}`).join(`
`));
return _el$5;
})()];
}
});
}
export { HelpModal };
+61
View File
@@ -0,0 +1,61 @@
// @bun
import {
Badge
} from "./chunk-shxcerba.js";
import {
theme
} from "./chunk-57mam43k.js";
// src/components/Toggle.tsx
import { setProp as _$setProp } from "@opentui/solid";
import { effect as _$effect } from "@opentui/solid";
import { insert as _$insert } from "@opentui/solid";
import { createComponent as _$createComponent } from "@opentui/solid";
import { memo as _$memo } from "@opentui/solid";
import { createElement as _$createElement } from "@opentui/solid";
import { TextAttributes } from "@opentui/core";
import { Show } from "solid-js";
function Toggle(props) {
const onColor = () => props.onColor ?? theme.success;
const offColor = () => props.offColor ?? theme.muted;
const nerdFonts = () => props.withNerdfont ?? theme.nerdFonts;
return (() => {
var _el$ = _$createElement("box");
_$insert(_el$, _$createComponent(Show, {
get when() {
return nerdFonts();
},
get fallback() {
return (() => {
var _el$2 = _$createElement("text");
_$insert(_el$2, () => props.on ? "on" : "off");
_$effect((_p$) => {
var _v$ = props.on ? onColor() : offColor(), _v$2 = TextAttributes.BOLD;
_v$ !== _p$.e && (_p$.e = _$setProp(_el$2, "fg", _v$, _p$.e));
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$2, "attributes", _v$2, _p$.t));
return _p$;
}, {
e: undefined,
t: undefined
});
return _el$2;
})();
},
get children() {
return _$createComponent(Badge, {
get label() {
return props.on ? " \u25CF" : "\u25CF ";
},
get color() {
return _$memo(() => !!props.on)() ? onColor() : offColor();
},
withNerdfont: true
});
}
}));
_$effect((_$p) => _$setProp(_el$, "onMouseDown", theme.mouse ? props.onToggle : undefined, _$p));
return _el$;
})();
}
export { Toggle };
+11
View File
@@ -0,0 +1,11 @@
// @bun
import {
Badge
} from "../chunk-shxcerba.js";
import"../chunk-57mam43k.js";
import"../chunk-ergc99dh.js";
import"../chunk-7f8jagy5.js";
import"../chunk-hcq62p48.js";
export {
Badge
};
+11
View File
@@ -0,0 +1,11 @@
// @bun
import {
HelpBar
} from "../chunk-dv2w3sfk.js";
import"../chunk-57mam43k.js";
import"../chunk-ergc99dh.js";
import"../chunk-7f8jagy5.js";
import"../chunk-hcq62p48.js";
export {
HelpBar
};
+13
View File
@@ -0,0 +1,13 @@
// @bun
import {
HelpModal
} from "../chunk-ydf2rnsn.js";
import"../chunk-840y6ygm.js";
import"../chunk-57mam43k.js";
import"../chunk-ergc99dh.js";
import"../chunk-7f8jagy5.js";
import"../chunk-hcq62p48.js";
import"../chunk-cyvpvpws.js";
export {
HelpModal
};
+11
View File
@@ -0,0 +1,11 @@
// @bun
import {
MinSizeGuard
} from "../chunk-syn54rcq.js";
import"../chunk-57mam43k.js";
import"../chunk-ergc99dh.js";
import"../chunk-7f8jagy5.js";
import"../chunk-hcq62p48.js";
export {
MinSizeGuard
};
+11
View File
@@ -0,0 +1,11 @@
// @bun
import {
Modal
} from "../chunk-840y6ygm.js";
import"../chunk-57mam43k.js";
import"../chunk-ergc99dh.js";
import"../chunk-7f8jagy5.js";
import"../chunk-hcq62p48.js";
export {
Modal
};
+12
View File
@@ -0,0 +1,12 @@
// @bun
import {
NotificationHost
} from "../chunk-g7p0f33m.js";
import"../chunk-57mam43k.js";
import"../chunk-ergc99dh.js";
import"../chunk-7f8jagy5.js";
import"../chunk-hcq62p48.js";
import"../chunk-y6txxzxk.js";
export {
NotificationHost
};
+11
View File
@@ -0,0 +1,11 @@
// @bun
import {
ProgressBar
} from "../chunk-ae0jkf2z.js";
import"../chunk-57mam43k.js";
import"../chunk-ergc99dh.js";
import"../chunk-7f8jagy5.js";
import"../chunk-hcq62p48.js";
export {
ProgressBar
};
+11
View File
@@ -0,0 +1,11 @@
// @bun
import {
Sidebar
} from "../chunk-wkg33t3z.js";
import"../chunk-57mam43k.js";
import"../chunk-ergc99dh.js";
import"../chunk-7f8jagy5.js";
import"../chunk-hcq62p48.js";
export {
Sidebar
};
+11
View File
@@ -0,0 +1,11 @@
// @bun
import {
SignalBars
} from "../chunk-xab9ag99.js";
import"../chunk-57mam43k.js";
import"../chunk-ergc99dh.js";
import"../chunk-7f8jagy5.js";
import"../chunk-hcq62p48.js";
export {
SignalBars
};
+39
View File
@@ -0,0 +1,39 @@
// @bun
import {
theme
} from "../chunk-57mam43k.js";
import"../chunk-ergc99dh.js";
import"../chunk-7f8jagy5.js";
import"../chunk-hcq62p48.js";
// src/components/Spinner.tsx
import { setProp as _$setProp } from "@opentui/solid";
import { effect as _$effect } from "@opentui/solid";
import { createElement as _$createElement } from "@opentui/solid";
import"opentui-spinner/solid";
function Spinner(props) {
return (() => {
var _el$ = _$createElement("spinner");
_$effect((_p$) => {
var { name: _v$, frames: _v$2, interval: _v$3 } = props, _v$4 = props.autoplay ?? !theme.reducedMotion, _v$5 = props.color ?? theme.primary, _v$6 = props.backgroundColor;
_v$ !== _p$.e && (_p$.e = _$setProp(_el$, "name", _v$, _p$.e));
_v$2 !== _p$.t && (_p$.t = _$setProp(_el$, "frames", _v$2, _p$.t));
_v$3 !== _p$.a && (_p$.a = _$setProp(_el$, "interval", _v$3, _p$.a));
_v$4 !== _p$.o && (_p$.o = _$setProp(_el$, "autoplay", _v$4, _p$.o));
_v$5 !== _p$.i && (_p$.i = _$setProp(_el$, "color", _v$5, _p$.i));
_v$6 !== _p$.n && (_p$.n = _$setProp(_el$, "backgroundColor", _v$6, _p$.n));
return _p$;
}, {
e: undefined,
t: undefined,
a: undefined,
o: undefined,
i: undefined,
n: undefined
});
return _el$;
})();
}
export {
Spinner
};
+13
View File
@@ -0,0 +1,13 @@
// @bun
import {
Tabs,
stepTabValue
} from "../chunk-d2tt920p.js";
import"../chunk-57mam43k.js";
import"../chunk-ergc99dh.js";
import"../chunk-7f8jagy5.js";
import"../chunk-hcq62p48.js";
export {
stepTabValue,
Tabs
};
+12
View File
@@ -0,0 +1,12 @@
// @bun
import {
Toggle
} from "../chunk-zs53wnet.js";
import"../chunk-shxcerba.js";
import"../chunk-57mam43k.js";
import"../chunk-ergc99dh.js";
import"../chunk-7f8jagy5.js";
import"../chunk-hcq62p48.js";
export {
Toggle
};
+17
View File
@@ -0,0 +1,17 @@
// @bun
import {
HelpModal
} from "../chunk-ydf2rnsn.js";
import"../chunk-840y6ygm.js";
import {
HelpBar
} from "../chunk-dv2w3sfk.js";
import"../chunk-57mam43k.js";
import"../chunk-ergc99dh.js";
import"../chunk-7f8jagy5.js";
import"../chunk-hcq62p48.js";
import"../chunk-cyvpvpws.js";
export {
HelpModal,
HelpBar
};
+46
View File
@@ -0,0 +1,46 @@
// @bun
import {
ProgressBar
} from "../chunk-ae0jkf2z.js";
import {
Sidebar
} from "../chunk-wkg33t3z.js";
import {
SignalBars
} from "../chunk-xab9ag99.js";
import {
NotificationHost
} from "../chunk-g7p0f33m.js";
import {
Toggle
} from "../chunk-zs53wnet.js";
import {
Tabs,
stepTabValue
} from "../chunk-d2tt920p.js";
import {
Modal
} from "../chunk-840y6ygm.js";
import {
Badge
} from "../chunk-shxcerba.js";
import {
MinSizeGuard
} from "../chunk-syn54rcq.js";
import"../chunk-57mam43k.js";
import"../chunk-ergc99dh.js";
import"../chunk-7f8jagy5.js";
import"../chunk-hcq62p48.js";
import"../chunk-y6txxzxk.js";
export {
stepTabValue,
Toggle,
Tabs,
SignalBars,
Sidebar,
ProgressBar,
NotificationHost,
Modal,
MinSizeGuard,
Badge
};
+17
View File
@@ -0,0 +1,17 @@
// @bun
import {
COLOR_KEYS,
mergeColors,
mergeConfig,
normalizeColor,
normalizeColors,
resolveBorderStyle
} from "./chunk-hcq62p48.js";
export {
resolveBorderStyle,
normalizeColors,
normalizeColor,
mergeConfig,
mergeColors,
COLOR_KEYS
};
+9
View File
@@ -0,0 +1,9 @@
// @bun
import {
helpOpen,
toggleHelp
} from "../chunk-cyvpvpws.js";
export {
toggleHelp,
helpOpen
};
+7
View File
@@ -0,0 +1,7 @@
// @bun
import {
createSimpleContext
} from "../chunk-2px9e43p.js";
export {
createSimpleContext
};
+21
View File
@@ -0,0 +1,21 @@
// @bun
import {
createSimpleContext
} from "../chunk-2px9e43p.js";
import {
helpOpen,
toggleHelp
} from "../chunk-cyvpvpws.js";
import {
dismiss,
notifications,
notify
} from "../chunk-y6txxzxk.js";
export {
toggleHelp,
notify,
notifications,
helpOpen,
dismiss,
createSimpleContext
};
+11
View File
@@ -0,0 +1,11 @@
// @bun
import {
dismiss,
notifications,
notify
} from "../chunk-y6txxzxk.js";
export {
notify,
notifications,
dismiss
};
+35
View File
@@ -0,0 +1,35 @@
# ilovetui default config
# Copy to ~/.config/ilovetui/config.yaml and edit to customize.
# Whether components may use Nerd Font glyphs (requires a patched font).
nerd_fonts: true
# Whether the terminal font can render emoji glyphs.
emoji_fonts: true
# Disable spinner animation and other motion across all ilovetui-based TUIs.
reduced_motion: false
# Whether components may register mouse handlers (e.g. click-to-dismiss).
mouse: true
# Border style used by panels across all ilovetui-based TUIs.
border: rounded
colors:
base00: "#110F12" # Background
base01: "#1C1920" # Lighter Background / Status Bars
base02: "#1D1A26" # Selection Background
base03: "#514D63" # Comments / Invisibles
base04: "#8E8AA0" # Dark Foreground / Status Bars
base05: "#C2BED6" # Default Foreground
base06: "#D8D5EA" # Light Foreground
base07: "#EAE7F7" # Light Background
base08: "#E07080" # Variables / Errors / Diff Deleted
base09: "#D49070" # Integers / Constants / Booleans
base0a: "#C4B060" # Classes / Warnings / Search Background
base0b: "#80B880" # Strings / Success / Diff Inserted
base0c: "#70B8C0" # Support / Regex / Escape Characters
base0d: "#9E97F8" # Functions / Methods / Headings / Accent
base0e: "#C090E8" # Keywords / Storage / Diff Changed
base0f: "#D080A0" # Embedded / Misc
+15
View File
@@ -0,0 +1,15 @@
// @bun
import {
presets,
theme
} from "./chunk-57mam43k.js";
import"./chunk-ergc99dh.js";
import {
configPath
} from "./chunk-7f8jagy5.js";
import"./chunk-hcq62p48.js";
export {
theme,
presets,
configPath
};
+27
View File
@@ -0,0 +1,27 @@
// @bun
// src/keymap/provider.tsx
import { createComponent as _$createComponent } from "@opentui/solid";
import { createDefaultOpenTuiKeymap } from "@opentui/keymap/opentui";
import { registerCommaBindings } from "@opentui/keymap/addons";
import { KeymapProvider as BaseKeymapProvider } from "@opentui/keymap/solid";
import { useRenderer } from "@opentui/solid";
import { onCleanup } from "solid-js";
import { useKeymap, useBindings, useKeymapSelector, reactiveMatcherFromSignal } from "@opentui/keymap/solid";
function KeymapProvider(props) {
const renderer = useRenderer();
const keymap = createDefaultOpenTuiKeymap(renderer);
onCleanup(registerCommaBindings(keymap));
return _$createComponent(BaseKeymapProvider, {
keymap,
get children() {
return props.children;
}
});
}
export {
useKeymapSelector,
useKeymap,
useBindings,
reactiveMatcherFromSignal,
KeymapProvider
};
+7
View File
@@ -0,0 +1,7 @@
// @bun
import {
buildPresets
} from "./chunk-ergc99dh.js";
export {
buildPresets
};
+75
View File
@@ -0,0 +1,75 @@
// @bun
import {
notify
} from "./chunk-y6txxzxk.js";
// src/project-config.ts
import { existsSync, readFileSync } from "fs";
import { homedir } from "os";
import { join } from "path";
import { parse as parseYAML } from "yaml";
import { z } from "zod";
function userConfigPath(projectName) {
const configHome = process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
return join(configHome, projectName, "config.yaml");
}
function readYaml(path) {
return parseYAML(readFileSync(path, "utf-8"));
}
function warn(projectName, path, message) {
const text = `${path}: ${message}`;
console.error(`[${projectName} config] ${text}`);
notify(text, { kind: "warning", duration: 0 });
}
function loadProjectConfig(options) {
const { projectName, defaultConfigPath, defaultSchema, userSchema } = options;
let rawDefaults;
try {
rawDefaults = readYaml(defaultConfigPath);
} catch (error) {
throw new Error(`Failed to read ${defaultConfigPath}: ${error instanceof Error ? error.message : error}`);
}
const defaultsResult = defaultSchema.safeParse(rawDefaults);
if (!defaultsResult.success) {
throw new Error(`${defaultConfigPath} is invalid:
${z.prettifyError(defaultsResult.error)}`);
}
const path = userConfigPath(projectName);
const user = (() => {
if (!existsSync(path))
return {};
let raw;
try {
raw = readYaml(path);
} catch (error) {
warn(projectName, path, error instanceof Error ? error.message : String(error));
return {};
}
const result = userSchema.safeParse(raw ?? {});
if (!result.success) {
warn(projectName, path, z.prettifyError(result.error));
return {};
}
return result.data;
})();
return { defaults: defaultsResult.data, user };
}
function keybindsSchema(names, required) {
const shape = {};
for (const name of names) {
shape[name] = required ? z.string().min(1) : z.string().min(1).optional();
}
return z.object(shape).strict();
}
function mergeKeybinds(names, defaults, user) {
const merged = {};
for (const name of names) {
merged[name] = user?.[name] ?? defaults[name];
}
return merged;
}
export {
mergeKeybinds,
loadProjectConfig,
keybindsSchema
};
+43
View File
@@ -0,0 +1,43 @@
// @bun
import {
presets,
theme
} from "./chunk-57mam43k.js";
import"./chunk-ergc99dh.js";
import"./chunk-7f8jagy5.js";
import"./chunk-hcq62p48.js";
// src/solid.ts
import { extend } from "@opentui/solid";
import {
ASCIIFontRenderable,
BoxRenderable,
InputRenderable,
SelectRenderable,
TabSelectRenderable,
TextareaRenderable,
TextRenderable
} from "@opentui/core";
function withThemeDefaults(Ctor, defaults, after) {
class Themed extends Ctor {
constructor(...args) {
super(...args);
Object.assign(this, defaults);
after?.(this);
}
}
return Themed;
}
var { borderStyle, borderColor, focusedBorderColor } = presets.box;
var boxDefaults = { borderStyle, borderColor, focusedBorderColor };
extend({
box: withThemeDefaults(BoxRenderable, boxDefaults, (instance) => {
instance.border = false;
}),
select: withThemeDefaults(SelectRenderable, presets.select),
tab_select: withThemeDefaults(TabSelectRenderable, presets.tabSelect),
input: withThemeDefaults(InputRenderable, presets.input),
textarea: withThemeDefaults(TextareaRenderable, presets.textarea),
text: withThemeDefaults(TextRenderable, { fg: theme.text }),
ascii_font: withThemeDefaults(ASCIIFontRenderable, { color: theme.primary })
});
+9
View File
@@ -0,0 +1,9 @@
// @bun
import {
configPath,
readYamlFile
} from "./chunk-7f8jagy5.js";
export {
readYamlFile,
configPath
};
-1
View File
@@ -18,7 +18,6 @@
"files": ["dist", "src"],
"scripts": {
"build": "bun run scripts/build.ts",
"prepare": "bun run scripts/build.ts",
"typecheck": "tsc --noEmit"
},
"peerDependencies": {