@nan0web/ui 1.0.4 → 1.3.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.
Files changed (95) hide show
  1. package/README.md +19 -14
  2. package/package.json +6 -4
  3. package/src/App/Command/DepsCommand.js +25 -0
  4. package/src/App/Core/CoreApp.js +18 -17
  5. package/src/App/Core/UI.js +12 -19
  6. package/src/App/Core/Widget.js +6 -10
  7. package/src/App/Core/index.js +3 -3
  8. package/src/App/Scenario.js +4 -4
  9. package/src/App/User/Command/Message.js +2 -29
  10. package/src/App/User/Command/index.js +3 -4
  11. package/src/App/User/UserApp.js +30 -23
  12. package/src/App/User/UserUI.js +2 -2
  13. package/src/App/User/index.js +2 -2
  14. package/src/App/index.js +5 -10
  15. package/src/Component/Process/Input.js +10 -17
  16. package/src/Component/Process/Process.js +3 -5
  17. package/src/Component/Process/index.js +2 -2
  18. package/src/Component/SortableList/SortableList.js +100 -0
  19. package/src/Component/SortableList/index.js +3 -0
  20. package/src/Component/Welcome/Input.js +2 -4
  21. package/src/Component/Welcome/Welcome.js +5 -9
  22. package/src/Component/Welcome/index.js +2 -2
  23. package/src/Component/index.js +5 -3
  24. package/src/Frame/Frame.js +163 -146
  25. package/src/Frame/Props.js +20 -20
  26. package/src/Locale.js +17 -18
  27. package/src/Model/User/User.js +3 -6
  28. package/src/Model/index.js +1 -1
  29. package/src/README.md.js +84 -94
  30. package/src/StdIn.js +8 -12
  31. package/src/StdOut.js +23 -27
  32. package/src/View/RenderOptions.js +1 -1
  33. package/src/View/View.js +42 -38
  34. package/src/core/Error/CancelError.js +2 -2
  35. package/src/core/Error/index.js +3 -5
  36. package/src/core/Flow.js +347 -0
  37. package/src/core/Form/Form.js +35 -33
  38. package/src/core/Form/Input.js +29 -14
  39. package/src/core/Form/Message.js +3 -6
  40. package/src/core/Form/index.js +4 -8
  41. package/src/core/InputAdapter.js +4 -6
  42. package/src/core/Message/Message.js +9 -12
  43. package/src/core/Message/OutputMessage.js +19 -17
  44. package/src/core/Message/index.js +2 -2
  45. package/src/core/OutputAdapter.js +12 -10
  46. package/src/core/Stream.js +4 -3
  47. package/src/core/StreamEntry.js +2 -2
  48. package/src/core/UiAdapter.js +57 -29
  49. package/src/core/index.js +38 -9
  50. package/src/functions.js +8 -15
  51. package/src/index.js +21 -32
  52. package/types/App/Command/DepsCommand.d.ts +16 -0
  53. package/types/App/Command/Options.d.ts +37 -40
  54. package/types/App/Command/index.d.ts +6 -6
  55. package/types/App/Core/CoreApp.d.ts +2 -2
  56. package/types/App/Core/UI.d.ts +6 -7
  57. package/types/App/Core/Widget.d.ts +4 -4
  58. package/types/App/Core/index.d.ts +3 -3
  59. package/types/App/Scenario.d.ts +1 -1
  60. package/types/App/User/Command/Message.d.ts +2 -16
  61. package/types/App/User/Command/Options.d.ts +29 -29
  62. package/types/App/User/Command/index.d.ts +2 -3
  63. package/types/App/User/UserApp.d.ts +5 -5
  64. package/types/App/User/index.d.ts +2 -2
  65. package/types/App/index.d.ts +4 -4
  66. package/types/Component/Process/Process.d.ts +2 -2
  67. package/types/Component/Process/index.d.ts +2 -2
  68. package/types/Component/SortableList/SortableList.d.ts +58 -0
  69. package/types/Component/SortableList/index.d.ts +2 -0
  70. package/types/Component/Welcome/Input.d.ts +1 -1
  71. package/types/Component/Welcome/Welcome.d.ts +1 -1
  72. package/types/Component/Welcome/index.d.ts +2 -2
  73. package/types/Component/index.d.ts +5 -3
  74. package/types/Frame/Frame.d.ts +1 -1
  75. package/types/Frame/Props.d.ts +1 -1
  76. package/types/Model/index.d.ts +1 -1
  77. package/types/StdIn.d.ts +2 -2
  78. package/types/StdOut.d.ts +1 -1
  79. package/types/View/View.d.ts +7 -7
  80. package/types/core/Error/index.d.ts +1 -1
  81. package/types/core/Flow.d.ts +320 -0
  82. package/types/core/Form/Form.d.ts +2 -2
  83. package/types/core/Form/Input.d.ts +15 -4
  84. package/types/core/Form/Message.d.ts +1 -1
  85. package/types/core/Form/index.d.ts +3 -3
  86. package/types/core/InputAdapter.d.ts +2 -2
  87. package/types/core/Intent.d.ts +65 -68
  88. package/types/core/Message/InputMessage.d.ts +65 -65
  89. package/types/core/Message/Message.d.ts +1 -1
  90. package/types/core/Message/OutputMessage.d.ts +1 -1
  91. package/types/core/Message/index.d.ts +2 -2
  92. package/types/core/Stream.d.ts +1 -2
  93. package/types/core/UiAdapter.d.ts +22 -4
  94. package/types/core/index.d.ts +5 -2
  95. package/types/index.d.ts +10 -10
