@nan0web/ui 1.0.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 (131) hide show
  1. package/.datasets/README.dataset.jsonl +12 -0
  2. package/.editorconfig +20 -0
  3. package/CONTRIBUTING.md +42 -0
  4. package/LICENSE +15 -0
  5. package/README.md +238 -0
  6. package/docs/uk/README.md +240 -0
  7. package/package.json +64 -0
  8. package/playground/User.js +52 -0
  9. package/playground/currency.exchange.js +48 -0
  10. package/playground/i18n/index.js +21 -0
  11. package/playground/i18n/uk.js +53 -0
  12. package/playground/language.form.js +25 -0
  13. package/playground/main.js +72 -0
  14. package/playground/registration.form.js +58 -0
  15. package/playground/topup.telephone.js +62 -0
  16. package/src/App/Command/Options.js +78 -0
  17. package/src/App/Command/index.js +9 -0
  18. package/src/App/Core/CoreApp.js +129 -0
  19. package/src/App/Core/UI.js +116 -0
  20. package/src/App/Core/Widget.js +67 -0
  21. package/src/App/Core/index.js +11 -0
  22. package/src/App/Scenario.js +45 -0
  23. package/src/App/User/Command/Message.js +44 -0
  24. package/src/App/User/Command/Options.js +48 -0
  25. package/src/App/User/Command/index.js +11 -0
  26. package/src/App/User/UserApp.js +73 -0
  27. package/src/App/User/UserApp.test.js +56 -0
  28. package/src/App/User/UserUI.js +20 -0
  29. package/src/App/User/UserUI.test.js +51 -0
  30. package/src/App/User/index.js +15 -0
  31. package/src/App/index.js +22 -0
  32. package/src/Component/Process/Input.js +70 -0
  33. package/src/Component/Process/Process.js +26 -0
  34. package/src/Component/Process/index.js +5 -0
  35. package/src/Component/Welcome/Input.js +50 -0
  36. package/src/Component/Welcome/Welcome.js +26 -0
  37. package/src/Component/Welcome/index.js +5 -0
  38. package/src/Component/index.js +9 -0
  39. package/src/Frame/Frame.js +591 -0
  40. package/src/Frame/Frame.test.js +429 -0
  41. package/src/Frame/Props.js +102 -0
  42. package/src/Locale.js +119 -0
  43. package/src/Model/User/User.js +56 -0
  44. package/src/Model/index.js +7 -0
  45. package/src/README.md.js +371 -0
  46. package/src/StdIn.js +111 -0
  47. package/src/StdOut.js +99 -0
  48. package/src/View/RenderOptions.js +48 -0
  49. package/src/View/View.js +289 -0
  50. package/src/View/View.test.js +77 -0
  51. package/src/core/Form/Form.js +289 -0
  52. package/src/core/Form/Form.test.js +116 -0
  53. package/src/core/Form/Input.js +116 -0
  54. package/src/core/Form/Input.test.js +58 -0
  55. package/src/core/Form/Message.js +86 -0
  56. package/src/core/Form/Message.test.js +54 -0
  57. package/src/core/Form/index.js +11 -0
  58. package/src/core/InputAdapter.js +41 -0
  59. package/src/core/InputAdapter.test.js +35 -0
  60. package/src/core/Message/InputMessage.js +119 -0
  61. package/src/core/Message/InputMessage.test.js +45 -0
  62. package/src/core/Message/Message.js +77 -0
  63. package/src/core/Message/Message.test.js +58 -0
  64. package/src/core/Message/OutputMessage.js +143 -0
  65. package/src/core/Message/OutputMessage.test.js +61 -0
  66. package/src/core/Message/index.js +7 -0
  67. package/src/core/OutputAdapter.js +50 -0
  68. package/src/core/OutputAdapter.test.js +35 -0
  69. package/src/core/Stream.js +71 -0
  70. package/src/core/Stream.test.js +78 -0
  71. package/src/core/StreamEntry.js +59 -0
  72. package/src/core/index.js +13 -0
  73. package/src/functions.js +38 -0
  74. package/src/index.js +34 -0
  75. package/src/index.test.js +14 -0
  76. package/src/models/SimpleUser.js +18 -0
  77. package/stories/App/AppView.js +15 -0
  78. package/stories/App/AppView.test.js +22 -0
  79. package/stories/App/RenderOptions.js +14 -0
  80. package/stories/nodejs/interface.test.js +27 -0
  81. package/system.md +187 -0
  82. package/system1.md +137 -0
  83. package/task.md +181 -0
  84. package/tsconfig.json +23 -0
  85. package/types/App/Command/Options.d.ts +46 -0
  86. package/types/App/Command/index.d.ts +8 -0
  87. package/types/App/Core/CoreApp.d.ts +70 -0
  88. package/types/App/Core/UI.d.ts +49 -0
  89. package/types/App/Core/Widget.d.ts +40 -0
  90. package/types/App/Core/index.d.ts +10 -0
  91. package/types/App/Scenario.d.ts +26 -0
  92. package/types/App/User/Command/Message.d.ts +30 -0
  93. package/types/App/User/Command/Options.d.ts +27 -0
  94. package/types/App/User/Command/index.d.ts +8 -0
  95. package/types/App/User/UserApp.d.ts +31 -0
  96. package/types/App/User/UserUI.d.ts +18 -0
  97. package/types/App/User/index.d.ts +12 -0
  98. package/types/App/index.d.ts +14 -0
  99. package/types/Component/Process/Input.d.ts +48 -0
  100. package/types/Component/Process/Process.d.ts +13 -0
  101. package/types/Component/Process/index.d.ts +4 -0
  102. package/types/Component/Welcome/Input.d.ts +34 -0
  103. package/types/Component/Welcome/Welcome.d.ts +13 -0
  104. package/types/Component/Welcome/index.d.ts +4 -0
  105. package/types/Component/index.d.ts +8 -0
  106. package/types/Frame/Frame.d.ts +186 -0
  107. package/types/Frame/Props.d.ts +77 -0
  108. package/types/Locale.d.ts +55 -0
  109. package/types/Model/User/User.d.ts +36 -0
  110. package/types/Model/index.d.ts +6 -0
  111. package/types/StdIn.d.ts +62 -0
  112. package/types/StdOut.d.ts +52 -0
  113. package/types/View/RenderOptions.d.ts +29 -0
  114. package/types/View/View.d.ts +115 -0
  115. package/types/core/Form/Form.d.ts +123 -0
  116. package/types/core/Form/Input.d.ts +69 -0
  117. package/types/core/Form/Message.d.ts +28 -0
  118. package/types/core/Form/index.d.ts +5 -0
  119. package/types/core/InputAdapter.d.ts +28 -0
  120. package/types/core/Message/InputMessage.d.ts +71 -0
  121. package/types/core/Message/Message.d.ts +50 -0
  122. package/types/core/Message/OutputMessage.d.ts +53 -0
  123. package/types/core/Message/index.d.ts +5 -0
  124. package/types/core/OutputAdapter.d.ts +33 -0
  125. package/types/core/Stream.d.ts +27 -0
  126. package/types/core/StreamEntry.d.ts +45 -0
  127. package/types/core/index.d.ts +9 -0
  128. package/types/functions.d.ts +3 -0
  129. package/types/index.d.ts +20 -0
  130. package/types/models/SimpleUser.d.ts +21 -0
  131. package/vitest.config.js +26 -0
