@nan0web/ui 1.5.2 → 1.6.2

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 CHANGED
@@ -182,10 +182,30 @@ web components across platforms. It supports:
182
182
  - **NaN0 Spec** — a concise YAML-based shorthand for declaring component variations.
183
183
  - **OlmuiInspector** — unified UI for exploring component models and props.
184
184
  - **Live Preview** — real-time rendering of component states.
185
- - **i18n UI** — fully localized interface for global developers.
185
+ - **i18n UI** — fully localized interface (UK/EN) for global developers.
186
+ - **Theme Editor** — Bootstrap-like CSS variable system with live preview.
186
187
 
187
188
  It follows the **Olmui** core pattern: *One Logic — Many UI* (same manifest powers both CLI and Web).
188
189
 
190
+ #### Theme Editor (CSS Variables)
191
+
192
+ Professional-grade theming with live preview. Supports:
193
+
194
+ - **Palette**: primary, secondary, success, warning, danger, info
195
+ - **Geometry**: border-radius (sm/md/lg/pill/circle), spacing (sm/md/lg)
196
+ - **Type-safe inputs**: `type="color"` for colors, number inputs for dimensions
197
+
198
+ #### Component Rendering Architecture
199
+
200
+ The IDE handles data transformation between YAML models and web components:
201
+
202
+ - **Table**: `rows[][] + columns[]` → `data[]` (array of objects)
203
+ - **Tree**: `data` → `items` mapping with 4-level taxonomy
204
+ - **Markdown**: Raw markdown → HTML via `_md2html()` converter
205
+ - **ProgressBar**: Tag alias (`ui-progress-bar` → `ui-progress`), variant colors
206
+ - **LangSelect**: `string[]` → `{code,title}[]` conversion
207
+ - **Hyphenated props**: Auto `camelCase` conversion (`show-label` → `showLabel`)
208
+
189
209
  #### NaN0 Spec (YAML)
190
210
 
191
211
  Concise format for defining variations:
@@ -197,6 +217,21 @@ How to define a component variation using NaN0 Spec?
197
217
  $outline: true