@@ -1,11 +1,11 @@
1
- import stringWidth from "string-width"
2
- import { to, typeOf, empty } from "@nan0web/types"
3
- import FrameProps from "./Props.js"
1
+ import stringWidth from 'string-width'
2
+ import { to, typeOf, empty } from '@nan0web/types'
3
+ import FrameProps from './Props.js'
4
4
 
5
5
  export class FrameRenderMethod {
6
- static APPEND = "append"
7
- static REPLACE = "replace"
8
- static VISIBLE = "visible"
6
+ static APPEND = 'append'
7
+ static REPLACE = 'replace'
8
+ static VISIBLE = 'visible'
9
9
  }
10
10
 
11
11
  /**
@@ -16,27 +16,27 @@ export default class Frame {
16
16
  static RenderMethod = FrameRenderMethod
17
17
  static Props = FrameProps
18
18
  /** @type {string} End of line */
19
- static EOL = "\n"
19
+ static EOL = '\n'
20
20
  /** @type {string} Beginning of line */
21
- static BOL = "\r"
21
+ static BOL = '\r'
22
22
  /** @type {string} Beginning of frame */
23
- static BOF = "\x1b[0;0H"
23
+ static BOF = '\x1b[0;0H'
24
24
  /** @type {string} Hide cursor */
25
- static HIDE_CURSOR = "\x1b[?25l"
25
+ static HIDE_CURSOR = '\x1b[?25l'
26
26
  /** @type {string} Show cursor */
27
- static SHOW_CURSOR = "\x1b[?25h"
27
+ static SHOW_CURSOR = '\x1b[?25h'
28
28
  /** @type {string} Tab */
29
- static TAB = "\t"
29
+ static TAB = '\t'
30
30
  /** @type {string} Bold */
31
- static BOLD = "\x1b[1m"
31
+ static BOLD = '\x1b[1m'
32
32
  /** @type {string} Italic */
33
- static ITALIC = "\x1b[3m"
33
+ static ITALIC = '\x1b[3m'
34
34
  /** @type {string} Underline */
35
- static UNDERLINE = "\x1b[4m"
35
+ static UNDERLINE = '\x1b[4m'
36
36
  /** @type {string} Strikethrough */
37
- static STRIKETHROUGH = "\x1b[9m"
37
+ static STRIKETHROUGH = '\x1b[9m'
38
38
  /** @type {string} Reset */
39
- static RESET = "\x1b[0m"
39
+ static RESET = '\x1b[0m'
40
40
  /** @type {string} Clear line */
41
41
  static CLEAR_LINE = '\x1b[2K'
