@nan0web/ui 1.9.0 → 1.11.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 +97 -12
- package/package.json +54 -25
- package/src/App/Command/DepsCommand.js +3 -4
- package/src/Frame/Props.js +12 -18
- package/src/InterfaceTemplate/InterfaceTemplate.js +9 -7
- package/src/Model/index.js +86 -2
- package/src/StdIn.js +2 -6
- package/src/cli.js +1 -0
- package/src/core/Form/Form.js +8 -7
- package/src/core/Form/Message.js +1 -1
- package/src/core/GeneratorRunner.js +77 -7
- package/src/core/InputAdapter.js +3 -1
- package/src/core/Intent.js +214 -16
- package/src/core/IntentErrorModel.js +6 -1
- package/src/core/Message/Message.js +4 -7
- package/src/core/Message/OutputMessage.js +4 -9
- package/src/core/Stream.js +16 -5
- package/src/core/StreamEntry.js +20 -28
- package/src/core/index.js +2 -1
- package/src/domain/Content.js +196 -0
- package/src/domain/Document.js +17 -0
- package/src/domain/FooterModel.js +37 -19
- package/src/domain/HeaderModel.js +47 -21
- package/src/domain/HeroModel.js +24 -22
- package/src/domain/LayoutModel.js +43 -0
- package/src/domain/ModelAsApp.js +46 -0
- package/src/domain/SandboxModel.js +19 -16
- package/src/domain/app/GalleryCommand.js +53 -0
- package/src/domain/app/GalleryRenderIntent.js +77 -0
- package/src/domain/app/SnapshotAuditor.js +401 -0
- package/src/domain/app/SnapshotRunner.js +264 -0
- package/src/domain/app/UIApp.js +78 -0
- package/src/domain/components/BreadcrumbModel.js +10 -6
- package/src/domain/components/FeatureGridModel.js +62 -0
- package/src/domain/components/MarkdownModel.js +24 -0
- package/src/domain/components/ShellModel.js +243 -0
- package/src/domain/components/TableModel.js +10 -6
- package/src/domain/components/ToastModel.js +10 -6
- package/src/domain/components/index.js +3 -1
- package/src/domain/index.js +14 -4
- package/src/index.js +21 -2
- package/src/inspect.js +2 -0
- package/src/test/ScenarioAdapter.js +59 -0
- package/src/test/ScenarioTest.js +51 -0
- package/src/test/ScenarioTest.story.js +56 -0
- package/src/testing/CrashReporter.js +56 -0
- package/src/testing/GalleryGenerator.js +29 -0
- package/src/testing/LogicInspector.js +55 -0
- package/src/testing/SnapshotRunner.js +22 -0
- package/src/testing/SpecAdapter.js +115 -0
- package/src/testing/SpecRunner.js +121 -0
- package/src/testing/VisualAdapter.js +46 -0
- package/src/testing/index.js +7 -0
- package/src/testing/verifySnapshot.js +17 -0
- package/types/App/Command/DepsCommand.d.ts +0 -2
- package/types/Model/index.d.ts +56 -4
- package/types/StdIn.d.ts +3 -3
- package/types/cli.d.ts +1 -0
- package/types/core/Form/Form.d.ts +2 -2
- package/types/core/GeneratorRunner.d.ts +18 -1
- package/types/core/InputAdapter.d.ts +2 -1
- package/types/core/Intent.d.ts +232 -26
- package/types/core/IntentErrorModel.d.ts +4 -0
- package/types/core/Message/Message.d.ts +2 -2
- package/types/core/Message/OutputMessage.d.ts +0 -2
- package/types/core/index.d.ts +2 -1
- package/types/domain/Content.d.ts +340 -0
- package/types/domain/Document.d.ts +21 -0
- package/types/domain/FooterModel.d.ts +22 -12
- package/types/domain/HeaderModel.d.ts +36 -13
- package/types/domain/HeroModel.d.ts +19 -17
- package/types/domain/LayoutModel.d.ts +34 -0
- package/types/domain/ModelAsApp.d.ts +23 -0
- package/types/domain/SandboxModel.d.ts +10 -0
- package/types/domain/app/GalleryCommand.d.ts +55 -0
- package/types/domain/app/GalleryRenderIntent.d.ts +31 -0
- package/types/domain/app/SnapshotAuditor.d.ts +99 -0
- package/types/domain/app/SnapshotRunner.d.ts +45 -0
- package/types/domain/app/UIApp.d.ts +60 -0
- package/types/domain/components/BreadcrumbModel.d.ts +6 -8
- package/types/domain/components/FeatureGridModel.d.ts +50 -0
- package/types/domain/components/MarkdownModel.d.ts +19 -0
- package/types/domain/components/ShellModel.d.ts +56 -0
- package/types/domain/components/TableModel.d.ts +4 -0
- package/types/domain/components/ToastModel.d.ts +4 -0
- package/types/domain/components/index.d.ts +3 -0
- package/types/domain/index.d.ts +10 -4
- package/types/index.d.ts +19 -1
- package/types/inspect.d.ts +2 -0
- package/types/test/ScenarioAdapter.d.ts +43 -0
- package/types/test/ScenarioTest.d.ts +24 -0
- package/types/test/ScenarioTest.story.d.ts +1 -0
- package/types/testing/CrashReporter.d.ts +13 -0
- package/types/testing/GalleryGenerator.d.ts +1 -0
- package/types/testing/LogicInspector.d.ts +22 -0
- package/types/testing/SnapshotRunner.d.ts +7 -0
- package/types/testing/SpecAdapter.d.ts +57 -0
- package/types/testing/SpecRunner.d.ts +41 -0
- package/types/testing/VisualAdapter.d.ts +9 -0
- package/types/testing/index.d.ts +7 -0
- package/types/testing/verifySnapshot.d.ts +14 -0
- package/src/README.md.js +0 -436
- package/types/App/Command/Options.d.ts +0 -43
- package/types/App/Command/index.d.ts +0 -8
- package/types/App/User/Command/Options.d.ts +0 -34
- package/types/core/Message/InputMessage.d.ts +0 -71
- package/types/domain/components/HeroModel.d.ts +0 -24
- package/types/domain/components/ShowcaseAppModel.d.ts +0 -32
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
import { Model } from '@nan0web/types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {Object} HTML5Elements
|
|
5
|
+
* @property {string|ContentData[]} [a]
|
|
6
|
+
* @property {string|ContentData[]} [abbr]
|
|
7
|
+
* @property {string|ContentData[]} [address]
|
|
8
|
+
* @property {string|ContentData[]} [area]
|
|
9
|
+
* @property {string|ContentData[]} [article]
|
|
10
|
+
* @property {string|ContentData[]} [aside]
|
|
11
|
+
* @property {string|ContentData[]} [audio]
|
|
12
|
+
* @property {string|ContentData[]} [b]
|
|
13
|
+
* @property {string|ContentData[]} [base]
|
|
14
|
+
* @property {string|ContentData[]} [bdi]
|
|
15
|
+
* @property {string|ContentData[]} [bdo]
|
|
16
|
+
* @property {string|ContentData[]} [blockquote]
|
|
17
|
+
* @property {string|ContentData[]} [body]
|
|
18
|
+
* @property {boolean|object} [br]
|
|
19
|
+
* @property {string|ContentData[]} [canvas]
|
|
20
|
+
* @property {string|ContentData[]} [caption]
|
|
21
|
+
* @property {string|ContentData[]} [cite]
|
|
22
|
+
* @property {string|ContentData[]} [code]
|
|
23
|
+
* @property {string|ContentData[]} [col]
|
|
24
|
+
* @property {string|ContentData[]} [colgroup]
|
|
25
|
+
* @property {string|ContentData[]} [data]
|
|
26
|
+
* @property {string|ContentData[]} [datalist]
|
|
27
|
+
* @property {string|ContentData[]} [dd]
|
|
28
|
+
* @property {string|ContentData[]} [del]
|
|
29
|
+
* @property {string|ContentData[]} [details]
|
|
30
|
+
* @property {string|ContentData[]} [dfn]
|
|
31
|
+
* @property {string|ContentData[]} [dialog]
|
|
32
|
+
* @property {string|ContentData[]} [div]
|
|
33
|
+
* @property {string|ContentData[]} [dl]
|
|
34
|
+
* @property {string|ContentData[]} [dt]
|
|
35
|
+
* @property {string|ContentData[]} [em]
|
|
36
|
+
* @property {string|ContentData[]} [embed]
|
|
37
|
+
* @property {string|ContentData[]} [fieldset]
|
|
38
|
+
* @property {string|ContentData[]} [figcaption]
|
|
39
|
+
* @property {string|ContentData[]} [figure]
|
|
40
|
+
* @property {string|ContentData[]} [footer]
|
|
41
|
+
* @property {string|ContentData[]} [form]
|
|
42
|
+
* @property {string|ContentData[]} [h1]
|
|
43
|
+
* @property {string|ContentData[]} [h2]
|
|
44
|
+
* @property {string|ContentData[]} [h3]
|
|
45
|
+
* @property {string|ContentData[]} [h4]
|
|
46
|
+
* @property {string|ContentData[]} [h5]
|
|
47
|
+
* @property {string|ContentData[]} [h6]
|
|
48
|
+
* @property {string|ContentData[]} [head]
|
|
49
|
+
* @property {string|ContentData[]} [header]
|
|
50
|
+
* @property {string|ContentData[]} [hgroup]
|
|
51
|
+
* @property {boolean|object} [hr]
|
|
52
|
+
* @property {string|ContentData[]} [html]
|
|
53
|
+
* @property {string|ContentData[]} [i]
|
|
54
|
+
* @property {string|ContentData[]} [iframe]
|
|
55
|
+
* @property {string|ContentData[]} [img]
|
|
56
|
+
* @property {string|ContentData[]} [ins]
|
|
57
|
+
* @property {string|ContentData[]} [kbd]
|
|
58
|
+
* @property {string|ContentData[]} [label]
|
|
59
|
+
* @property {string|ContentData[]} [legend]
|
|
60
|
+
* @property {string|ContentData[]} [li]
|
|
61
|
+
* @property {string|ContentData[]} [link]
|
|
62
|
+
* @property {string|ContentData[]} [main]
|
|
63
|
+
* @property {string|ContentData[]} [map]
|
|
64
|
+
* @property {string|ContentData[]} [mark]
|
|
65
|
+
* @property {string|ContentData[]} [meta]
|
|
66
|
+
* @property {string|ContentData[]} [meter]
|
|
67
|
+
* @property {boolean|any} [input]
|
|
68
|
+
* @property {boolean|any} [button]
|
|
69
|
+
* @property {boolean|any} [select]
|
|
70
|
+
* @property {string|ContentData[]} [nav]
|
|
71
|
+
* @property {string|ContentData[]} [noscript]
|
|
72
|
+
* @property {string|ContentData[]} [object]
|
|
73
|
+
* @property {string|ContentData[]} [ol]
|
|
74
|
+
* @property {string|ContentData[]} [optgroup]
|
|
75
|
+
* @property {string|ContentData[]} [option]
|
|
76
|
+
* @property {string|ContentData[]} [output]
|
|
77
|
+
* @property {string|ContentData[]} [p]
|
|
78
|
+
* @property {string|ContentData[]} [picture]
|
|
79
|
+
* @property {string|ContentData[]} [pre]
|
|
80
|
+
* @property {string|ContentData[]} [progress]
|
|
81
|
+
* @property {string|ContentData[]} [q]
|
|
82
|
+
* @property {string|ContentData[]} [rp]
|
|
83
|
+
* @property {string|ContentData[]} [rt]
|
|
84
|
+
* @property {string|ContentData[]} [ruby]
|
|
85
|
+
* @property {string|ContentData[]} [s]
|
|
86
|
+
* @property {string|ContentData[]} [samp]
|
|
87
|
+
* @property {string|ContentData[]} [script]
|
|
88
|
+
* @property {string|ContentData[]} [section]
|
|
89
|
+
* @property {string|ContentData[]} [slot]
|
|
90
|
+
* @property {string|ContentData[]} [small]
|
|
91
|
+
* @property {string|ContentData[]} [source]
|
|
92
|
+
* @property {string|ContentData[]} [span]
|
|
93
|
+
* @property {string|ContentData[]} [strong]
|
|
94
|
+
* @property {string|ContentData[]} [style]
|
|
95
|
+
* @property {string|ContentData[]} [sub]
|
|
96
|
+
* @property {string|ContentData[]} [summary]
|
|
97
|
+
* @property {string|ContentData[]} [sup]
|
|
98
|
+
* @property {string|ContentData[]} [table]
|
|
99
|
+
* @property {string|ContentData[]} [tbody]
|
|
100
|
+
* @property {string|ContentData[]} [td]
|
|
101
|
+
* @property {string|ContentData[]} [template]
|
|
102
|
+
* @property {string|ContentData[]} [textarea]
|
|
103
|
+
* @property {string|ContentData[]} [tfoot]
|
|
104
|
+
* @property {string|ContentData[]} [th]
|
|
105
|
+
* @property {string|ContentData[]} [thead]
|
|
106
|
+
* @property {string|ContentData[]} [time]
|
|
107
|
+
* @property {string|ContentData[]} [title]
|
|
108
|
+
* @property {string|ContentData[]} [tr]
|
|
109
|
+
* @property {string|ContentData[]} [track]
|
|
110
|
+
* @property {string|ContentData[]} [u]
|
|
111
|
+
* @property {string|ContentData[]} [ul]
|
|
112
|
+
* @property {string|ContentData[]} [var]
|
|
113
|
+
* @property {string|ContentData[]} [video]
|
|
114
|
+
* @property {string|ContentData[]} [wbr]
|
|
115
|
+
* @property {string|ContentData[]} [svg]
|
|
116
|
+
* @property {string|ContentData[]} [path]
|
|
117
|
+
* @property {string|ContentData[]} [circle]
|
|
118
|
+
* @property {string|ContentData[]} [rect]
|
|
119
|
+
* @property {string|ContentData[]} [line]
|
|
120
|
+
* @property {string|ContentData[]} [polyline]
|
|
121
|
+
* @property {string|ContentData[]} [polygon]
|
|
122
|
+
* @property {string|ContentData[]} [g]
|
|
123
|
+
* @property {string|ContentData[]} [defs]
|
|
124
|
+
* @property {string|ContentData[]} [symbol]
|
|
125
|
+
* @property {string|ContentData[]} [use]
|
|
126
|
+
* @property {string|ContentData[]} [text]
|
|
127
|
+
*/
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* @typedef {Object} CoreUIElements
|
|
131
|
+
* @property {import('./components/AccordionModel.js').AccordionModel} [accordion]
|
|
132
|
+
* @property {import('./components/AutocompleteModel.js').AutocompleteModel} [autocomplete]
|
|
133
|
+
* @property {import('./components/BannerModel.js').BannerModel} [banner]
|
|
134
|
+
* @property {import('./components/BreadcrumbModel.js').BreadcrumbModel} [breadcrumb]
|
|
135
|
+
* @property {import('./components/ButtonModel.js').ButtonModel} [button]
|
|
136
|
+
* @property {import('./components/CommentModel.js').CommentModel} [comment]
|
|
137
|
+
* @property {import('./components/ConfirmModel.js').ConfirmModel} [confirm]
|
|
138
|
+
* @property {import('./components/EmptyStateModel.js').EmptyStateModel} [emptyState]
|
|
139
|
+
* @property {import('./components/FAQModel.js').FAQModel} [faq]
|
|
140
|
+
* @property {import('./components/FeatureGridModel.js').FeatureGridModel} [featureGrid]
|
|
141
|
+
* @property {import('./components/GalleryModel.js').GalleryModel} [gallery]
|
|
142
|
+
* @property {import('./components/InputModel.js').InputModel} [input]
|
|
143
|
+
* @property {import('./components/MarkdownModel.js').MarkdownModel} [markdown]
|
|
144
|
+
* @property {import('./components/PriceModel.js').PriceModel} [price]
|
|
145
|
+
* @property {import('./components/PricingModel.js').PricingModel} [pricing]
|
|
146
|
+
* @property {import('./components/PricingSectionModel.js').PricingSectionModel} [pricingSection]
|
|
147
|
+
* @property {import('./components/ProfileDropdownModel.js').ProfileDropdownModel} [profileDropdown]
|
|
148
|
+
* @property {import('./components/SelectModel.js').SelectModel} [select]
|
|
149
|
+
* @property {import('./components/ShellModel.js').ShellModel} [shell]
|
|
150
|
+
* @property {import('./components/SpinnerModel.js').SpinnerModel} [spinner]
|
|
151
|
+
* @property {import('./components/StatsItemModel.js').StatsItemModel} [statsItem]
|
|
152
|
+
* @property {import('./components/StatsModel.js').StatsModel} [stats]
|
|
153
|
+
* @property {import('./components/TableModel.js').TableModel} [tableUI]
|
|
154
|
+
* @property {import('./components/TabsModel.js').TabsModel} [tabs]
|
|
155
|
+
* @property {import('./components/TestimonialModel.js').TestimonialModel} [testimonial]
|
|
156
|
+
* @property {import('./components/TimelineItemModel.js').TimelineItemModel} [timelineItem]
|
|
157
|
+
* @property {import('./components/TimelineModel.js').TimelineModel} [timeline]
|
|
158
|
+
* @property {import('./components/ToastModel.js').ToastModel} [toast]
|
|
159
|
+
* @property {import('./components/TreeModel.js').TreeModel} [tree]
|
|
160
|
+
* @property {ContentData[]} [sortable] - Інтерактивний Drag-n-Drop контейнер
|
|
161
|
+
*/
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* @typedef {Partial<Content & HTML5Elements & CoreUIElements> & Record<string, any>} ContentData
|
|
165
|
+
*/
|
|
166
|
+
|
|
167
|
+
export class Content extends Model {
|
|
168
|
+
static content = { type: 'string', help: 'Content' }
|
|
169
|
+
static children = { type: 'array', model: Content, help: 'Children' }
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* @param {ContentData | string} [data={}]
|
|
173
|
+
* @param {import('@nan0web/types').ModelOptions} [options={}]
|
|
174
|
+
*/
|
|
175
|
+
constructor(data = {}, options = {}) {
|
|
176
|
+
if ('string' === typeof data) {
|
|
177
|
+
data = { content: data }
|
|
178
|
+
}
|
|
179
|
+
super(data, options)
|
|
180
|
+
|
|
181
|
+
// ── Base Fields ──
|
|
182
|
+
/** @type {string|undefined} Content */ this.content
|
|
183
|
+
/** @type {Array<Content>|undefined} Children */ this.children
|
|
184
|
+
|
|
185
|
+
// ── Hydration ──
|
|
186
|
+
if (Array.isArray(this.children)) {
|
|
187
|
+
this.children = this.children.map((child) => new Content(child, options))
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const { content, children, ...rest } = /** @type {any} */ (data)
|
|
191
|
+
|
|
192
|
+
for (const [key, value] of Object.entries(rest)) {
|
|
193
|
+
/** @type {any} */ (this)[key] = value
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Model } from '@nan0web/types'
|
|
2
|
+
import { Content } from './Content.js'
|
|
3
|
+
|
|
4
|
+
export class Document extends Model {
|
|
5
|
+
static title = { type: 'string', help: 'Title' }
|
|
6
|
+
static content = { type: 'array', model: Content, help: 'Content' }
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* @param {Partial<Document>} [data]
|
|
10
|
+
* @param {import('@nan0web/types').ModelOptions} [options]
|
|
11
|
+
*/
|
|
12
|
+
constructor(data = {}, options = {}) {
|
|
13
|
+
super(data, options)
|
|
14
|
+
/** @type {string} Title */ this.title
|
|
15
|
+
/** @type {Array<Content>} Content */ this.content
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -1,30 +1,31 @@
|
|
|
1
1
|
import { Model } from '@nan0web/types'
|
|
2
|
+
import { Language } from '@nan0web/i18n'
|
|
2
3
|
import Navigation from './Navigation.js'
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
|
-
* FooterModel — OLMUI Model
|
|
6
|
-
* Universal footer structure
|
|
6
|
+
* FooterModel — OLMUI Component Model
|
|
7
|
+
* Universal footer structure.
|
|
7
8
|
*/
|
|
8
|
-
export
|
|
9
|
+
export class FooterModel extends Model {
|
|
9
10
|
static $id = '@nan0web/ui/FooterModel'
|
|
10
11
|
|
|
11
12
|
static copyright = {
|
|
12
|
-
help: 'Copyright text',
|
|
13
|
-
placeholder: '© 2026
|
|
13
|
+
help: 'Copyright notice text',
|
|
14
|
+
placeholder: '© 2026 My Site',
|
|
14
15
|
default: '',
|
|
15
16
|
}
|
|
16
17
|
static version = {
|
|
17
|
-
help: '
|
|
18
|
+
help: 'App version to display',
|
|
18
19
|
placeholder: '1.0.0',
|
|
19
20
|
default: '',
|
|
20
21
|
}
|
|
21
22
|
static license = {
|
|
22
|
-
help: 'License
|
|
23
|
+
help: 'License name or link',
|
|
23
24
|
placeholder: 'ISC',
|
|
24
25
|
default: '',
|
|
25
26
|
}
|
|
26
27
|
static nav = {
|
|
27
|
-
help: '
|
|
28
|
+
help: 'Terms of Service, Privacy Policy, etc.',
|
|
28
29
|
type: 'Navigation[]',
|
|
29
30
|
hint: Navigation,
|
|
30
31
|
default: [],
|
|
@@ -35,23 +36,40 @@ export default class FooterModel extends Model {
|
|
|
35
36
|
hint: Navigation,
|
|
36
37
|
default: [],
|
|
37
38
|
}
|
|
39
|
+
static lang = {
|
|
40
|
+
help: 'Active language',
|
|
41
|
+
default: null,
|
|
42
|
+
}
|
|
38
43
|
static langs = {
|
|
39
|
-
help: '
|
|
44
|
+
help: 'Languages for switcher',
|
|
40
45
|
type: 'Language[]',
|
|
46
|
+
hint: Language,
|
|
41
47
|
default: [],
|
|
42
48
|
}
|
|
43
49
|
|
|
44
50
|
/**
|
|
45
|
-
* @param {Partial<FooterModel>
|
|
46
|
-
* @param {object} [options] Extended options (db, etc.)
|
|
51
|
+
* @param {Partial<FooterModel>} data
|
|
47
52
|
*/
|
|
48
|
-
constructor(data = {}
|
|
49
|
-
super(data
|
|
50
|
-
/** @type {string}
|
|
51
|
-
/** @type {string}
|
|
52
|
-
/** @type {string}
|
|
53
|
-
/** @type {Navigation[]}
|
|
54
|
-
|
|
55
|
-
/** @type {
|
|
53
|
+
constructor(data = {}) {
|
|
54
|
+
super(data)
|
|
55
|
+
/** @type {string} */ this.copyright
|
|
56
|
+
/** @type {string} */ this.version
|
|
57
|
+
/** @type {string} */ this.license
|
|
58
|
+
/** @type {Navigation[]} */
|
|
59
|
+
this.nav = this.#map(this.nav)
|
|
60
|
+
/** @type {Navigation[]} */
|
|
61
|
+
this.share = this.#map(this.share)
|
|
62
|
+
/** @type {Language|null} */
|
|
63
|
+
this.lang = this.lang && !(this.lang instanceof Language) ? new Language(this.lang) : this.lang
|
|
64
|
+
/** @type {Language[]} */
|
|
65
|
+
this.langs = Array.isArray(this.langs)
|
|
66
|
+
? this.langs.map((l) => (l instanceof Language ? l : new Language(l)))
|
|
67
|
+
: []
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
#map(arr) {
|
|
71
|
+
return Array.isArray(arr)
|
|
72
|
+
? arr.map((i) => (i instanceof Navigation ? i : new Navigation(i)))
|
|
73
|
+
: []
|
|
56
74
|
}
|
|
57
75
|
}
|
|
@@ -2,49 +2,75 @@ import { Model } from '@nan0web/types'
|
|
|
2
2
|
import Navigation from './Navigation.js'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* HeaderModel — OLMUI Model
|
|
6
|
-
* Universal header structure
|
|
5
|
+
* HeaderModel — OLMUI Component Model
|
|
6
|
+
* Universal header structure with logo, navigation, and language controls.
|
|
7
7
|
*/
|
|
8
|
-
export
|
|
8
|
+
export class HeaderModel extends Model {
|
|
9
9
|
static $id = '@nan0web/ui/HeaderModel'
|
|
10
10
|
|
|
11
11
|
static title = {
|
|
12
|
-
help: '
|
|
13
|
-
placeholder: 'My
|
|
12
|
+
help: 'Header title text',
|
|
13
|
+
placeholder: 'My Site',
|
|
14
14
|
default: '',
|
|
15
15
|
}
|
|
16
16
|
static logo = {
|
|
17
|
-
help: '
|
|
18
|
-
placeholder: '
|
|
17
|
+
help: 'Primary logo path',
|
|
18
|
+
placeholder: 'logo.svg',
|
|
19
19
|
default: '',
|
|
20
20
|
}
|
|
21
|
+
static logoDark = {
|
|
22
|
+
help: 'Dark theme logo path',
|
|
23
|
+
placeholder: 'logo-dark.svg',
|
|
24
|
+
default: '',
|
|
25
|
+
}
|
|
26
|
+
static nav = {
|
|
27
|
+
help: 'Main navigation links',
|
|
28
|
+
type: 'Navigation[]',
|
|
29
|
+
hint: Navigation,
|
|
30
|
+
default: [],
|
|
31
|
+
}
|
|
21
32
|
static actions = {
|
|
22
|
-
help: '
|
|
33
|
+
help: 'CTA or specific header actions',
|
|
34
|
+
type: 'Navigation[]',
|
|
35
|
+
hint: Navigation,
|
|
36
|
+
default: [],
|
|
37
|
+
}
|
|
38
|
+
static share = {
|
|
39
|
+
help: 'Social sharing or utility links',
|
|
23
40
|
type: 'Navigation[]',
|
|
24
41
|
hint: Navigation,
|
|
25
42
|
default: [],
|
|
26
43
|
}
|
|
27
44
|
static lang = {
|
|
28
|
-
help: '
|
|
29
|
-
type: 'Language',
|
|
45
|
+
help: 'Active language code or object',
|
|
30
46
|
default: null,
|
|
31
47
|
}
|
|
32
48
|
static langs = {
|
|
33
|
-
help: 'Available languages
|
|
34
|
-
type: 'Language[]',
|
|
49
|
+
help: 'Available languages',
|
|
35
50
|
default: [],
|
|
36
51
|
}
|
|
37
52
|
|
|
38
53
|
/**
|
|
39
|
-
* @param {Partial<HeaderModel>
|
|
40
|
-
* @param {object} [options] Extended options (db, etc.)
|
|
54
|
+
* @param {Partial<HeaderModel>} data
|
|
41
55
|
*/
|
|
42
|
-
constructor(data = {}
|
|
43
|
-
super(data
|
|
44
|
-
/** @type {string}
|
|
45
|
-
/** @type {string}
|
|
46
|
-
/** @type {
|
|
47
|
-
/** @type {
|
|
48
|
-
|
|
56
|
+
constructor(data = {}) {
|
|
57
|
+
super(data)
|
|
58
|
+
/** @type {string} */ this.title
|
|
59
|
+
/** @type {string} */ this.logo
|
|
60
|
+
/** @type {string} */ this.logoDark
|
|
61
|
+
/** @type {Navigation[]} */
|
|
62
|
+
this.nav = this.#map(this.nav)
|
|
63
|
+
/** @type {Navigation[]} */
|
|
64
|
+
this.actions = this.#map(this.actions)
|
|
65
|
+
/** @type {Navigation[]} */
|
|
66
|
+
this.share = this.#map(this.share)
|
|
67
|
+
/** @type {any} */
|
|
68
|
+
this.lang = this.lang
|
|
69
|
+
/** @type {any[]} */
|
|
70
|
+
this.langs = Array.isArray(this.langs) ? this.langs : []
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
#map(arr) {
|
|
74
|
+
return Array.isArray(arr) ? arr.map(i => i instanceof Navigation ? i : new Navigation(i)) : []
|
|
49
75
|
}
|
|
50
76
|
}
|
package/src/domain/HeroModel.js
CHANGED
|
@@ -2,47 +2,49 @@ import { Model } from '@nan0web/types'
|
|
|
2
2
|
import Navigation from './Navigation.js'
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* HeroModel — OLMUI Model
|
|
6
|
-
*
|
|
7
|
-
* Uses Navigation[] for actions instead of a single CTA.
|
|
5
|
+
* HeroModel — OLMUI Component Model
|
|
6
|
+
* Represents the top presentation section of a page.
|
|
8
7
|
*/
|
|
9
|
-
export
|
|
8
|
+
export class HeroModel extends Model {
|
|
10
9
|
static $id = '@nan0web/ui/HeroModel'
|
|
11
10
|
|
|
11
|
+
static badge = {
|
|
12
|
+
help: 'Top small badge text or icon',
|
|
13
|
+
placeholder: 'v1.4.0 out now',
|
|
14
|
+
default: '',
|
|
15
|
+
}
|
|
12
16
|
static title = {
|
|
13
|
-
help: 'Hero
|
|
14
|
-
placeholder: '
|
|
17
|
+
help: 'Hero heading',
|
|
18
|
+
placeholder: 'Build Amazing Apps',
|
|
15
19
|
default: '',
|
|
16
20
|
required: true,
|
|
17
21
|
}
|
|
18
|
-
static
|
|
19
|
-
help: 'Hero
|
|
20
|
-
placeholder: '
|
|
22
|
+
static subtitle = {
|
|
23
|
+
help: 'Hero secondary text',
|
|
24
|
+
placeholder: 'The open architecture for the next web.',
|
|
21
25
|
default: '',
|
|
22
26
|
}
|
|
23
|
-
static
|
|
24
|
-
help: '
|
|
25
|
-
placeholder: 'https://...',
|
|
26
|
-
hint: 'image',
|
|
27
|
-
upload: true,
|
|
27
|
+
static code = {
|
|
28
|
+
help: 'Code snippet or secondary markup',
|
|
28
29
|
default: '',
|
|
29
30
|
}
|
|
30
31
|
static actions = {
|
|
31
|
-
help: '
|
|
32
|
+
help: 'CTA buttons',
|
|
32
33
|
type: 'Navigation[]',
|
|
33
|
-
|
|
34
|
+
model: Navigation,
|
|
34
35
|
default: [],
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
/**
|
|
38
|
-
* @param {Partial<HeroModel
|
|
39
|
-
* @param {
|
|
39
|
+
* @param {Partial<HeroModel | Record<string, any>>} [data={}]
|
|
40
|
+
* @param {import('@nan0web/types').ModelOptions} [options={}]
|
|
40
41
|
*/
|
|
41
42
|
constructor(data = {}, options = {}) {
|
|
42
43
|
super(data, options)
|
|
43
|
-
/** @type {string}
|
|
44
|
-
/** @type {string} Hero
|
|
45
|
-
/** @type {string} Hero
|
|
46
|
-
/** @type {
|
|
44
|
+
/** @type {string} Top small badge text ior icon */ this.badge
|
|
45
|
+
/** @type {string} Hero heading */ this.title
|
|
46
|
+
/** @type {string} Hero secondary text */ this.subtitle
|
|
47
|
+
/** @type {string} Code snippet or secondary markup */ this.code
|
|
48
|
+
/** @type {Navigation[]} CTA buttons */ this.actions
|
|
47
49
|
}
|
|
48
50
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Model } from '@nan0web/types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {'flow'|'sticky-bottom'|'sticky-top'|'dialog-modal'|'spatial-xyz'} LayoutType
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Universal Layout Interface for OLMUI.
|
|
9
|
+
* Defines the semantic spatial placement of a component in any renderer.
|
|
10
|
+
*/
|
|
11
|
+
export class LayoutModel extends Model {
|
|
12
|
+
static type = {
|
|
13
|
+
help: 'Base layout type',
|
|
14
|
+
default: 'flow',
|
|
15
|
+
options: [
|
|
16
|
+
{ value: 'flow', label: 'Inline Flow' },
|
|
17
|
+
{ value: 'sticky-bottom', label: 'Sticky Bottom' },
|
|
18
|
+
{ value: 'sticky-top', label: 'Sticky Top' },
|
|
19
|
+
{ value: 'dialog-modal', label: 'Modal / Dialog' },
|
|
20
|
+
{ value: 'spatial-xyz', label: 'Spatial XYZ Coordinates' }
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static coordinates = {
|
|
25
|
+
help: 'Physical, screen, or audio coordinates if type requires it',
|
|
26
|
+
default: null,
|
|
27
|
+
type: 'object'
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Creates a new LayoutModel instance to define spatial placement.
|
|
32
|
+
* @param {Partial<LayoutModel> | Record<string, any>} [data] Input model data.
|
|
33
|
+
* @param {object} [options] Model options.
|
|
34
|
+
*/
|
|
35
|
+
constructor(data = {}, options = {}) {
|
|
36
|
+
super(data, options)
|
|
37
|
+
/** @type {LayoutType} Base layout type */
|
|
38
|
+
this.type
|
|
39
|
+
|
|
40
|
+
/** @type {object | null} Configuration or specific layout parameters */
|
|
41
|
+
this.coordinates
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Model } from '@nan0web/types'
|
|
2
|
+
import { result } from '../core/Intent.js'
|
|
3
|
+
import { InputAdapter } from '../core/InputAdapter.js'
|
|
4
|
+
|
|
5
|
+
/** @typedef {import('@nan0web/types').ModelOptions & { adapter: InputAdapter }} ModelAsAppOptions */
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The model with a run generator.
|
|
9
|
+
*/
|
|
10
|
+
export class ModelAsApp extends Model {
|
|
11
|
+
/** @type {ModelAsAppOptions} */
|
|
12
|
+
#appOptions = {
|
|
13
|
+
t: (key) => key,
|
|
14
|
+
plugins: {},
|
|
15
|
+
adapter: null,
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* @param {Partial<ModelAsApp> | Record<string, any>} [data={}]
|
|
19
|
+
* @param {ModelAsAppOptions} [options={}]
|
|
20
|
+
*/
|
|
21
|
+
constructor(data = {}, options = {}) {
|
|
22
|
+
super(data, options)
|
|
23
|
+
this.#appOptions = {
|
|
24
|
+
...options,
|
|
25
|
+
t:
|
|
26
|
+
options.t ||
|
|
27
|
+
((key, props = {}) =>
|
|
28
|
+
String(key)
|
|
29
|
+
.replace(/{(\w+)}/g, (_, x) => props[x] ?? `{${x}}`)
|
|
30
|
+
.replace(/_/g, ' ')),
|
|
31
|
+
plugins: options.plugins || {},
|
|
32
|
+
adapter: options.adapter || new InputAdapter(),
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** @returns {ModelAsAppOptions} */
|
|
37
|
+
get _() {
|
|
38
|
+
return this.#appOptions
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* @returns {AsyncGenerator<import('@nan0web/ui').Intent, import('@nan0web/ui').ResultIntent, any>}
|
|
42
|
+
*/
|
|
43
|
+
async *run() {
|
|
44
|
+
return result({})
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Model } from '@nan0web/types'
|
|
2
2
|
import { BreadcrumbModel } from './components/BreadcrumbModel.js'
|
|
3
|
+
import { show, result, ask } from '../core/Intent.js'
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* SandboxModel — OLMUI Model-as-Schema
|
|
@@ -8,8 +9,19 @@ import { BreadcrumbModel } from './components/BreadcrumbModel.js'
|
|
|
8
9
|
export class SandboxModel extends Model {
|
|
9
10
|
static $id = '@nan0web/ui/SandboxModel'
|
|
10
11
|
|
|
12
|
+
static UI = {
|
|
13
|
+
breadcrumb: '\n{path}',
|
|
14
|
+
componentsHelp: 'List of registered UI components available for inspection',
|
|
15
|
+
selectedComponentHelp: 'The component currently being inspected in the sandbox',
|
|
16
|
+
selectedComponentPlaceholder: 'Button',
|
|
17
|
+
themeFormatHelp: 'The file format chosen to export the custom theme configuration',
|
|
18
|
+
selectComponentHelp: 'Select a component to inspect',
|
|
19
|
+
configurePropertiesHelp: 'Configure {component} properties',
|
|
20
|
+
exportFormatHelp: 'Choose export format',
|
|
21
|
+
}
|
|
22
|
+
|
|
11
23
|
static components = {
|
|
12
|
-
help:
|
|
24
|
+
help: SandboxModel.UI.componentsHelp,
|
|
13
25
|
type: 'string[]',
|
|
14
26
|
default: [],
|
|
15
27
|
}
|
|
@@ -52,13 +64,10 @@ export class SandboxModel extends Model {
|
|
|
52
64
|
|
|
53
65
|
if (!this.selectedComponent) {
|
|
54
66
|
// Show breadcrumb
|
|
55
|
-
yield {
|
|
56
|
-
type: 'log',
|
|
57
|
-
level: 'info',
|
|
58
|
-
message: `\n${nav}`,
|
|
67
|
+
yield show(this._.t(SandboxModel.UI.breadcrumb, { path: String(nav) }), 'info', {
|
|
59
68
|
component: 'Breadcrumbs',
|
|
60
69
|
model: nav,
|
|
61
|
-
}
|
|
70
|
+
})
|
|
62
71
|
|
|
63
72
|
const response = yield {
|
|
64
73
|
type: 'ask',
|
|
@@ -79,13 +88,10 @@ export class SandboxModel extends Model {
|
|
|
79
88
|
// 2. Component Configuration Mode
|
|
80
89
|
let configResponse
|
|
81
90
|
try {
|
|
82
|
-
yield {
|
|
83
|
-
type: 'log',
|
|
84
|
-
level: 'info',
|
|
85
|
-
message: `\n${nav}`,
|
|
91
|
+
yield show(this._.t(SandboxModel.UI.breadcrumb, { path: String(nav) }), 'info', {
|
|
86
92
|
component: 'Breadcrumbs',
|
|
87
93
|
model: nav,
|
|
88
|
-
}
|
|
94
|
+
})
|
|
89
95
|
|
|
90
96
|
configResponse = yield {
|
|
91
97
|
type: 'ask',
|
|
@@ -107,13 +113,10 @@ export class SandboxModel extends Model {
|
|
|
107
113
|
// 3. Theme Export Mode
|
|
108
114
|
try {
|
|
109
115
|
nav.push('Export', 'export')
|
|
110
|
-
yield {
|
|
111
|
-
type: 'log',
|
|
112
|
-
level: 'info',
|
|
113
|
-
message: `\n${nav}`,
|
|
116
|
+
yield show(this._.t(SandboxModel.UI.breadcrumb, { path: String(nav) }), 'info', {
|
|
114
117
|
component: 'Breadcrumbs',
|
|
115
118
|
model: nav,
|
|
116
|
-
}
|
|
119
|
+
})
|
|
117
120
|
|
|
118
121
|
const themeResponse = yield {
|
|
119
122
|
type: 'ask',
|