@kljj04/cli-kit 1.2.0 → 1.2.1

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.long.md ADDED
@@ -0,0 +1,245 @@
1
+ # @kljj04/cli-kit — Full Documentation
2
+
3
+ All-in-one terminal styling library for Node.js.
4
+ RGB truecolor, boxes, tables, spinners, and progress bars — all in one package, zero dependencies.
5
+
6
+ ---
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ npm install @kljj04/cli-kit
12
+ ```
13
+
14
+ ---
15
+
16
+ ## Core Concept
17
+
18
+ All styling follows a consistent 3-step chain:
19
+
20
+ ```js
21
+ kit.color(R, G, B).style(...args).context(value)
22
+ ```
23
+
24
+ | Step | Method | Description |
25
+ |---|---|---|
26
+ | 1 | `color(r, g, b)` | Set RGB truecolor (0–255 each) |
27
+ | 2 | `style(...args)` | Set text styles + output type |
28
+ | 3 | `context(value)` | Render the output |
29
+
30
+ You can also write it across multiple lines:
31
+
32
+ ```js
33
+ kit
34
+ .color(255, 100, 50)
35
+ .style('bold', 'box')
36
+ .context('Hello!')
37
+ ```
38
+
39
+ ---
40
+
41
+ ## color(r, g, b)
42
+
43
+ Sets the foreground color using RGB truecolor.
44
+ Requires a terminal with truecolor support (Windows Terminal, iTerm2, most modern terminals).
45
+
46
+ ```js
47
+ kit.color(255, 0, 0) // red
48
+ kit.color(0, 255, 0) // green
49
+ kit.color(0, 0, 255) // blue
50
+ kit.color(255, 255, 255) // white
51
+ ```
52
+
53
+ ---
54
+
55
+ ## style(...args)
56
+
57
+ Accepts any combination of text styles and one output type.
58
+
59
+ ### Text Styles
60
+
61
+ | Value | Description |
62
+ |---|---|
63
+ | `bold` | Bold text |
64
+ | `dim` | Dimmed text |
65
+ | `italic` | Italic text |
66
+ | `underline` | Underlined text |
67
+ | `inverse` | Inverted fg/bg colors |
68
+ | `strikethrough` | Strikethrough text |
69
+
70
+ ### Output Types
71
+
72
+ | Value | Description |
73
+ |---|---|
74
+ | `print` | Plain text (default) |
75
+ | `box` | Unicode box border |
76
+ | `spinner` | Animated spinner |
77
+ | `progress` | Progress bar |
78
+ | `table` | Formatted table |
79
+
80
+ Multiple text styles can be combined. Only one output type should be passed.
81
+
82
+ ```js
83
+ kit.color(255, 100, 50).style('bold', 'italic', 'box').context('Hello!')
84
+ ```
85
+
86
+ ---
87
+
88
+ ## Output Types
89
+
90
+ ### print (default)
91
+
92
+ Prints styled text to stdout. Output type can be omitted.
93
+
94
+ ```js
95
+ kit.color(255, 100, 50).style('bold').context('Hello!')
96
+ kit.color(255, 100, 50).style('bold', 'print').context('Hello!')
97
+ ```
98
+
99
+ ---
100
+
101
+ ### box
102
+
103
+ Wraps text in a Unicode box border. Supports multiline strings (`\n`).
104
+
105
+ ```js
106
+ kit.color(100, 200, 255).style('box').context('Hello!')
107
+ ```
108
+
109
+ ```
110
+ ┌────────┐
111
+ │ Hello! │
112
+ └────────┘
113
+ ```
114
+
115
+ Multiline:
116
+
117
+ ```js
118
+ kit.color(150, 255, 100).style('box').context('Line one\nLine two\nLine three')
119
+ ```
120
+
121
+ ```
122
+ ┌────────────┐
123
+ │ Line one │
124
+ │ Line two │
125
+ │ Line three │
126
+ └────────────┘
127
+ ```
128
+
129
+ ---
130
+
131
+ ### spinner
132
+
133
+ Returns a spinner object with a `.stop(text)` method.
134
+
135
+ ```js
136
+ const s = kit.color(0, 255, 200).style('spinner').context('Loading...')
137
+
138
+ setTimeout(() => {
139
+ s.stop('Done!') // clears spinner, prints final message
140
+ }, 2000)
141
+ ```
142
+
143
+ | Method | Description |
144
+ |---|---|
145
+ | `s.stop(text?)` | Stop spinner. Optionally print a final message. |
146
+
147
+ ---
148
+
149
+ ### progress
150
+
151
+ Pass a number from 0 to 100.
152
+
153
+ ```js
154
+ kit.color(255, 200, 0).style('progress').context(72)
155
+ // [██████████████████████░░░░░░░░] 72%
156
+ ```
157
+
158
+ **Live mode** — pass `{ value, override: true }` to overwrite the same line.
159
+ Useful inside loops or intervals.
160
+
161
+ ```js
162
+ // style에 override 추가
163
+ kit.color(0, 255, 150).style('progress', 'override').context(i)
164
+ ```
165
+
166
+ Example with interval:
167
+
168
+ ```js
169
+ let i = 0
170
+ const interval = setInterval(() => {
171
+ i++
172
+ kit.color(0, 255, 150).style('progress', 'override').context(i)
173
+ if (i >= 100) clearInterval(interval)
174
+ }, 30)
175
+ ```
176
+
177
+ ---
178
+
179
+ ### table
180
+
181
+ Pass an array of objects. Keys are used as column headers automatically.
182
+
183
+ ```js
184
+ kit.color(200, 150, 255).style('table').context([
185
+ { name: 'Alice', age: 20, role: 'dev' },
186
+ { name: 'Bob', age: 25, role: 'designer' },
187
+ { name: 'Carol', age: 30, role: 'PM' },
188
+ ])
189
+ ```
190
+
191
+ ```
192
+ ┌───────┬─────┬──────────┐
193
+ │ name │ age │ role │
194
+ ┼───────┼─────┼──────────┼
195
+ │ Alice │ 20 │ dev │
196
+ │ Bob │ 25 │ designer │
197
+ │ Carol │ 30 │ PM │
198
+ └───────┴─────┴──────────┘
199
+ ```
200
+
201
+ ---
202
+
203
+ ## Full Example
204
+
205
+ ```js
206
+ const kit = require('@kljj04/cli-kit')
207
+
208
+ // box
209
+ kit.color(0, 255, 100).style('bold', 'box').context('Welcome!')
210
+
211
+ // spinner
212
+ const s = kit.color(100, 200, 255).style('spinner').context('Loading...')
213
+ setTimeout(() => s.stop('Done!'), 1500)
214
+
215
+ // table
216
+ kit.color(200, 150, 255).style('table').context([
217
+ { task: 'Build', status: 'OK' },
218
+ { task: 'Deploy', status: 'OK' },
219
+ ])
220
+
221
+ // progress (live)
222
+ let i = 0
223
+ const iv = setInterval(() => {
224
+ i++
225
+ kit.color(255, 200, 0).style('progress', 'override').context(i)
226
+ if (i >= 100) {
227
+ clearInterval(iv)
228
+ kit.color(0, 255, 100).style('bold').context('Complete!')
229
+ }
230
+ }, 20)
231
+ ```
232
+
233
+ ---
234
+
235
+ ## Planned Features
236
+
237
+ - `gradient([r,g,b], [r,g,b])` — per-character color interpolation for progress bars
238
+ - `style('round', 'box')` — rounded box corners
239
+ - `bgColor(r, g, b)` — background color support
240
+
241
+ ---
242
+
243
+ ## License
244
+
245
+ MIT
package/README.md CHANGED
@@ -1,3 +1,7 @@
1
+ > [!WARNING]
2
+ > This README is old and outdated. It will be updated as soon as possible.
3
+ > AI.md, README.long.md too.
4
+
1
5
  # @kljj04/cli-kit
2
6
 
3
7
  All-in-one terminal styling library for Node.js.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kljj04/cli-kit",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "All-in-one terminal styling library. Colors, boxes, tables, spinners, and progress bars.",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/src/color.js CHANGED
@@ -26,6 +26,7 @@ class KitBuilder {
26
26
  this._outputType = 'print';
27
27
  this._override = false;
28
28
  this._gradientColors = null;
29
+ this._fixedGradient = false;
29
30
  }
30
31
 
31
32
  color(r, g, b) {
@@ -45,6 +46,8 @@ class KitBuilder {
45
46
  args.forEach(arg => {
46
47
  if (arg === 'override') {
47
48
  this._override = true;
49
+ } else if (arg === 'fixedgradient') {
50
+ this._fixedGradient = true;
48
51
  } else if (outputTypes.includes(arg)) {
49
52
  this._outputType = arg;
50
53
  } else if (STYLES[arg]) {
@@ -72,7 +75,7 @@ class KitBuilder {
72
75
  case 'spinner':
73
76
  return require('./spinner').spinner(prefix, value);
74
77
  case 'progress':
75
- require('./progress').progress(prefix, value, this._override, this._gradientColors);
78
+ require('./progress').progress(prefix, value, this._override, this._gradientColors, this._fixedGradient);
76
79
  break;
77
80
  case 'table':
78
81
  require('./table').table(prefix, value);
@@ -82,6 +85,7 @@ class KitBuilder {
82
85
  this._outputType = 'print';
83
86
  this._override = false;
84
87
  this._gradientColors = null;
88
+ this._fixedGradient = false;
85
89
  }
86
90
  }
87
91
 
package/src/progress.js CHANGED
@@ -12,48 +12,57 @@ function delinearize(c) {
12
12
 
13
13
  function rgbToOklch(r, g, b) {
14
14
  const lr = linearize(r), lg = linearize(g), lb = linearize(b);
15
- const l = 0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb;
16
- const m = 0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb;
17
- const s = 0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb;
15
+ const l = 0.4122214708*lr + 0.5363325363*lg + 0.0514459929*lb;
16
+ const m = 0.2119034982*lr + 0.6806995451*lg + 0.1073969566*lb;
17
+ const s = 0.0883024619*lr + 0.2817188376*lg + 0.6299787005*lb;
18
18
  const l_ = Math.cbrt(l), m_ = Math.cbrt(m), s_ = Math.cbrt(s);
19
- const L = 0.2104542553 * l_ + 0.7936177850 * m_ - 0.0040720468 * s_;
20
- const a = 1.9779984951 * l_ - 2.4285922050 * m_ + 0.4505937099 * s_;
21
- const bVal = 0.0259040371 * l_ + 0.7827717662 * m_ - 0.8086757660 * s_;
22
- const C = Math.sqrt(a * a + bVal * bVal);
23
- const H = Math.atan2(bVal, a) * (180 / Math.PI);
24
- return [L, C, H < 0 ? H + 360 : H];
19
+ const L = 0.2104542553*l_ + 0.7936177850*m_ - 0.0040720468*s_;
20
+ const a = 1.9779984951*l_ - 2.4285922050*m_ + 0.4505937099*s_;
21
+ const bVal = 0.0259040371*l_ + 0.7827717662*m_ - 0.8086757660*s_;
22
+ const C = Math.sqrt(a*a + bVal*bVal);
23
+ const H = Math.atan2(bVal, a) * (180/Math.PI);
24
+ return [L, C, H < 0 ? H+360 : H];
25
25
  }
26
26
 
27
27
  function oklchToRgb(L, C, H) {
28
- const hRad = H * (Math.PI / 180);
29
- const a = C * Math.cos(hRad);
30
- const b = C * Math.sin(hRad);
31
- const l_ = L + 0.3963377774 * a + 0.2158037573 * b;
32
- const m_ = L - 0.1055613458 * a - 0.0638541728 * b;
33
- const s_ = L - 0.0894841775 * a - 1.2914855480 * b;
34
- const lc = l_ * l_ * l_, mc = m_ * m_ * m_, sc = s_ * s_ * s_;
35
- const lr = 4.0767416621 * lc - 3.3077115913 * mc + 0.2309699292 * sc;
36
- const lg = -1.2684380046 * lc + 2.6097574011 * mc - 0.3413193965 * sc;
37
- const lb = -0.0041960863 * lc - 0.7034186147 * mc + 1.7076147010 * sc;
28
+ const hRad = H * (Math.PI/180);
29
+ const a = C*Math.cos(hRad);
30
+ const b = C*Math.sin(hRad);
31
+ const l_ = L+0.3963377774*a+0.2158037573*b;
32
+ const m_ = L-0.1055613458*a-0.0638541728*b;
33
+ const s_ = L-0.0894841775*a-1.2914855480*b;
34
+ const lc=l_*l_*l_, mc=m_*m_*m_, sc=s_*s_*s_;
35
+ const lr = 4.0767416621*lc - 3.3077115913*mc + 0.2309699292*sc;
36
+ const lg = -1.2684380046*lc + 2.6097574011*mc - 0.3413193965*sc;
37
+ const lb = -0.0041960863*lc - 0.7034186147*mc + 1.7076147010*sc;
38
38
  return [delinearize(lr), delinearize(lg), delinearize(lb)];
39
39
  }
40
40
 
41
41
  function lerpOklch(from, to, t) {
42
42
  const a = rgbToOklch(...from);
43
43
  const b = rgbToOklch(...to);
44
- let dH = b[2] - a[2];
44
+ let dH = b[2]-a[2];
45
45
  if (dH > 180) dH -= 360;
46
46
  if (dH < -180) dH += 360;
47
- return oklchToRgb(a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t, a[2] + dH * t);
47
+ return oklchToRgb(a[0]+(b[0]-a[0])*t, a[1]+(b[1]-a[1])*t, a[2]+dH*t);
48
48
  }
49
49
 
50
- function renderBar(prefix, pct, gradientColors) {
50
+ function renderBar(prefix, pct, gradientColors, fixedGradient) {
51
51
  const width = 30;
52
52
  const filled = Math.round((pct / 100) * width);
53
53
  const empty = width - filled;
54
54
 
55
55
  let bar = '';
56
- if (gradientColors) {
56
+ if (gradientColors && fixedGradient) {
57
+ // 전체 30칸 기준으로 색 미리 계산, 채워진 만큼만 표시
58
+ for (let i = 0; i < filled; i++) {
59
+ const t = (width > 1) ? i / (width - 1) : 0;
60
+ const [r, g, b] = lerpOklch(gradientColors[0], gradientColors[1], t);
61
+ bar += `\x1b[38;2;${r};${g};${b}m█`;
62
+ }
63
+ bar += `${RESET}${'░'.repeat(empty)}`;
64
+ } else if (gradientColors) {
65
+ // 채워진 칸 기준 보간 (기존 gradient)
57
66
  for (let i = 0; i < filled; i++) {
58
67
  const t = filled > 1 ? i / (filled - 1) : 0;
59
68
  const [r, g, b] = lerpOklch(gradientColors[0], gradientColors[1], t);
@@ -67,9 +76,9 @@ function renderBar(prefix, pct, gradientColors) {
67
76
  return `${prefix}[${bar}] ${pct}%${RESET}`;
68
77
  }
69
78
 
70
- function progress(prefix, value, override, gradientColors) {
79
+ function progress(prefix, value, override, gradientColors, fixedGradient) {
71
80
  const pct = Math.min(100, Math.max(0, Number(value)));
72
- const bar = renderBar(prefix, pct, gradientColors);
81
+ const bar = renderBar(prefix, pct, gradientColors, fixedGradient);
73
82
  if (override) {
74
83
  process.stdout.write(`\r${bar}`);
75
84
  if (pct >= 100) process.stdout.write('\n');