42
42
  /**
@@ -81,26 +81,29 @@ export default class Frame {
81
81
  value = [],
82
82
  width = -1,
83
83
  height = -1,
84
- imprint = "",
85
- renderMethod = "append",
84
+ imprint = '',
85
+ renderMethod = 'append',
86
86
  defaultProps = new FrameProps(),
87
87
  } = input
88
88
  if (value instanceof Frame) {
89
89
  value = value.value
90
90
  }
91
91
  if (!typeOf(Array)(value)) {
92
- throw new TypeError([
93
- "Frame constructor allows only string[] for rows or string[][] for rows with columns",
94
- "Provided value:", JSON.stringify(value, null, 2),
95
- ].join("\n"))
92
+ throw new TypeError(
93
+ [
94
+ 'Frame constructor allows only string[] for rows or string[][] for rows with columns',
95
+ 'Provided value:',
96
+ JSON.stringify(value, null, 2),
97
+ ].join('\n'),
98
+ )
96
99
  }
97
- value = value.map(row => {
100
+ value = value.map((row) => {
98
101
  if (typeOf(Array)(row)) {
99
102
  return row.map(String)
100
103
  }
101
104
  return [row]
102
105
  })
103
- this.value = value.map(v => Array.isArray(v) ? v : [v])
106
+ this.value = value.map((v) => (Array.isArray(v) ? v : [v]))
104
107
  this.imprint = String(imprint)
105
108
  this.width = width
106
109
  this.height = height
@@ -130,56 +133,51 @@ export default class Frame {
130
133
  * @returns {string} The rendered frame as a string.
131
134
  */
