@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/README.md
CHANGED
|
@@ -1,373 +1,36 @@
|
|
|
1
1
|
# @nan0web/ui
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Легкий, агностичний UI-фреймворк, розроблений за філософією **nan0web** — одна логіка додатка, багато UI-реалізацій (One Logic — Many UI).
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Documentation / Документація
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
— one application logic, many UI implementations.
|
|
7
|
+
Оберіть мову документації:
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
- 🏴 [**English Documentation**](./docs/en/README.md)
|
|
10
|
+
- 🇺🇦 [**Українська документація**](./docs/uk/README.md)
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
- Forms with validation
|
|
15
|
-
- Progress tracking
|
|
16
|
-
- Component rendering
|
|
17
|
-
- View management with Frame rendering
|
|
18
|
-
- App structure with core and user apps
|
|
12
|
+
---
|
|
19
13
|
|
|
20
|
-
|
|
21
|
-
focusing on type safety, minimalism, and pure JavaScript design.
|
|
14
|
+
## Quick Start / Швидкий старт
|
|
22
15
|
|
|
23
|
-
## Installation
|
|
24
|
-
|
|
25
|
-
How to install with npm?
|
|
26
16
|
```bash
|
|
27
17
|
npm install @nan0web/ui
|
|
28
18
|
```
|
|
29
19
|
|
|
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
|
-
- **`OutputMessage`** – system output (content, error, priority)
|
|
48
|
-
|
|
49
|
-
Messages are simple, serializable data containers. They help build
|
|
50
|
-
decoupled communication systems between UI components.
|
|
51
|
-
|
|
52
|
-
How to create input and output messages?
|
|
53
|
-
```js
|
|
54
|
-
import { InputMessage, OutputMessage } from '@nan0web/ui'
|
|
55
|
-
const input = UiMessage.from({ body: 'Hello User' })
|
|
56
|
-
const output = OutputMessage.from({ content: ['Welcome to @nan0web/ui'] })
|
|
57
|
-
console.info(input) // ← Message { body: "Hello User", head: {}, id: "....", type: "" }
|
|
58
|
-
console.info(String(output)) // ← Welcome to @nan0web/ui
|
|
59
|
-
```
|
|
60
|
-
### Forms
|
|
61
|
-
|
|
62
|
-
`UiForm` supports field definitions, data management, and schema validation.
|
|
63
|
-
Every form includes a title, fields, and current state.
|
|
64
|
-
|
|
65
|
-
Field types include:
|
|
66
|
-
|
|
67
|
-
- `text`
|
|
68
|
-
- `email`
|
|
69
|
-
- `number`
|
|
70
|
-
- `select`
|
|
71
|
-
- `checkbox`
|
|
72
|
-
- `textarea`
|
|
73
|
-
|
|
74
|
-
How to define and validate a UiForm?
|
|
75
20
|
```js
|
|
76
|
-
import {
|
|
77
|
-
const
|
|
78
|
-
title: 'Contact Form',
|
|
79
|
-
fields: [
|
|
80
|
-
FormInput.from({ name: 'email', label: 'Email Address', type: 'email', required: true }),
|
|
81
|
-
FormInput.from({
|
|
82
|
-
name: 'message',
|
|
83
|
-
label: 'Your Message',
|
|
84
|
-
type: 'textarea',
|
|
85
|
-
required: true,
|
|
86
|
-
}),
|
|
87
|
-
],
|
|
88
|
-
state: {
|
|
89
|
-
email: 'invalid-email',
|
|
90
|
-
message: 'Hello!',
|
|
91
|
-
},
|
|
92
|
-
})
|
|
93
|
-
const { isValid, errors } = form.validate()
|
|
94
|
-
console.info(Object.keys(errors).length) // ← 1
|
|
95
|
-
console.info(errors.email) // ← Invalid email format
|
|
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
|
|
21
|
+
import { Models } from '@nan0web/ui'
|
|
22
|
+
const { HeaderModel } = Models
|
|
103
23
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
import { Welcome } from '@nan0web/ui'
|
|
107
|
-
const frame = Welcome({ user: { name: 'Alice' } })
|
|
108
|
-
const firstLine = frame[0].join('')
|
|
109
|
-
console.info(firstLine) // ← Welcome Alice!
|
|
24
|
+
const header = new HeaderModel({ title: 'My App' })
|
|
25
|
+
console.log(header.title)
|
|
110
26
|
```
|
|
111
|
-
### View Manager
|
|
112
|
-
|
|
113
|
-
`View` combines components and renders frames.
|
|
114
|
-
|
|
115
|
-
Every view has:
|
|
116
|
-
|
|
117
|
-
- Locale – formatted text, numbers, currency
|
|
118
|
-
- StdIn / StdOut – input/output streams
|
|
119
|
-
- Frame – output buffer with visual properties
|
|
120
|
-
|
|
121
|
-
How to render frame with View?
|
|
122
|
-
```js
|
|
123
|
-
import { View } from '@nan0web/ui'
|
|
124
|
-
const view = new View()
|
|
125
|
-
view.render(1)(['Hello, world'])
|
|
126
|
-
console.info(String(view.frame)) // ← "\rHello, world"
|
|
127
|
-
```
|
|
128
|
-
### Frame Rendering
|
|
129
|
-
|
|
130
|
-
`Frame` manages visual rendering with width and height limits.
|
|
131
|
-
Useful for fixed-size terminals or UI blocks.
|
|
132
|
-
|
|
133
|
-
Render methods:
|
|
134
|
-
|
|
135
|
-
- `APPEND` – adds content after previous frame
|
|
136
|
-
- `REPLACE` – erases and replaces full frame area
|
|
137
|
-
- `VISIBLE` – renders only visible part of frame
|
|
138
|
-
|
|
139
|
-
How to create a Frame with fixed size?
|
|
140
|
-
```js
|
|
141
|
-
import { Frame } from '@nan0web/ui'
|
|
142
|
-
const frame = new Frame({
|
|
143
|
-
value: [['Frame content']],
|
|
144
|
-
width: 20,
|
|
145
|
-
height: 5,
|
|
146
|
-
renderMethod: Frame.RenderMethod.APPEND,
|
|
147
|
-
})
|
|
148
|
-
const rendered = frame.render()
|
|
149
|
-
console.info(rendered.includes('Frame content')) // ← true
|
|
150
|
-
```
|
|
151
|
-
### Domain Models (v1.9.0)
|
|
152
|
-
|
|
153
|
-
v1.9.0 introduces a comprehensive set of domain models for layout and components.
|
|
154
|
-
These models follow the **Model-as-Schema** pattern.
|
|
155
|
-
|
|
156
|
-
#### Layout Models
|
|
157
|
-
- `HeaderModel` — title, logo, navigation actions
|
|
158
|
-
- `FooterModel` — copyright, version, social links
|
|
159
|
-
- `HeroModel` — prominent call-to-action
|
|
160
|
-
|
|
161
|
-
#### HTML5 Base Elements
|
|
162
|
-
Fully typed zero-cost support for standard tags: `div`, `span`, `p`, `h1`-`h6`, `a`, `ul`, `table`, etc., plus SVG basics (`svg`, `path`, `rect`). Data must be standard `camelCase`.
|
|
163
|
-
|
|
164
|
-
#### Component Models
|
|
165
|
-
- `PricingModel` / `PricingSection` — plans with features and prices
|
|
166
|
-
- `FeatureGrid` — grid of feature highlights
|
|
167
|
-
- `ProfileDropdown` — user avatar and settings menu
|
|
168
|
-
- `CommentModel` & `TestimonialModel` — social proof
|
|
169
|
-
- `StatsModel` — data visualizations
|
|
170
|
-
- `TimelineModel` — event history
|
|
171
|
-
|
|
172
|
-
How to use the new Header and Hero models?
|
|
173
|
-
```js
|
|
174
|
-
import { Model } from '@nan0web/ui'
|
|
175
|
-
const { HeaderModel, HeroModel } = Model
|
|
176
|
-
const header = new HeaderModel({
|
|
177
|
-
title: 'NaN•Web',
|
|
178
|
-
logo: '/logo.svg',
|
|
179
|
-
actions: [{ title: 'Docs', href: '/docs' }],
|
|
180
|
-
})
|
|
181
|
-
const hero = new HeroModel({
|
|
182
|
-
title: 'One Logic — Many UI',
|
|
183
|
-
actions: [{ title: 'Get Started', href: '/start' }],
|
|
184
|
-
})
|
|
185
|
-
console.info(header.title) // ← NaN•Web
|
|
186
|
-
console.info(hero.actions[0].title) // ← Get Started
|
|
187
|
-
```
|
|
188
|
-
### Intent Generators (v1.11.0)
|
|
189
|
-
|
|
190
|
-
From v1.11.0, Intent creators are standard named functions generating
|
|
191
|
-
strict interactions (ask, progress, show, render, result).
|
|
192
|
-
|
|
193
|
-
- `ask(field, schema)` — requests input from the environment.
|
|
194
|
-
- `progress(message)` — updates a visual loader.
|
|
195
|
-
- `show(message, level, data)` — displays a notification (replaces deprecated `log`).
|
|
196
|
-
- `render(component, props)` — renders a specific component view.
|
|
197
|
-
- `result(data)` — ends the model execution cleanly.
|
|
198
|
-
|
|
199
|
-
How to use Intent generators? (v1.11.0)
|
|
200
|
-
```js
|
|
201
|
-
import { ask, show, result } from '@nan0web/ui'
|
|
202
|
-
const nameIntent = ask('name', { help: 'Your name' })
|
|
203
|
-
const msgIntent = show('Processing...', 'info')
|
|
204
|
-
const endIntent = result({ ok: true })
|
|
205
|
-
```
|
|
206
|
-
### Testing UI (v1.11.0 Deterministic Testing)
|
|
207
|
-
|
|
208
|
-
Core unit-tested to ensure stability in different environments.
|
|
209
|
-
With **v1.11.0**, the architecture formally introduces `ScenarioTest` for zero-I/O deterministic testing.
|
|
210
|
-
|
|
211
|
-
By lifting the asynchronous logic and providing an explicit scenario array, models are evaluated instantly without waiting on user prompt delays.
|
|
212
|
-
|
|
213
|
-
How to test Model pipelines deterministically?
|
|
214
|
-
```js
|
|
215
|
-
import { ModelAsApp, ask, result, show } from '@nan0web/ui'
|
|
216
|
-
import { ScenarioTest } from '@nan0web/ui/test/ScenarioTest.js'
|
|
217
|
-
const { ModelAsApp, ask, result, show } = await import('./index.js')
|
|
218
|
-
const { ScenarioTest } = await import('./test/ScenarioTest.js')
|
|
219
|
-
class ShoppingCartApp extends ModelAsApp {
|
|
220
|
-
*run() {
|
|
221
|
-
const product = yield ask('product', { help: 'Select product' })
|
|
222
|
-
if (product?.value === 'laptop') {
|
|
223
|
-
yield show('Good choice!', 'ok')
|
|
224
|
-
}
|
|
225
|
-
const confirm = yield ask('confirm', { help: 'Confirm purchase?' })
|
|
226
|
-
return result({ product: product?.value, confirm: confirm?.value })
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
const res = await ScenarioTest.run(ShoppingCartApp, [
|
|
230
|
-
{ field: 'product', value: 'laptop' },
|
|
231
|
-
{ field: 'confirm', value: true }
|
|
232
|
-
])
|
|
233
|
-
```
|
|
234
|
-
You can also verify exceptions and validation rules by observing the final error in ScenarioTest.
|
|
235
|
-
|
|
236
|
-
How to test validation errors with ScenarioTest?
|
|
237
|
-
```js
|
|
238
|
-
import { ModelAsApp, ask, result } from '@nan0web/ui'
|
|
239
|
-
import { ScenarioTest } from '@nan0web/ui/test/ScenarioTest.js'
|
|
240
|
-
const { ModelAsApp, ask, result } = await import('./index.js')
|
|
241
|
-
const { ScenarioTest } = await import('./test/ScenarioTest.js')
|
|
242
|
-
class ValidatedApp extends ModelAsApp {
|
|
243
|
-
*run() {
|
|
244
|
-
const code = yield ask('code', { help: 'Enter code', required: true })
|
|
245
|
-
if (!code?.value) throw new Error('Code is mandatory')
|
|
246
|
-
return result({ code: code?.value })
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
const res = await ScenarioTest.run(ValidatedApp, [
|
|
250
|
-
{ field: 'code', value: '' } // Simulating empty response
|
|
251
|
-
])
|
|
252
|
-
```
|
|
253
|
-
### Story Testing (.nan0 spec files)
|
|
254
|
-
|
|
255
|
-
The `SpecRunner.executeFile` helper allows running `.nan0` spec stories automatically without boilerplate DBFS setup.
|
|
256
|
-
All manual assertions are omitted because `SpecAdapter` handles strict expectation matching internally.
|
|
257
|
-
|
|
258
|
-
How to execute .nan0 spec files automatically?
|
|
259
|
-
```js
|
|
260
|
-
import { SpecRunner } from '@nan0web/ui/testing'
|
|
261
|
-
const { SpecRunner } = await import('./testing/index.js')
|
|
262
|
-
```
|
|
263
|
-
All components, adapters, and models are designed to be testable
|
|
264
|
-
with minimal setup.
|
|
265
|
-
|
|
266
|
-
How to test visual UI components with assertions?
|
|
267
|
-
```js
|
|
268
|
-
import { Welcome } from '@nan0web/ui'
|
|
269
|
-
const output = Welcome({ user: { name: 'Test' } })
|
|
270
|
-
console.info(output) // ← Welcome Test!
|
|
271
|
-
```
|
|
272
|
-
### Master IDE (Component Sandbox)
|
|
273
|
-
|
|
274
|
-
The Master IDE (OlmuiInspector) provides a unified environment for testing and documenting
|
|
275
|
-
web components across platforms. It supports:
|
|
276
|
-
|
|
277
|
-
- **NaN0 Spec** — a concise YAML-based shorthand for declaring component variations.
|
|
278
|
-
- **OlmuiInspector** — unified UI for exploring component models and props.
|
|
279
|
-
- **Live Preview** — real-time rendering of component states.
|
|
280
|
-
- **i18n UI** — fully localized interface (UK/EN) for global developers.
|
|
281
|
-
- **Theme Editor** — Bootstrap-like CSS variable system with live preview.
|
|
282
|
-
|
|
283
|
-
It follows the **Olmui** core pattern: *One Logic — Many UI* (same manifest powers both CLI and Web).
|
|
284
|
-
|
|
285
|
-
#### Theme Editor (CSS Variables)
|
|
286
|
-
|
|
287
|
-
Professional-grade theming with live preview. Supports:
|
|
288
|
-
|
|
289
|
-
- **Palette**: primary, secondary, success, warning, danger, info
|
|
290
|
-
- **Geometry**: border-radius (sm/md/lg/pill/circle), spacing (sm/md/lg)
|
|
291
|
-
- **Type-safe inputs**: `type="color"` for colors, number inputs for dimensions
|
|
292
|
-
|
|
293
|
-
#### Component Rendering Architecture
|
|
294
|
-
|
|
295
|
-
The IDE handles data transformation between YAML models and web components:
|
|
296
|
-
|
|
297
|
-
- **Table**: `rows[][] + columns[]` → `data[]` (array of objects)
|
|
298
|
-
- **Tree**: `data` → `items` mapping with 4-level taxonomy
|
|
299
|
-
- **Markdown**: Raw markdown → HTML via `_md2html()` converter
|
|
300
|
-
- **ProgressBar**: Tag alias (`ui-progress-bar` → `ui-progress`), variant colors
|
|
301
|
-
- **LangSelect**: `string[]` → `{code,title}[]` conversion
|
|
302
|
-
- **Hyphenated props**: Auto `camelCase` conversion (`show-label` → `showLabel`)
|
|
303
|
-
|
|
304
|
-
#### NaN0 Spec (YAML)
|
|
305
|
-
|
|
306
|
-
Concise format for defining variations:
|
|
307
|
-
|
|
308
|
-
How to define a component variation using NaN0 Spec?
|
|
309
|
-
```yaml
|
|
310
|
-
- Button: Primary
|
|
311
|
-
$variant: brand
|
|
312
|
-
$outline: true
|
|
313
|
-
```
|
|
314
|
-
|
|
315
|
-
#### Documentation Site
|
|
316
|
-
|
|
317
|
-
The IDE includes an auto-generated documentation site.
|
|
318
|
-
HTML pages are generated from `ide.html` template via `generate-pages.js`:
|
|
319
|
-
|
|
320
|
-
- Per-language pages (`/uk/Data/Table.html`, `/en/Feedback/Alert.html`)
|
|
321
|
-
- SEO-optimized with `<title>` and `<meta>` per component
|
|
322
|
-
- Category-based URL routing (`/Data/`, `/Feedback/`, `/Forms/`, `/Actions/`, `/System/`)
|
|
323
|
-
- i18n navbar with `data-i18n` attributes
|
|
324
|
-
|
|
325
|
-
How to run the documentation site?
|
|
326
|
-
```bash
|
|
327
|
-
npm run docs:dev
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
## Playground Demos
|
|
331
|
-
|
|
332
|
-
The library includes rich playground demos:
|
|
333
|
-
|
|
334
|
-
- [Registration Form](./play/registration.form.js)
|
|
335
|
-
- [Currency Exchange](./play/currency.exchange.js)
|
|
336
|
-
- [Mobile Top-up](./play/topup.telephone.js)
|
|
337
|
-
- [Language Selector](./play/language.form.js)
|
|
338
|
-
|
|
339
|
-
Run to explore live functionality:
|
|
340
|
-
|
|
341
|
-
How to run the playground?
|
|
342
|
-
```bash
|
|
343
|
-
# Clone repository and run playground
|
|
344
|
-
git clone https://github.com/nan0web/ui.git
|
|
345
|
-
cd ui
|
|
346
|
-
npm install
|
|
347
|
-
npm run play
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
## API Documentation
|
|
351
|
-
|
|
352
|
-
Detailed API docs are available in each class JSDoc.
|
|
353
|
-
Explore:
|
|
354
|
-
|
|
355
|
-
- [Messages](./src/core/Message/)
|
|
356
|
-
- [Forms](./src/core/Form/)
|
|
357
|
-
- [Stream](./src/core/Stream.js)
|
|
358
|
-
- [Components](./src/Component/)
|
|
359
|
-
- [View](./src/View/)
|
|
360
|
-
- [App](./src/App/)
|
|
361
|
-
- [Models](./src/Model/)
|
|
362
|
-
|
|
363
|
-
## Project Architecture & Specs
|
|
364
|
-
|
|
365
|
-
How the universal block spec is designed? - [check Universal Blocks Spec (`project.md`)](./project.md)
|
|
366
|
-
|
|
367
|
-
## Contributing
|
|
368
27
|
|
|
369
|
-
|
|
28
|
+
## Resources / Ресурси
|
|
370
29
|
|
|
371
|
-
|
|
30
|
+
- 🏴 [Project Architecture (`project.md`)](./docs/en/project.md)
|
|
31
|
+
- 🇺🇦 [Архітектура проєкту (`project.md`)](./docs/uk/project.md)
|
|
32
|
+
- [Contributing](./CONTRIBUTING.md)
|
|
33
|
+
- [License (ISC)](./LICENSE)
|
|
372
34
|
|
|
373
|
-
|
|
35
|
+
---
|
|
36
|
+
© 2026 nan0web
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nan0web/ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"description": "NaN•Web UI. One application logic (algorithm) and many UI.",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"types": "types/index.d.ts",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"files": [
|
|
9
9
|
"src/**/*.js",
|
|
10
10
|
"!src/**/*.test.js",
|
|
11
|
-
"!src/
|
|
11
|
+
"!src/docs/**/*.md.js",
|
|
12
12
|
"types/**/*.d.ts"
|
|
13
13
|
],
|
|
14
14
|
"exports": {
|
|
@@ -32,6 +32,10 @@
|
|
|
32
32
|
"import": "./src/domain/index.js",
|
|
33
33
|
"types": "./types/domain/index.d.ts"
|
|
34
34
|
},
|
|
35
|
+
"./models": {
|
|
36
|
+
"import": "./src/Model/index.js",
|
|
37
|
+
"types": "./types/Model/index.d.ts"
|
|
38
|
+
},
|
|
35
39
|
"./inspect": {
|
|
36
40
|
"import": "./src/inspect.js",
|
|
37
41
|
"types": "./types/inspect.d.ts"
|
|
@@ -52,11 +56,20 @@
|
|
|
52
56
|
"nan0web": {
|
|
53
57
|
"workflowDir": "docs/{locale}/workflows",
|
|
54
58
|
"workflows": [
|
|
55
|
-
"
|
|
56
|
-
"olm-ui-architecture-core.md",
|
|
57
|
-
"olm-ui-architecture-adapters.md",
|
|
59
|
+
"architecture.md",
|
|
58
60
|
"forge-component.md",
|
|
59
|
-
"interface-welding.md"
|
|
61
|
+
"interface-welding.md",
|
|
62
|
+
"nan0web-v2-roadmap.md",
|
|
63
|
+
"nan0web.md",
|
|
64
|
+
"olm-ui-architecture-adapters.md",
|
|
65
|
+
"olm-ui-architecture-core.md",
|
|
66
|
+
"olm-ui-architecture-i18n.md",
|
|
67
|
+
"olm-ui-architecture-testing.md",
|
|
68
|
+
"olm-ui-architecture.md",
|
|
69
|
+
"pipeline-no4-adapter.md",
|
|
70
|
+
"pipeline-no7-ui-web.md",
|
|
71
|
+
"pipeline-no8-ui-mobile.md",
|
|
72
|
+
"ui-update.md"
|
|
60
73
|
],
|
|
61
74
|
"inspectors": [
|
|
62
75
|
"./src/domain/app/SnapshotAuditor.js"
|
|
@@ -67,6 +80,7 @@
|
|
|
67
80
|
"devDependencies": {
|
|
68
81
|
"@playwright/test": "^1.58.2",
|
|
69
82
|
"@rollup/plugin-yaml": "^4.1.2",
|
|
83
|
+
"@types/node": "^25.6.0",
|
|
70
84
|
"@vitest/coverage-v8": "^3.2.4",
|
|
71
85
|
"husky": "^9.1.7",
|
|
72
86
|
"js-yaml": "^4.1.1",
|
|
@@ -74,23 +88,23 @@
|
|
|
74
88
|
"lit": "^3.3.2",
|
|
75
89
|
"vite": "^6.4.1",
|
|
76
90
|
"vitest": "^3.2.4",
|
|
77
|
-
"@nan0web/db-fs": "1.
|
|
78
|
-
"@nan0web/
|
|
79
|
-
"@nan0web/
|
|
80
|
-
"@nan0web/inspect": "1.0
|
|
81
|
-
"@nan0web/test": "
|
|
82
|
-
"@nan0web/ui-
|
|
83
|
-
"@nan0web/
|
|
84
|
-
"@nan0web/
|
|
85
|
-
"@nan0web/
|
|
86
|
-
"@nan0web/nan0web.app": "0.1.0"
|
|
91
|
+
"@nan0web/db-fs": "3.1.0",
|
|
92
|
+
"@nan0web/i18n": "3.1.0",
|
|
93
|
+
"@nan0web/icons": "3.1.0",
|
|
94
|
+
"@nan0web/inspect": "3.1.0",
|
|
95
|
+
"@nan0web/test": "3.1.0",
|
|
96
|
+
"@nan0web/ui-lit": "3.1.0",
|
|
97
|
+
"@nan0web/ui-cli": "3.1.0",
|
|
98
|
+
"@nan0web/nan0web.app": "3.1.0",
|
|
99
|
+
"@nan0web/release": "3.1.0"
|
|
87
100
|
},
|
|
88
101
|
"dependencies": {
|
|
89
102
|
"string-width": "^7.2.0",
|
|
90
|
-
"@nan0web/co": "
|
|
91
|
-
"@nan0web/core": "
|
|
92
|
-
"@nan0web/
|
|
93
|
-
"@nan0web/log": "
|
|
103
|
+
"@nan0web/co": "3.1.0",
|
|
104
|
+
"@nan0web/core": "3.1.0",
|
|
105
|
+
"@nan0web/event": "3.1.0",
|
|
106
|
+
"@nan0web/log": "3.1.0",
|
|
107
|
+
"@nan0web/types": "3.1.0"
|
|
94
108
|
},
|
|
95
109
|
"scripts": {
|
|
96
110
|
"prebuild": "rm -rf types/",
|
|
@@ -101,14 +115,14 @@
|
|
|
101
115
|
"test:nan0test": "node --test --test-timeout=3333 \"src/**/*.test.js\" | nan0test parse --fail",
|
|
102
116
|
"test:coverage": "node --experimental-test-coverage --test-coverage-include=\"src/**/*.js\" --test-coverage-exclude=\"src/**/*.test.js\" --test \"src/**/*.test.js\"",
|
|
103
117
|
"test:coverage:collect": "nan0test coverage",
|
|
104
|
-
"test:docs": "node --test src/
|
|
118
|
+
"test:docs": "node --test --test-timeout=3333 'src/docs/**/*.md.js'",
|
|
105
119
|
"release:spec": "node --test \"src/test/releases/**/*.test.js\"",
|
|
106
120
|
"test:release": "node --test \"src/test/releases/**/*.test.js\"",
|
|
107
121
|
"test:status": "nan0test status --hide-name",
|
|
108
122
|
"test:play": "node --test --test-timeout=3333 \"play/**/*.test.js\"",
|
|
109
123
|
"test:snapshots": "node src/testing/GalleryGenerator.js",
|
|
110
124
|
"test:gallery": "npm run test:snapshots && npx nan0gallery --dir=snapshots/core",
|
|
111
|
-
"test:audit": "nan0cli
|
|
125
|
+
"test:audit": "nan0cli snapshots --dir snapshots/core --data .",
|
|
112
126
|
"test:stories": "node --test \"src/**/*.story.js\"",
|
|
113
127
|
"test:all": "npm run test && npm run test:docs && npm run test:play && npm run test:stories && npm run knip",
|
|
114
128
|
"knip": "knip --production",
|
package/src/Component/index.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
import Welcome from './Welcome/index.js'
|
|
2
|
-
import Process from './Process/index.js'
|
|
3
1
|
import SortableList from './SortableList/index.js'
|
|
4
2
|
|
|
5
|
-
export {
|
|
3
|
+
export { SortableList }
|
|
6
4
|
|
|
7
5
|
export default {
|
|
8
|
-
Welcome,
|
|
9
|
-
Process,
|
|
10
6
|
SortableList,
|
|
11
7
|
}
|