@nan0web/ui 1.8.0 → 1.9.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/package.json +9 -10
- package/src/core/Intent.js +4 -3
- package/src/domain/FooterModel.js +57 -0
- package/src/domain/HeaderModel.js +50 -0
- package/src/domain/HeroModel.js +48 -0
- package/src/domain/Navigation.js +11 -10
- package/src/domain/SandboxModel.js +66 -115
- package/src/domain/ShowcaseAppModel.js +133 -50
- package/src/domain/components/AccordionModel.js +38 -0
- package/src/domain/components/AutocompleteModel.js +11 -21
- package/src/domain/components/BannerModel.js +37 -0
- package/src/domain/components/BreadcrumbModel.js +11 -9
- package/src/domain/components/ButtonModel.js +31 -58
- package/src/domain/components/CommentModel.js +44 -0
- package/src/domain/components/ConfirmModel.js +26 -33
- package/src/domain/components/EmptyStateModel.js +45 -0
- package/src/domain/components/FAQModel.js +32 -0
- package/src/domain/components/FooterConfigModel.js +26 -0
- package/src/domain/components/FooterVisibilityModel.js +48 -0
- package/src/domain/components/GalleryModel.js +36 -0
- package/src/domain/components/HeaderConfigModel.js +26 -0
- package/src/domain/components/HeaderVisibilityModel.js +54 -0
- package/src/domain/components/InputModel.js +21 -41
- package/src/domain/components/PriceModel.js +30 -0
- package/src/domain/components/PricingModel.js +39 -0
- package/src/domain/components/PricingSectionModel.js +32 -0
- package/src/domain/components/ProfileDropdownModel.js +45 -0
- package/src/domain/components/SelectModel.js +11 -21
- package/src/domain/components/SpinnerModel.js +11 -26
- package/src/domain/components/StatsItemModel.js +38 -0
- package/src/domain/components/StatsModel.js +32 -0
- package/src/domain/components/TableModel.js +11 -24
- package/src/domain/components/TabsModel.js +30 -0
- package/src/domain/components/TestimonialModel.js +24 -0
- package/src/domain/components/TimelineItemModel.js +38 -0
- package/src/domain/components/TimelineModel.js +32 -0
- package/src/domain/components/ToastModel.js +24 -51
- package/src/domain/components/TreeModel.js +10 -26
- package/src/domain/components/index.js +34 -0
- package/src/domain/index.js +24 -0
- package/src/index.js +2 -0
- package/types/domain/FooterModel.d.ts +52 -0
- package/types/domain/HeaderModel.d.ts +45 -0
- package/types/domain/HeroModel.d.ts +43 -0
- package/types/domain/Navigation.d.ts +10 -9
- package/types/domain/SandboxModel.d.ts +16 -40
- package/types/domain/ShowcaseAppModel.d.ts +26 -54
- package/types/domain/components/AccordionModel.d.ts +33 -0
- package/types/domain/components/AutocompleteModel.d.ts +10 -29
- package/types/domain/components/BannerModel.d.ts +32 -0
- package/types/domain/components/BreadcrumbModel.d.ts +13 -6
- package/types/domain/components/ButtonModel.d.ts +18 -54
- package/types/domain/components/CommentModel.d.ts +39 -0
- package/types/domain/components/ConfirmModel.d.ts +20 -35
- package/types/domain/components/EmptyStateModel.d.ts +40 -0
- package/types/domain/components/FAQModel.d.ts +27 -0
- package/types/domain/components/FooterConfigModel.d.ts +21 -0
- package/types/domain/components/FooterVisibilityModel.d.ts +43 -0
- package/types/domain/components/GalleryModel.d.ts +35 -0
- package/types/domain/components/HeaderConfigModel.d.ts +21 -0
- package/types/domain/components/HeaderVisibilityModel.d.ts +49 -0
- package/types/domain/components/HeroModel.d.ts +24 -0
- package/types/domain/components/InputModel.d.ts +19 -59
- package/types/domain/components/PriceModel.d.ts +25 -0
- package/types/domain/components/PricingModel.d.ts +34 -0
- package/types/domain/components/PricingSectionModel.d.ts +27 -0
- package/types/domain/components/ProfileDropdownModel.d.ts +40 -0
- package/types/domain/components/SelectModel.d.ts +13 -28
- package/types/domain/components/ShowcaseAppModel.d.ts +32 -0
- package/types/domain/components/SpinnerModel.d.ts +10 -27
- package/types/domain/components/StatsItemModel.d.ts +33 -0
- package/types/domain/components/StatsModel.d.ts +27 -0
- package/types/domain/components/TableModel.d.ts +10 -26
- package/types/domain/components/TabsModel.d.ts +28 -0
- package/types/domain/components/TestimonialModel.d.ts +18 -0
- package/types/domain/components/TimelineItemModel.d.ts +33 -0
- package/types/domain/components/TimelineModel.d.ts +27 -0
- package/types/domain/components/ToastModel.d.ts +16 -45
- package/types/domain/components/TreeModel.d.ts +13 -36
- package/types/domain/components/index.d.ts +20 -0
- package/types/domain/index.d.ts +4 -1
- package/types/index.d.ts +1 -0
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Model } from '@nan0web/types'
|
|
2
|
+
import Navigation from '../Navigation.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* EmptyStateModel — OLMUI Model-as-Schema
|
|
6
|
+
* Onboarding placeholder for empty tables, lists, or dashboards.
|
|
7
|
+
*/
|
|
8
|
+
export class EmptyStateModel extends Model {
|
|
9
|
+
static $id = '@nan0web/ui/EmptyStateModel'
|
|
10
|
+
|
|
11
|
+
static icon = {
|
|
12
|
+
help: 'Illustration or icon name for the empty state',
|
|
13
|
+
placeholder: 'inbox',
|
|
14
|
+
default: '',
|
|
15
|
+
}
|
|
16
|
+
static title = {
|
|
17
|
+
help: 'Empty state headline',
|
|
18
|
+
placeholder: 'No items yet',
|
|
19
|
+
default: '',
|
|
20
|
+
required: true,
|
|
21
|
+
}
|
|
22
|
+
static description = {
|
|
23
|
+
help: 'Helpful description guiding the user',
|
|
24
|
+
placeholder: 'Create your first item to get started',
|
|
25
|
+
default: '',
|
|
26
|
+
}
|
|
27
|
+
static action = {
|
|
28
|
+
help: 'Primary CTA action (Navigation link or button)',
|
|
29
|
+
type: 'Navigation',
|
|
30
|
+
hint: Navigation,
|
|
31
|
+
default: null,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {Partial<EmptyStateModel> | Record<string, any>} data Model input data.
|
|
36
|
+
* @param {object} [options] Extended options (db, etc.)
|
|
37
|
+
*/
|
|
38
|
+
constructor(data = {}, options = {}) {
|
|
39
|
+
super(data, options)
|
|
40
|
+
/** @type {string} Illustration or icon name for the empty state */ this.icon
|
|
41
|
+
/** @type {string} Empty state headline */ this.title
|
|
42
|
+
/** @type {string} Helpful description guiding the user */ this.description
|
|
43
|
+
/** @type {Navigation|null} Primary CTA action (Navigation link or button) */ this.action
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Model } from '@nan0web/types'
|
|
2
|
+
import { AccordionModel } from './AccordionModel.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* FAQModel — OLMUI Model-as-Schema
|
|
6
|
+
* A section containing a title and a collection of FAQ (accordion) items.
|
|
7
|
+
*/
|
|
8
|
+
export class FAQModel extends Model {
|
|
9
|
+
static $id = '@nan0web/ui/FAQModel'
|
|
10
|
+
|
|
11
|
+
static title = {
|
|
12
|
+
help: 'Section title',
|
|
13
|
+
placeholder: 'Frequently Asked Questions',
|
|
14
|
+
default: '',
|
|
15
|
+
}
|
|
16
|
+
static items = {
|
|
17
|
+
help: 'Array of FAQ items',
|
|
18
|
+
type: 'AccordionModel[]',
|
|
19
|
+
hint: AccordionModel,
|
|
20
|
+
default: [],
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @param {Partial<FAQModel> | Record<string, any>} data Model input data.
|
|
25
|
+
* @param {object} [options] Extended options (db, etc.)
|
|
26
|
+
*/
|
|
27
|
+
constructor(data = {}, options = {}) {
|
|
28
|
+
super(data, options)
|
|
29
|
+
/** @type {string} Section title */ this.title
|
|
30
|
+
/** @type {AccordionModel[]} Array of FAQ items */ this.items
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Model } from '@nan0web/types'
|
|
2
|
+
import { FooterVisibilityModel } from './FooterVisibilityModel.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* FooterConfigModel — OLMUI Model-as-Schema
|
|
6
|
+
* Configuration container mapping UI variant keys to FooterVisibilityModel instances.
|
|
7
|
+
*/
|
|
8
|
+
export class FooterConfigModel extends Model {
|
|
9
|
+
static $id = '@nan0web/ui/FooterConfigModel'
|
|
10
|
+
|
|
11
|
+
static ui = {
|
|
12
|
+
help: 'Map of UI variant name → FooterVisibilityModel',
|
|
13
|
+
type: 'Record<string, FooterVisibilityModel>',
|
|
14
|
+
hint: FooterVisibilityModel,
|
|
15
|
+
default: {},
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {Partial<FooterConfigModel> | Record<string, any>} data Model input data.
|
|
20
|
+
* @param {object} [options] Extended options (db, etc.)
|
|
21
|
+
*/
|
|
22
|
+
constructor(data = {}, options = {}) {
|
|
23
|
+
super(data, options)
|
|
24
|
+
/** @type {Record<string, FooterVisibilityModel>} Map of UI variant name → FooterVisibilityModel */ this.ui
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Model } from '@nan0web/types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* FooterVisibilityModel — OLMUI Model-as-Schema
|
|
5
|
+
* Boolean flags controlling which footer elements are visible.
|
|
6
|
+
*/
|
|
7
|
+
export class FooterVisibilityModel extends Model {
|
|
8
|
+
static $id = '@nan0web/ui/FooterVisibilityModel'
|
|
9
|
+
|
|
10
|
+
static copyright = {
|
|
11
|
+
help: 'Show copyright text',
|
|
12
|
+
default: true,
|
|
13
|
+
type: 'boolean',
|
|
14
|
+
}
|
|
15
|
+
static version = {
|
|
16
|
+
help: 'Show version string',
|
|
17
|
+
default: true,
|
|
18
|
+
type: 'boolean',
|
|
19
|
+
}
|
|
20
|
+
static license = {
|
|
21
|
+
help: 'Show license info',
|
|
22
|
+
default: false,
|
|
23
|
+
type: 'boolean',
|
|
24
|
+
}
|
|
25
|
+
static nav = {
|
|
26
|
+
help: 'Show footer navigation',
|
|
27
|
+
default: true,
|
|
28
|
+
type: 'boolean',
|
|
29
|
+
}
|
|
30
|
+
static clock = {
|
|
31
|
+
help: 'Show clock widget',
|
|
32
|
+
default: false,
|
|
33
|
+
type: 'boolean',
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* @param {Partial<FooterVisibilityModel> | Record<string, any>} data Model input data.
|
|
38
|
+
* @param {object} [options] Extended options (db, etc.)
|
|
39
|
+
*/
|
|
40
|
+
constructor(data = {}, options = {}) {
|
|
41
|
+
super(data, options)
|
|
42
|
+
/** @type {boolean} Show copyright text */ this.copyright
|
|
43
|
+
/** @type {boolean} Show version string */ this.version
|
|
44
|
+
/** @type {boolean} Show license info */ this.license
|
|
45
|
+
/** @type {boolean} Show footer navigation */ this.nav
|
|
46
|
+
/** @type {boolean} Show clock widget */ this.clock
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Model } from '@nan0web/types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* GalleryModel — OLMUI Model-as-Schema
|
|
5
|
+
* Image gallery / media grid with optional captions.
|
|
6
|
+
*/
|
|
7
|
+
export class GalleryModel extends Model {
|
|
8
|
+
static $id = '@nan0web/ui/GalleryModel'
|
|
9
|
+
|
|
10
|
+
static title = {
|
|
11
|
+
help: 'Gallery section title',
|
|
12
|
+
placeholder: 'Photo Gallery',
|
|
13
|
+
default: '',
|
|
14
|
+
}
|
|
15
|
+
static items = {
|
|
16
|
+
help: 'Gallery items (image URL + caption + alt)',
|
|
17
|
+
type: 'object[]',
|
|
18
|
+
default: [],
|
|
19
|
+
}
|
|
20
|
+
static columns = {
|
|
21
|
+
help: 'Number of columns in grid layout',
|
|
22
|
+
default: 3,
|
|
23
|
+
type: 'number',
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* @param {Partial<GalleryModel> | Record<string, any>} data Model input data.
|
|
28
|
+
* @param {object} [options] Extended options (db, etc.)
|
|
29
|
+
*/
|
|
30
|
+
constructor(data = {}, options = {}) {
|
|
31
|
+
super(data, options)
|
|
32
|
+
/** @type {string} Gallery section title */ this.title
|
|
33
|
+
/** @type {Array<{src: string, caption?: string, alt?: string}>} Gallery items */ this.items
|
|
34
|
+
/** @type {number} Number of columns in grid layout */ this.columns
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Model } from '@nan0web/types'
|
|
2
|
+
import { HeaderVisibilityModel } from './HeaderVisibilityModel.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* HeaderConfigModel — OLMUI Model-as-Schema
|
|
6
|
+
* Configuration container mapping UI variant keys to HeaderVisibilityModel instances.
|
|
7
|
+
*/
|
|
8
|
+
export class HeaderConfigModel extends Model {
|
|
9
|
+
static $id = '@nan0web/ui/HeaderConfigModel'
|
|
10
|
+
|
|
11
|
+
static ui = {
|
|
12
|
+
help: 'Map of UI variant name → HeaderVisibilityModel',
|
|
13
|
+
type: 'Record<string, HeaderVisibilityModel>',
|
|
14
|
+
hint: HeaderVisibilityModel,
|
|
15
|
+
default: {},
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {Partial<HeaderConfigModel> | Record<string, any>} data Model input data.
|
|
20
|
+
* @param {object} [options] Extended options (db, etc.)
|
|
21
|
+
*/
|
|
22
|
+
constructor(data = {}, options = {}) {
|
|
23
|
+
super(data, options)
|
|
24
|
+
/** @type {Record<string, HeaderVisibilityModel>} Map of UI variant name → HeaderVisibilityModel */ this.ui
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Model } from '@nan0web/types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* HeaderVisibilityModel — OLMUI Model-as-Schema
|
|
5
|
+
* Boolean flags controlling which header elements are visible.
|
|
6
|
+
*/
|
|
7
|
+
export class HeaderVisibilityModel extends Model {
|
|
8
|
+
static $id = '@nan0web/ui/HeaderVisibilityModel'
|
|
9
|
+
|
|
10
|
+
static logo = {
|
|
11
|
+
help: 'Show logo',
|
|
12
|
+
default: true,
|
|
13
|
+
type: 'boolean',
|
|
14
|
+
}
|
|
15
|
+
static theme = {
|
|
16
|
+
help: 'Show theme toggle (dark/light)',
|
|
17
|
+
default: true,
|
|
18
|
+
type: 'boolean',
|
|
19
|
+
}
|
|
20
|
+
static search = {
|
|
21
|
+
help: 'Show search input',
|
|
22
|
+
default: false,
|
|
23
|
+
type: 'boolean',
|
|
24
|
+
}
|
|
25
|
+
static share = {
|
|
26
|
+
help: 'Show share button',
|
|
27
|
+
default: false,
|
|
28
|
+
type: 'boolean',
|
|
29
|
+
}
|
|
30
|
+
static nav = {
|
|
31
|
+
help: 'Show navigation links',
|
|
32
|
+
default: true,
|
|
33
|
+
type: 'boolean',
|
|
34
|
+
}
|
|
35
|
+
static langs = {
|
|
36
|
+
help: 'Show language switcher',
|
|
37
|
+
default: true,
|
|
38
|
+
type: 'boolean',
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @param {Partial<HeaderVisibilityModel> | Record<string, any>} data Model input data.
|
|
43
|
+
* @param {object} [options] Extended options (db, etc.)
|
|
44
|
+
*/
|
|
45
|
+
constructor(data = {}, options = {}) {
|
|
46
|
+
super(data, options)
|
|
47
|
+
/** @type {boolean} Show logo */ this.logo
|
|
48
|
+
/** @type {boolean} Show theme toggle (dark/light) */ this.theme
|
|
49
|
+
/** @type {boolean} Show search input */ this.search
|
|
50
|
+
/** @type {boolean} Show share button */ this.share
|
|
51
|
+
/** @type {boolean} Show navigation links */ this.nav
|
|
52
|
+
/** @type {boolean} Show language switcher */ this.langs
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -1,30 +1,9 @@
|
|
|
1
|
-
import { Model } from '@nan0web/
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @typedef {'text'|'email'|'password'|'number'|'tel'|'url'|'date'} InputType
|
|
5
|
-
* @typedef {Object} InputData
|
|
6
|
-
* @property {InputType} [type]
|
|
7
|
-
* @property {string} [label]
|
|
8
|
-
* @property {string} [placeholder]
|
|
9
|
-
* @property {boolean} [required]
|
|
10
|
-
* @property {string} [pattern]
|
|
11
|
-
* @property {string} [min]
|
|
12
|
-
* @property {string} [max]
|
|
13
|
-
* @property {string} [step]
|
|
14
|
-
* @property {string} [hint]
|
|
15
|
-
* @property {boolean} [disabled]
|
|
16
|
-
* @property {string} [content]
|
|
17
|
-
*/
|
|
1
|
+
import { Model } from '@nan0web/types'
|
|
18
2
|
|
|
19
3
|
/**
|
|
20
4
|
* Model-as-Schema for Input component.
|
|
21
|
-
* Used exclusively for schema definition, validation, and editor reflection.
|
|
22
5
|
*/
|
|
23
6
|
export class InputModel extends Model {
|
|
24
|
-
// ==========================================
|
|
25
|
-
// 1. MODEL AS SCHEMA (Static Definition)
|
|
26
|
-
// ==========================================
|
|
27
|
-
|
|
28
7
|
static type = {
|
|
29
8
|
help: 'HTML5 Input type attribute',
|
|
30
9
|
default: 'text',
|
|
@@ -92,27 +71,27 @@ export class InputModel extends Model {
|
|
|
92
71
|
}
|
|
93
72
|
|
|
94
73
|
/**
|
|
95
|
-
* @param {
|
|
74
|
+
* @param {Partial<InputModel> | Record<string, any>} data Model input data.
|
|
75
|
+
* @param {object} [options] Extended options (db, etc.)
|
|
96
76
|
*/
|
|
97
|
-
constructor(data = {}) {
|
|
98
|
-
super(data)
|
|
99
|
-
/** @type {
|
|
100
|
-
/** @type {string
|
|
101
|
-
/** @type {string
|
|
102
|
-
/** @type {boolean
|
|
103
|
-
/** @type {string
|
|
104
|
-
/** @type {string
|
|
105
|
-
/** @type {string
|
|
106
|
-
/** @type {string
|
|
107
|
-
/** @type {string
|
|
108
|
-
/** @type {boolean
|
|
109
|
-
/** @type {string
|
|
77
|
+
constructor(data = {}, options = {}) {
|
|
78
|
+
super(data, options)
|
|
79
|
+
/** @type {string} HTML5 Input type attribute */ this.type
|
|
80
|
+
/** @type {string} Label displayed above the input */ this.label
|
|
81
|
+
/** @type {string} Placeholder text shown when empty */ this.placeholder
|
|
82
|
+
/** @type {boolean} Whether the field must be filled out */ this.required
|
|
83
|
+
/** @type {string} RegExp pattern for validation */ this.pattern
|
|
84
|
+
/** @type {string} Minimum value */ this.min
|
|
85
|
+
/** @type {string} Maximum value */ this.max
|
|
86
|
+
/** @type {string} Step interval */ this.step
|
|
87
|
+
/** @type {string} Helper text displayed below the input */ this.hint
|
|
88
|
+
/** @type {boolean} Whether the input is disabled */ this.disabled
|
|
89
|
+
/** @type {string} The actual value of the input */ this.content
|
|
110
90
|
}
|
|
111
91
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
92
|
+
/**
|
|
93
|
+
* @returns {AsyncGenerator<any, any, any>}
|
|
94
|
+
*/
|
|
116
95
|
async *run() {
|
|
117
96
|
const response = yield {
|
|
118
97
|
type: 'ask',
|
|
@@ -127,13 +106,14 @@ export class InputModel extends Model {
|
|
|
127
106
|
if (!re.test(val)) return 'Invalid format'
|
|
128
107
|
} catch (e) {
|
|
129
108
|
// fallback if pattern is malformed
|
|
109
|
+
return 'Invalid format'
|
|
130
110
|
}
|
|
131
111
|
}
|
|
132
112
|
return true
|
|
133
113
|
},
|
|
134
114
|
},
|
|
135
115
|
component: 'Input',
|
|
136
|
-
model:
|
|
116
|
+
model: this,
|
|
137
117
|
}
|
|
138
118
|
|
|
139
119
|
this.content = response.value
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Model } from '@nan0web/types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* PriceModel — OLMUI Model-as-Schema
|
|
5
|
+
* Represents a monetary value with currency.
|
|
6
|
+
*/
|
|
7
|
+
export class PriceModel extends Model {
|
|
8
|
+
static $id = '@nan0web/ui/PriceModel'
|
|
9
|
+
|
|
10
|
+
static value = {
|
|
11
|
+
help: 'Numeric price value',
|
|
12
|
+
default: 0,
|
|
13
|
+
type: 'number',
|
|
14
|
+
}
|
|
15
|
+
static currency = {
|
|
16
|
+
help: 'Currency code (ISO 4217)',
|
|
17
|
+
placeholder: 'USD',
|
|
18
|
+
default: 'USD',
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @param {Partial<PriceModel> | Record<string, any>} data Model input data.
|
|
23
|
+
* @param {object} [options] Extended options (db, etc.)
|
|
24
|
+
*/
|
|
25
|
+
constructor(data = {}, options = {}) {
|
|
26
|
+
super(data, options)
|
|
27
|
+
/** @type {number} Numeric price value */ this.value
|
|
28
|
+
/** @type {string} Currency code (ISO 4217) */ this.currency
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Model } from '@nan0web/types'
|
|
2
|
+
import { PriceModel } from './PriceModel.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* PricingModel — OLMUI Model-as-Schema
|
|
6
|
+
* A pricing tier/plan with title, price, and feature list.
|
|
7
|
+
*/
|
|
8
|
+
export class PricingModel extends Model {
|
|
9
|
+
static $id = '@nan0web/ui/PricingModel'
|
|
10
|
+
|
|
11
|
+
static title = {
|
|
12
|
+
help: 'Pricing plan name',
|
|
13
|
+
placeholder: 'Pro Plan',
|
|
14
|
+
default: '',
|
|
15
|
+
required: true,
|
|
16
|
+
}
|
|
17
|
+
static price = {
|
|
18
|
+
help: 'Price object (value + currency)',
|
|
19
|
+
type: 'PriceModel',
|
|
20
|
+
hint: PriceModel,
|
|
21
|
+
default: null,
|
|
22
|
+
}
|
|
23
|
+
static features = {
|
|
24
|
+
help: 'List of features included in this plan',
|
|
25
|
+
type: 'string[]',
|
|
26
|
+
default: [],
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {Partial<PricingModel> | Record<string, any>} data Model input data.
|
|
31
|
+
* @param {object} [options] Extended options (db, etc.)
|
|
32
|
+
*/
|
|
33
|
+
constructor(data = {}, options = {}) {
|
|
34
|
+
super(data, options)
|
|
35
|
+
/** @type {string} Pricing plan name */ this.title
|
|
36
|
+
/** @type {PriceModel|null} Price object (value + currency) */ this.price
|
|
37
|
+
/** @type {string[]} List of features included in this plan */ this.features
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Model } from '@nan0web/types'
|
|
2
|
+
import { PricingModel } from './PricingModel.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* PricingSectionModel — OLMUI Model-as-Schema
|
|
6
|
+
* A section containing a title and a collection of pricing tiers.
|
|
7
|
+
*/
|
|
8
|
+
export class PricingSectionModel extends Model {
|
|
9
|
+
static $id = '@nan0web/ui/PricingSectionModel'
|
|
10
|
+
|
|
11
|
+
static title = {
|
|
12
|
+
help: 'Section title',
|
|
13
|
+
placeholder: 'Pricing Plans',
|
|
14
|
+
default: '',
|
|
15
|
+
}
|
|
16
|
+
static items = {
|
|
17
|
+
help: 'Array of pricing tiers',
|
|
18
|
+
type: 'PricingModel[]',
|
|
19
|
+
hint: PricingModel,
|
|
20
|
+
default: [],
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @param {Partial<PricingSectionModel> | Record<string, any>} data Model input data.
|
|
25
|
+
* @param {object} [options] Extended options (db, etc.)
|
|
26
|
+
*/
|
|
27
|
+
constructor(data = {}, options = {}) {
|
|
28
|
+
super(data, options)
|
|
29
|
+
/** @type {string} Section title */ this.title
|
|
30
|
+
/** @type {PricingModel[]} Array of pricing tiers */ this.items
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Model } from '@nan0web/types'
|
|
2
|
+
import Navigation from '../Navigation.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* ProfileDropdownModel — OLMUI Model-as-Schema
|
|
6
|
+
* Account/profile dropdown in the header (user menu).
|
|
7
|
+
*/
|
|
8
|
+
export class ProfileDropdownModel extends Model {
|
|
9
|
+
static $id = '@nan0web/ui/ProfileDropdownModel'
|
|
10
|
+
|
|
11
|
+
static profileName = {
|
|
12
|
+
alias: 'name',
|
|
13
|
+
help: 'Display name of the user',
|
|
14
|
+
placeholder: 'Jane Doe',
|
|
15
|
+
default: '',
|
|
16
|
+
}
|
|
17
|
+
static email = {
|
|
18
|
+
help: 'User email address',
|
|
19
|
+
placeholder: 'jane@example.com',
|
|
20
|
+
default: '',
|
|
21
|
+
}
|
|
22
|
+
static avatar = {
|
|
23
|
+
help: 'User avatar image URL',
|
|
24
|
+
placeholder: 'https://...',
|
|
25
|
+
default: '',
|
|
26
|
+
}
|
|
27
|
+
static actions = {
|
|
28
|
+
help: 'Dropdown menu items (Settings, Logout, etc.)',
|
|
29
|
+
type: 'Navigation[]',
|
|
30
|
+
hint: Navigation,
|
|
31
|
+
default: [],
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @param {Partial<ProfileDropdownModel> | Record<string, any>} data Model input data.
|
|
36
|
+
* @param {object} [options] Extended options (db, etc.)
|
|
37
|
+
*/
|
|
38
|
+
constructor(data = {}, options = {}) {
|
|
39
|
+
super(data, options)
|
|
40
|
+
/** @type {string} Display name of the user */ this.profileName
|
|
41
|
+
/** @type {string} User email address */ this.email
|
|
42
|
+
/** @type {string} User avatar image URL */ this.avatar
|
|
43
|
+
/** @type {Navigation[]} Dropdown menu items */ this.actions
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -1,20 +1,10 @@
|
|
|
1
|
-
import { Model } from '@nan0web/
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @typedef {Object} SelectData
|
|
5
|
-
* @property {string} [content]
|
|
6
|
-
* @property {string[]} [options]
|
|
7
|
-
*/
|
|
1
|
+
import { Model } from '@nan0web/types'
|
|
8
2
|
|
|
9
3
|
/**
|
|
10
4
|
* Model-as-Schema for Select component.
|
|
11
5
|
* Represents a dropdown choice selection.
|
|
12
6
|
*/
|
|
13
7
|
export class SelectModel extends Model {
|
|
14
|
-
// ==========================================
|
|
15
|
-
// 1. MODEL AS SCHEMA (Static Definition)
|
|
16
|
-
// ==========================================
|
|
17
|
-
|
|
18
8
|
static content = {
|
|
19
9
|
help: 'Currently selected item or default placeholder',
|
|
20
10
|
default: 'Choose option',
|
|
@@ -28,18 +18,18 @@ export class SelectModel extends Model {
|
|
|
28
18
|
}
|
|
29
19
|
|
|
30
20
|
/**
|
|
31
|
-
* @param {
|
|
21
|
+
* @param {Partial<SelectModel> | Record<string, any>} data Model input data.
|
|
22
|
+
* @param {object} [options] Extended options (db, etc.)
|
|
32
23
|
*/
|
|
33
|
-
constructor(data = {}) {
|
|
34
|
-
super(data)
|
|
35
|
-
/** @type {string
|
|
36
|
-
/** @type {string[]
|
|
24
|
+
constructor(data = {}, options = {}) {
|
|
25
|
+
super(data, options)
|
|
26
|
+
/** @type {string} Currently selected item or default placeholder */ this.content
|
|
27
|
+
/** @type {string[]} List of available options for selection */ this.options
|
|
37
28
|
}
|
|
38
29
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
30
|
+
/**
|
|
31
|
+
* @returns {AsyncGenerator<any, { type: 'result', data: { selected: string } }, any>}
|
|
32
|
+
*/
|
|
43
33
|
async *run() {
|
|
44
34
|
const response = yield {
|
|
45
35
|
type: 'ask',
|
|
@@ -50,7 +40,7 @@ export class SelectModel extends Model {
|
|
|
50
40
|
validate: (val) => this.options?.includes(val) || 'Invalid option selected',
|
|
51
41
|
},
|
|
52
42
|
component: 'Select',
|
|
53
|
-
model:
|
|
43
|
+
model: this,
|
|
54
44
|
}
|
|
55
45
|
|
|
56
46
|
this.content = response.value
|
|
@@ -1,21 +1,10 @@
|
|
|
1
|
-
import { Model } from '@nan0web/
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @typedef {'sm'|'md'|'lg'} SpinnerSize
|
|
5
|
-
* @typedef {Object} SpinnerData
|
|
6
|
-
* @property {SpinnerSize} [size]
|
|
7
|
-
* @property {string} [color]
|
|
8
|
-
*/
|
|
1
|
+
import { Model } from '@nan0web/types'
|
|
9
2
|
|
|
10
3
|
/**
|
|
11
4
|
* Model-as-Schema for Spinner component.
|
|
12
5
|
* Represents a loading or progress state without user interaction.
|
|
13
6
|
*/
|
|
14
7
|
export class SpinnerModel extends Model {
|
|
15
|
-
// ==========================================
|
|
16
|
-
// 1. MODEL AS SCHEMA (Static Definition)
|
|
17
|
-
// ==========================================
|
|
18
|
-
|
|
19
8
|
static size = {
|
|
20
9
|
help: 'Spinner diameter',
|
|
21
10
|
default: 'md',
|
|
@@ -29,30 +18,26 @@ export class SpinnerModel extends Model {
|
|
|
29
18
|
}
|
|
30
19
|
|
|
31
20
|
/**
|
|
32
|
-
* @param {
|
|
21
|
+
* @param {Partial<SpinnerModel> | Record<string, any>} data Model input data.
|
|
22
|
+
* @param {object} [options] Extended options (db, etc.)
|
|
33
23
|
*/
|
|
34
|
-
constructor(data = {}) {
|
|
35
|
-
super(data)
|
|
36
|
-
/** @type {
|
|
37
|
-
/** @type {string
|
|
24
|
+
constructor(data = {}, options = {}) {
|
|
25
|
+
super(data, options)
|
|
26
|
+
/** @type {'sm'|'md'|'lg'} Spinner diameter */ this.size
|
|
27
|
+
/** @type {string} Override for base color token */ this.color
|
|
38
28
|
}
|
|
39
29
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
30
|
+
/**
|
|
31
|
+
* @returns {AsyncGenerator<any, any, any>}
|
|
32
|
+
*/
|
|
44
33
|
async *run() {
|
|
45
|
-
// A spinner does not ask for anything, it simply indicates progress.
|
|
46
|
-
// However, as a pure component it doesn't do any work itself,
|
|
47
|
-
// so running it just means declaring its state.
|
|
48
34
|
yield {
|
|
49
35
|
type: 'progress',
|
|
50
36
|
message: 'Loading...',
|
|
51
37
|
component: 'Spinner',
|
|
52
|
-
model:
|
|
38
|
+
model: this,
|
|
53
39
|
}
|
|
54
40
|
|
|
55
|
-
// Instant exit since it performs no async task internally
|
|
56
41
|
return { type: 'result', data: { completed: true } }
|
|
57
42
|
}
|
|
58
43
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Model } from '@nan0web/types'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* StatsItemModel — OLMUI Model-as-Schema
|
|
5
|
+
* A single stat entry (e.g. "Users: 10,000 ↑12%").
|
|
6
|
+
*/
|
|
7
|
+
export class StatsItemModel extends Model {
|
|
8
|
+
static $id = '@nan0web/ui/StatsItemModel'
|
|
9
|
+
|
|
10
|
+
static label = {
|
|
11
|
+
help: 'Stat label (e.g. "Active Users")',
|
|
12
|
+
placeholder: 'Users',
|
|
13
|
+
default: '',
|
|
14
|
+
required: true,
|
|
15
|
+
}
|
|
16
|
+
static value = {
|
|
17
|
+
help: 'Stat value (number or formatted string)',
|
|
18
|
+
placeholder: '10,000',
|
|
19
|
+
default: '',
|
|
20
|
+
required: true,
|
|
21
|
+
}
|
|
22
|
+
static trend = {
|
|
23
|
+
help: 'Trend indicator (e.g. "+12%", "-3%", or empty)',
|
|
24
|
+
placeholder: '+12%',
|
|
25
|
+
default: '',
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @param {Partial<StatsItemModel> | Record<string, any>} data Model input data.
|
|
30
|
+
* @param {object} [options] Extended options (db, etc.)
|
|
31
|
+
*/
|
|
32
|
+
constructor(data = {}, options = {}) {
|
|
33
|
+
super(data, options)
|
|
34
|
+
/** @type {string} Stat label (e.g. "Active Users") */ this.label
|
|
35
|
+
/** @type {string} Stat value (number or formatted string) */ this.value
|
|
36
|
+
/** @type {string} Trend indicator (e.g. "+12%", "-3%", or empty) */ this.trend
|
|
37
|
+
}
|
|
38
|
+
}
|