198
218
  ```
199
219
 
220
+ #### Documentation Site
221
+
222
+ The IDE includes an auto-generated documentation site.
223
+ HTML pages are generated from `ide.html` template via `generate-pages.js`:
224
+
225
+ - Per-language pages (`/uk/Data/Table.html`, `/en/Feedback/Alert.html`)
226
+ - SEO-optimized with `<title>` and `<meta>` per component
227
+ - Category-based URL routing (`/Data/`, `/Feedback/`, `/Forms/`, `/Actions/`, `/System/`)
228
+ - i18n navbar with `data-i18n` attributes
229
+
230
+ How to run the documentation site?
231
+ ```bash
232
+ npm run docs:dev
233
+ ```
234
+
200
235
  ## Playground Demos
201
236
 
202
237
  The library includes rich playground demos:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nan0web/ui",
3
- "version": "1.5.2",
3
+ "version": "1.6.2",
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",
@@ -22,7 +22,8 @@
22
22
  "test:release": "node --test \"releases/**/*.test.js\"",
23
23
  "test:status": "nan0test status --hide-name",
24
24
  "test:play": "node --test --test-timeout=3333 \"play/**/*.test.js\"",
25
- "test:e2e": "playwright test",
25
+ "test:e2e": "playwright test --ignore-snapshots e2e/components.spec.js e2e/debug-label.spec.js",
26
+ "test:e2e:slow": "E2E_SLOW=1 playwright test e2e/visual.spec.js",
26
27
  "test:all": "npm run test && npm run test:docs && npm run test:play && npm run test:e2e && npm run build && npm run knip",
27
28
  "knip": "knip --production",
28
29
  "precommit": "npm test",
@@ -0,0 +1,111 @@
1
+ /**
2
+ * ArchitectureMap — a cross-package component readiness registry.
3
+ *
4
+ * Tracks which UI components are implemented in which packages
5
+ * (ui-lit, ui-cli, ui-react-bootstrap, etc.) and provides
6
+ * a programmatic readiness matrix.
7
+ *
8
+ * @example
9
+ * const map = new ArchitectureMap()
10
+ * map.register('ui-lit', ['Button', 'Input', 'Select'])
11
+ * map.register('ui-cli', ['Button', 'Input'])
12
+ * map.getMatrix()
13
+ * // → { Button: { 'ui-lit': true, 'ui-cli': true },
14
+ * // Input: { 'ui-lit': true, 'ui-cli': true },
15
+ * // Select: { 'ui-lit': true, 'ui-cli': false } }
16
+ * map.getReadiness('Button') // → true (in all packages)
17
+ * map.getReadiness('Select') // → false (missing from ui-cli)
18
+ */
19
+ export default class ArchitectureMap {
20
+ /** @type {Map<string, Set<string>>} packageName → Set of component names */
21
+ #packages = new Map()
22
+
23
+ /** @type {Set<string>} all known component names */
24
+ #components = new Set()
25
+
26
+ /**
27
+ * Register a package and its exported components.
28
+ *
29
+ * @param {string} packageName — e.g. 'ui-lit', 'ui-cli', 'ui-react-bootstrap'
30
+ * @param {string[]} componentsList — e.g. ['Button', 'Input', 'Select']
31
+ */
32
+ register(packageName, componentsList = []) {
33
+ this.#packages.set(packageName, new Set(componentsList))
34
+ for (const name of componentsList) {
35
+ this.#components.add(name)
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Get the list of all registered package names.
41
+ *
42
+ * @returns {string[]}
43
+ */
44
+ getPackages() {
45
+ return [...this.#packages.keys()]
46
+ }
47
+
48
+ /**
49
+ * Get all known component names (union of all packages).
50
+ *
51
+ * @returns {string[]}
52
+ */
53
+ getComponents() {
54
+ return [...this.#components].sort()
55
+ }
56
+
57
+ /**
58
+ * Build a readiness matrix: { componentName → { packageName → boolean } }.
59
+ *
60
+ * Every known component gets an entry for every registered package.
61
+ *
62
+ * @returns {Object<string, Object<string, boolean>>}
63
+ */
64
+ getMatrix() {
65
+ const packages = this.getPackages()
66
+ /** @type {Object<string, Object<string, boolean>>} */
67
+ const matrix = {}
68
+
69
+ for (const comp of this.#components) {
70
+ matrix[comp] = {}
71
+ for (const pkg of packages) {
72
+ matrix[comp][pkg] = this.#packages.get(pkg)?.has(comp) ?? false
73
+ }
74
+ }
75
+
76
+ return matrix
77
+ }
78
+
79
+ /**
80
+ * Check if a component is implemented in ALL registered packages.
81
+ *
82
+ * @param {string} componentName
83
+ * @returns {boolean}
84
+ */
85
+ getReadiness(componentName) {
86
+ if (this.#packages.size === 0) return false
87
+ for (const components of this.#packages.values()) {
88
+ if (!components.has(componentName)) return false
89
+ }
90
+ return true
91
+ }
92
+
93
+ /**
94
+ * Get a summary: { total, ready, notReady, readyPercent }.
95
+ *
96
+ * @returns {{ total: number, ready: number, notReady: number, readyPercent: number }}
97
+ */
98
+ getSummary() {
99
+ const components = this.getComponents()
100
+ const total = components.length
101
+ const ready = components.filter((c) => this.getReadiness(c)).length
102
+ return {
103
+ total,
104
+ ready,
105
+ notReady: total - ready,
106
+ readyPercent: total > 0 ? Math.round((ready / total) * 100) : 0,
107
+ }
108
+ }
109
+ }
110
+
111
+ export { ArchitectureMap }
@@ -0,0 +1 @@
1
+ export { default, ArchitectureMap } from './ArchitectureMap.js'
@@ -0,0 +1,95 @@
1
+ /**
2
+ * InterfaceTemplate — base class for defining new UI interfaces.
3
+ *
4
+ * Establishes the inheritance pattern for the "One Logic, Many UI" architecture.
5
+ * Each UI interface (CLI, Web, Mobile, Chat, Audio) extends this template
6
+ * and overrides the required methods.
7
+ *
8
+ * @example
9
+ * class CliInterface extends InterfaceTemplate {
10
+ * render(data) { return formatForTerminal(data) }
11
+ * async ask(prompt) { return readlinePrompt(prompt) }
12
+ * }
13
+ *
14
+ * @abstract
15
+ */
16
+ export default class InterfaceTemplate {
17
+ /**
18
+ * List of methods that MUST be overridden by concrete implementations.
19
+ * Used for documentation and runtime validation.
20
+ *
21
+ * @type {string[]}
22
+ */
23
+ static requiredMethods = ['render', 'ask']
24
+
25
+ /**
26
+ * The name of this interface (e.g. 'cli', 'web', 'mobile').
27
+ * Override in subclass.
28
+ *
29
+ * @type {string}
30
+ */
31
+ name = 'base'
32
+
33
+ /**
34
+ * Render data to the user through the interface.
35
+ * Must be overridden by each concrete implementation.
36
+ *
37
+ * @param {any} [data] - data to render
38
+ * @returns {any} rendered output (string for CLI, DOM for web, etc.)
39
+ * @throws {Error} if not overridden
40
+ */
41
+ render(data) {
42
+ throw new Error(
43
+ `InterfaceTemplate.render() must be overridden by ${this.name || 'subclass'}. ` +
44
+ 'This is the primary output method for the interface.',
45
+ )
46
+ }
47
+
48
+ /**
49
+ * Request input from the user through the interface.
50
+ * Must be overridden by each concrete implementation.
51
+ *
52
+ * @param {string} prompt - question or label for the input
53
+ * @param {object} [options] - options (type, choices, default, etc.)
54
+ * @returns {Promise<any>} user's response
55
+ * @throws {Error} if not overridden
56
+ */
57
+ async ask(prompt, options = {}) {
58
+ throw new Error(
59
+ `InterfaceTemplate.ask() must be overridden by ${this.name || 'subclass'}. ` +
60
+ 'This is the primary input method for the interface.',
61
+ )
62
+ }
63
+
64
+ /**
65
+ * Validate that all required methods have been overridden.
66
+ * Call this in the subclass constructor to get early feedback.
67
+ *
68
+ * @returns {string[]} list of missing method overrides (empty = valid)
69
+ */
70
+ validate() {
71
+ const missing = []
72
+ for (const method of InterfaceTemplate.requiredMethods) {
73
+ if (this[method] === InterfaceTemplate.prototype[method]) {
74
+ missing.push(method)
75
+ }
76
+ }
77
+ return missing
78
+ }
79
+
80
+ /**
81
+ * Get interface capabilities info.
82
+ *
83
+ * @returns {{ name: string, requiredMethods: string[], isComplete: boolean }}
84
+ */
85
+ info() {
86
+ const missing = this.validate()
87
+ return {
88
+ name: this.name,
89
+ requiredMethods: [...InterfaceTemplate.requiredMethods],
90
+ isComplete: missing.length === 0,
91
+ }
92
+ }
93
+ }
94
+
95
+ export { InterfaceTemplate }
@@ -0,0 +1 @@
1
+ export { default, InterfaceTemplate } from './InterfaceTemplate.js'
package/src/README.md.js CHANGED
@@ -288,10 +288,30 @@ function testRender() {
288
288
  * - **NaN0 Spec** — a concise YAML-based shorthand for declaring component variations.
289
289
  * - **OlmuiInspector** — unified UI for exploring component models and props.
290
290
  * - **Live Preview** — real-time rendering of component states.
291
- * - **i18n UI** — fully localized interface for global developers.
291
+ * - **i18n UI** — fully localized interface (UK/EN) for global developers.
292
+ * - **Theme Editor** — Bootstrap-like CSS variable system with live preview.
292
293
  *
293
294
  * It follows the **Olmui** core pattern: *One Logic — Many UI* (same manifest powers both CLI and Web).
294
295
  *
296
+ * #### Theme Editor (CSS Variables)
297
+ *
298
+ * Professional-grade theming with live preview. Supports:
299
+ *
300
+ * - **Palette**: primary, secondary, success, warning, danger, info
301
+ * - **Geometry**: border-radius (sm/md/lg/pill/circle), spacing (sm/md/lg)
302
+ * - **Type-safe inputs**: `type="color"` for colors, number inputs for dimensions
303
+ *
304
+ * #### Component Rendering Architecture
305
+ *
306
+ * The IDE handles data transformation between YAML models and web components:
307
+ *
308
+ * - **Table**: `rows[][] + columns[]` → `data[]` (array of objects)
309
+ * - **Tree**: `data` → `items` mapping with 4-level taxonomy
310
+ * - **Markdown**: Raw markdown → HTML via `_md2html()` converter
311
+ * - **ProgressBar**: Tag alias (`ui-progress-bar` → `ui-progress`), variant colors
312
+ * - **LangSelect**: `string[]` → `{code,title}[]` conversion
313
+ * - **Hyphenated props**: Auto `camelCase` conversion (`show-label` → `showLabel`)
314
+ *
295
315
  * #### NaN0 Spec (YAML)
296
316
  *
297
317
  * Concise format for defining variations:
@@ -307,6 +327,27 @@ function testRender() {
307
327
  assert.ok(pkg.name === '@nan0web/ui')
308
328
  })
309
329
 
330
+ /**
331
+ * @docs
332
+ * #### Documentation Site
333
+ *
334
+ * The IDE includes an auto-generated documentation site.
335
+ * HTML pages are generated from `ide.html` template via `generate-pages.js`:
336
+ *
337
+ * - Per-language pages (`/uk/Data/Table.html`, `/en/Feedback/Alert.html`)
338
+ * - SEO-optimized with `<title>` and `<meta>` per component
339
+ * - Category-based URL routing (`/Data/`, `/Feedback/`, `/Forms/`, `/Actions/`, `/System/`)
340
+ * - i18n navbar with `data-i18n` attributes
341
+ */
342
+ it('How to run the documentation site?', () => {
343
+ /**
344
+ * ```bash
345
+ * npm run docs:dev
346
+ * ```
347
+ */
348
+ assert.ok(pkg.scripts?.['docs:dev'])
349
+ })
350
+
310
351
  /**
311
352
  * @docs
312
353
  * ## Playground Demos
@@ -0,0 +1,70 @@
1
+ /**
2
+ * ArchitectureMap — a cross-package component readiness registry.
3
+ *
4
+ * Tracks which UI components are implemented in which packages
5
+ * (ui-lit, ui-cli, ui-react-bootstrap, etc.) and provides
6
+ * a programmatic readiness matrix.
7
+ *
8
+ * @example
9
+ * const map = new ArchitectureMap()
10
+ * map.register('ui-lit', ['Button', 'Input', 'Select'])
11
+ * map.register('ui-cli', ['Button', 'Input'])
12
+ * map.getMatrix()
13
+ * // → { Button: { 'ui-lit': true, 'ui-cli': true },
14
+ * // Input: { 'ui-lit': true, 'ui-cli': true },
15
+ * // Select: { 'ui-lit': true, 'ui-cli': false } }
16
+ * map.getReadiness('Button') // → true (in all packages)
17
+ * map.getReadiness('Select') // → false (missing from ui-cli)
18
+ */
19
+ export default class ArchitectureMap {
20
+ /**
21
+ * Register a package and its exported components.
22
+ *
23
+ * @param {string} packageName — e.g. 'ui-lit', 'ui-cli', 'ui-react-bootstrap'
24
+ * @param {string[]} componentsList — e.g. ['Button', 'Input', 'Select']
25
+ */
26
+ register(packageName: string, componentsList?: string[]): void;
27
+ /**
28
+ * Get the list of all registered package names.
29
+ *
30
+ * @returns {string[]}
31
+ */
32
+ getPackages(): string[];
33
+ /**
34
+ * Get all known component names (union of all packages).
35
+ *
36
+ * @returns {string[]}
37
+ */
38
+ getComponents(): string[];
39
+ /**
40
+ * Build a readiness matrix: { componentName → { packageName → boolean } }.
41
+ *
42
+ * Every known component gets an entry for every registered package.
43
+ *
44
+ * @returns {Object<string, Object<string, boolean>>}
45
+ */
46
+ getMatrix(): {
47
+ [x: string]: {
48
+ [x: string]: boolean;
49
+ };
50
+ };
51
+ /**
52
+ * Check if a component is implemented in ALL registered packages.
53
+ *
54
+ * @param {string} componentName
55
+ * @returns {boolean}
56
+ */
57
+ getReadiness(componentName: string): boolean;
58
+ /**
59
+ * Get a summary: { total, ready, notReady, readyPercent }.
60
+ *
61
+ * @returns {{ total: number, ready: number, notReady: number, readyPercent: number }}
62
+ */
63
+ getSummary(): {
64
+ total: number;
65
+ ready: number;
66
+ notReady: number;
67
+ readyPercent: number;
68
+ };
69
+ #private;
70
+ }
@@ -0,0 +1 @@
1
+ export { default, ArchitectureMap } from "./ArchitectureMap.js";
@@ -0,0 +1,67 @@
1
+ /**
2
+ * InterfaceTemplate — base class for defining new UI interfaces.
3
+ *
4
+ * Establishes the inheritance pattern for the "One Logic, Many UI" architecture.
5
+ * Each UI interface (CLI, Web, Mobile, Chat, Audio) extends this template
6
+ * and overrides the required methods.
7
+ *
8
+ * @example
9
+ * class CliInterface extends InterfaceTemplate {
10
+ * render(data) { return formatForTerminal(data) }
11
+ * async ask(prompt) { return readlinePrompt(prompt) }
12
+ * }
13
+ *
14
+ * @abstract
15
+ */
16
+ export default class InterfaceTemplate {
17
+ /**
18
+ * List of methods that MUST be overridden by concrete implementations.
19
+ * Used for documentation and runtime validation.
20
+ *
21
+ * @type {string[]}
22
+ */
23
+ static requiredMethods: string[];
24
+ /**
25
+ * The name of this interface (e.g. 'cli', 'web', 'mobile').
26
+ * Override in subclass.
27
+ *
28
+ * @type {string}
29
+ */
30
+ name: string;
31
+ /**
32
+ * Render data to the user through the interface.
33
+ * Must be overridden by each concrete implementation.
34
+ *
35
+ * @param {any} [data] - data to render
36
+ * @returns {any} rendered output (string for CLI, DOM for web, etc.)
37
+ * @throws {Error} if not overridden
38
+ */
39
+ render(data?: any): any;
40
+ /**
41
+ * Request input from the user through the interface.
42
+ * Must be overridden by each concrete implementation.
43
+ *
44
+ * @param {string} prompt - question or label for the input
45
+ * @param {object} [options] - options (type, choices, default, etc.)
46
+ * @returns {Promise<any>} user's response
47
+ * @throws {Error} if not overridden
48
+ */
49
+ ask(prompt: string, options?: object): Promise<any>;
50
+ /**
51
+ * Validate that all required methods have been overridden.
52
+ * Call this in the subclass constructor to get early feedback.
53
+ *
54
+ * @returns {string[]} list of missing method overrides (empty = valid)
55
+ */
56
+ validate(): string[];
57
+ /**
58
+ * Get interface capabilities info.
59
+ *
60
+ * @returns {{ name: string, requiredMethods: string[], isComplete: boolean }}
61
+ */
62
+ info(): {
63
+ name: string;
64
+ requiredMethods: string[];
65
+ isComplete: boolean;
66
+ };
67
+ }
@@ -0,0 +1 @@
1
+ export { default, InterfaceTemplate } from "./InterfaceTemplate.js";