kyh 0.0.1 → 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.
- package/dist/index.js +327 -15
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -50971,6 +50971,35 @@ var AppContext = import_react.createContext({
|
|
|
50971
50971
|
keyHandler: null,
|
|
50972
50972
|
renderer: null
|
|
50973
50973
|
});
|
|
50974
|
+
var useAppContext = () => {
|
|
50975
|
+
return import_react.useContext(AppContext);
|
|
50976
|
+
};
|
|
50977
|
+
function useEffectEvent(handler) {
|
|
50978
|
+
const handlerRef = import_react3.useRef(handler);
|
|
50979
|
+
import_react3.useLayoutEffect(() => {
|
|
50980
|
+
handlerRef.current = handler;
|
|
50981
|
+
});
|
|
50982
|
+
return import_react3.useCallback((...args) => {
|
|
50983
|
+
const fn = handlerRef.current;
|
|
50984
|
+
return fn(...args);
|
|
50985
|
+
}, []);
|
|
50986
|
+
}
|
|
50987
|
+
var useKeyboard = (handler, options = { release: false }) => {
|
|
50988
|
+
const { keyHandler } = useAppContext();
|
|
50989
|
+
const stableHandler = useEffectEvent(handler);
|
|
50990
|
+
import_react2.useEffect(() => {
|
|
50991
|
+
keyHandler?.on("keypress", stableHandler);
|
|
50992
|
+
if (options?.release) {
|
|
50993
|
+
keyHandler?.on("keyrelease", stableHandler);
|
|
50994
|
+
}
|
|
50995
|
+
return () => {
|
|
50996
|
+
keyHandler?.off("keypress", stableHandler);
|
|
50997
|
+
if (options?.release) {
|
|
50998
|
+
keyHandler?.off("keyrelease", stableHandler);
|
|
50999
|
+
}
|
|
51000
|
+
};
|
|
51001
|
+
}, [keyHandler, options.release]);
|
|
51002
|
+
};
|
|
50974
51003
|
class ErrorBoundary extends import_react8.default.Component {
|
|
50975
51004
|
constructor(props) {
|
|
50976
51005
|
super(props);
|
|
@@ -51372,30 +51401,313 @@ function createRoot(renderer) {
|
|
|
51372
51401
|
};
|
|
51373
51402
|
}
|
|
51374
51403
|
|
|
51404
|
+
// src/index.tsx
|
|
51405
|
+
var import_react12 = __toESM(require_react(), 1);
|
|
51406
|
+
|
|
51407
|
+
// src/data/content.ts
|
|
51408
|
+
var name = "Kaiyu Hsu";
|
|
51409
|
+
var heroText = `Hello world. You can call me Kai since we're pretty much friends now. I enjoy creating things for the internet. By day, I get to do that through investing, advising, and building products you may not have heard of, yet. Welcome to my corner of the web.`;
|
|
51410
|
+
var projects = [
|
|
51411
|
+
{
|
|
51412
|
+
title: "Vibedgames",
|
|
51413
|
+
description: "Games made with vibes",
|
|
51414
|
+
url: "https://vibedgames.com"
|
|
51415
|
+
},
|
|
51416
|
+
{
|
|
51417
|
+
title: "Yours Sincerely",
|
|
51418
|
+
description: "Anonymous love letters written in disappearing ink",
|
|
51419
|
+
url: "https://yourssincerely.org"
|
|
51420
|
+
},
|
|
51421
|
+
{
|
|
51422
|
+
title: "UICapsule",
|
|
51423
|
+
description: "A curated collection of components that spark joy",
|
|
51424
|
+
url: "https://uicapsule.com"
|
|
51425
|
+
},
|
|
51426
|
+
{
|
|
51427
|
+
title: "Inteligir",
|
|
51428
|
+
description: "Lifelong learning",
|
|
51429
|
+
url: "https://inteligir.com"
|
|
51430
|
+
},
|
|
51431
|
+
{
|
|
51432
|
+
title: "Dataembed",
|
|
51433
|
+
description: "Search the web like a database",
|
|
51434
|
+
url: "https://dataembed.com"
|
|
51435
|
+
},
|
|
51436
|
+
{
|
|
51437
|
+
title: "Founding",
|
|
51438
|
+
description: "Your proxy founding team",
|
|
51439
|
+
url: "https://founding.so"
|
|
51440
|
+
},
|
|
51441
|
+
{
|
|
51442
|
+
title: "Total Compensation Calculator",
|
|
51443
|
+
description: "Navigate tech startup compensation",
|
|
51444
|
+
url: "https://tc.kyh.io"
|
|
51445
|
+
},
|
|
51446
|
+
{
|
|
51447
|
+
title: "Covid-19 Dashboard",
|
|
51448
|
+
description: "Visualize global Covid-19 data",
|
|
51449
|
+
url: "https://covid-19.kyh.io"
|
|
51450
|
+
},
|
|
51451
|
+
{
|
|
51452
|
+
title: "Keiko and Friends",
|
|
51453
|
+
description: "Cute sticker pack",
|
|
51454
|
+
url: "https://apps.apple.com/us/app/id1209391711"
|
|
51455
|
+
},
|
|
51456
|
+
{
|
|
51457
|
+
title: "Init",
|
|
51458
|
+
description: "An AI native starter kit to build, launch, and scale your next project",
|
|
51459
|
+
url: "https://init.kyh.io"
|
|
51460
|
+
}
|
|
51461
|
+
];
|
|
51462
|
+
var work = [
|
|
51463
|
+
{
|
|
51464
|
+
title: "Sequoia",
|
|
51465
|
+
description: "Helping the daring build legendary companies",
|
|
51466
|
+
url: "https://sequoiacap.com"
|
|
51467
|
+
},
|
|
51468
|
+
{
|
|
51469
|
+
title: "Vercel",
|
|
51470
|
+
description: "Build and publish wonderful things",
|
|
51471
|
+
url: "https://vercel.com"
|
|
51472
|
+
},
|
|
51473
|
+
{
|
|
51474
|
+
title: "Google",
|
|
51475
|
+
description: "Looking for something?",
|
|
51476
|
+
url: "https://grow.google"
|
|
51477
|
+
},
|
|
51478
|
+
{
|
|
51479
|
+
title: "Amazon",
|
|
51480
|
+
description: "Earth's biggest bookstore",
|
|
51481
|
+
url: "https://amazon.design"
|
|
51482
|
+
},
|
|
51483
|
+
{
|
|
51484
|
+
title: "Cardiogram",
|
|
51485
|
+
description: "Your personal healthcare assistant",
|
|
51486
|
+
url: "https://apps.apple.com/us/app/cardiogram/id1000017994"
|
|
51487
|
+
}
|
|
51488
|
+
];
|
|
51489
|
+
var contactLinks = [
|
|
51490
|
+
{ label: "Website", value: "kyh.io", url: "https://kyh.io" },
|
|
51491
|
+
{ label: "GitHub", value: "github.com/kyh", url: "https://github.com/kyh" },
|
|
51492
|
+
{ label: "X", value: "x.com/kaiyuhsu", url: "https://x.com/kaiyuhsu" },
|
|
51493
|
+
{ label: "LinkedIn", value: "linkedin.com/in/kyh", url: "https://linkedin.com/in/kyh" },
|
|
51494
|
+
{ label: "Email", value: "hello@kyh.io", url: "mailto:hello@kyh.io" }
|
|
51495
|
+
];
|
|
51496
|
+
|
|
51497
|
+
// src/lib/utils.ts
|
|
51498
|
+
import { exec } from "child_process";
|
|
51499
|
+
import { platform } from "os";
|
|
51500
|
+
function openUrl(url) {
|
|
51501
|
+
const cmd = platform() === "win32" ? "start" : platform() === "darwin" ? "open" : "xdg-open";
|
|
51502
|
+
exec(`${cmd} "${url}"`);
|
|
51503
|
+
}
|
|
51504
|
+
function wrapText(text, width) {
|
|
51505
|
+
const words = text.split(" ");
|
|
51506
|
+
const lines = [];
|
|
51507
|
+
let currentLine = "";
|
|
51508
|
+
for (const word of words) {
|
|
51509
|
+
if (currentLine.length + word.length + 1 <= width) {
|
|
51510
|
+
currentLine += (currentLine ? " " : "") + word;
|
|
51511
|
+
} else {
|
|
51512
|
+
if (currentLine)
|
|
51513
|
+
lines.push(currentLine);
|
|
51514
|
+
currentLine = word;
|
|
51515
|
+
}
|
|
51516
|
+
}
|
|
51517
|
+
if (currentLine)
|
|
51518
|
+
lines.push(currentLine);
|
|
51519
|
+
return lines;
|
|
51520
|
+
}
|
|
51521
|
+
|
|
51375
51522
|
// node_modules/@opentui/react/jsx-dev-runtime.js
|
|
51376
51523
|
var import_jsx_dev_runtime2 = __toESM(require_jsx_dev_runtime(), 1);
|
|
51377
51524
|
|
|
51378
51525
|
// src/index.tsx
|
|
51526
|
+
var TITLE_WIDTH = 32;
|
|
51527
|
+
var PREFIX_WIDTH = 2;
|
|
51528
|
+
var DESC_INDENT = PREFIX_WIDTH + TITLE_WIDTH;
|
|
51529
|
+
var LABEL_WIDTH = 10;
|
|
51530
|
+
var DIM = "#666666";
|
|
51531
|
+
var HIGHLIGHT = "#00FFFF";
|
|
51532
|
+
var allItems = [...projects, ...work];
|
|
51533
|
+
process.stdout.write("\x1B[2J\x1B[H\x1B[?25l");
|
|
51534
|
+
process.on("exit", () => process.stdout.write("\x1B[?25h\x1B[2J\x1B[H"));
|
|
51379
51535
|
function App() {
|
|
51380
|
-
|
|
51381
|
-
|
|
51382
|
-
|
|
51383
|
-
|
|
51384
|
-
|
|
51385
|
-
|
|
51386
|
-
|
|
51536
|
+
const [selectedIndex, setSelectedIndex] = import_react12.useState(0);
|
|
51537
|
+
const [showContact, setShowContact] = import_react12.useState(false);
|
|
51538
|
+
const [contactIndex, setContactIndex] = import_react12.useState(0);
|
|
51539
|
+
const termWidth = process.stdout.columns || 80;
|
|
51540
|
+
const contentWidth = termWidth - 4;
|
|
51541
|
+
const descWidth = contentWidth - DESC_INDENT;
|
|
51542
|
+
useKeyboard((key) => {
|
|
51543
|
+
if (showContact) {
|
|
51544
|
+
switch (key.name) {
|
|
51545
|
+
case "up":
|
|
51546
|
+
case "k":
|
|
51547
|
+
setContactIndex((i) => i > 0 ? i - 1 : contactLinks.length - 1);
|
|
51548
|
+
break;
|
|
51549
|
+
case "down":
|
|
51550
|
+
case "j":
|
|
51551
|
+
setContactIndex((i) => i < contactLinks.length - 1 ? i + 1 : 0);
|
|
51552
|
+
break;
|
|
51553
|
+
case "return":
|
|
51554
|
+
openUrl(contactLinks[contactIndex].url);
|
|
51555
|
+
break;
|
|
51556
|
+
case "escape":
|
|
51557
|
+
case "c":
|
|
51558
|
+
setShowContact(false);
|
|
51559
|
+
setContactIndex(0);
|
|
51560
|
+
break;
|
|
51561
|
+
}
|
|
51562
|
+
return;
|
|
51563
|
+
}
|
|
51564
|
+
switch (key.name) {
|
|
51565
|
+
case "up":
|
|
51566
|
+
case "k":
|
|
51567
|
+
setSelectedIndex((i) => i > 0 ? i - 1 : allItems.length - 1);
|
|
51568
|
+
break;
|
|
51569
|
+
case "down":
|
|
51570
|
+
case "j":
|
|
51571
|
+
setSelectedIndex((i) => i < allItems.length - 1 ? i + 1 : 0);
|
|
51572
|
+
break;
|
|
51573
|
+
case "return":
|
|
51574
|
+
openUrl(allItems[selectedIndex].url);
|
|
51575
|
+
break;
|
|
51576
|
+
case "c":
|
|
51577
|
+
setShowContact(true);
|
|
51578
|
+
break;
|
|
51579
|
+
case "escape":
|
|
51580
|
+
case "q":
|
|
51581
|
+
process.exit(0);
|
|
51582
|
+
break;
|
|
51583
|
+
}
|
|
51584
|
+
});
|
|
51585
|
+
const heroLines = wrapText(heroText, contentWidth);
|
|
51586
|
+
const divider = "\u2500".repeat(contentWidth);
|
|
51587
|
+
const renderItem = (item, index, isFirst) => {
|
|
51588
|
+
const isSelected = index === selectedIndex;
|
|
51589
|
+
const prefix = isSelected ? "> " : " ";
|
|
51590
|
+
const title = item.title.padEnd(TITLE_WIDTH);
|
|
51591
|
+
const descLines = wrapText(item.description, descWidth);
|
|
51592
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
51593
|
+
flexDirection: "column",
|
|
51387
51594
|
children: [
|
|
51388
|
-
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("
|
|
51389
|
-
|
|
51390
|
-
|
|
51595
|
+
!isFirst && /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
51596
|
+
fg: DIM,
|
|
51597
|
+
children: divider
|
|
51391
51598
|
}, undefined, false, undefined, this),
|
|
51392
51599
|
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
51393
|
-
|
|
51394
|
-
children:
|
|
51395
|
-
|
|
51600
|
+
fg: isSelected ? undefined : DIM,
|
|
51601
|
+
children: [
|
|
51602
|
+
prefix,
|
|
51603
|
+
title,
|
|
51604
|
+
descLines[0]
|
|
51605
|
+
]
|
|
51606
|
+
}, undefined, true, undefined, this),
|
|
51607
|
+
descLines.slice(1).map((line, i) => /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
51608
|
+
fg: isSelected ? undefined : DIM,
|
|
51609
|
+
children: [
|
|
51610
|
+
" ".repeat(DESC_INDENT),
|
|
51611
|
+
line
|
|
51612
|
+
]
|
|
51613
|
+
}, i, true, undefined, this))
|
|
51396
51614
|
]
|
|
51397
|
-
},
|
|
51398
|
-
}
|
|
51615
|
+
}, item.title, true, undefined, this);
|
|
51616
|
+
};
|
|
51617
|
+
if (showContact) {
|
|
51618
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
51619
|
+
flexDirection: "column",
|
|
51620
|
+
alignItems: "center",
|
|
51621
|
+
justifyContent: "center",
|
|
51622
|
+
flexGrow: 1,
|
|
51623
|
+
children: /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
51624
|
+
flexDirection: "column",
|
|
51625
|
+
children: [
|
|
51626
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
51627
|
+
children: "Contact"
|
|
51628
|
+
}, undefined, false, undefined, this),
|
|
51629
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
51630
|
+
children: " "
|
|
51631
|
+
}, undefined, false, undefined, this),
|
|
51632
|
+
contactLinks.map((link2, i) => {
|
|
51633
|
+
const isSelected = i === contactIndex;
|
|
51634
|
+
const prefix = isSelected ? "> " : " ";
|
|
51635
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
51636
|
+
flexDirection: "row",
|
|
51637
|
+
children: [
|
|
51638
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
51639
|
+
children: prefix
|
|
51640
|
+
}, undefined, false, undefined, this),
|
|
51641
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
51642
|
+
fg: HIGHLIGHT,
|
|
51643
|
+
children: link2.label.padEnd(LABEL_WIDTH)
|
|
51644
|
+
}, undefined, false, undefined, this),
|
|
51645
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
51646
|
+
fg: isSelected ? undefined : DIM,
|
|
51647
|
+
children: link2.value
|
|
51648
|
+
}, undefined, false, undefined, this)
|
|
51649
|
+
]
|
|
51650
|
+
}, link2.label, true, undefined, this);
|
|
51651
|
+
}),
|
|
51652
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
51653
|
+
children: " "
|
|
51654
|
+
}, undefined, false, undefined, this),
|
|
51655
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
51656
|
+
fg: DIM,
|
|
51657
|
+
children: "\u2191\u2193 navigate enter open esc close"
|
|
51658
|
+
}, undefined, false, undefined, this)
|
|
51659
|
+
]
|
|
51660
|
+
}, undefined, true, undefined, this)
|
|
51661
|
+
}, undefined, false, undefined, this);
|
|
51662
|
+
}
|
|
51663
|
+
return /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
51664
|
+
flexDirection: "column",
|
|
51665
|
+
paddingLeft: 2,
|
|
51666
|
+
paddingTop: 1,
|
|
51667
|
+
flexGrow: 1,
|
|
51668
|
+
children: [
|
|
51669
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("box", {
|
|
51670
|
+
flexDirection: "column",
|
|
51671
|
+
flexGrow: 1,
|
|
51672
|
+
children: [
|
|
51673
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
51674
|
+
children: name
|
|
51675
|
+
}, undefined, false, undefined, this),
|
|
51676
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
51677
|
+
children: " "
|
|
51678
|
+
}, undefined, false, undefined, this),
|
|
51679
|
+
heroLines.map((line, i) => /* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
51680
|
+
fg: DIM,
|
|
51681
|
+
children: line
|
|
51682
|
+
}, i, false, undefined, this)),
|
|
51683
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
51684
|
+
children: " "
|
|
51685
|
+
}, undefined, false, undefined, this),
|
|
51686
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
51687
|
+
children: "Projects"
|
|
51688
|
+
}, undefined, false, undefined, this),
|
|
51689
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
51690
|
+
children: " "
|
|
51691
|
+
}, undefined, false, undefined, this),
|
|
51692
|
+
projects.map((project, i) => renderItem(project, i, i === 0)),
|
|
51693
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
51694
|
+
children: " "
|
|
51695
|
+
}, undefined, false, undefined, this),
|
|
51696
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
51697
|
+
children: "Work"
|
|
51698
|
+
}, undefined, false, undefined, this),
|
|
51699
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
51700
|
+
children: " "
|
|
51701
|
+
}, undefined, false, undefined, this),
|
|
51702
|
+
work.map((item, i) => renderItem(item, projects.length + i, i === 0))
|
|
51703
|
+
]
|
|
51704
|
+
}, undefined, true, undefined, this),
|
|
51705
|
+
/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV("text", {
|
|
51706
|
+
fg: DIM,
|
|
51707
|
+
children: "\u2191\u2193 navigate enter open c contact q quit"
|
|
51708
|
+
}, undefined, false, undefined, this)
|
|
51709
|
+
]
|
|
51710
|
+
}, undefined, true, undefined, this);
|
|
51399
51711
|
}
|
|
51400
51712
|
var renderer = await createCliRenderer();
|
|
51401
51713
|
createRoot(renderer).render(/* @__PURE__ */ import_jsx_dev_runtime2.jsxDEV(App, {}, undefined, false, undefined, this));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kyh",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Personal CLI tool",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
"access": "public"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@opentui/core": "^0.1.
|
|
17
|
-
"@opentui/react": "^0.1.
|
|
16
|
+
"@opentui/core": "^0.1.69",
|
|
17
|
+
"@opentui/react": "^0.1.69",
|
|
18
18
|
"react": "^19.2.3"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|