132
135
  render(options = {}) {
133
- const {
134
- method = this.renderMethod,
135
- props = this.defaultProps,
136
- } = options
137
- let rows = this.value.map(row => {
136
+ const { method = this.renderMethod, props = this.defaultProps } = options
137
+ let rows = this.value.map((row) => {
138
138
  if (typeOf(Array)(row)) {
139
- row = row.join("")
139
+ row = row.join('')
140
140
  }
141
141
  return row
142
142
  })
143
- let spacesOn = ""
143
+ let spacesOn = ''
144
144
  if (Frame.BOF === rows[0]) {
145
145
  rows = rows.slice(1)
146
- spacesOn = "top"
147
- }
148
- else if (Frame.BOF === rows[rows.length - 1]) {
146
+ spacesOn = 'top'
147
+ } else if (Frame.BOF === rows[rows.length - 1]) {
149
148
  rows = rows.slice(0, -1)
150
- spacesOn = "bottom"
149
+ spacesOn = 'bottom'
151
150
  }
152
151
  if (this.height >= 0 && rows.length > this.height) {
153
152
  rows = rows.slice(0, this.height)
154
153
  }
155
154
  if (this.width >= 0 && rows.length > 0) {
156
- rows = rows.map(row => {
155
+ rows = rows.map((row) => {
157
156
  if (row.length > this.width) {
158
157
  row = row.slice(0, this.width)
159
158
  }
160
159
  return row
161
160
  })
162
161
  }
163
- let carret = ""
162
+ let carret = ''
164
163
  if (method === Frame.RenderMethod.REPLACE) {
165
164
  const printedRows = rows.map(
166
- row => row + " ".repeat(Math.max(0, this.width - this.lengthOf(row)))
165
+ (row) => row + ' '.repeat(Math.max(0, this.width - this.lengthOf(row))),
167
166
  )
168
167
  const left = this.height >= 0 ? this.height - rows.length : 0
169
168
  const eraser = []
170
- for (let i = 0; i < left; i++) eraser.push(" ".repeat(this.width))
169
+ for (let i = 0; i < left; i++) eraser.push(' '.repeat(this.width))
171
170
  carret = Frame.BOF
172
- if ("bottom" === spacesOn) {
171
+ if ('bottom' === spacesOn) {
173
172
  rows = left > 0 ? [...printedRows, ...eraser] : []
174
173
  } else {
175
174
  rows = left > 0 ? [...eraser, ...printedRows] : []
176
175
  }
177
- }
178
- else if (method === Frame.RenderMethod.APPEND) {
179
- rows = rows.map(row => {
176
+ } else if (method === Frame.RenderMethod.APPEND) {
177
+ rows = rows.map((row) => {
180
178
  const used = this.lengthOf(row)
181
179
  const left = Math.max(0, this.width - used)
182
- row = row + " ".repeat(left)
180
+ row = row + ' '.repeat(left)
183
181
  if (row.length > this.width) row = row.slice(0, this.width)
184
182
  return row
185
183
  })
@@ -190,54 +188,48 @@ export default class Frame {
190
188
  carret = Frame.BOF
191
189
  const left = this.height >= 0 ? this.height - rows.length : 0
192
190
  const eraser = []
193
- for (let i = 0; i < left; i++) eraser.push("")
194
- if (spacesOn === "top") {
191
+ for (let i = 0; i < left; i++) eraser.push('')
192
+ if (spacesOn === 'top') {
195
193
  rows = left > 0 ? [...eraser, ...rows] : []
196
- }
197
- else if (spacesOn === "bottom") {
194
+ } else if (spacesOn === 'bottom') {
198
195
  rows = left > 0 ? [...rows, ...eraser] : []
199
196
  }
200
197
  }
201
- }
202
- else if (method === Frame.RenderMethod.VISIBLE) {
198
+ } else if (method === Frame.RenderMethod.VISIBLE) {
203
199
  // Move cursor up # lines (Math.max(0, Math.min(rows.length, height))) before rendering
204
200
  if (spacesOn) {
205
- let moveUpLines = Math.max(0, Math.min(rows.length, this.height >= 0 ? this.height : rows.length))
201
+ let moveUpLines = Math.max(
202
+ 0,
203
+ Math.min(rows.length, this.height >= 0 ? this.height : rows.length),
204
+ )
206
205
  if (moveUpLines > 0) {
207
206
  --moveUpLines
208
207
  }
209
208
  carret = Frame.cursorUp(moveUpLines)
210
209
  }
211
- rows = rows.map(
212
- row => Frame.clearLine("\r") + row
213
- )
214
- }
215
- else {
210
+ rows = rows.map((row) => Frame.clearLine('\r') + row)
211
+ } else {
216
212
  if (spacesOn) {
217
213
  carret = Frame.BOF
218
214
  const left = this.height >= 0 ? this.height - rows.length : 0
219
215
  const eraser = []
220
- for (let i = 0; i < left; i++) eraser.push("")
221
- if (spacesOn === "top") {
216
+ for (let i = 0; i < left; i++) eraser.push('')
217
+ if (spacesOn === 'top') {
222
218
  rows = left > 0 ? [...eraser, ...rows] : []
223
- }
224
- else if (spacesOn === "bottom") {
219
+ } else if (spacesOn === 'bottom') {
225
220
  rows = left > 0 ? [...rows, ...eraser] : []
226
221
  }
227
222
  }
228
223
  }
229
- if ("bottom" === spacesOn) {
230
- this.imprint = rows.join("\n") + carret
224
+ if ('bottom' === spacesOn) {
225
+ this.imprint = rows.join('\n') + carret
231
226
  } else {
232
- this.imprint = carret + rows.join("\n")
227
+ this.imprint = carret + rows.join('\n')
233
228
  }
234
229
  return this.imprint
235
230
  }
236
231
  #render1(options = {}) {
237
- const {
238
- method = this.renderMethod,
239
- props = this.defaultProps,
240
- } = options
232
+ const { method = this.renderMethod, props = this.defaultProps } = options
241
233
 
242
234
  /**
243
235
  * Helper to apply CLI style codes.
@@ -247,7 +239,7 @@ export default class Frame {
247
239
  */
248
240
  function applyStyle(str, style = {}) {
249
241
  let out = str
250
- let prefix = ""
242
+ let prefix = ''
251
243
  let suffix = Frame.RESET
252
244
 
253
245
  if (style.bold) prefix += Frame.BOLD
@@ -260,20 +252,34 @@ export default class Frame {
260
252
  const color = style.color
261
253
  if (/^#[0-9a-f]{3,6}$/i.test(color)) {
262
254
  // 24-bit color
263
- const hex = color.replace("#", "")
264
- const rgb = hex.length === 3
265
- ? [0, 1, 2].map(i => parseInt(hex[i] + hex[i], 16))
266
- : [0, 2, 4].map(i => parseInt(hex.slice(i, i + 2), 16))
255
+ const hex = color.replace('#', '')
256
+ const rgb =
257
+ hex.length === 3
258
+ ? [0, 1, 2].map((i) => parseInt(hex[i] + hex[i], 16))
259
+ : [0, 2, 4].map((i) => parseInt(hex.slice(i, i + 2), 16))
267
260
  prefix += `\x1b[38;2;${rgb[0]};${rgb[1]};${rgb[2]}m`
268
261
  } else if (/^\d+$/.test(color)) {
269
262
  prefix += `\x1b[38;5;${color}m`
270
263
  } else {
271
264
  // Named color, map to 8-bit
272
265
  const map = {
273
- black: 30, red: 31, green: 32, yellow: 33, blue: 34,
274
- magenta: 35, cyan: 36, white: 37, gray: 90, grey: 90,
275
- brightRed: 91, brightGreen: 92, brightYellow: 93, brightBlue: 94,
276
- brightMagenta: 95, brightCyan: 96, brightWhite: 97,
266
+ black: 30,
267
+ red: 31,
268
+ green: 32,
269
+ yellow: 33,
270
+ blue: 34,
271
+ magenta: 35,
272
+ cyan: 36,
273
+ white: 37,
274
+ gray: 90,
275
+ grey: 90,
276
+ brightRed: 91,
277
+ brightGreen: 92,
278
+ brightYellow: 93,
279
+ brightBlue: 94,
280
+ brightMagenta: 95,
281
+ brightCyan: 96,
282
+ brightWhite: 97,
277
283
  }
278
284
  if (map[color]) prefix += `\x1b[${map[color]}m`
279
285
  }
@@ -282,19 +288,33 @@ export default class Frame {
282
288
  if (style.bgColor) {
283
289
  const color = style.bgColor
284
290
  if (/^#[0-9a-f]{3,6}$/i.test(color)) {
285
- const hex = color.replace("#", "")
286
- const rgb = hex.length === 3
287
- ? [0, 1, 2].map(i => parseInt(hex[i] + hex[i], 16))
288
- : [0, 2, 4].map(i => parseInt(hex.slice(i, i + 2), 16))
291
+ const hex = color.replace('#', '')
292
+ const rgb =
293
+ hex.length === 3
294
+ ? [0, 1, 2].map((i) => parseInt(hex[i] + hex[i], 16))
295
+ : [0, 2, 4].map((i) => parseInt(hex.slice(i, i + 2), 16))
289
296
  prefix += `\x1b[48;2;${rgb[0]};${rgb[1]};${rgb[2]}m`
290
297
  } else if (/^\d+$/.test(color)) {
291
298
  prefix += `\x1b[48;5;${color}m`
292
299
  } else {
293
300
  const map = {
294
- black: 40, red: 41, green: 42, yellow: 43, blue: 44,
295
- magenta: 45, cyan: 46, white: 47, gray: 100, grey: 100,
296
- brightRed: 101, brightGreen: 102, brightYellow: 103, brightBlue: 104,
297
- brightMagenta: 105, brightCyan: 106, brightWhite: 107,
301
+ black: 40,
302
+ red: 41,
303
+ green: 42,
304
+ yellow: 43,
305
+ blue: 44,
306
+ magenta: 45,
307
+ cyan: 46,
308
+ white: 47,
309
+ gray: 100,
310
+ grey: 100,
311
+ brightRed: 101,
312
+ brightGreen: 102,
313
+ brightYellow: 103,
314
+ brightBlue: 104,
315
+ brightMagenta: 105,
316
+ brightCyan: 106,
317
+ brightWhite: 107,
298
318
  }
299
319
  if (map[color]) prefix += `\x1b[${map[color]}m`
300
320
  }
@@ -322,18 +342,18 @@ export default class Frame {
322
342
  if (cell.length === 2 && typeOf(Object)(cell[1])) {
323
343
  return { text: String(cell[0]), style: mergeStyles(inherited, cell[1]) }
324
344
  }
325
- return { text: cell.map(c => parseCell(c, inherited).text).join(""), style: inherited }
345
+ return { text: cell.map((c) => parseCell(c, inherited).text).join(''), style: inherited }
326
346
  }
327
347
  if (typeOf(Object)(cell)) {
328
- return { text: "", style: mergeStyles(inherited, cell) }
348
+ return { text: '', style: mergeStyles(inherited, cell) }
329
349
  }
330
- if (typeof cell === "string" && cell.startsWith("<") && cell.endsWith(">")) {
350
+ if (typeof cell === 'string' && cell.startsWith('<') && cell.endsWith('>')) {
331
351
  // Simple XML-like tag parser for <b>, <i>, <u>, <s>, <fg=...>, <bg=...>
332
352
  let text = cell
333
353
  let style = { ...inherited }
334
354
  const tagPattern = /<([bius]|fg|bg)(?:=([#\w\d]+))?>|<\/([bius]|fg|bg)>/gi
335
355
  let stack = []
336
- let result = ""
356
+ let result = ''
337
357
  let lastIndex = 0
338
358
  let m
339
359
  while ((m = tagPattern.exec(cell))) {
@@ -343,14 +363,26 @@ export default class Frame {
343
363
  // Opening tag
344
364
  let tag = m[1]
345
365
  let val = m[2]
346
- let newStyle = { ...stack.length ? stack[stack.length - 1] : style }
366
+ let newStyle = { ...(stack.length ? stack[stack.length - 1] : style) }
347
367
  switch (tag) {
348
- case "b": newStyle.bold = true; break
349
- case "i": newStyle.italic = true; break
350
- case "u": newStyle.underline = true; break
351
- case "s": newStyle.strikethrough = true; break
352
- case "fg": newStyle.color = val; break
353
- case "bg": newStyle.bgColor = val; break
368
+ case 'b':
369
+ newStyle.bold = true
370
+ break
371
+ case 'i':
372
+ newStyle.italic = true
373
+ break
374
+ case 'u':
375
+ newStyle.underline = true
376
+ break
377
+ case 's':
378
+ newStyle.strikethrough = true
379
+ break
380
+ case 'fg':
381
+ newStyle.color = val
382
+ break
383
+ case 'bg':
384
+ newStyle.bgColor = val
385
+ break
354
386
  }
355
387
  stack.push(newStyle)
356
388
  } else if (m[3]) {
@@ -367,13 +399,17 @@ export default class Frame {
367
399
 
368
400
  // Determine frame-level style
369
401
  let frameStyle = {}
370
- if (typeOf(Array)(this.value) && this.value.length && typeOf(Object)(this.value[this.value.length - 1])) {
402
+ if (
403
+ typeOf(Array)(this.value) &&
404
+ this.value.length &&
405
+ typeOf(Object)(this.value[this.value.length - 1])
406
+ ) {
371
407
  frameStyle = this.value[this.value.length - 1]
372
408
  }
373
409
 
374
410
  let rows = this.value
375
- .filter(row => !(typeOf(Object)(row) && !typeOf(Array)(row)))
376
- .map(row => {
411
+ .filter((row) => !(typeOf(Object)(row) && !typeOf(Array)(row)))
412
+ .map((row) => {
377
413
  let rowStyle = frameStyle
378
414
  let cells = row
379
415
  if (typeOf(Array)(row) && row.length && typeOf(Object)(row[row.length - 1])) {
@@ -381,32 +417,27 @@ export default class Frame {
381
417
  cells = row.slice(0, -1)
382
418
  }
383
419
  if (!typeOf(Array)(cells)) cells = [cells]
384
- let styled = cells.map(cell => {
420
+ let styled = cells.map((cell) => {
385
421
  const { text, style } = parseCell(cell, mergeStyles(props, rowStyle))
386
422
  return applyStyle(text, style)
387
423
  })
388
- return styled.join("")
424
+ return styled.join('')
389
425
  })
390
426
 
391
427
  if (method === FrameRenderMethod.REPLACE) {
392
- let emptyRows = rows.map(row => " ".repeat(this.lengthOf(row)))
428
+ let emptyRows = rows.map((row) => ' '.repeat(this.lengthOf(row)))
393
429
  if (rows.length > this.height) {
394
430
  emptyRows = emptyRows.slice(0, this.height)
395
431
  rows = rows.slice(0, this.height)
396
432
  }
397
- rows = [
398
- ...emptyRows,
399
- Frame.BOF,
400
- ...rows,
401
- ]
402
- }
403
- else if (method === FrameRenderMethod.APPEND) {
404
- rows = rows.map(row => {
433
+ rows = [...emptyRows, Frame.BOF, ...rows]
434
+ } else if (method === FrameRenderMethod.APPEND) {
435
+ rows = rows.map((row) => {
405
436
  const used = this.lengthOf(row)
406
437
  const left = this.width - used
407
- row = row + " ".repeat(Math.max(0, left))
438
+ row = row + ' '.repeat(Math.max(0, left))
408
439
  if (stringWidth(row) > this.width) {
409
- let acc = ""
440
+ let acc = ''
410
441
  let w = 0
411
442
  for (let ch of row) {
412
443
  let chW = stringWidth(ch)
@@ -421,28 +452,23 @@ export default class Frame {
421
452
  if (rows.length > this.height) {
422
453
  rows = rows.slice(0, this.height)
423
454
  }
424
- }
425
- else if (method === FrameRenderMethod.VISIBLE) {
426
- const moveUpLines = Math.max(0, Math.min(rows.length, this.height >= 0 ? this.height : rows.length))
427
- rows = [
428
- `\x1b[${moveUpLines}A${Frame.BOF}`,
429
- ...rows,
430
- ]
455
+ } else if (method === FrameRenderMethod.VISIBLE) {
456
+ const moveUpLines = Math.max(
457
+ 0,
458
+ Math.min(rows.length, this.height >= 0 ? this.height : rows.length),
459
+ )
460
+ rows = [`\x1b[${moveUpLines}A${Frame.BOF}`, ...rows]
431
461
  if (rows.length > this.height && this.height >= 0) {
432
462
  rows = rows.slice(0, this.height + 1) // +1 for the cursor move line
433
463
  }
434
- }
435
- else {
464
+ } else {
436
465
  if (rows.length > this.height) {
437
466
  rows = rows.slice(0, this.height)
438
467
  }
439
- rows = [
440
- Frame.BOF,
441
- ...rows,
442
- ]
468
+ rows = [Frame.BOF, ...rows]
443
469
  }
444
470
 
445
- this.imprint = rows.join("\n")
471
+ this.imprint = rows.join('\n')
446
472
  return this.imprint
447
473
  }
448
474
  /**
@@ -458,9 +484,7 @@ export default class Frame {
458
484
  * @returns {Frame} A new Frame with transformed values.
459
485
  */
460
486
  transform(fn) {
461
- const value = this.value.map(
462
- row => row.map(fn)
463
- )
487
+ const value = this.value.map((row) => row.map(fn))
464
488
  return new Frame({ ...this, value })
465
489
  }
466
490
  /**
@@ -494,7 +518,7 @@ export default class Frame {
494
518
  static from(input) {
495
519
  if (input instanceof Frame) return input
496
520
  if (input?.value instanceof Frame) return new Frame(to(Object)(input.value))
497
- if ("string" === typeof input) input = [input]
521
+ if ('string' === typeof input) input = [input]
498
522
  if (Array.isArray(input)) return new Frame({ value: input })
499
523
  return new Frame(input)
500
524
  }
@@ -508,12 +532,11 @@ export default class Frame {
508
532
  */
509
533
  static spaces(options = {}) {
510
534
  const { cols = [], padding = 1, aligns = [] } = options
511
- return (row) => (
535
+ return (row) =>
512
536
  row.map((str, i) => {
513
- const pad = " ".repeat(cols[i] - str.length + padding)
514
- return aligns[i] === "r" ? pad + str : str + pad
537
+ const pad = ' '.repeat(cols[i] - str.length + padding)
538
+ return aligns[i] === 'r' ? pad + str : str + pad
515
539
  })
516
- )
517
540
  }
518
541
  /**
519
542
  *
@@ -521,9 +544,9 @@ export default class Frame {
521
544
  * @returns {(v) => number[]}
522
545
  */
523
546
  static weight(arr) {
524
- return (Fn = v => v) => {
547
+ return (Fn = (v) => v) => {
525
548
  const cols = []
526
- arr.forEach(m => {
549
+ arr.forEach((m) => {
527
550
  Fn(m).forEach((str, i) => {
528
551
  if (undefined === cols[i]) cols[i] = 0
529
552
  cols[i] = Math.max(String(str).length, cols[i])
@@ -542,18 +565,13 @@ export default class Frame {
542
565
  * @returns {(arr: []) => string[][]}
543
566
  */
544
567
  static table(options = {}) {
545
- const {
546
- fn = v => v,
547
- cols: initialCols = [],
548
- padding = 1,
549
- aligns = []
550
- } = options
568
+ const { fn = (v) => v, cols: initialCols = [], padding = 1, aligns = [] } = options
551
569
  return (arr) => {
552
570
  let cols = initialCols
553
571
  if (empty(cols)) {
554
572
  cols = Frame.weight(arr)(fn)
555
573
  }
556
- return arr.map(row => Frame.spaces({ cols, padding, aligns })(row))
574
+ return arr.map((row) => Frame.spaces({ cols, padding, aligns })(row))
557
575
  }
558
576
  }
559
577
  /**
@@ -577,7 +595,7 @@ export default class Frame {
577
595
  * @param {string} [str="\r"] - String to append after clearing.
578
596
  * @returns {string} ANSI escape code for line clearing followed by the string.
579
597
  */
580
- static clearLine(str = "\r") {
598
+ static clearLine(str = '\r') {
581
599
  return Frame.CLEAR_LINE + str
582
600
  }
583
601
  /**
@@ -587,5 +605,4 @@ export default class Frame {
587
605
  static clearScreen() {
588
606
  return '\x1b[2J\x1b[0;0H'
589
607
  }
590
-
591
- }
608
+ }
@@ -1,4 +1,4 @@
1
- import { typeOf, ObjectWithAlias } from "@nan0web/types"
1
+ import { typeOf, ObjectWithAlias } from '@nan0web/types'
2
2
 
3
3
  /**
4
4
  * Represents default styling properties for Frame rendering.
@@ -7,7 +7,7 @@ import { typeOf, ObjectWithAlias } from "@nan0web/types"
7
7
  * If you want to apply different props to multiple values, you can use an object with the props.
8
8
  * If you want to apply props to a single value, you can use a string with the props in XML format.
9
9
  * Parser checks every atom for its beginning and end and if it's a tag, it applies the props to the value.
10
- *
10
+ *
11
11
  * @example
12
12
  * const defaultProps = new FrameProps({
13
13
  * color: "red",
@@ -40,34 +40,34 @@ import { typeOf, ObjectWithAlias } from "@nan0web/types"
40
40
  * const defaultProps = new FrameProps(rows)
41
41
  */
42
42
  class FrameProps extends ObjectWithAlias {
43
- /**
43
+ /**
44
44
  * Property aliases for shorthand notation.
45
45
  * @type {Record<string, string>}
46
46
  */
47
47
  static ALIAS = {
48
- fg: "color",
49
- bg: "bgColor",
50
- b: "bold",
51
- i: "italic",
52
- u: "underline",
53
- s: "strikethrough",
48
+ fg: 'color',
49
+ bg: 'bgColor',
50
+ b: 'bold',
51
+ i: 'italic',
52
+ u: 'underline',
53
+ s: 'strikethrough',
54
54
  }
55
-
55
+
56
56
  /** @type {string} Text color */
57
- color = ""
58
-
57
+ color = ''
58
+
59
59
  /** @type {string} Background color */
60
- bgColor = ""
61
-
60
+ bgColor = ''
61
+
62
62
  /** @type {boolean} Bold text flag */
63
63
  bold = false
64
-
64
+
65
65
  /** @type {boolean} Italic text flag */
66
66
  italic = false
67
-
67
+
68
68
  /** @type {boolean} Underline text flag */
69
69
  underline = false
70
-
70
+
71
71
  /** @type {boolean} Strikethrough text flag */
72
72
  strikethrough = false
73
73
 
@@ -83,8 +83,8 @@ class FrameProps extends ObjectWithAlias {
83
83
  constructor(props = {}) {
84
84
  super()
85
85
  const {
86
- color = "",
87
- bgColor = "",
86
+ color = '',
87
+ bgColor = '',
88
88
  bold = false,
89
89
  italic = false,
90
90
  underline = false,
@@ -99,4 +99,4 @@ class FrameProps extends ObjectWithAlias {
99
99
  }
100
100
  }
101
101
 
102
- export default FrameProps
102
+ export default FrameProps