@nan0web/ui 1.12.2 → 3.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 +18 -355
- package/package.json +36 -22
- package/src/Component/index.js +1 -5
- package/src/Model/Element.js +183 -0
- package/src/Model/index.js +2 -2
- package/src/Theme/AppTheme.js +19 -0
- package/src/Theme/CustomTheme.js +32 -0
- package/src/Theme/DarkLightTheme.js +34 -0
- package/src/Theme/Theme.js +25 -0
- package/src/Theme/atoms/Avatar.js +20 -0
- package/src/Theme/atoms/Badge.js +28 -0
- package/src/Theme/atoms/Button.js +88 -0
- package/src/Theme/atoms/Checkbox.js +26 -0
- package/src/Theme/atoms/Input.js +28 -0
- package/src/Theme/atoms/Radio.js +26 -0
- package/src/Theme/atoms/Select.js +16 -0
- package/src/Theme/atoms/TextArea.js +17 -0
- package/src/Theme/atoms/Typography.js +26 -0
- package/src/Theme/atoms/index.js +11 -0
- package/src/Theme/createTheme.js +22 -0
- package/src/Theme/index.js +20 -0
- package/src/Theme/molecules/Card.js +24 -0
- package/src/Theme/molecules/index.js +3 -0
- package/src/Theme/organisms/Modal.js +24 -0
- package/src/Theme/organisms/index.js +3 -0
- package/src/Theme/presets/HighContrastTheme.js +65 -0
- package/src/Theme/presets/NightTheme.js +66 -0
- package/src/Theme/presets/index.js +4 -0
- package/src/Theme/tokens.js +115 -0
- package/src/core/InputAdapter.js +1 -2
- package/src/core/Intent.js +22 -8
- package/src/core/Message/Message.js +3 -0
- package/src/core/OutputAdapter.js +9 -13
- package/src/core/index.js +7 -4
- package/src/core/resolvePositionalArgs.js +51 -0
- package/src/domain/Content.js +5 -5
- package/src/domain/Document.js +1 -1
- package/src/domain/HeroModel.js +1 -1
- package/src/domain/ModelAsApp.js +310 -20
- package/src/domain/ModelAsApp.story.js +117 -0
- package/src/domain/app/GalleryCommand.js +9 -8
- package/src/domain/app/{GalleryRenderIntent.js → GalleryRenderCommand.js} +20 -20
- package/src/domain/app/IntentAuditor.js +53 -0
- package/src/domain/app/JsIntentAuditor.js +145 -0
- package/src/domain/app/PyIntentAuditor.js +144 -0
- package/src/domain/app/SnapshotAuditor.js +82 -86
- package/src/domain/app/SnapshotRunner.js +1 -1
- package/src/domain/app/UIApp.js +12 -21
- package/src/domain/components/ShellModel.js +2 -2
- package/src/index.js +38 -10
- package/src/inspect.js +4 -0
- package/src/testing/SnapshotRunner.js +2 -1
- package/src/utils/format.js +21 -0
- package/src/utils/processI18n.js +27 -0
- package/src/utils/resolveContext.js +79 -0
- package/types/Component/index.d.ts +1 -5
- package/types/Model/Element.d.ts +87 -0
- package/types/Model/index.d.ts +2 -2
- package/types/Theme/AppTheme.d.ts +14 -0
- package/types/Theme/CustomTheme.d.ts +21 -0
- package/types/Theme/DarkLightTheme.d.ts +16 -0
- package/types/Theme/Theme.d.ts +18 -0
- package/types/Theme/atoms/Avatar.d.ts +14 -0
- package/types/Theme/atoms/Badge.d.ts +22 -0
- package/types/Theme/atoms/Button.d.ts +144 -0
- package/types/Theme/atoms/Checkbox.d.ts +20 -0
- package/types/Theme/atoms/Input.d.ts +22 -0
- package/types/Theme/atoms/Radio.d.ts +20 -0
- package/types/Theme/atoms/Select.d.ts +15 -0
- package/types/Theme/atoms/TextArea.d.ts +17 -0
- package/types/Theme/atoms/Typography.d.ts +47 -0
- package/types/Theme/atoms/index.d.ts +10 -0
- package/types/Theme/createTheme.d.ts +7 -0
- package/types/Theme/index.d.ts +10 -0
- package/types/Theme/molecules/Card.d.ts +18 -0
- package/types/Theme/molecules/index.d.ts +2 -0
- package/types/Theme/organisms/Modal.d.ts +18 -0
- package/types/Theme/organisms/index.d.ts +2 -0
- package/types/Theme/presets/HighContrastTheme.d.ts +2 -0
- package/types/Theme/presets/NightTheme.d.ts +2 -0
- package/types/Theme/presets/index.d.ts +3 -0
- package/types/Theme/tokens.d.ts +119 -0
- package/types/core/Intent.d.ts +10 -7
- package/types/core/Message/Message.d.ts +3 -0
- package/types/core/OutputAdapter.d.ts +2 -4
- package/types/core/index.d.ts +5 -2
- package/types/core/resolvePositionalArgs.d.ts +24 -0
- package/types/docs/README.md.d.ts +1 -0
- package/types/domain/Content.d.ts +2 -2
- package/types/domain/Document.d.ts +4 -3
- package/types/domain/FooterModel.d.ts +2 -1
- package/types/domain/HeroModel.d.ts +2 -2
- package/types/domain/ModelAsApp.d.ts +49 -5
- package/types/domain/ModelAsApp.story.d.ts +1 -0
- package/types/domain/app/GalleryCommand.d.ts +6 -37
- package/types/domain/app/GalleryRenderCommand.d.ts +27 -0
- package/types/domain/app/IntentAuditor.d.ts +23 -0
- package/types/domain/app/JsIntentAuditor.d.ts +22 -0
- package/types/domain/app/PyIntentAuditor.d.ts +22 -0
- package/types/domain/app/SnapshotAuditor.d.ts +34 -25
- package/types/domain/app/SnapshotRunner.d.ts +2 -2
- package/types/domain/app/UIApp.d.ts +14 -11
- package/types/domain/components/ShellModel.d.ts +1 -5
- package/types/index.d.ts +10 -10
- package/types/inspect.d.ts +4 -0
- package/types/testing/verifySnapshot.d.ts +1 -1
- package/types/utils/format.d.ts +5 -0
- package/types/utils/processI18n.d.ts +8 -0
- package/types/utils/resolveContext.d.ts +21 -0
- package/src/App/Command/DepsCommand.js +0 -24
- package/src/App/Core/CoreApp.js +0 -125
- package/src/App/Core/UI.js +0 -63
- package/src/App/Core/Widget.js +0 -61
- package/src/App/Core/index.js +0 -11
- package/src/App/Scenario.js +0 -45
- package/src/App/User/Command/Message.js +0 -3
- package/src/App/User/Command/index.js +0 -5
- package/src/App/User/UserApp.js +0 -85
- package/src/App/User/UserUI.js +0 -20
- package/src/App/User/index.js +0 -9
- package/src/App/index.js +0 -14
- package/src/Component/Process/Input.js +0 -63
- package/src/Component/Process/Process.js +0 -24
- package/src/Component/Process/index.js +0 -5
- package/src/Component/Welcome/Input.js +0 -48
- package/src/Component/Welcome/Welcome.js +0 -22
- package/src/Component/Welcome/index.js +0 -5
- package/src/Frame/Frame.js +0 -608
- package/src/Frame/Props.js +0 -96
- package/src/StdIn.js +0 -100
- package/src/StdOut.js +0 -95
- package/src/View/RenderOptions.js +0 -48
- package/src/View/View.js +0 -306
- package/src/core/Message/index.js +0 -6
- package/types/App/Command/DepsCommand.d.ts +0 -14
- package/types/App/Core/CoreApp.d.ts +0 -70
- package/types/App/Core/UI.d.ts +0 -38
- package/types/App/Core/Widget.d.ts +0 -39
- package/types/App/Core/index.d.ts +0 -10
- package/types/App/Scenario.d.ts +0 -26
- package/types/App/User/Command/Message.d.ts +0 -2
- package/types/App/User/Command/index.d.ts +0 -3
- package/types/App/User/UserApp.d.ts +0 -41
- package/types/App/User/UserUI.d.ts +0 -9
- package/types/App/User/index.d.ts +0 -8
- package/types/App/index.d.ts +0 -12
- package/types/Component/Process/Input.d.ts +0 -48
- package/types/Component/Process/Process.d.ts +0 -13
- package/types/Component/Process/index.d.ts +0 -4
- package/types/Component/Welcome/Input.d.ts +0 -34
- package/types/Component/Welcome/Welcome.d.ts +0 -13
- package/types/Component/Welcome/index.d.ts +0 -4
- package/types/Frame/Frame.d.ts +0 -186
- package/types/Frame/Props.d.ts +0 -77
- package/types/StdIn.d.ts +0 -62
- package/types/StdOut.d.ts +0 -52
- package/types/View/RenderOptions.d.ts +0 -29
- package/types/View/View.d.ts +0 -124
- package/types/core/Message/index.d.ts +0 -4
- package/types/domain/app/GalleryRenderIntent.d.ts +0 -31
package/src/StdIn.js
DELETED
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import EventProcessor from '@nan0web/event/oop'
|
|
2
|
-
import { typeOf } from '@nan0web/types'
|
|
3
|
-
import { UiMessage } from './core/index.js'
|
|
4
|
-
|
|
5
|
-
class Processor extends EventProcessor {}
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Handles standard input stream with message buffering.
|
|
9
|
-
*/
|
|
10
|
-
export default class StdIn extends EventProcessor {
|
|
11
|
-
/** @type {number} Read interval in milliseconds */
|
|
12
|
-
static READ_INTERVAL = 99
|
|
13
|
-
|
|
14
|
-
/** @type {string[]} Messages to ignore */
|
|
15
|
-
static IGNORE_MESSAGES = ['', 'undefined']
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Creates a new StdIn instance.
|
|
19
|
-
* @param {object} props - StdIn properties
|
|
20
|
-
* @param {Processor} [props.processor] - Input processor
|
|
21
|
-
* @param {UiMessage[]} [props.stream=[]] - Initial input stream
|
|
22
|
-
*/
|
|
23
|
-
constructor(props = {}) {
|
|
24
|
-
super()
|
|
25
|
-
const { processor = new Processor(), stream = [] } = props
|
|
26
|
-
/** @type {Processor} Input processor */
|
|
27
|
-
this.processor = processor
|
|
28
|
-
/** @type {UiMessage[]} Input message buffer */
|
|
29
|
-
this.stream = stream
|
|
30
|
-
this.processor?.on('data', (data) => {
|
|
31
|
-
this.write(data)
|
|
32
|
-
})
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Checks if there are messages waiting in the input stream.
|
|
37
|
-
* @returns {boolean} True if waiting messages, false otherwise
|
|
38
|
-
*/
|
|
39
|
-
get waiting() {
|
|
40
|
-
return this.stream.length > 0
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Checks if the input stream has ended (no messages left).
|
|
45
|
-
* @returns {boolean} True if no messages left, false otherwise
|
|
46
|
-
*/
|
|
47
|
-
get ended() {
|
|
48
|
-
return 0 === this.stream.length
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Reads a message from the input stream.
|
|
53
|
-
* Waits until messages are available if stream is empty.
|
|
54
|
-
* @returns {Promise<UiMessage>} Next input message
|
|
55
|
-
*/
|
|
56
|
-
async read() {
|
|
57
|
-
while (this.ended) {
|
|
58
|
-
await new Promise((resolve) => setTimeout(resolve, StdIn.READ_INTERVAL))
|
|
59
|
-
}
|
|
60
|
-
return this.stream.shift() ?? new UiMessage()
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Writes a message to the input stream.
|
|
65
|
-
* @param {string} message - Message to write
|
|
66
|
-
* @returns {boolean} True if message accepted, False if ignored
|
|
67
|
-
*/
|
|
68
|
-
write(message) {
|
|
69
|
-
// this.processor?.emit("data", message)
|
|
70
|
-
const text = String(message)
|
|
71
|
-
if (StdIn.IGNORE_MESSAGES.includes(text)) {
|
|
72
|
-
return false
|
|
73
|
-
}
|
|
74
|
-
this.stream.push(this.decode(text))
|
|
75
|
-
return true
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Decodes a message into an UiMessage instance.
|
|
80
|
-
* @param {UiMessage | string[] | any} message - Message to decode
|
|
81
|
-
* @returns {UiMessage} Decoded input message
|
|
82
|
-
*/
|
|
83
|
-
decode(message) {
|
|
84
|
-
if (message instanceof UiMessage) return message
|
|
85
|
-
if (Array.isArray(message) && message.every(typeOf(String))) {
|
|
86
|
-
return new UiMessage({ value: message })
|
|
87
|
-
}
|
|
88
|
-
return new UiMessage(message)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* Creates a StdIn instance from the given input.
|
|
93
|
-
* @param {StdIn|object} input - The input to create from
|
|
94
|
-
* @returns {StdIn} A StdIn instance
|
|
95
|
-
*/
|
|
96
|
-
static from(input) {
|
|
97
|
-
if (input instanceof StdIn) return input
|
|
98
|
-
return new this(input)
|
|
99
|
-
}
|
|
100
|
-
}
|
package/src/StdOut.js
DELETED
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { typeOf } from '@nan0web/types'
|
|
2
|
-
import EventProcessor from '@nan0web/event/oop'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Handles standard output stream with formatting capabilities.
|
|
6
|
-
*/
|
|
7
|
-
class StdOut extends EventProcessor {
|
|
8
|
-
/** @type {string} End of line character */
|
|
9
|
-
static EOL = '\n'
|
|
10
|
-
|
|
11
|
-
/** @type {string} Beginning of line character */
|
|
12
|
-
static BOL = '\r'
|
|
13
|
-
|
|
14
|
-
/** @type {string} Reset formatting escape code */
|
|
15
|
-
static RESET = '\x1b[0m'
|
|
16
|
-
|
|
17
|
-
/** @type {string} Clear screen escape code */
|
|
18
|
-
static CLEAR = '\x1b[2J\x1b[H'
|
|
19
|
-
|
|
20
|
-
/** @type {object} Color escape codes */
|
|
21
|
-
static COLORS = {
|
|
22
|
-
red: '\x1b[31m',
|
|
23
|
-
green: '\x1b[32m',
|
|
24
|
-
yellow: '\x1b[33m',
|
|
25
|
-
blue: '\x1b[34m',
|
|
26
|
-
magenta: '\x1b[35m',
|
|
27
|
-
cyan: '\x1b[36m',
|
|
28
|
-
white: '\x1b[37m',
|
|
29
|
-
gray: '\x1b[90m',
|
|
30
|
-
black: '\x1b[30m',
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/** @type {Record<string, string>} Style escape codes */
|
|
34
|
-
static STYLES = {
|
|
35
|
-
dim: '\x1b[2m',
|
|
36
|
-
bold: '\x1b[1m',
|
|
37
|
-
underline: '\x1b[4m',
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* @todo define go top by rows constants.
|
|
42
|
-
*/
|
|
43
|
-
|
|
44
|
-
/** @type {string[]} Output stream buffer */
|
|
45
|
-
stream = []
|
|
46
|
-
|
|
47
|
-
/** @type {number[]} Window size [width, height] */
|
|
48
|
-
windowSize = []
|
|
49
|
-
|
|
50
|
-
/** @type {any} Output processor */
|
|
51
|
-
processor
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Creates a new StdOut instance.
|
|
55
|
-
* @param {object} props - StdOut properties
|
|
56
|
-
* @param {any} [props.processor] - Output processor
|
|
57
|
-
* @param {string[]} [props.stream=[]] - Initial output stream
|
|
58
|
-
* @param {number[]} [props.windowSize=[144, 33]] - Window size [width, height]
|
|
59
|
-
*/
|
|
60
|
-
constructor(props = {}) {
|
|
61
|
-
super()
|
|
62
|
-
const { processor, stream = [], windowSize = [144, 33] } = props
|
|
63
|
-
this.processor = processor
|
|
64
|
-
this.stream = stream
|
|
65
|
-
this.windowSize = windowSize
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Writes output to the output stream.
|
|
70
|
-
* Must be overwritten by other apps.
|
|
71
|
-
* @param {any} output - Output to write
|
|
72
|
-
* @param {Function} onError - Error handler callback
|
|
73
|
-
*/
|
|
74
|
-
write(output, onError = (v) => 1) {
|
|
75
|
-
/**
|
|
76
|
-
* @todo manage the
|
|
77
|
-
*/
|
|
78
|
-
if (typeOf(Array)(output)) {
|
|
79
|
-
output = output.join('\n')
|
|
80
|
-
}
|
|
81
|
-
this.stream.push(output)
|
|
82
|
-
this.processor?.write(output, onError)
|
|
83
|
-
this.emit('data', output)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Gets the window size.
|
|
88
|
-
* @returns {number[]} Window size [width, height]
|
|
89
|
-
*/
|
|
90
|
-
getWindowSize() {
|
|
91
|
-
return this.processor?.getWindowSize?.() ?? this.windowSize
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
export default StdOut
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import Frame from '../Frame/Frame.js'
|
|
2
|
-
|
|
3
|
-
class RenderOptions {
|
|
4
|
-
static DEFAULTS = {
|
|
5
|
-
resizeToView: false,
|
|
6
|
-
translateFrame: false,
|
|
7
|
-
render: true,
|
|
8
|
-
renderMethod: Frame.RenderMethod.VISIBLE,
|
|
9
|
-
}
|
|
10
|
-
/** @type {boolean} [false] */
|
|
11
|
-
resizeToView
|
|
12
|
-
/** @type {boolean} [false] */
|
|
13
|
-
translateFrame
|
|
14
|
-
/** @type {boolean} [true] */
|
|
15
|
-
render
|
|
16
|
-
/** @type {string} */
|
|
17
|
-
renderMethod
|
|
18
|
-
/** @type {number} */
|
|
19
|
-
width
|
|
20
|
-
/** @type {number} */
|
|
21
|
-
height
|
|
22
|
-
constructor(props = {}) {
|
|
23
|
-
const DEFAULTS = this.DEFAULTS
|
|
24
|
-
const {
|
|
25
|
-
resizeToView = DEFAULTS.resizeToView,
|
|
26
|
-
translateFrame = DEFAULTS.translateFrame,
|
|
27
|
-
render = DEFAULTS.render,
|
|
28
|
-
renderMethod = DEFAULTS.renderMethod,
|
|
29
|
-
width = 0,
|
|
30
|
-
height = 0,
|
|
31
|
-
} = props
|
|
32
|
-
this.resizeToView = resizeToView
|
|
33
|
-
this.translateFrame = translateFrame
|
|
34
|
-
this.render = render
|
|
35
|
-
this.renderMethod = renderMethod
|
|
36
|
-
this.width = width
|
|
37
|
-
this.height = height
|
|
38
|
-
}
|
|
39
|
-
get DEFAULTS() {
|
|
40
|
-
return /** @type {typeof RenderOptions} */ (this.constructor).DEFAULTS
|
|
41
|
-
}
|
|
42
|
-
static from(props = {}) {
|
|
43
|
-
if (props instanceof RenderOptions) return props
|
|
44
|
-
return new this(props)
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
export default RenderOptions
|
package/src/View/View.js
DELETED
|
@@ -1,306 +0,0 @@
|
|
|
1
|
-
import { empty, equal, typeOf } from '@nan0web/types'
|
|
2
|
-
import Frame, { FrameRenderMethod } from '../Frame/Frame.js'
|
|
3
|
-
import Locale from '../Locale.js'
|
|
4
|
-
import StdOut from '../StdOut.js'
|
|
5
|
-
import StdIn from '../StdIn.js'
|
|
6
|
-
import RenderOptions from './RenderOptions.js'
|
|
7
|
-
import UiMessage from '../core/Message/Message.js'
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* @typedef {Object} ComponentFn
|
|
11
|
-
* @property {string} name
|
|
12
|
-
* @property {(input: UiMessage) => Promise<any>} ask
|
|
13
|
-
* @property {Function} bind
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
export default class View {
|
|
17
|
-
/** @type {typeof RenderOptions} */
|
|
18
|
-
static RenderOptions = RenderOptions
|
|
19
|
-
/** @type {typeof FrameRenderMethod} */
|
|
20
|
-
static RenderMethod = Frame.RenderMethod
|
|
21
|
-
/** @type {StdIn} */
|
|
22
|
-
stdin
|
|
23
|
-
/** @type {StdOut} */
|
|
24
|
-
stdout
|
|
25
|
-
/** @type {number} */
|
|
26
|
-
startedAt
|
|
27
|
-
/** @type {Frame} */
|
|
28
|
-
frame
|
|
29
|
-
/** @type {Locale} */
|
|
30
|
-
locale
|
|
31
|
-
/** @type {Map<string, string>} */
|
|
32
|
-
vocab
|
|
33
|
-
/** @type {number[]} */
|
|
34
|
-
windowSize
|
|
35
|
-
/** @type {Map<string, ComponentFn>} */
|
|
36
|
-
components
|
|
37
|
-
/** @type {string} */
|
|
38
|
-
renderMethod
|
|
39
|
-
/**
|
|
40
|
-
* @param {object} [input]
|
|
41
|
-
* @param {StdIn} [input.stdin]
|
|
42
|
-
* @param {StdOut} [input.stdout]
|
|
43
|
-
* @param {number} [input.startedAt]
|
|
44
|
-
* @param {Frame} [input.frame]
|
|
45
|
-
* @param {Locale} [input.locale]
|
|
46
|
-
* @param {Map<string, string>} [input.vocab]
|
|
47
|
-
* @param {number[]} [input.windowSize]
|
|
48
|
-
* @param {Map<string, ComponentFn>} [input.components]
|
|
49
|
-
* @param {string} [input.renderMethod]
|
|
50
|
-
*/
|
|
51
|
-
constructor(input = {}) {
|
|
52
|
-
const {
|
|
53
|
-
stdin = new StdIn(),
|
|
54
|
-
stdout = new StdOut(),
|
|
55
|
-
startedAt = Date.now(),
|
|
56
|
-
frame = new Frame(),
|
|
57
|
-
locale = Locale.from('uk-UA'),
|
|
58
|
-
vocab = new Map(),
|
|
59
|
-
windowSize = [0, 0],
|
|
60
|
-
components = new Map(),
|
|
61
|
-
renderMethod = Frame.RenderMethod.VISIBLE,
|
|
62
|
-
} = input
|
|
63
|
-
this.stdin = stdin
|
|
64
|
-
this.stdout = stdout
|
|
65
|
-
this.startedAt = startedAt
|
|
66
|
-
this.frame = frame
|
|
67
|
-
this.locale = locale
|
|
68
|
-
this.vocab = vocab
|
|
69
|
-
this.windowSize = /** @type {number[]} */ (null === windowSize ? this.stdout.getWindowSize() : windowSize)
|
|
70
|
-
this.components = components
|
|
71
|
-
this.renderMethod = renderMethod
|
|
72
|
-
if (!empty(frame)) {
|
|
73
|
-
this.render(1)(this.frame)
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
get empty() {
|
|
77
|
-
return empty(this.frame)
|
|
78
|
-
}
|
|
79
|
-
get RenderMethod() {
|
|
80
|
-
return /** @type {typeof View} */ (this.constructor).RenderMethod
|
|
81
|
-
}
|
|
82
|
-
get RenderOptions() {
|
|
83
|
-
return /** @type {typeof View} */ (this.constructor).RenderOptions
|
|
84
|
-
}
|
|
85
|
-
getWindowSize() {
|
|
86
|
-
return equal(this.windowSize, [0, 0]) ? this.stdout.getWindowSize() : this.windowSize
|
|
87
|
-
}
|
|
88
|
-
/**
|
|
89
|
-
* @param {number} width
|
|
90
|
-
* @param {number} height
|
|
91
|
-
*/
|
|
92
|
-
setWindowSize(width, height) {
|
|
93
|
-
this.windowSize = [width, height]
|
|
94
|
-
}
|
|
95
|
-
startTimer() {
|
|
96
|
-
this.startedAt = Date.now()
|
|
97
|
-
}
|
|
98
|
-
spent(checkpoint = this.startedAt) {
|
|
99
|
-
return Math.round((Date.now() - checkpoint) / 1000)
|
|
100
|
-
}
|
|
101
|
-
/**
|
|
102
|
-
* @param {boolean | number | Function | ComponentFn} [shouldRender=0]
|
|
103
|
-
* @param {RenderOptions} [options]
|
|
104
|
-
* @returns {(value: Frame|string|string[], ...args: any) => Frame}
|
|
105
|
-
*/
|
|
106
|
-
render(shouldRender = 0, options = new this.RenderOptions()) {
|
|
107
|
-
const [width, height] = this.getWindowSize()
|
|
108
|
-
options = this.RenderOptions.from({
|
|
109
|
-
...options,
|
|
110
|
-
renderMethod: this.renderMethod,
|
|
111
|
-
width,
|
|
112
|
-
height,
|
|
113
|
-
// @ts-ignore
|
|
114
|
-
})
|
|
115
|
-
const renderFn =
|
|
116
|
-
'function' === typeof shouldRender // no errors.
|
|
117
|
-
? // const renderFn = typeOf(Function)(shouldRender) // Property 'bind' does not exist on type 'number | boolean | Function'.
|
|
118
|
-
shouldRender.bind(this)
|
|
119
|
-
: 'string' === typeof shouldRender
|
|
120
|
-
? this.components.get(shouldRender)?.bind(this)
|
|
121
|
-
: null
|
|
122
|
-
|
|
123
|
-
return (value, ...args) => {
|
|
124
|
-
if (renderFn) {
|
|
125
|
-
/** @type {Frame} */
|
|
126
|
-
let rendered = renderFn.bind(this)(value, ...args)
|
|
127
|
-
if (!(rendered instanceof Frame)) {
|
|
128
|
-
rendered = new Frame({
|
|
129
|
-
value: rendered,
|
|
130
|
-
renderMethod: options.renderMethod,
|
|
131
|
-
width: options.width,
|
|
132
|
-
height: options.height,
|
|
133
|
-
})
|
|
134
|
-
}
|
|
135
|
-
rendered = View.fixFrame(rendered, options)
|
|
136
|
-
rendered = rendered.transform(this.t.bind(this))
|
|
137
|
-
rendered.render()
|
|
138
|
-
if (options.render) {
|
|
139
|
-
this.stdout.write(String(rendered))
|
|
140
|
-
this.frame = rendered
|
|
141
|
-
}
|
|
142
|
-
return rendered
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
let frame = Frame.from({ ...options, value })
|
|
146
|
-
frame = View.fixFrame(frame, options)
|
|
147
|
-
let clearFrame = false
|
|
148
|
-
if (String(frame.value[0] ?? '') === Frame.BOF) {
|
|
149
|
-
frame.value = frame.value.slice(1)
|
|
150
|
-
clearFrame = true
|
|
151
|
-
}
|
|
152
|
-
let translated = options.translateFrame ? frame.transform(this.t.bind(this)) : frame
|
|
153
|
-
translated = View.fixFrame(translated, options)
|
|
154
|
-
|
|
155
|
-
let rendered = translated
|
|
156
|
-
rendered.render()
|
|
157
|
-
if (shouldRender) {
|
|
158
|
-
if (clearFrame) {
|
|
159
|
-
const distance = options.height - frame.value.length
|
|
160
|
-
this.stdout.write(Frame.BOF)
|
|
161
|
-
for (let i = 0; i < distance; i++) {
|
|
162
|
-
this.stdout.write(Frame.EOL)
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
this.stdout.write(Frame.RESET + String(rendered))
|
|
166
|
-
this.frame = rendered
|
|
167
|
-
}
|
|
168
|
-
return rendered
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
clear(shouldRender = 0) {
|
|
173
|
-
const [width, height] = this.windowSize
|
|
174
|
-
const frame = new Frame({ width, height, renderMethod: Frame.RenderMethod.REPLACE })
|
|
175
|
-
frame.value = []
|
|
176
|
-
for (let i = 0; i < height; i++) frame.value.push([])
|
|
177
|
-
return this.render(shouldRender)(frame)
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
progress(shouldRender = false) {
|
|
181
|
-
return (value) => {
|
|
182
|
-
const frame = Frame.from(value)
|
|
183
|
-
frame.renderMethod = Frame.RenderMethod.REPLACE
|
|
184
|
-
return this.render(!!shouldRender)(frame)
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/** @param {any} value */
|
|
189
|
-
t(value) {
|
|
190
|
-
if (typeOf(Array)(value)) {
|
|
191
|
-
value = value.map((row) => {
|
|
192
|
-
if (typeOf(Array)(row)) {
|
|
193
|
-
return row.map((col) => {
|
|
194
|
-
return this.vocab.has(col) ? this.vocab.get(col) : col
|
|
195
|
-
})
|
|
196
|
-
}
|
|
197
|
-
return this.vocab.has(row) ? this.vocab.get(row) : row
|
|
198
|
-
})
|
|
199
|
-
return value
|
|
200
|
-
}
|
|
201
|
-
return this.vocab.has(value) ? this.vocab.get(value) : value
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/** @param {any[]} args */
|
|
205
|
-
debug(...args) {
|
|
206
|
-
// @ts-ignore
|
|
207
|
-
return this.render(1)([StdOut.STYLES.dim, 'Debug: ', args.join(' '), Frame.EOL, StdOut.RESET])
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/** @param {any[]} args */
|
|
211
|
-
info(...args) {
|
|
212
|
-
// @ts-ignore
|
|
213
|
-
return this.render(1)([StdOut.COLORS.green, 'Info : ', args.join(' '), Frame.EOL, StdOut.RESET])
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/** @param {any[]} args */
|
|
217
|
-
warn(...args) {
|
|
218
|
-
return this.render(1)([
|
|
219
|
-
// @ts-ignore
|
|
220
|
-
StdOut.COLORS.yellow,
|
|
221
|
-
'Warn : ',
|
|
222
|
-
args.join(' '),
|
|
223
|
-
Frame.EOL,
|
|
224
|
-
StdOut.RESET,
|
|
225
|
-
])
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/** @param {any[]} args */
|
|
229
|
-
error(...args) {
|
|
230
|
-
return this.render(1)([
|
|
231
|
-
// @ts-ignore
|
|
232
|
-
StdOut.COLORS.red,
|
|
233
|
-
StdOut.STYLES.bold,
|
|
234
|
-
'Error: ',
|
|
235
|
-
args.join(' '),
|
|
236
|
-
Frame.EOL,
|
|
237
|
-
StdOut.RESET,
|
|
238
|
-
])
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* @param {string} name
|
|
243
|
-
* @param {ComponentFn} component
|
|
244
|
-
*/
|
|
245
|
-
register(name, component) {
|
|
246
|
-
if (undefined === component && 'function' === typeof name) {
|
|
247
|
-
component = name
|
|
248
|
-
name = component.name
|
|
249
|
-
}
|
|
250
|
-
this.components.set(name, component)
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
/**
|
|
254
|
-
* @param {string} name
|
|
255
|
-
*/
|
|
256
|
-
unregister(name) {
|
|
257
|
-
this.components.delete(name)
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* @param {string} name
|
|
262
|
-
* @returns {boolean}
|
|
263
|
-
*/
|
|
264
|
-
has(name) {
|
|
265
|
-
return this.components.has(name)
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
/**
|
|
269
|
-
* @param {string} name
|
|
270
|
-
* @returns {ComponentFn | undefined}
|
|
271
|
-
*/
|
|
272
|
-
get(name) {
|
|
273
|
-
return this.components.get(name)
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* @param {UiMessage} input
|
|
278
|
-
* @returns {Promise<UiMessage | null>}
|
|
279
|
-
*/
|
|
280
|
-
async ask(input) {
|
|
281
|
-
const name = input.constructor.name.replace(/Input$/, '')
|
|
282
|
-
const component = this.get(name)
|
|
283
|
-
if (component) {
|
|
284
|
-
return await component.ask.apply(this, [input])
|
|
285
|
-
}
|
|
286
|
-
let result = null
|
|
287
|
-
do {
|
|
288
|
-
const answer = await this.stdin.read()
|
|
289
|
-
result = /** @type {typeof UiMessage} */ (input.constructor).from(answer)
|
|
290
|
-
} while (!result.isValid && !result.head.cancelled)
|
|
291
|
-
return result.head.cancelled ? null : result
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
/**
|
|
295
|
-
* @param {Frame} frame
|
|
296
|
-
* @param {RenderOptions} [options]
|
|
297
|
-
* @returns {Frame}
|
|
298
|
-
*/
|
|
299
|
-
static fixFrame(frame, options = new RenderOptions()) {
|
|
300
|
-
if (options.resizeToView && !equal(options.width, frame.width, options.height, frame.height)) {
|
|
301
|
-
frame.setWindowSize(options.width, options.height)
|
|
302
|
-
}
|
|
303
|
-
// @todo add multiline visibility, for instance extended frame row into rows if it's wider than width.
|
|
304
|
-
return frame
|
|
305
|
-
}
|
|
306
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export class DepsCommand extends UiMessage {
|
|
2
|
-
static Body: typeof DepsCommandBody;
|
|
3
|
-
constructor(input?: {});
|
|
4
|
-
}
|
|
5
|
-
export default DepsCommand;
|
|
6
|
-
import UiMessage from '../../core/Message/Message.js';
|
|
7
|
-
declare class DepsCommandBody {
|
|
8
|
-
static fix: {
|
|
9
|
-
help: string;
|
|
10
|
-
defaultValue: boolean;
|
|
11
|
-
};
|
|
12
|
-
constructor(input?: {});
|
|
13
|
-
fix: boolean;
|
|
14
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/** @typedef {Function} CommandFn */
|
|
2
|
-
/**
|
|
3
|
-
* Abstract base class for all apps.
|
|
4
|
-
* Each app processes input commands and produces output.
|
|
5
|
-
*/
|
|
6
|
-
export default class CoreApp {
|
|
7
|
-
/**
|
|
8
|
-
* Creates a new CoreApp instance.
|
|
9
|
-
* @param {object} props - CoreApp properties
|
|
10
|
-
* @param {string} [props.name="CoreApp"] - App name
|
|
11
|
-
* @param {object} [props.state={}] - Initial state object
|
|
12
|
-
* @param {Message} [props.startCommand=new Message()] - Command line arguments to parse
|
|
13
|
-
*/
|
|
14
|
-
constructor(props?: {
|
|
15
|
-
name?: string | undefined;
|
|
16
|
-
state?: object;
|
|
17
|
-
startCommand?: Message | undefined;
|
|
18
|
-
});
|
|
19
|
-
/** @type {string} App name */
|
|
20
|
-
name: string;
|
|
21
|
-
/** @type {Map<string, CommandFn>} Registered command handlers */
|
|
22
|
-
commands: Map<string, CommandFn>;
|
|
23
|
-
/** @type {Record<string, any>} App state */
|
|
24
|
-
state: Record<string, any>;
|
|
25
|
-
/** @type {Message} Starting command parsed from argv */
|
|
26
|
-
startCommand: Message;
|
|
27
|
-
/**
|
|
28
|
-
* Sets app state.
|
|
29
|
-
* @param {string|object} state - State key or object with multiple keys
|
|
30
|
-
* @param {any} [value] - State value if state is a string key
|
|
31
|
-
* @returns {object} Updated state
|
|
32
|
-
*/
|
|
33
|
-
set(state: string | object, value?: any): object;
|
|
34
|
-
/**
|
|
35
|
-
* Register a command handler.
|
|
36
|
-
* @param {string} commandName - Name of the command to register
|
|
37
|
-
* @param {Function} handler - async function or sync function that accepts params and returns output
|
|
38
|
-
*/
|
|
39
|
-
registerCommand(commandName: string, handler: Function): void;
|
|
40
|
-
/**
|
|
41
|
-
* Returns a string representation of the app.
|
|
42
|
-
* @returns {string} String representation including name and state
|
|
43
|
-
*/
|
|
44
|
-
toString(): string;
|
|
45
|
-
/**
|
|
46
|
-
* Process a command message.
|
|
47
|
-
* @param {Message} msg - Command to process
|
|
48
|
-
* @param {UI} ui - UI instance to use for rendering
|
|
49
|
-
* @returns {Promise<any>} Output of the command
|
|
50
|
-
* @throws {Error} If the command is not registered
|
|
51
|
-
*/
|
|
52
|
-
processCommand(msg: Message, ui: UI): Promise<any>;
|
|
53
|
-
/**
|
|
54
|
-
* Process an array of command messages sequentially.
|
|
55
|
-
* @param {Message[]} Messages - Array of commands to process
|
|
56
|
-
* @param {UI} ui - UI instance to use for rendering
|
|
57
|
-
* @returns {Promise<any[]>} Array of command outputs
|
|
58
|
-
*/
|
|
59
|
-
processCommands(Messages: Message[], ui: UI): Promise<any[]>;
|
|
60
|
-
/**
|
|
61
|
-
* Select a command to run. Must be implemented by subclasses.
|
|
62
|
-
* @param {UI} ui - UI instance for interaction
|
|
63
|
-
* @returns {Promise<string>} Command name to execute
|
|
64
|
-
* @throws {Error} Always thrown as this method must be implemented by subclasses
|
|
65
|
-
*/
|
|
66
|
-
selectCommand(ui: UI): Promise<string>;
|
|
67
|
-
}
|
|
68
|
-
export type CommandFn = Function;
|
|
69
|
-
import { Message } from '@nan0web/co';
|
|
70
|
-
import UI from './UI.js';
|
package/types/App/Core/UI.d.ts
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/** @typedef {import("../../View/View.js").ComponentFn} ComponentFn */
|
|
2
|
-
/**
|
|
3
|
-
* Abstract UI class to connect apps and widgets.
|
|
4
|
-
* Supports input/output data typed classes and views.
|
|
5
|
-
*/
|
|
6
|
-
export default class UI extends Widget {
|
|
7
|
-
/**
|
|
8
|
-
* Creates a new UI instance.
|
|
9
|
-
* @param {CoreApp} app - The app to connect to this UI
|
|
10
|
-
* @param {View} [view] - View instance for rendering (default: new View())
|
|
11
|
-
*/
|
|
12
|
-
constructor(app: CoreApp, view?: View);
|
|
13
|
-
/** @type {CoreApp} The app instance connected to this UI */
|
|
14
|
-
app: CoreApp;
|
|
15
|
-
/**
|
|
16
|
-
* Convert raw input to Message array.
|
|
17
|
-
* Must be implemented by subclasses.
|
|
18
|
-
* @param {any} rawInput - Raw input to convert
|
|
19
|
-
* @returns {Message[]} Array of command messages
|
|
20
|
-
* @throws {Error} Always thrown as this method must be implemented by subclasses
|
|
21
|
-
*/
|
|
22
|
-
convertInput(rawInput: any): Message[];
|
|
23
|
-
/**
|
|
24
|
-
* Sets up event handlers for UI process events.
|
|
25
|
-
* @param {ComponentFn} UIProcess - Process view component
|
|
26
|
-
*/
|
|
27
|
-
show(UIProcess: ComponentFn): void;
|
|
28
|
-
/**
|
|
29
|
-
* Output results to the interface.
|
|
30
|
-
* @param {any[]} results - Results to output
|
|
31
|
-
*/
|
|
32
|
-
output(results: any[]): void;
|
|
33
|
-
}
|
|
34
|
-
export type ComponentFn = import("../../View/View.js").ComponentFn;
|
|
35
|
-
import Widget from './Widget.js';
|
|
36
|
-
import CoreApp from './CoreApp.js';
|
|
37
|
-
import { Message } from '@nan0web/co';
|
|
38
|
-
import View from '../../View/View.js';
|