@@ -0,0 +1,12 @@
1
+ {"instruction":"How to install with npm?","output":"```bash\nnpm install @nan0web/ui\n```\n","context":["h1:@nan0web/ui","h2:Installation"],"input":"## Installation\n\n","tags":["@nan0web/ui","Installation"],"proven":"assert-in-@nan0web/ui"}
2
+ {"instruction":"How to install with pnpm?","output":"```bash\npnpm add @nan0web/ui\n```\n","context":["h1:@nan0web/ui","h2:Installation"],"input":"## Installation\n\n","tags":["@nan0web/ui","Installation"],"proven":"assert-in-@nan0web/ui"}
3
+ {"instruction":"How to install with yarn?","output":"```bash\nyarn add @nan0web/ui\n```\n","context":["h1:@nan0web/ui","h2:Installation"],"input":"## Installation\n\n","tags":["@nan0web/ui","Installation"],"proven":"assert-in-@nan0web/ui"}
4
+ {"instruction":"How to create input and output messages?","output":"```js\nimport { InputMessage, OutputMessage } from '@nan0web/ui'\n\nconst input = InputMessage.from({ value: 'Hello User' })\nconst output = OutputMessage.from({ content: ['Welcome to @nan0web/ui'] })\nconsole.info(input.value) // ← Hello User\nconsole.info(output.content[0]) // ← Welcome to @nan0web/ui\n```\n","context":["h1:@nan0web/ui","h2:Concepts & Architecture","h3:Message Flow"],"input":"### Message Flow\n\nUI communication is built around messages:\n\n- **`UIMessage`** – abstract message base class\n- **`InputMessage`** – user input message (value, options)\n- **`OutputMessage`** – system output (content, error, priority)\n\nMessages are simple, serializable data containers. They help build\ndecoupled communication systems between UI components.\n\n","tags":["@nan0web/ui","Concepts & Architecture","Message Flow"],"proven":"assert-in-@nan0web/ui"}
5
+ {"instruction":"How to define and validate a UIForm?","output":"```js\nimport { UIForm } from '@nan0web/ui'\n\nconst form = new UIForm({\n\ttitle: \"Contact Form\",\n\tfields: [\n\t\tFormInput.from({ name: \"email\", label: \"Email Address\", type: \"email\", required: true }),\n\t\tFormInput.from({ name: \"message\", label: \"Your Message\", type: \"textarea\", required: true })\n\t],\n\tstate: {\n\t\temail: \"invalid-email\",\n\t\tmessage: \"Hello!\"\n\t}\n})\n\nconst result = form.validate()\nconsole.info(result.isValid) // ← false\nconsole.info(result.errors.email) // ← Invalid email format\n\n```\n","context":["h1:@nan0web/ui","h2:Concepts & Architecture","h3:Forms"],"input":"### Forms\n\n`UIForm` supports field definitions, data management, and schema validation.\nEvery form includes a title, fields, and current state.\n\nField types include:\n\n- `text`\n- `email`\n- `number`\n- `select`\n- `checkbox`\n- `textarea`\n\n","tags":["@nan0web/ui","Concepts & Architecture","Forms"],"proven":"assert-in-@nan0web/ui"}
6
+ {"instruction":"How to render the Welcome component?","output":"```js\nimport { Welcome } from '@nan0web/ui'\n\nconst frame = Welcome({ user: { name: \"Alice\" } })\nconst firstLine = frame[0].join(\"\")\nconsole.info(firstLine) // ← Welcome Alice!\n```\n","context":["h1:@nan0web/ui","h2:Concepts & Architecture","h3:Components"],"input":"### Components\n\nComponents render data as frame-ready output.\n\n- `Welcome` – greets user by name\n- `Process` – shows progress bar and time\n\n","tags":["@nan0web/ui","Concepts & Architecture","Components"],"proven":"assert-in-@nan0web/ui"}
7
+ {"instruction":"How to render frame with View?","output":"```js\nimport { View } from '@nan0web/ui'\n\nconst view = new View()\nview.render(1)([\"Hello, world\"])\nconsole.info(String(view.frame)) // ← \"\\rHello, world\"\n```\n","context":["h1:@nan0web/ui","h2:Concepts & Architecture","h3:View Manager"],"input":"### View Manager\n\n`View` combines components and renders frames.\n\nEvery view has:\n\n- Locale – formatted text, numbers, currency\n- StdIn / StdOut – input/output streams\n- Frame – output buffer with visual properties\n\n","tags":["@nan0web/ui","Concepts & Architecture","View Manager"],"proven":"assert-in-@nan0web/ui"}
8
+ {"instruction":"How to create a Frame with fixed size?","output":"```js\nimport { Frame } from '@nan0web/ui'\n\nconst frame = new Frame({\n\tvalue: [[\"Frame content\"]],\n\twidth: 20,\n\theight: 5,\n\trenderMethod: Frame.RenderMethod.APPEND,\n})\n\nconst rendered = frame.render()\nconsole.info(rendered.includes(\"Frame content\")) // ← true\n```\n","context":["h1:@nan0web/ui","h2:Concepts & Architecture","h3:Frame Rendering"],"input":"### Frame Rendering\n\n`Frame` manages visual rendering with width and height limits.\nUseful for fixed-size terminals or UI blocks.\n\n","tags":["@nan0web/ui","Concepts & Architecture","Frame Rendering"],"proven":"assert-in-@nan0web/ui"}
9
+ {"instruction":"How to create a basic user app that greets?","output":"```js\nimport { App, View } from '@nan0web/ui'\n\nconst app = new App.User.App({ name: \"GreetApp\" })\nconst view = new View()\nview.register(\"Welcome\", Welcome)\n\nconst cmd = App.Command.Message.parse(\"welcome --user Bob\")\nconst result = await app.processCommand(cmd, new App.User.UI(app, view))\nconsole.info(String(result)) // ← Welcome Bob!\n```\n","context":["h1:@nan0web/ui","h2:Concepts & Architecture","h3:App Architecture"],"input":"### App Architecture\n\n`App` provides the main application logic.\n\n- Core – minimal UI layer\n- User – user-specific UI commands\n\nEach app registers commands and binds them to UI actions.\n\n","tags":["@nan0web/ui","Concepts & Architecture","App Architecture"],"proven":"assert-in-@nan0web/ui"}
10
+ {"instruction":"How to use a User model?","output":"```js\nimport { Model } from '@nan0web/ui'\n\nconst user = new Model.User({ name: \"Charlie\", email: \"charlie@example.com\" })\nconsole.info(user.name) // ← Charlie\nconsole.info(user.email) // ← charlie@example.com\n```\n","context":["h1:@nan0web/ui","h2:Concepts & Architecture","h3:Models"],"input":"### Models\n\nUI models are plain data objects managed by `Model` classes.\n\n- `User` – user data\n\n","tags":["@nan0web/ui","Concepts & Architecture","Models"],"proven":"assert-in-@nan0web/ui"}
11
+ {"instruction":"How to test UI components with assertions?","output":"```js\nimport { Welcome, InputMessage } from '@nan0web/ui'\n\nconst output = Welcome({ user: { name: \"Test\" } })\nconst input = InputMessage.from({ value: \"test\" })\nconsole.log(output[0].join(\"\")) // ← Welcome Test!\n```\n","context":["h1:@nan0web/ui","h2:Concepts & Architecture","h3:Testing UI"],"input":"### Testing UI\n\nCore unit-tested to ensure stability in different environments.\n\nAll components, adapters, and models are designed to be testable\nwith minimal setup.\n\n","tags":["@nan0web/ui","Concepts & Architecture","Testing UI"],"proven":"assert-in-@nan0web/ui"}
12
+ {"instruction":"How to run the playground?","output":"```bash\n# Clone repository and run playground\ngit clone https://github.com/nan0web/ui.git\ncd ui\nnpm install\nnpm run playground\n```\n","context":["h1:@nan0web/ui","h2:Playground Demos"],"input":"## Playground Demos\n\nThe library includes rich playground demos:\n\n- [Registration Form](./playground/registration.form.js)\n- [Currency Exchange](./playground/currency.exchange.js)\n- [Mobile Top-up](./playground/topup.telephone.js)\n- [Language Selector](./playground/language.form.js)\n\nRun to explore live functionality:\n\n","tags":["@nan0web/ui","Playground Demos"],"proven":"assert-in-@nan0web/ui"}
package/.editorconfig ADDED
@@ -0,0 +1,20 @@
1
+ root = true
2
+
3
+ [*]
4
+ indent_style = tab
5
+ indent_size = 2
6
+ charset = utf-8
7
+ end_of_line = lf
8
+ trim_trailing_whitespace = true
9
+ insert_final_newline = true
10
+
11
+ [*.md]
12
+ trim_trailing_whitespace = false
13
+
14
+ [*.jsx]
15
+ indent_style = tab
16
+ indent_size = 2
17
+
18
+ [*.{md,nano,yaml}]
19
+ indent_style = space
20
+ indent_size = 2
@@ -0,0 +1,42 @@
1
+ # Contributing
2
+
3
+ ## Developer Certificate of Origin and License
4
+ By contributing, You accept and agree to the following terms and conditions for your present and future contributions submitted.
5
+ Except for the license granted herein, You reserve all right, title, and interest in and to your Contributions.
6
+ All contributions are subject to the Developer Certificate of Origin and license as set out in the LICENSE file.
7
+
8
+ ## Code of Conduct
9
+ As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
10
+
11
+ We are committed to making participation in this project a harassment-free experience for everyone, regardless of:
12
+ - Level of experience,
13
+ - Gender,
14
+ - Gender identity and expression,
15
+ - Sexual orientation,
16
+ - Disability,
17
+ - Personal appearance,
18
+ - Body size,
19
+ - Race,
20
+ - Ethnicity,
21
+ - Age,
22
+ - Religion.
23
+
24
+ > We recognize all people as the foundation of humanity, and our actions contribute to the continued existence and growth of our shared humanity.
25
+
26
+ ### Release versioning
27
+ - Keep releases close to the minor versions and publish patches only if required.
28
+
29
+ ### Examples of unacceptable behavior by participants:
30
+ - Use of sexual language or imagery.
31
+ - Derogatory comments or personal attacks.
32
+ - Trolling, public or private harassment.
33
+ - Insults or other unprofessional conduct.
34
+
35
+ ### Enforcement
36
+ Project maintainers have the right and responsibility to:
37
+ - Remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions not aligned with this Code of Conduct.
38
+ - Remove maintainers who violate this Code of Conduct.
39
+
40
+ Instances of unacceptable behavior can be reported by contacting the project team.
41
+
42
+ This Code of Conduct is adapted from the [Contributor Covenant, version 1.1.0](https://contributor-covenant.org/version/1/1/0/).
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2025, ЯRаСлав (YaRaSLove) <support@yaro.page>
4
+
5
+ Permission to use, copy, modify, and distribute this software for any purpose
6
+ with or without fee is hereby granted, provided that the above copyright notice
7
+ and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
+ PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,238 @@
1
+ # @nan0web/ui
2
+
3
+ |[Status](https://github.com/nan0web/monorepo/blob/main/system.md#написання-сценаріїв)|Documentation|Test coverage|Features|Npm version|
4
+ |---|---|---|---|---|
5
+ |🟢 `96.6%` |🧪 [English 🏴󠁧󠁢󠁥󠁮󠁧󠁿](https://github.com/nan0web/ui/blob/main/README.md)<br />[Українською 🇺🇦](https://github.com/nan0web/ui/blob/main/docs/uk/README.md) |🟡 `80.9%` |✅ d.ts 📜 system.md 🕹️ playground |— |
6
+
7
+ A lightweight, agnostic UI framework designed with the **nan0web philosophy**
8
+ — one application logic, many UI implementations.
9
+
10
+ This library provides core classes and utilities for building structured user interfaces.
11
+ It supports:
12
+
13
+ - Messaging (Input/Output)
14
+ - Forms with validation
15
+ - Progress tracking
16
+ - Component rendering
17
+ - View management with Frame rendering
18
+ - App structure with core and user apps
19
+
20
+ Built to work in sync or async, terminal-based or web-based apps,
21
+ focusing on type safety, minimalism, and pure JavaScript design.
22
+
23
+ ## Installation
24
+
25
+ How to install with npm?
26
+ ```bash
27
+ npm install @nan0web/ui
28
+ ```
29
+
30
+ How to install with pnpm?
31
+ ```bash
32
+ pnpm add @nan0web/ui
33
+ ```
34
+
35
+ How to install with yarn?
36
+ ```bash
37
+ yarn add @nan0web/ui
38
+ ```
39
+
40
+ ## Concepts & Architecture
41
+
42
+ ### Message Flow
43
+
44
+ UI communication is built around messages:
45
+
46
+ - **`UIMessage`** – abstract message base class
47
+ - **`InputMessage`** – user input message (value, options)
48
+ - **`OutputMessage`** – system output (content, error, priority)
49
+
50
+ Messages are simple, serializable data containers. They help build
51
+ decoupled communication systems between UI components.
52
+
53
+ How to create input and output messages?
54
+ ```js
55
+ import { InputMessage, OutputMessage } from '@nan0web/ui'
56
+
57
+ const input = InputMessage.from({ value: 'Hello User' })
58
+ const output = OutputMessage.from({ content: ['Welcome to @nan0web/ui'] })
59
+ console.info(input.value) // ← Hello User
60
+ console.info(output.content[0]) // ← Welcome to @nan0web/ui
61
+ ```
62
+ ### Forms
63
+
64
+ `UIForm` supports field definitions, data management, and schema validation.
65
+ Every form includes a title, fields, and current state.
66
+
67
+ Field types include:
68
+
69
+ - `text`
70
+ - `email`
71
+ - `number`
72
+ - `select`
73
+ - `checkbox`
74
+ - `textarea`
75
+
76
+ How to define and validate a UIForm?
77
+ ```js
78
+ import { UIForm } from '@nan0web/ui'
79
+
80
+ const form = new UIForm({
81
+ title: "Contact Form",
82
+ fields: [
83
+ FormInput.from({ name: "email", label: "Email Address", type: "email", required: true }),
84
+ FormInput.from({ name: "message", label: "Your Message", type: "textarea", required: true })
85
+ ],
86
+ state: {
87
+ email: "invalid-email",
88
+ message: "Hello!"
89
+ }
90
+ })
91
+
92
+ const result = form.validate()
93
+ console.info(result.isValid) // ← false
94
+ console.info(result.errors.email) // ← Invalid email format
95
+
96
+ ```
97
+ ### Components
98
+
99
+ Components render data as frame-ready output.
100
+
101
+ - `Welcome` – greets user by name
102
+ - `Process` – shows progress bar and time
103
+
104
+ How to render the Welcome component?
105
+ ```js
106
+ import { Welcome } from '@nan0web/ui'
107
+
108
+ const frame = Welcome({ user: { name: "Alice" } })
109
+ const firstLine = frame[0].join("")
110
+ console.info(firstLine) // ← Welcome Alice!
111
+ ```
112
+ ### View Manager
113
+
114
+ `View` combines components and renders frames.
115
+
116
+ Every view has:
117
+
118
+ - Locale – formatted text, numbers, currency
119
+ - StdIn / StdOut – input/output streams
120
+ - Frame – output buffer with visual properties
121
+
122
+ How to render frame with View?
123
+ ```js
124
+ import { View } from '@nan0web/ui'
125
+
126
+ const view = new View()
127
+ view.render(1)(["Hello, world"])
128
+ console.info(String(view.frame)) // ← "\rHello, world"
129
+ ```
130
+ ### Frame Rendering
131
+
132
+ `Frame` manages visual rendering with width and height limits.
133
+ Useful for fixed-size terminals or UI blocks.
134
+
135
+ How to create a Frame with fixed size?
136
+ ```js
137
+ import { Frame } from '@nan0web/ui'
138
+
139
+ const frame = new Frame({
140
+ value: [["Frame content"]],
141
+ width: 20,
142
+ height: 5,
143
+ renderMethod: Frame.RenderMethod.APPEND,
144
+ })
145
+
146
+ const rendered = frame.render()
147
+ console.info(rendered.includes("Frame content")) // ← true
148
+ ```
149
+ ### App Architecture
150
+
151
+ `App` provides the main application logic.
152
+
153
+ - Core – minimal UI layer
154
+ - User – user-specific UI commands
155
+
156
+ Each app registers commands and binds them to UI actions.
157
+
158
+ How to create a basic user app that greets?
159
+ ```js
160
+ import { App, View } from '@nan0web/ui'
161
+
162
+ const app = new App.User.App({ name: "GreetApp" })
163
+ const view = new View()
164
+ view.register("Welcome", Welcome)
165
+
166
+ const cmd = App.Command.Message.parse("welcome --user Bob")
167
+ const result = await app.processCommand(cmd, new App.User.UI(app, view))
168
+ console.info(String(result)) // ← Welcome Bob!
169
+ ```
170
+ ### Models
171
+
172
+ UI models are plain data objects managed by `Model` classes.
173
+
174
+ - `User` – user data
175
+
176
+ How to use a User model?
177
+ ```js
178
+ import { Model } from '@nan0web/ui'
179
+
180
+ const user = new Model.User({ name: "Charlie", email: "charlie@example.com" })
181
+ console.info(user.name) // ← Charlie
182
+ console.info(user.email) // ← charlie@example.com
183
+ ```
184
+ ### Testing UI
185
+
186
+ Core unit-tested to ensure stability in different environments.
187
+
188
+ All components, adapters, and models are designed to be testable
189
+ with minimal setup.
190
+
191
+ How to test UI components with assertions?
192
+ ```js
193
+ import { Welcome, InputMessage } from '@nan0web/ui'
194
+
195
+ const output = Welcome({ user: { name: "Test" } })
196
+ const input = InputMessage.from({ value: "test" })
197
+ console.log(output[0].join("")) // ← Welcome Test!
198
+ ```
199
+ ## Playground Demos
200
+
201
+ The library includes rich playground demos:
202
+
203
+ - [Registration Form](./playground/registration.form.js)
204
+ - [Currency Exchange](./playground/currency.exchange.js)
205
+ - [Mobile Top-up](./playground/topup.telephone.js)
206
+ - [Language Selector](./playground/language.form.js)
207
+
208
+ Run to explore live functionality:
209
+
210
+ How to run the playground?
211
+ ```bash
212
+ # Clone repository and run playground
213
+ git clone https://github.com/nan0web/ui.git
214
+ cd ui
215
+ npm install
216
+ npm run playground
217
+ ```
218
+
219
+ ## API Documentation
220
+
221
+ Detailed API docs are available in each class JSDoc.
222
+ Explore:
223
+
224
+ - [Messages](./src/core/Message/)
225
+ - [Forms](./src/core/Form/)
226
+ - [Stream](./src/core/Stream.js)
227
+ - [Components](./src/Component/)
228
+ - [View](./src/View/)
229
+ - [App](./src/App/)
230
+ - [Models](./src/Model/)
231
+
232
+ ## Contributing
233
+
234
+ How to contribute? - [check here](./CONTRIBUTING.md)
235
+
236
+ ## License
237
+
238
+ How to license ISC? - [check here](./LICENSE)
@@ -0,0 +1,240 @@
1
+ # @nan0web/ui
2
+
3
+ |[Статус](https://github.com/nan0web/monorepo/blob/main/system.md#написання-сценаріїв)|Документація|Тестове покриття|Фічі|Версія npm|
4
+ |---|---|---|---|---|
5
+ |🟢 `96.6%` |🧪 [English 🏴󠁧󠁢󠁥󠁮󠁧󠁿](https://github.com/nan0web/ui/blob/main/README.md)<br />[Українською 🇺🇦](https://github.com/nan0web/ui/blob/main/docs/uk/README.md) |🟡 `80.9%` |✅ d.ts 📜 system.md 🕹️ playground |— |
6
+
7
+ Легкий, незалежний UI-фреймворк, створений за філософією **nan0web** —
8
+ одна логіка програми, багато UI-реалізацій.
9
+
10
+ Бібліотека надає базові класи та утиліти для побудови структурованих інтерфейсів.
11
+ Вона підтримує:
12
+
13
+ - Обмін повідомленнями (Input/Output)
14
+ - Форми з валідацією
15
+ - Відстеження прогресу
16
+ - Рендеринг компонентів
17
+ - Управління представленням за допомогою Frame-рендерингу
18
+ - Архітектуру додатку з core- та user-частинами
19
+
20
+ Працює синхронно та асинхронно, у терміналі та у веб-програмах,
21
+ зосереджуючись на типобезпеці, мінімалізмі та чистому JavaScript.
22
+
23
+ ## Встановлення
24
+
25
+ Як встановити через npm?
26
+ ```bash
27
+ npm install @nan0web/ui
28
+ ```
29
+
30
+ Як встановити через pnpm?
31
+ ```bash
32
+ pnpm add @nan0web/ui
33
+ ```
34
+
35
+ Як встановити через yarn?
36
+ ```bash
37
+ yarn add @nan0web/ui
38
+ ```
39
+
40
+ ## Концепції та архітектура
41
+
42
+ ### Потік повідомлень
43
+
44
+ UI-комунікація будована навколо повідомлень:
45
+
46
+ - **`UIMessage`** – базовий абстрактний клас повідомлення
47
+ - **`InputMessage`** – повідомлення користувача (значення, опції)
48
+ - **`OutputMessage`** – системне повідомлення (вміст, помилка, пріоритет)
49
+
50
+ Повідомлення — прості, серіалізовані контейнери даних. Вони допомагають будувати
51
+ розслаблену комунікацію між UI-компонентами.
52
+
53
+ Як створити вхідне та вихідне повідомлення?
54
+ ```js
55
+ import { InputMessage, OutputMessage } from '@nan0web/ui'
56
+
57
+ const input = InputMessage.from({ value: 'Hello User' })
58
+ const output = OutputMessage.from({ content: ['Welcome to @nan0web/ui'] })
59
+ console.info(input.value) // ← Hello User
60
+ console.info(output.content[0]) // ← Welcome to @nan0web/ui
61
+ ```
62
+
63
+ ### Форми
64
+
65
+ `UIForm` підтримує визначення полів, управління даними та схему валідації.
66
+ Кожна форма має заголовок, список полів та поточний стан.
67
+
68
+ Типи полів:
69
+
70
+ - `text`
71
+ - `email`
72
+ - `number`
73
+ - `select`
74
+ - `checkbox`
75
+ - `textarea`
76
+
77
+ Як визначити та валідати форму?
78
+ ```js
79
+ import { UIForm } from '@nan0web/ui'
80
+
81
+ const form = new UIForm({
82
+ title: "Контактна форма",
83
+ fields: [
84
+ FormInput.from({ name: "email", label: "Email-адреса", type: "email", required: true }),
85
+ FormInput.from({ name: "message", label: "Ваше повідомлення", type: "textarea", required: true })
86
+ ],
87
+ state: {
88
+ email: "invalid-email",
89
+ message: "Привіт!"
90
+ }
91
+ })
92
+
93
+ const result = form.validate()
94
+ console.info(result.isValid) // ← false
95
+ console.info(result.errors.email) // ← Неправильний формат email
96
+ ```
97
+
98
+ ### Компоненти
99
+
100
+ Компоненти рендерять дані у вигляді готових до виведення кадрів.
101
+
102
+ - `Welcome` – привітання користувача за ім’ям
103
+ - `Process` – індикатор прогресу
104
+
105
+ Як відрендерити компонент Welcome?
106
+ ```js
107
+ import { Welcome } from '@nan0web/ui'
108
+
109
+ const frame = Welcome({ user: { name: "Аліса" } })
110
+ const firstLine = frame[0].join("")
111
+ console.info(firstLine) // ← Вітаємо, Аліса!
112
+ ```
113
+
114
+ ### Менеджер представлення (View)
115
+
116
+ `View` поєднує компоненти та рендерить кадри.
117
+
118
+ Кожне представлення має:
119
+
120
+ - Локаль – форматування тексту, чисел, валют
121
+ - StdIn / StdOut – потоки вводу/виводу
122
+ - Frame – буфер виводу з візуальними властивостями
123
+
124
+ Як вивести кадр за допомогою View?
125
+ ```js
126
+ import { View } from '@nan0web/ui'
127
+
128
+ const view = new View()
129
+ view.render(1)(["Привіт, світе!"])
130
+ console.info(String(view.frame)) // ← "\rПривіт, світе!"
131
+ ```
132
+
133
+ ### Рендеринг кадрів (Frame)
134
+
135
+ `Frame` керує візуальним рендерингом з обмеженнями ширини та висоти.
136
+ Корисно для терміналів фіксованого розміру або блокових UI.
137
+
138
+ Як створити кадр фіксованого розміру?
139
+ ```js
140
+ import { Frame } from '@nan0web/ui'
141
+
142
+ const frame = new Frame({
143
+ value: [["Вміст кадру"]],
144
+ width: 20,
145
+ height: 5,
146
+ renderMethod: Frame.RenderMethod.APPEND,
147
+ })
148
+
149
+ const rendered = frame.render()
150
+ console.info(rendered.includes("Вміст кадру")) // ← true
151
+ ```
152
+
153
+ ### Архітектура додатку (App)
154
+
155
+ `App` забезпечує основну логіку програми.
156
+
157
+ - Core – мінімальний UI-шар
158
+ - User – користувацькі UI-команди
159
+
160
+ Кожен додаток реєструє команди та прив’язує їх до UI-дій.
161
+
162
+ Як створити простий користувацький додаток, який вітає?
163
+ ```js
164
+ import { App, View } from '@nan0web/ui'
165
+
166
+ const app = new App.User.App({ name: "GreetApp" })
167
+ const view = new View()
168
+ view.register("Welcome", Welcome)
169
+
170
+ const cmd = App.Command.Message.parse("welcome --user Боб")
171
+ const result = await app.processCommand(cmd, new App.User.UI(app, view))
172
+ console.info(String(result)) // ← Вітаємо, Боб!
173
+ ```
174
+
175
+ ### Моделі
176
+
177
+ UI-моделі – це прості об’єкти даних, що керуються класами `Model`.
178
+
179
+ - `User` – дані користувача
180
+
181
+ Як використовувати модель User?
182
+ ```js
183
+ import { Model } from '@nan0web/ui'
184
+
185
+ const user = new Model.User({ name: "Чарлі", email: "charlie@example.com" })
186
+ console.info(user.name) // ← Чарлі
187
+ console.info(user.email) // ← charlie@example.com
188
+ ```
189
+
190
+ ### Тестування UI
191
+
192
+ Основні модулі покриті юніт-тестами для забезпечення стабільності у різних середовищах.
193
+
194
+ Як тестувати UI-компоненти за допомогою асерцій?
195
+ ```js
196
+ import { Welcome, InputMessage } from '@nan0web/ui'
197
+
198
+ const output = Welcome({ user: { name: "Тест" } })
199
+ const input = InputMessage.from({ value: "тест" })
200
+ console.log(output[0].join("")) // ← Вітаємо, Тест!
201
+ ```
202
+
203
+ ## Демо-плейграунди
204
+
205
+ Бібліотека містить багаті демо-плейграунди:
206
+
207
+ - [Форма реєстрації](./playground/registration.form.js)
208
+ - [Обмін валют](./playground/currency.exchange.js)
209
+ - [Поповнення мобільного телефону](./playground/topup.telephone.js)
210
+ - [Вибір мови](./playground/language.form.js)
211
+
212
+ Як запустити плейграунд?
213
+ ```bash
214
+ # Клонувати репозиторій та запустити плейграунд
215
+ git clone https://github.com/nan0web/ui.git
216
+ cd ui
217
+ npm install
218
+ npm run playground
219
+ ```
220
+
221
+ ## API Документація
222
+
223
+ Детальна API-документація доступна у JSDoc кожного класу.
224
+ Перегляньте:
225
+
226
+ - [Повідомлення](./src/core/Message/)
227
+ - [Форми](./src/core/Form/)
228
+ - [Поток (Stream)](./src/core/Stream.js)
229
+ - [Компоненти](./src/Component/)
230
+ - [View](./src/View/)
231
+ - [App](./src/App/)
232
+ - [Моделі](./src/Model/)
233
+
234
+ ## Внесок у проєкт
235
+
236
+ Як зробити внесок? – [докладніше тут](./CONTRIBUTING.md)
237
+
238
+ ## Ліцензія
239
+
240
+ Як ознайомитися з ліцензією ISC? – [докладніше тут](./LICENSE)
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "@nan0web/ui",
3
+ "version": "1.0.0",
4
+ "description": "NaN•Web UI. One application logic (algorithm) and many UI.",
5
+ "main": "src/index.js",
6
+ "types": "types/index.d.ts",
7
+ "type": "module",
8
+ "scripts": {
9
+ "build": "tsc",
10
+ "playground": "node playground/main.js",
11
+ "test": "node --test --test-timeout=3333 \"src/**/*.test.js\" | nan0test parse --fail",
12
+ "test:coverage": "node --experimental-test-coverage --test-coverage-include=\"src/**/*.js\" --test-coverage-exclude=\"src/**/*.test.js\" --test \"src/**/*.test.js\"",
13
+ "test:coverage:collect": "nan0test coverage",
14
+ "test:docs": "node --test src/README.md.js",
15
+ "test:release": "node --test \"releases/**/*.test.js\"",
16
+ "test:status": "nan0test status --hide-name",
17
+ "precommit": "npm test",
18
+ "prepush": "npm test",
19
+ "prepare": "husky",
20
+ "release": "nan0release publish",
21
+ "clean": "rm -rf .cache/ && rm -rf dist/",
22
+ "clean:modules": "rm -rf node_modules"
23
+ },
24
+ "exports": {
25
+ ".": {
26
+ "import": "./src/index.js",
27
+ "types": "./types/index.d.ts"
28
+ },
29
+ "./components": {
30
+ "import": "./src/Component/index.js",
31
+ "types": "./types/Component/index.d.ts"
32
+ },
33
+ "./cli-app": "./apps/cli/src/index.js",
34
+ "./mobile-app": "./apps/mobile/src/index.js",
35
+ "./web-app": "./apps/web/src/App.jsx"
36
+ },
37
+ "keywords": [
38
+ "ui",
39
+ "nanoweb"
40
+ ],
41
+ "author": "YaRaSLove (ЯRаСлав) <support@yaro.page>",
42
+ "license": "ISC",
43
+ "packageManager": "pnpm@10.11.0",
44
+ "devDependencies": {
45
+ "@nan0web/co": "workspace:*",
46
+ "@nan0web/event": "workspace:*",
47
+ "@nan0web/i18n": "workspace:*",
48
+ "@nan0web/release": "workspace:*",
49
+ "@nan0web/test": "workspace:*",
50
+ "@nan0web/types": "workspace:*",
51
+ "@nan0web/ui-cli": "workspace:*",
52
+ "@vitest/coverage-v8": "^3.2.4",
53
+ "vitest": "^3.2.4",
54
+ "husky": "^9.1.7"
55
+ },
56
+ "dependencies": {
57
+ "string-width": "^7.2.0"
58
+ },
59
+ "peerDependencies": {
60
+ "@nan0web/co": "^1.0.0",
61
+ "@nan0web/event": "^1.0.0",
62
+ "@nan0web/types": "^1.0.0"
63
+ }
64
+ }