milstead 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/README.md +39 -0
- package/bin/milst.js +5 -0
- package/dist/cli.js +274 -0
- package/package.json +48 -0
package/README.md
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# milst
|
|
2
|
+
|
|
3
|
+
Michael Milstead's personal profile, as a terminal app.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npx milst
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
A full-screen terminal UI: a pixel wordmark, your name, an ANSI-art portrait,
|
|
10
|
+
and links you can open in your browser.
|
|
11
|
+
|
|
12
|
+
## Keys
|
|
13
|
+
|
|
14
|
+
| Key | Action |
|
|
15
|
+
| -------------- | ------------------------------- |
|
|
16
|
+
| `s` | open personal site |
|
|
17
|
+
| `g` | open GitHub profile |
|
|
18
|
+
| `x` | open X profile |
|
|
19
|
+
| `q` / `Esc` | quit |
|
|
20
|
+
|
|
21
|
+
## Make it yours
|
|
22
|
+
|
|
23
|
+
- **Content** — edit [`src/data/profile.ts`](src/data/profile.ts): wordmark,
|
|
24
|
+
name, and links. That's the only file you need to touch.
|
|
25
|
+
- **Portrait** — drop a photo at `assets/portrait.png` and run
|
|
26
|
+
`npm run portrait`. See [`assets/README.md`](assets/README.md).
|
|
27
|
+
|
|
28
|
+
## Develop
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npm install
|
|
32
|
+
npm run portrait # generate the portrait (placeholder if no photo)
|
|
33
|
+
npm run build # compile src/ -> dist/
|
|
34
|
+
npm start # run the built CLI locally
|
|
35
|
+
npm test # vitest
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Built with [Ink](https://github.com/vadimdemedes/ink) (React for the terminal),
|
|
39
|
+
compiled with [tsup](https://tsup.egoist.dev/).
|
package/bin/milst.js
ADDED
package/dist/cli.js
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
// src/cli.tsx
|
|
2
|
+
import { render } from "ink";
|
|
3
|
+
|
|
4
|
+
// src/app.tsx
|
|
5
|
+
import { Box as Box5 } from "ink";
|
|
6
|
+
|
|
7
|
+
// src/data/profile.ts
|
|
8
|
+
var profile = {
|
|
9
|
+
wordmark: "milst",
|
|
10
|
+
name: "Michael Milstead",
|
|
11
|
+
tagline: "Building creative uses of AI",
|
|
12
|
+
githubUrl: "https://github.com/MichaelMilstead",
|
|
13
|
+
xUrl: "https://x.com/michael_milst",
|
|
14
|
+
siteUrl: "https://milste.ad",
|
|
15
|
+
githubLabel: "github.com/MichaelMilstead",
|
|
16
|
+
xLabel: "x.com/michael_milst",
|
|
17
|
+
siteLabel: "milste.ad"
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// src/data/portrait.ts
|
|
21
|
+
var portraitFrames = [" \n \n \n \n :=+***+-:. \n .=#####%###%#*=. \n :*****#%%%%%%%%##. \n ==:.::-+**#####%#- \n . .---=---+*####+ \n :-.=+====---+++=+= \n :.--....:---=+-= \n .===. .:----=-= \n .-=-:::------:. \n .-=----=====-: \n .::-=++++++=- \n :-+******+=-::=- \n .==+**+===-*%%%*-. \n :=+#%%+------+#%%%%%%%##*-. \n .=*#%%%%%%%==+*#%@@%%%%%%%%%%%##*: \n +%#%%%%%%%%%%%@@@@@@@%%@@%%%%%%%%%%#*. \n =%%%%%%%%%%%%%%%@@@@@@%@@%%%%%@%%%%%%##: \n -#%%%@%%%%%%@@%%@@@@@@@%@@%%%%@%@%%%%%%%# \n .#%%%%%%%%%%@@@%@@@@@@@@@@@@@%%@@%%@@%%%%%+ \n +%%%%@%%%%%@@@@@@@@@@@@%@@@@@%@@@@@@%%%%%%#: ....", " \n \n \n \n :=+***+-:. \n .+#####%###%#*=. \n :*****#%%%%%%%%##. \n +=:.::-+**#####%#- \n .---=---**####+ \n :-.=+====---+++=+- \n :.--....:---=+-= \n .===. .:----=-= \n .-=-:::------: \n .-=----=====-: \n .::-=++++++=- \n :-+******+=-::=- \n .==+**+===-*%%%*-. \n :=+#%%+------+#%%%%%%%##*-. \n .=*#%%%%%%%==+*#%@@%%%%%%%%%%%##*: \n +%#%%%%%%%%%%%@@@@@@@%%@@%%%%%%%%%%#*. \n =%%%%%%%%%%%%%%%@@@@@@%@@%%%%%@%%%%%%##. \n -#%%%@%%%%%%@@%%@@@@@@@%@@%%%%@@@%%%%%%%# \n .#%%%%%%%%%%@@@%@@@@@@@%@@@@@%%@@%%@@%%%%%+ \n *%%%%@%%%%@@@@@@@@@@@@@%@@@@@%@@@@@@%%%%%%#: ....", " \n \n \n \n :=+***+-:. \n .+#####%###%#*=. \n -#****#%%%%%%%%#*. \n ==:.::-+**#####%#- \n .---=---**####+ \n :-.=+====---+++=+- \n :.--....----=+-= \n :===. .:----=-= \n .-=-:::------: \n .-=----====--: \n .::-=++++++=- \n :-+******+=-::=- \n .==+**+===-*%%%*-. \n :=+#%%+------+#%%%%%%%##*-. \n .=#%%%%%%%%==+*#@@@%%%@%%%%%%%##*: \n *%#%%%%%%%%%%%@@@@@@@%%@@%%%%%%%%%%#*. \n =%%%%%%%%%%%%%%%@@@@@@%@@%%%%%@%%%%%%##. \n -#%%%@%%%%%%@@%%@@@@@@@%@@%%%%@@@%%%%%%%# \n .#%%%%%%%%%%@@@%@@@@@@@%@@@@@%%@@%%@@%%%%%+ \n *%%@%@%%%%@@@@@@@@@@@@@%@@@@@%@@@@@@@%%%%%#: .....", " \n \n \n \n :=+***+=:. \n .+#####%###%##+. \n -##**##%%%%%%%%%#. \n ==:.::-+**#####%#- \n .---=---**####+ \n :-.=+====--=+++=+= \n :.--....----=+-= \n :===. .:----=-= \n :-=-:::------:. \n .-==---=====-: \n .::-=+*++++=- \n :=+******+=-::=- \n .==+**+===-*%%%*-. \n :=+#%%+------+#%%%%%%%##*-. \n .=##%%%%%%%==+*#%@@%%%@%%%%%%%##*: \n *%#%%%%%%%%%%%@@@@@@@%%@@%%%%%%%%%%#*. \n =%%%%%%%%%%%%%%%@@@@@@%@@%%%%%@%%%%%%##. \n -#%%%@%%%%%%@@%%@@@@@@@%@@%%%%@@@%%%%%%%# \n .#%%%%%%%%%%@@@%@@@@@@@%@@@@@%%@@%%@@%%%%%+ \n *%%@%@%%%%@@@@@@@@@@@@@%@@@@@%@@@@@@@%%%%%#: .....", " \n \n \n \n :=+****=:. \n .+#####%###%##+. \n -*****#%%%%%%%%%#. \n ==:.::-+**#####%#= \n .---=---+*####* \n :-.=+==+=---+++=+= \n :.--....:---=+-= \n .===. .:----=-= \n .-=-:::------:. \n .-==---=====-: \n .::-=++++++=-. \n :-+******+=-::=- \n .==+**+===-*%%%*-: \n :=*#%%+-=----+#%%%%%%%##*-. \n .=#%%%%%%%%==+*#%@@%%%%%%%%%%%##*: \n +%#%%%%%%%%%%%@@@@@@@%%@@%%%%%%%%%%#*: \n =%%%%%%%%%%%%%%%@@@@@@%@@%%%%%@%%%%%%##: \n -#%%%@%%%%%%@@%%@@@@@@@%@@%%%%@@@%%%%%%%# \n .#%%%%%%%%%%@@@%@@@@@@@%@@@@@%%@@%%@@%%%%%* \n +%%%%@%%%%@@@@@@@@@@@@@%@@@@@%@@@@@@@%%%%%#- .....", " \n \n \n \n :=**##*+-: \n -*#####%%####+: \n +*****#%%%%%%###- \n :=-:..:--++*#####+ \n ....:====--=****= \n :--:+==++=--=++=: \n :.:--::::----+- \n :===..:----=- \n .--==--------. \n .:-==--====-- \n .::-=++++++-. \n .-+******+=-:+= \n .=-+***++==*%%%#=: \n :=+#%%+:-====+#%%%%%%%##*=. \n .=#%%%%%%%%==+*#%@@%%%@%%%%%%%##*: \n *%#%%%%%%%%%%%%@@@@@@%%@@%%%%%%%%%%##: \n =%%%%%%%%%%%%%%%@@@@@@%@@%%%%%@%%%%%%%#- \n -#%%%@%%%%%%@@%%@@@@@@@%@@%%%%@@@%%%%%%%#. \n .#%%%%%%%%%%@@@%@@@@@@@@@@@@@%%@@%%@@%%%%%* \n *%%%%@%%%%@@@@@@@@@@@@@%@@@@@%@@@@@@@%%%%%%- .....", " \n \n \n ... \n :+**###*=: \n =######%%%##*- \n .**+++++*#%%%###+ \n .*:.::..:--=+*##*. \n =.::..-=+==::**- \n -=+::+*+++=:=+- \n ... .------::+= \n :-==-:--:-- \n .:=++==---: \n .:-=+++===-. \n :::--=+++=: \n .=+*****+=:+= \n .=:-+****++*%%%#=: \n :=*#%%+:-===+*#%%%%%%%##*=. \n :=##%%%%%%%+=++#%@@%%%%%%%%%%%##*- \n *%#%%%%%%%%%%%%@@@@@@%%@@%%%%%%%%%%##- \n +%%%%%%%%%%%%%%%@@@@@@%%@@%%%%@%%%%%%%#- \n =#%%%@%%%%%%@@%%@@@@@@@%@@%%%%@@@%%%%%%%#: \n -#%%%%%%%%%%@@@%@@@@@@@@%@@@@%%@@%%@@%%%%%# \n #%%%%@%%%%%@@@@@@@@@@@@@@@@@@@@@@@@@@%%%%%%= .....", " \n \n \n .:-.. \n :+**####*+: \n :+#######%%##*= \n =*#+==++**##%%#*- \n .*+...:--:--=+**- \n +:.:::::-===::* \n :.:=++::+**+=:= \n : .:. .:===-:-. \n ..:-----:: \n ..-=++=--: \n .:--=+++=-. \n .:::-===+= \n :-==++*+=-=+. \n .=::=+****+*%%%%+-. \n .-+*##%*::===+*#@@@%%%%%#*=: \n -+#%%%%%%%%+=++*%@@@%%%%%%%%%%%#*- \n #%%%%%%%%%%%%%%@@@@@@@%%@%%%%%%%%%%##= \n *%%%%%%%%%%%%%%%@@@@@@@%@@%%%%%@%%%%%%#+ \n +#%%%@%%%%%%@@%%@@@@@@@%@@@%%%%@%%%%%%%%#- \n =#%%%%%%%%%%@@@@@@@@@@@@%@@@@%%@@@%%@@%%%%# \n #%%@%@%%%%@@@@@@@@@@@@@@%@@@@@%@@@@@@%%%%%%+ .....", " \n \n \n .--=:. \n -*#######*=. \n =#######%%%%##*: \n -###++=+**##%%##* \n :*#+:..:-====++*- \n ++: .::-----::. \n -- :=+*+:-+**+: \n :: .-=: .=*+-: \n .. . .:---: \n .:.==+==:. \n ..:--=++++- \n .:-::=++==. \n :=---==+=-+: \n :=-.:=*****+#%@%+-. \n :=*#%#%*::-===+#@@@@%%%%#*=: \n .=*#%%%%%%%%*-+=+#@@@@@%@%%%%%%%#*= \n .#%#%%%%%%%%%%%%@@@@@@@%%@@%%%%%%%%%##+ \n #%%%%%%%%%%%%%%%@@@@@@@%@@%%%%%@%%%%%%#* \n *#%%%@%%%%%%@@%%@@@@@@@@%@@%%%%@@%%%%%%%#+ \n *#%%%%%%%%%%@@@@@@@@@@@@@@@@@%%%@@%%@@%%%%#: \n .%%%@%@%%%%@@@@@@@@@@@@@@%@@@@@%@@@@@@%%%%%%# .....", " \n \n \n .:-=+=:. \n .-*########*- \n +########%%%%#*= \n :#*#++=+*###%%%#*- \n .*#+:..:-===++*#+ \n =+: ..:------:- \n -: :=+*+--+**+:. \n :. .:==: :+**=: \n .. .. .:---: \n .:.--==-: \n ..:--=+++=- \n ::-:-+++++. \n .--::-==+=== \n .=+.:-+****++%%%#-. \n -+*#%##%=.:-==+*%@@@@%%%%*=. \n -+##%%%%%%%%%====+%@@@@@%%%%%%%##+- \n #%%%%%%%%%%%%%%%@@@@@@@%%@%%%%%%%%%%#+ \n *%%%%%%%%%%%%%%%@@@@@@@@%@@%%%%%@%%%%%##. \n *#%%%@%%%%%%@@@%%@@@@@@@@@@@%%%%@%%%%%%%## \n *#%%@%@%%%%%@@@@%@@@@@@@@%@@@@%%@@@%%%@%%%%+ \n .%%@@@@%%%%@@@@@@@@@@@@@@@@@@@@@%@@@@@@%%%%%#: .....", " \n \n \n .:-=++-:. \n :*#%######*+. \n =########%%%%#**: \n **#*===+*###%%#*+ \n =**-...-===++*##- \n :+- .:-------= \n .- :-+*+--=+*+-- \n :. .-=-..+**+-. \n . .. .:=--: \n .:.--==-:. \n ..:--=+++=- \n ::-:-+++++: \n .--::-==+==: \n .=*+.:-++***++%%%+. \n -+##%%%%#:.:===+*%@@@%%%%#=: \n -*##%%%%%%%%%#-===*%@@@@@%%%%%%%#*- \n =%%%%%%%%%%%%%%%@@@@@@@@%%@%%%%%%%%%#*: \n +#%%%%%%%%%%%%%%@@@@@@@@@%@@%%%%%@%%%%%#+ \n +#%%%%@%%%%%@@@@%@@@@@@@@%@@@%%%%@@%%%%%%#= \n -#%%@%@%%%%%@@@@@@@@@@@@@@%@@@@%%@@@%%%%%%%#: \n #%%@@%@%%%@@@@@@@@@@@@@@@@@@@@@@%@@@@@@%%%%%# ......", " \n \n \n ..:-==: \n .-*########*: \n +########%%###*= \n .*##++++*###%%##*- \n **=...:===+**##*: \n += .:------== \n = .-=++--=+++-:. \n .: .-=-..+##+-: \n . . .:===-. \n .:.::-=--: \n .::-=+++=- \n ::-:=++++=: \n .-:::==++=- \n .-+#+.:-=++**++%%#: \n .:+##%%%%%#:.-=+++*#@@@%%%#=. \n *##%%%%%%%%%%#==-=*%@@@@%%%%%%%#+: \n *%%%%%%%%%%%%%%%@@@@@@@@%%@%%%%%%%%#*: \n :##%%%@%%%%%%@%%%@@@@@@@@%%@@%%%%%%%%%%#* \n :#%%@%@@%%%%@@@@%%@@@@@@@@%@@%%%%%@%%%%%%#* \n *%%%@%@@%%@@@@@@@@@@@@@@@@@@@@@%%@@@%%%%%%#* \n +%%@@@%@%%@@@@@@@@@@@@@@@@%@@@@@%@@@%%@@@%%%#- ......", " \n \n \n ..:. \n :=*######*- \n =#######%###**-. \n :*#*++**###%%##*= \n. .*+::.-=+++*#%#*+. \n:.. +. .:----==+*- \n-::... .:.-=+-:--=+=-.+ \n--::.. : :=+- -*#*+=:= \n=--:.. :====-:: \n---::. ..:.--=--:. \n----:. .::-=+++=-. \n----:. .:::=++++=- \n-::::. .:. -::-==++=. \n:........:-: .:--+#=:==++**+=*%#- \n. ..::---: =##%%%%%%%%#::=+++*#%@@@%%*- \n::--=++: :+#%%@@%@@%@%%%#+++*#@@@@@%%%%%%#=. \n=+++=. .+%%%%@@@%@@%@@@%%@@@@@@@@%%@%%%%%%%%#+. \n+**= .#%@@@@@@@@@@@@@@@@@@@@@@@@%@@%%%%%%%%%%#+ \n**+..+%%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%%%%#* \n**++#%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%%%%%#+ \n**=::-*%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%%%#- ......", " \n \n \n .:: \n -*##*####=. \n -*###########*+: \n =+*==+**###%%#*+. \n -. .-=:-..-===+*###*- \n - .-:::-:...:::---=+= \n :. :-:.-::::--:=+++=:=. \n :::::::-. .:-::-+**+=:- \n :---:::.::-:..:---==--:- \n :--::..:--: .--==+==---. \n .:......:: .-==+**+*==: \n :. ...::: ...:=*++++- \n .:--=:---==-:---===++++= \n .:-=+**#*#####%%+.-+****+=*%*: \n ..-==+**%%@@@%@@@%%%::=+++*#%@@@%#=. \n ..:=++**%@@@@@@@@@@@%%%#%#%@@@@@@%%%%%#+: \n .::-=+**#%@@@@@@@@@@@@@@@@@@@@@@@@@@@%%%%%%#*- \n::-=+**#%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%%%%%%##: \n--=+**++#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%%@@%%%%%#= \n=+*******%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%@@%%%%%%%#: \n+*******#%@@@@@@@@@@@@@@@@@@@@@@@@@@@@%@@@%%%%%%%%#.......", " \n \n \n .. :. ... \n . -..-. . -+##*###*- \n :- :- .- .-. -*##########**-. \n :- :- :: :: *#*===**###%##*+ \n : .:..: :- *+.. .---=+*##*+. \n ..:.....:- =....::::----=*- \n ::-:....-. :.:=+=:-=+++-.+ \n .:-:. .: . .:-:.:+**+-:- \n .:: .: :::..:::::----::. \n .:. .::..:: :.---==+==--: \n :::::::-==-. .:====++++=- \n .:-=++=: ----=+==+=. \n .:-==+=. :==-===++: \n .-=+++: .+*=+**##%%*.:=+****==#+. \n .:=++*+::+%%%%@@%%@%@%%%--=+++**#@%%%+: \n.:-=+**+=#%%@@%@@@%@@%@@%%%%%%%%@@@@@%%%%#*- \n:-=+***#%%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%%%%%#*: \n-=+**+==*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%%%%%%%%#+ \n++****+++*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%%%%%%%%%##. \n**********#@@@@@@@@@@@@@@@@@@@@@@@@@@@%%%%@%%%%%%#* \n*********#@@*@@@@@@@@@@@@@@@@@@@@@@@@@@%%@%%%%%%%%#+......", " \n \n \n \n -+***#*+-. \n . -*##########*=. \n - .: .: :+*+==+**#####*+: \n :: .: : ::...:---+*###*= \n :. :. : :-.....::::--=++. \n ......: .-- :-++-:-+++=:-- \n .:::.. .:: . .--..=**+=:- \n :::.. .:. :::--:----:- \n .::. .: .:--=++===-:. \n .. ... .:-==+*++==: \n ... ...:-:.:. :=--=++=+=- \n :--===-::. -=====++= \n ..--=++=+=-++**###:.-=****+=**: \n :-=++*#%%%@@%@@%@%%*::=+=+*#%%%%#- \n ..-=+**#%@@%@@@@@@@@%%%%%##%%@@@@%%%%%#=. \n .::-++*#%@@@@@@@@@@@@@@@@@@@@@@@@@@@@%%%%%##= \n.::-=+***%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%%%%%%%#*. \n:--=+**++*%@@@@@@@@@@@@@@@@@@@@@@@@@@@@%%%%%%%%%##= \n-=+*******#@@@@@@@@@@@@@@@@@@@@@@@@@@@%%%%@%%%%%%##- \n=+*******#%@%@@@@@@@@@@@@@@@@@@@@@@@@@@%%@%%%%%%%%%#:.....", " \n \n \n \n .=******=: \n .=*#########*+: \n .. : +#*==+**#####**= \n : :-.-. +*:. .:--=+*##*+. \n :- :- :: :: =......::::--+*= \n :. .-..: :: : :=+=::=++=-.+ \n .....:: :: . .:. :+*++-:- \n ::::.. .:-. ....:----:: \n .:::. .- .:::==+==-:: \n .:. .. .:=-=+++++=- \n .. .: .::. ----++==== \n .:.....:--::. .======+= \n .:--+=::=**=+++**##=.:=+***+=+#: \n .:-=+++++#%%%%%%@%@%%#::=++=+*#%%%#- \n :-=++*#%%%%@@@@%@@%@%%%%%###%%@@@%%%%%#=. \n .-=+***%%%@@%@@@@@@@@@@@@@@@@@@@@@@%%%%%%###=. \n.:-=+**#%%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%%%%%%%%##: \n:-++**==*%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%%%%%%%%%##+ \n=+********%@@@@@@@@@@@@@@@@@@@@@@@@@@@%%%%@%%%%%%##+ \n+********#%@@@@@@@@@@@@@@@@@@@@@@%@@@@@%%@@%%%%%%%%#-.....", " \n \n \n \n .=*#****+- \n .=*####*#####*-. \n =**===+***####*+. \n =*- .:---+**#**- \n -: ....::::--=+= \n : :-+=:.-=++-.=. \n .:. .=*++=:= \n .::. .:---::: \n.:-+=-: ...--===-::. \n--=++=---:. .:::-=+++=-. \n==++++===: :...-=====: \n=+++++===. .-::--===: \n=====---: .. -+=***##=..-+***+==#- \n-=--. .:. :-+%%%%%%%%%%%#..:===+*#%%%#=. \n--: .:..=*#%%%@%%@%%%%%%#**+*#%@@%%%%%%#=. \n--:...:--=+#%%@%@@%@%%@%%%%%@@@@@@@%%%%%%%%###=. \n-=-===+*#%%@@%%@@@@@%%@@@%%@@@@@@@@%%@@%%%%%%%%##- \n-=+***#%%%@@@%@@@@@@@@@@@@@@@@@@@@@@@@@%%%%%%%%%##+ \n=+**+#%%%@@@@%@@@@@@@@@@@@@@@@@@@@@@@@@@%%%@%%%%%##+ \n+**=.:=*%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%%@%%%%%%%%#=.....", " \n \n \n .:: \n -+##**#**=. \n -*#####*#####*=. \n *#*=-=++**####*+: \n *+. .:---=+*#*+: \n =.......::::-=+= \n .. :-+=..-+++-.= \n . .:. .+*++-.- \n .:---::. \n ...--===-:: \n .-::-=+++=- \n :. .-=====. \n .-:::-===. \n .--++*###. .-+***+=+#- \n =##%%%%%%%%##- .-===+*#%%%#-. \n .*%%%%%%%%%%%%%#++==+#%@@%%%%%##=. \n =##%%%%%%%%%%%%%%%%@@@@@%%%%%%%%%###+. \n *#%%%%@%%%%%%%%%%%%@@@@%%%%%@%%%%%%%%%##= \n *%%%%%%@%%%%%%@@@%%@@@@@%%%%@@%%%%%%%%%%##* \n *#%%@%%%%%%%%%@@@@%@@@@%@@@%@@%%%%%%@%%%%%##* \n *#%%%@%%%%%%%@@@@@@@@@@@@@@%%@@%%%%%@%%%%%%%%#+.....", " \n \n \n :-=++=:. \n :+###*####*+: \n -*##*#########*+: \n -#+---=++*##%##*+ \n -+. :-::-=+##*+. \n :..:::::::---:=+: \n . :-+=.:=**+=::= \n . .. :=+++=::- \n . ::--:::- \n .:.-=+==--:. \n .:::-=+++==- \n :..-====== \n ::::-==+=:. \n .-=+*##..:-+***+++%#= \n :=*###%%%%%%+ .:===+*#@@%%#*- \n -#%#%%%%%%%%%%%+====*%@@@%%%%%%##=. \n :#%%%%%%%%%%%%%%%%%@@@@@%%%%%%%%%%###=. \n ##%%%%%%%%%%%%%%%%@@@@%%%%%@%%%%%%%%%##* \n *#%%%%%%%%%%@@@%%%@@@@@%@%%@@%%%%%%%%%%%##. \n +#%%@%%%%%%@@@@@%%@@@@@@@@%@@@%%%%@@%%%%%%## \n +##%@%%%%%%%@@@@@@@@@@@@@@%%@@@@%%@@%%%%%%%%#*......", " \n \n \n :-+**+=-. \n .=*#########+- \n +#########%%##**. \n *+=-==++*##%%##**. \n *. .::::-=+****+ \n :.:::..:----:-** \n .:=+=.-+***+-:+= \n ... -=====-.=- \n .:---::::-. \n .:.-=+++=--:. \n .-:-=++++==: \n ..:=====+= \n :::-==+++=:-. \n :-=*#+.-=****++*%%#- \n :=*##%%%%%#:.-===+#%@@%%%%#=. \n *##%%%%%%%%%%*===+#%@@@%%%%%%%##+. \n +%%%%%%%%%%%%%%%@@@@@@%%%@%%%%%%%%##+ \n -#%%%%%%%%%%%%%%%@@@@@@%%@@%%%%%%%%%%##+ \n #%%%%%%%%%%%@%%%@@@@@@%%@@@%%%%%@%%%%%%#* \n =#%%%%%%%%@@@@@%@@@@@@@@%@@%%%%%@%%%%%%%%#+ \n :#%%%%%%%%@@@@@@%@@@@@@@%@@@@@%%@@@%%%%%%%%#: ......", " \n \n \n :-+++=-. \n .=**#######+-. \n .+#######%%%###*= \n +*+=+++**#%%%##**= \n --...:.:--=+*****- \n .:.....:----::+*= \n :-+=.-+***+-:-+- \n .:: -=====-::=- \n :---::-::- \n ..:=+++=---:. \n :---=+++===: \n ...-====++=: \n .::-=++*++--=. \n .=#=-=+****++#%%#: \n -+###%%%#.:=+=+*#@@@%%%%#+: \n :*##%%%%%%%%%+-==*%@@@%%%%%%%###*- \n :#%%%%%%%%%%%%%%@@@@@@%%%@%%%%%%%%##*: \n #%%%%%%%%%%%%%%%@@@@@@%%@@%%%%%%%%%%##* \n *#%%%%%%%%%%@@%%@@@@@@@%@@%%%%%@%%%%%%%#* \n -#%%%%%%%%%%@@@%@@@@@@@%@@@%%%%@%%%%%%%%%#+ \n .#%%%%%%%%@@@@@@@@@@@@@@%@@@@@%@@@@%@@@%%%%#: .....", " \n \n \n :-==-:. \n :+########+-. \n :*#######%%%###+ \n :**+++***#%%%%##*+ \n *:..::::-=+*****= \n = ....:---::-** \n :=+=.-+***+-:+= \n .:-: -+===--:-= \n :---::-:-: \n ..:-+++=---: \n :---=+++===. \n ...:====++=. \n ::--=++++--=. \n :+--=+****++#%%%=. \n :=*#%%#*::=+++*#%@@%%%%%#+: \n :=*#%%%%%%%%*:-=+#%@@%%%%%%%%####=. \n #%#%%%%%%%%%%%%%@@@@@%%%@%%%%%%%%%##*- \n *%%%%%%%%%%%%%%%%@@@@@@%@@%%%%%%%%%%%##+ \n =#%%%%%%%%%%%@%%%@@@@@@%%@@%%%%@%%%%%%%%#= \n #%%%%%%%%%%%@@@%@@@@@@@%@@@%%%@@%%%%%%%%%#: \n +%%%%%%%%%@@@@@@@@@@@@@@%@@@@@%@@@%@@%%%%%%* ....", " \n \n \n .-=-:: \n :+#*######=-. \n .+#######%%%##*- \n -**++****##%%%##*= \n *-:.:-::-==+****- \n =. ...:----::++ \n :-==::=**+=-:== \n :--..=+++=-::= \n .:--:::::: \n ..-=++==--: \n .---==+++==- \n :..-====+=- \n .::-==+++-:+- \n --:=+****++*%%%*-. \n .=*#%##:.-++++*%@@@%%%%##+- \n .-*##%%%%%%#::-=*%@@@%%%%%%%%####+: \n =##%%%%%%%%%%%%%@@@@@@%%%@%%%%%%%%%###: \n :#%%%%%%%%%%%%%%%@@@@@@%%@@%%%%%@%%%%%##- \n ##%%%%%%%%%%%@%%@@@@@@@%@@@%%%%@%%%%%%%%#: \n +#%%%@%%%%%%@@@%%@@@@@@@%@@%%%%@@@%%%%%%%%# \n #%%@%%%%%%%@@@@@@@@@@@@@%@@@@@%@@%@@@%%%%%%+ ....", " \n \n \n :-=-:. \n :+#*#####*=: \n :*#######%%###*: \n =**+++***##%%##**. \n .*-..:-::-==+***+. \n + ...:----.:+- \n .:-=+-:=**++-.=- \n :--. -+=+=-::= \n ::-:::::. \n ..:=+++=--: \n .---==+++==: \n :..-======. \n :::-==++=-=+. \n :=::=+****++#%%%+-. \n .-+####*..-++++#%@@%%%%%##+- \n :+##%%%%%%%*:--=*%@@@%%%%%%%%%###+. \n ###%%%%%%%%%%%%%@@@@@%%%%@%%%%%%%%%##* \n *%%%%%%%%%%%%%%%@@@@@@@%%@%%%%%@%%%%%%##. \n =#%%%%%%%%%%%%@%%@@@@@@@%@@%%%%%@%%%%%%%#* \n :#%%%%@%%%%%%@@@%@@@@@@@@%@@%%%%@@%%%@%%%%#+ \n *#%%@%%%%%%@@@@@%@@@@@@@@%@@@@%%@@@@@%%%%%%#: ....", " \n \n \n :-=-:. \n -*#*####**-: \n -*#######%%##*+ \n +**+++***##%%##*+ \n :*-..:-::-==+***+ \n + ..::---:.-*. \n ::-=+-:=***+-.+: \n :--. -+++=-.-: \n ::-::::: \n ..:=+++=--: \n .---==+++=-. \n .:..-====== \n :::-=+++=:+= \n -+.-=+***+++%%%#=-. \n :=*#%##=.:=+++*#@@@%%%%%##+: \n :=*#%%%%%%%%+--=+#%@@%%%%%%%%%####= \n :#%%%%%%%%%%%%%%%@@@@@%%%@@%%%%%%%%###+ \n -#%%%%%%%%%%%%%%%@@@@@@@%%@%%%%%@%%%%%##* \n :##%@%@%%%%%%%@@%%@@@@@@@%@@%%%%@%%%%%%%%#+ \n :##%%@%@%%%%%@@@@%@@@@@@@@%@@%%%%@@%%%%%%%%#: \n +%%%%@@@%%%@@@@@@%@@@@@@@@@@@@@%@@%@@@%%%%%%* ....", " \n \n \n .:-=:: \n .=*#*####*+:. \n .+########%%##*- \n .***+=++**##%%##*- \n =*:. .--:-==+***: \n .= ..:::---:.-+ \n ::-++-.=***+-:= \n . .--. :==+=-.- \n .:-:::.: \n ..:=++==--. \n .----=+++=- \n .:..-=====- \n .:::-=+++-=+: \n -+-.-=****+=#%%%*=- \n .-=##%%##:.:=+++*%@@@%%%%%##+: \n -+#%%%%%%%%%#====*%@@@%%%%%%%%%####= \n .*%%%%%%@%%%%%%%%@@@@@@%%%@%%%%%%%%%###- \n =##%@%@%%@%%%%%%%%@@@@@@@%@@%%%%%@%%%%%##= \n +#%%%@@@%%@%%@@@@%%@@@@@@@%@@%%%%@%%%%%%%%#: \n +#%%%@@@@%%%%%@@@@%@@@@@@@@%@@%%%%@%%@@%%%%%# \n :#%%%@@%@@%%%@@@@@@@@@@@@@@@@@@@@%@@@@@%%%%%%#= ....", " \n \n \n .-==:: \n :+##*####*+: \n :*########%%#**: \n :*#+==++**##%%##*. \n +*:. .:---==+**+ \n :- .::::---:.== \n ..:-++=.=***+-:- \n .:-. :=++=:.- \n .:-:::. \n ..:=++==-: \n .----=+++=- \n .:.:-=====. \n :-::-=++=:*=. \n -**.:=+***+++%%%#+=: \n .=+##%%%#+:.-++++#@@@%%%%%##*=. \n =*#%%%%%%%%%%#=+++#%@@@%%%%%%%%%###*: \n :*#%%%%%@@%%%%%%%%@@@@@@%%%@%%%%%%%%%##* \n +#%%%%%@%@@%@@%@%%%@@@@@@@%@@%%%%%%%%%%%##. \n ##%%%@%@@%@@%@@@@%%@@@@@@@%%@@%%%%@%%%%%%%#* \n =#%%%@@@@@%@@%@@@@@@@@@@@@@%@@@%%%@@%%@@%%%%#= \n:#%%%@@@@@@%@@@@@@@@@@@@@@@@%@@@@@%@@@@%%%%%%%# ....", " \n \n \n .:-==-: \n -*#**####*+: \n =*########%%#**: \n -*#+===+**###%##+ \n *+. .-----==+*+ \n -: .:::::-==:.=: \n : :-++-.=***=:-: \n . .:: :===-::: \n ::-:::. \n :.-=++==-: \n ..=:-==+++=: \n ::.:-===== \n :---=+++=-#=. \n .=#+.:=+***++*%%%#*=: \n -+*##%%%#+.:-==+*%@@@%%%%%##*=. \n *##%%%%%%%%%%*+++*%@@@@%%%%%%%%%%##*: \n =##%%%%%@@%@%%%%%@@@@@@@%%@@%%%%%%%%%##+ \n .*#%%%%@@%@@%@@@@%%@@@@@@@%%@@%%%%@%%%%%##* \n ##%%%@%@@%@@%@@@@%%@@@@@@@%@@%%%%@%%%%%%%%#+ \n =#%%%@@@@@%@@%@@@@@@@@@@@@@%@@%%%%@@%@@%%%%%#: \n-#%%%@@@@@@%@@@@@@@@@@@@@@@@%@@@@@%@@@@%%%%%%%* ....."];
|
|
22
|
+
|
|
23
|
+
// src/components/portrait.tsx
|
|
24
|
+
import { Box, Text } from "ink";
|
|
25
|
+
import { useEffect, useMemo, useState } from "react";
|
|
26
|
+
import { jsx } from "react/jsx-runtime";
|
|
27
|
+
var FRAME_MS = 120;
|
|
28
|
+
function pingPongOrder(n) {
|
|
29
|
+
if (n <= 1) return [0];
|
|
30
|
+
const forward = Array.from({ length: n }, (_, i) => i);
|
|
31
|
+
const backward = Array.from({ length: n - 2 }, (_, i) => n - 2 - i);
|
|
32
|
+
return forward.concat(backward);
|
|
33
|
+
}
|
|
34
|
+
function Portrait() {
|
|
35
|
+
const order = useMemo(() => pingPongOrder(portraitFrames.length), []);
|
|
36
|
+
const [step, setStep] = useState(0);
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (portraitFrames.length <= 1) return;
|
|
39
|
+
const id = setInterval(() => setStep((s) => (s + 1) % order.length), FRAME_MS);
|
|
40
|
+
id.unref?.();
|
|
41
|
+
return () => clearInterval(id);
|
|
42
|
+
}, [order.length]);
|
|
43
|
+
const frame = portraitFrames[order[step]] ?? portraitFrames[0] ?? "";
|
|
44
|
+
if (!frame) return null;
|
|
45
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", flexShrink: 0, children: frame.split("\n").map((line, i) => /* @__PURE__ */ jsx(Text, { wrap: "truncate", children: line }, i)) });
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// src/components/header.tsx
|
|
49
|
+
import { Box as Box3, Text as Text3 } from "ink";
|
|
50
|
+
|
|
51
|
+
// src/components/wordmark.tsx
|
|
52
|
+
import { Box as Box2, Text as Text2 } from "ink";
|
|
53
|
+
|
|
54
|
+
// src/components/pixel-font.ts
|
|
55
|
+
var GLYPHS = {
|
|
56
|
+
A: [".###.", "#...#", "#####", "#...#", "#...#"],
|
|
57
|
+
B: ["####.", "#...#", "####.", "#...#", "####."],
|
|
58
|
+
C: [".####", "#....", "#....", "#....", ".####"],
|
|
59
|
+
D: ["####.", "#...#", "#...#", "#...#", "####."],
|
|
60
|
+
E: ["#####", "#....", "###..", "#....", "#####"],
|
|
61
|
+
F: ["#####", "#....", "###..", "#....", "#...."],
|
|
62
|
+
G: [".####", "#....", "#..##", "#...#", ".###."],
|
|
63
|
+
H: ["#...#", "#...#", "#####", "#...#", "#...#"],
|
|
64
|
+
I: ["#####", "..#..", "..#..", "..#..", "#####"],
|
|
65
|
+
J: ["..###", "...#.", "...#.", "#..#.", ".##.."],
|
|
66
|
+
K: ["#...#", "#..#.", "###..", "#..#.", "#...#"],
|
|
67
|
+
L: ["#....", "#....", "#....", "#....", "#####"],
|
|
68
|
+
M: ["#...#", "##.##", "#.#.#", "#...#", "#...#"],
|
|
69
|
+
N: ["#...#", "##..#", "#.#.#", "#..##", "#...#"],
|
|
70
|
+
O: [".###.", "#...#", "#...#", "#...#", ".###."],
|
|
71
|
+
P: ["####.", "#...#", "####.", "#....", "#...."],
|
|
72
|
+
Q: [".###.", "#...#", "#.#.#", "#..#.", ".##.#"],
|
|
73
|
+
R: ["####.", "#...#", "####.", "#..#.", "#...#"],
|
|
74
|
+
S: [".####", "#....", ".###.", "....#", "####."],
|
|
75
|
+
T: ["#####", "..#..", "..#..", "..#..", "..#.."],
|
|
76
|
+
U: ["#...#", "#...#", "#...#", "#...#", ".###."],
|
|
77
|
+
V: ["#...#", "#...#", "#...#", ".#.#.", "..#.."],
|
|
78
|
+
W: ["#...#", "#...#", "#.#.#", "##.##", "#...#"],
|
|
79
|
+
X: ["#...#", ".#.#.", "..#..", ".#.#.", "#...#"],
|
|
80
|
+
Y: ["#...#", ".#.#.", "..#..", "..#..", "..#.."],
|
|
81
|
+
Z: ["#####", "...#.", "..#..", ".#...", "#####"],
|
|
82
|
+
"0": [".###.", "#..##", "#.#.#", "##..#", ".###."],
|
|
83
|
+
"1": ["..#..", ".##..", "..#..", "..#..", ".###."],
|
|
84
|
+
"2": [".###.", "#...#", "..##.", ".#...", "#####"],
|
|
85
|
+
"3": ["####.", "....#", ".###.", "....#", "####."],
|
|
86
|
+
"4": ["#..#.", "#..#.", "#####", "...#.", "...#."],
|
|
87
|
+
"5": ["#####", "#....", "####.", "....#", "####."],
|
|
88
|
+
"6": [".###.", "#....", "####.", "#...#", ".###."],
|
|
89
|
+
"7": ["#####", "...#.", "..#..", ".#...", ".#..."],
|
|
90
|
+
"8": [".###.", "#...#", ".###.", "#...#", ".###."],
|
|
91
|
+
"9": [".###.", "#...#", ".####", "....#", ".###."],
|
|
92
|
+
" ": [".....", ".....", ".....", ".....", "....."],
|
|
93
|
+
// Lowercase forms for the letters used in the wordmark. Letters without a
|
|
94
|
+
// lowercase glyph fall back to their uppercase form (see renderWordmark).
|
|
95
|
+
m: [".....", ".....", "#####", "#.#.#", "#.#.#"],
|
|
96
|
+
i: ["..#..", ".....", "..#..", "..#..", "..#.."],
|
|
97
|
+
l: ["..#..", "..#..", "..#..", "..#..", "..#.."],
|
|
98
|
+
s: [".....", ".####", "###..", "..###", "####."],
|
|
99
|
+
t: [".#...", "####.", ".#...", ".#...", ".###."]
|
|
100
|
+
};
|
|
101
|
+
var FALLBACK = ["#####", "#####", "#####", "#####", "#####"];
|
|
102
|
+
var GLYPH_HEIGHT = 5;
|
|
103
|
+
var ON = "\u2588\u2588";
|
|
104
|
+
var OFF = " ";
|
|
105
|
+
var GLYPH_GAP = " ";
|
|
106
|
+
function trimGlyph(rows) {
|
|
107
|
+
let min = Infinity;
|
|
108
|
+
let max = -1;
|
|
109
|
+
for (const row of rows) {
|
|
110
|
+
for (let c = 0; c < row.length; c++) {
|
|
111
|
+
if (row[c] === "#") {
|
|
112
|
+
if (c < min) min = c;
|
|
113
|
+
if (c > max) max = c;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (max < 0) return rows.map(() => "..");
|
|
118
|
+
return rows.map((r) => r.slice(min, max + 1));
|
|
119
|
+
}
|
|
120
|
+
function renderWordmark(text) {
|
|
121
|
+
const glyphs = [...text].map(
|
|
122
|
+
(c) => trimGlyph(GLYPHS[c] ?? GLYPHS[c.toUpperCase()] ?? FALLBACK)
|
|
123
|
+
);
|
|
124
|
+
const rows = [];
|
|
125
|
+
for (let r = 0; r < GLYPH_HEIGHT; r++) {
|
|
126
|
+
const row = glyphs.map((g) => [...g[r]].map((p) => p === "#" ? ON : OFF).join("")).join(GLYPH_GAP);
|
|
127
|
+
rows.push(row);
|
|
128
|
+
}
|
|
129
|
+
return rows;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// src/components/wordmark.tsx
|
|
133
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
134
|
+
function Wordmark({ text }) {
|
|
135
|
+
const rows = renderWordmark(text);
|
|
136
|
+
return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", children: rows.map((row, i) => /* @__PURE__ */ jsx2(Text2, { color: "white", children: row }, i)) });
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/components/header.tsx
|
|
140
|
+
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
141
|
+
function Header({ wordmark, name, tagline, siteLabel, githubLabel, xLabel }) {
|
|
142
|
+
return /* @__PURE__ */ jsxs(Box3, { flexDirection: "column", alignItems: "center", marginTop: 1, children: [
|
|
143
|
+
/* @__PURE__ */ jsx3(Wordmark, { text: wordmark }),
|
|
144
|
+
/* @__PURE__ */ jsxs(Box3, { flexDirection: "column", alignItems: "center", marginTop: 1, children: [
|
|
145
|
+
/* @__PURE__ */ jsx3(Text3, { bold: true, children: name }),
|
|
146
|
+
/* @__PURE__ */ jsx3(Text3, { color: "gray", children: tagline }),
|
|
147
|
+
/* @__PURE__ */ jsx3(Box3, { marginTop: 1, children: /* @__PURE__ */ jsxs(Text3, { color: "gray", children: [
|
|
148
|
+
siteLabel,
|
|
149
|
+
" ",
|
|
150
|
+
githubLabel,
|
|
151
|
+
" ",
|
|
152
|
+
xLabel
|
|
153
|
+
] }) })
|
|
154
|
+
] })
|
|
155
|
+
] });
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// src/components/footer.tsx
|
|
159
|
+
import { Box as Box4, Text as Text4 } from "ink";
|
|
160
|
+
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
161
|
+
var HINTS = [
|
|
162
|
+
{ key: "s", label: "site" },
|
|
163
|
+
{ key: "g", label: "github" },
|
|
164
|
+
{ key: "x", label: "x.com" },
|
|
165
|
+
{ key: "q", label: "quit" }
|
|
166
|
+
];
|
|
167
|
+
function Footer() {
|
|
168
|
+
return /* @__PURE__ */ jsx4(Box4, { marginTop: 1, children: HINTS.map((hint, i) => /* @__PURE__ */ jsxs2(Text4, { children: [
|
|
169
|
+
i > 0 ? " " : "",
|
|
170
|
+
/* @__PURE__ */ jsx4(Text4, { color: "cyan", bold: true, children: hint.key }),
|
|
171
|
+
" ",
|
|
172
|
+
/* @__PURE__ */ jsx4(Text4, { color: "gray", children: hint.label })
|
|
173
|
+
] }, hint.key)) });
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// src/hooks/use-keyboard-actions.ts
|
|
177
|
+
import { useApp, useInput } from "ink";
|
|
178
|
+
|
|
179
|
+
// src/lib/open-url.ts
|
|
180
|
+
import open from "open";
|
|
181
|
+
async function openUrl(url) {
|
|
182
|
+
try {
|
|
183
|
+
await open(url);
|
|
184
|
+
} catch {
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// src/hooks/use-keyboard-actions.ts
|
|
189
|
+
function useKeyboardActions({ githubUrl, xUrl, siteUrl }) {
|
|
190
|
+
const { exit } = useApp();
|
|
191
|
+
useInput((input, key) => {
|
|
192
|
+
if (input === "g") void openUrl(githubUrl);
|
|
193
|
+
else if (input === "x") void openUrl(xUrl);
|
|
194
|
+
else if (input === "s") void openUrl(siteUrl);
|
|
195
|
+
else if (input === "q" || key.escape || key.ctrl && input === "c") exit();
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// src/hooks/use-terminal-size.ts
|
|
200
|
+
import { useStdout } from "ink";
|
|
201
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
202
|
+
function useTerminalSize() {
|
|
203
|
+
const { stdout } = useStdout();
|
|
204
|
+
const [size, setSize] = useState2({
|
|
205
|
+
columns: stdout?.columns ?? 80,
|
|
206
|
+
rows: stdout?.rows ?? 24
|
|
207
|
+
});
|
|
208
|
+
useEffect2(() => {
|
|
209
|
+
if (!stdout) return;
|
|
210
|
+
const onResize = () => {
|
|
211
|
+
setSize({ columns: stdout.columns, rows: stdout.rows });
|
|
212
|
+
};
|
|
213
|
+
stdout.on("resize", onResize);
|
|
214
|
+
return () => {
|
|
215
|
+
stdout.off("resize", onResize);
|
|
216
|
+
};
|
|
217
|
+
}, [stdout]);
|
|
218
|
+
return size;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// src/app.tsx
|
|
222
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
223
|
+
var TEXT_BLOCK_ROWS = 11;
|
|
224
|
+
var FIXED_CHROME_ROWS = 4;
|
|
225
|
+
var MAX_WIDTH = 62;
|
|
226
|
+
function App() {
|
|
227
|
+
const { columns, rows } = useTerminalSize();
|
|
228
|
+
useKeyboardActions({
|
|
229
|
+
githubUrl: profile.githubUrl,
|
|
230
|
+
xUrl: profile.xUrl,
|
|
231
|
+
siteUrl: profile.siteUrl
|
|
232
|
+
});
|
|
233
|
+
const portraitRows = portraitFrames[0] ? portraitFrames[0].split("\n").length : 0;
|
|
234
|
+
const frameWidth = Math.min(MAX_WIDTH, columns);
|
|
235
|
+
const contentRows = portraitRows + TEXT_BLOCK_ROWS + FIXED_CHROME_ROWS;
|
|
236
|
+
const canCenterVertically = rows > contentRows;
|
|
237
|
+
return /* @__PURE__ */ jsx5(
|
|
238
|
+
Box5,
|
|
239
|
+
{
|
|
240
|
+
width: columns,
|
|
241
|
+
height: canCenterVertically ? rows : void 0,
|
|
242
|
+
flexDirection: "column",
|
|
243
|
+
alignItems: "center",
|
|
244
|
+
justifyContent: canCenterVertically ? "center" : "flex-start",
|
|
245
|
+
children: /* @__PURE__ */ jsxs3(Box5, { flexDirection: "column", width: frameWidth, paddingX: 1, paddingY: 1, alignItems: "center", children: [
|
|
246
|
+
/* @__PURE__ */ jsx5(Portrait, {}),
|
|
247
|
+
/* @__PURE__ */ jsx5(
|
|
248
|
+
Header,
|
|
249
|
+
{
|
|
250
|
+
wordmark: profile.wordmark,
|
|
251
|
+
name: profile.name,
|
|
252
|
+
tagline: profile.tagline,
|
|
253
|
+
siteLabel: profile.siteLabel,
|
|
254
|
+
githubLabel: profile.githubLabel,
|
|
255
|
+
xLabel: profile.xLabel
|
|
256
|
+
}
|
|
257
|
+
),
|
|
258
|
+
/* @__PURE__ */ jsx5(Footer, {})
|
|
259
|
+
] })
|
|
260
|
+
}
|
|
261
|
+
);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// src/cli.tsx
|
|
265
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
266
|
+
var ENTER_ALT_SCREEN = "\x1B[?1049h\x1B[H";
|
|
267
|
+
var EXIT_ALT_SCREEN = "\x1B[?1049l";
|
|
268
|
+
process.stdout.write(ENTER_ALT_SCREEN);
|
|
269
|
+
var { waitUntilExit } = render(/* @__PURE__ */ jsx6(App, {}));
|
|
270
|
+
try {
|
|
271
|
+
await waitUntilExit();
|
|
272
|
+
} finally {
|
|
273
|
+
process.stdout.write(EXIT_ALT_SCREEN);
|
|
274
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "milstead",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Michael Milstead's personal profile, as a terminal app. Run: npx milstead",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"milst": "bin/milst.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"bin"
|
|
12
|
+
],
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=18"
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsup",
|
|
18
|
+
"dev": "tsup --watch",
|
|
19
|
+
"start": "node bin/milst.js",
|
|
20
|
+
"test": "vitest run",
|
|
21
|
+
"test:watch": "vitest",
|
|
22
|
+
"portrait": "tsx scripts/generate-portrait.ts",
|
|
23
|
+
"prepublishOnly": "npm run build"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"cli",
|
|
27
|
+
"tui",
|
|
28
|
+
"ink",
|
|
29
|
+
"profile",
|
|
30
|
+
"npx"
|
|
31
|
+
],
|
|
32
|
+
"author": "Michael Milstead",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"ink": "^5.0.1",
|
|
36
|
+
"open": "^10.1.0",
|
|
37
|
+
"react": "^18.3.1"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/react": "^18.3.12",
|
|
41
|
+
"ink-testing-library": "^4.0.0",
|
|
42
|
+
"jimp": "^1.6.0",
|
|
43
|
+
"tsup": "^8.3.5",
|
|
44
|
+
"tsx": "^4.19.2",
|
|
45
|
+
"typescript": "^5.7.2",
|
|
46
|
+
"vitest": "^2.1.8"
|
|
47
|
+
}
|
|
48
|
+
}
|