@nan0web/ui 1.8.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/README.md +29 -10
  2. package/package.json +18 -22
  3. package/src/Model/index.js +32 -3
  4. package/src/core/Form/Form.js +8 -7
  5. package/src/core/Form/Message.js +1 -1
  6. package/src/core/GeneratorRunner.js +10 -0
  7. package/src/core/Intent.js +21 -5
  8. package/src/core/IntentErrorModel.js +6 -1
  9. package/src/core/Stream.js +16 -5
  10. package/src/core/index.js +1 -1
  11. package/src/domain/FooterModel.js +57 -0
  12. package/src/domain/HeaderModel.js +50 -0
  13. package/src/domain/HeroModel.js +48 -0
  14. package/src/domain/Navigation.js +11 -10
  15. package/src/domain/SandboxModel.js +66 -115
  16. package/src/domain/ShowcaseAppModel.js +133 -50
  17. package/src/domain/components/AccordionModel.js +38 -0
  18. package/src/domain/components/AutocompleteModel.js +11 -21
  19. package/src/domain/components/BannerModel.js +37 -0
  20. package/src/domain/components/BreadcrumbModel.js +11 -9
  21. package/src/domain/components/ButtonModel.js +31 -58
  22. package/src/domain/components/CommentModel.js +44 -0
  23. package/src/domain/components/ConfirmModel.js +26 -33
  24. package/src/domain/components/EmptyStateModel.js +45 -0
  25. package/src/domain/components/FAQModel.js +32 -0
  26. package/src/domain/components/FooterConfigModel.js +26 -0
  27. package/src/domain/components/FooterVisibilityModel.js +48 -0
  28. package/src/domain/components/GalleryModel.js +36 -0
  29. package/src/domain/components/HeaderConfigModel.js +26 -0
  30. package/src/domain/components/HeaderVisibilityModel.js +54 -0
  31. package/src/domain/components/InputModel.js +21 -41
  32. package/src/domain/components/PriceModel.js +30 -0
  33. package/src/domain/components/PricingModel.js +39 -0
  34. package/src/domain/components/PricingSectionModel.js +32 -0
  35. package/src/domain/components/ProfileDropdownModel.js +45 -0
  36. package/src/domain/components/SelectModel.js +11 -21
  37. package/src/domain/components/SpinnerModel.js +11 -26
  38. package/src/domain/components/StatsItemModel.js +38 -0
  39. package/src/domain/components/StatsModel.js +32 -0
  40. package/src/domain/components/TableModel.js +11 -24
  41. package/src/domain/components/TabsModel.js +30 -0
  42. package/src/domain/components/TestimonialModel.js +24 -0
  43. package/src/domain/components/TimelineItemModel.js +38 -0
  44. package/src/domain/components/TimelineModel.js +32 -0
  45. package/src/domain/components/ToastModel.js +24 -51
  46. package/src/domain/components/TreeModel.js +10 -26
  47. package/src/domain/components/index.js +34 -0
  48. package/src/domain/index.js +24 -0
  49. package/src/index.js +2 -0
  50. package/src/testing/GalleryGenerator.js +85 -0
  51. package/src/testing/LogicInspector.js +55 -0
  52. package/src/testing/SnapshotInspector.js +84 -0
  53. package/src/testing/VisualAdapter.js +41 -0
  54. package/src/testing/index.js +3 -0
  55. package/types/Model/index.d.ts +62 -4
  56. package/types/core/Form/Form.d.ts +2 -2
  57. package/types/core/GeneratorRunner.d.ts +4 -0
  58. package/types/core/Intent.d.ts +31 -3
  59. package/types/core/IntentErrorModel.d.ts +4 -0
  60. package/types/core/index.d.ts +1 -1
  61. package/types/domain/FooterModel.d.ts +52 -0
  62. package/types/domain/HeaderModel.d.ts +45 -0
  63. package/types/domain/HeroModel.d.ts +43 -0
  64. package/types/domain/Navigation.d.ts +10 -9
  65. package/types/domain/SandboxModel.d.ts +16 -40
  66. package/types/domain/ShowcaseAppModel.d.ts +26 -54
  67. package/types/domain/components/AccordionModel.d.ts +33 -0
  68. package/types/domain/components/AutocompleteModel.d.ts +10 -29
  69. package/types/domain/components/BannerModel.d.ts +32 -0
  70. package/types/domain/components/BreadcrumbModel.d.ts +13 -6
  71. package/types/domain/components/ButtonModel.d.ts +18 -54
  72. package/types/domain/components/CommentModel.d.ts +39 -0
  73. package/types/domain/components/ConfirmModel.d.ts +20 -35
  74. package/types/domain/components/EmptyStateModel.d.ts +40 -0
  75. package/types/domain/components/FAQModel.d.ts +27 -0
  76. package/types/domain/components/FooterConfigModel.d.ts +21 -0
  77. package/types/domain/components/FooterVisibilityModel.d.ts +43 -0
  78. package/types/domain/components/GalleryModel.d.ts +35 -0
  79. package/types/domain/components/HeaderConfigModel.d.ts +21 -0
  80. package/types/domain/components/HeaderVisibilityModel.d.ts +49 -0
  81. package/types/domain/components/HeroModel.d.ts +24 -0
  82. package/types/domain/components/InputModel.d.ts +19 -59
  83. package/types/domain/components/PriceModel.d.ts +25 -0
  84. package/types/domain/components/PricingModel.d.ts +34 -0
  85. package/types/domain/components/PricingSectionModel.d.ts +27 -0
  86. package/types/domain/components/ProfileDropdownModel.d.ts +40 -0
  87. package/types/domain/components/SelectModel.d.ts +13 -28
  88. package/types/domain/components/ShowcaseAppModel.d.ts +32 -0
  89. package/types/domain/components/SpinnerModel.d.ts +10 -27
  90. package/types/domain/components/StatsItemModel.d.ts +33 -0
  91. package/types/domain/components/StatsModel.d.ts +27 -0
  92. package/types/domain/components/TableModel.d.ts +10 -26
  93. package/types/domain/components/TabsModel.d.ts +28 -0
  94. package/types/domain/components/TestimonialModel.d.ts +18 -0
  95. package/types/domain/components/TimelineItemModel.d.ts +33 -0
  96. package/types/domain/components/TimelineModel.d.ts +27 -0
  97. package/types/domain/components/ToastModel.d.ts +16 -45
  98. package/types/domain/components/TreeModel.d.ts +13 -36
  99. package/types/domain/components/index.d.ts +20 -0
  100. package/types/domain/index.d.ts +4 -1
  101. package/types/index.d.ts +1 -0
  102. package/types/testing/GalleryGenerator.d.ts +1 -0
  103. package/types/testing/LogicInspector.d.ts +22 -0
  104. package/types/testing/SnapshotInspector.d.ts +17 -0
  105. package/types/testing/VisualAdapter.d.ts +15 -0
  106. package/types/testing/index.d.ts +3 -0
  107. package/src/README.md.js +0 -436
@@ -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/core'
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 {SelectData | any} [data]
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|undefined} */ this.content
36
- /** @type {string[]|undefined} */ this.options
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
- // 2. AGNOSTIC LOGIC (Async Generator)
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: /** @type {any} */ (this),
43
+ model: this,
54
44
  }
55
45
 
56
46
  this.content = response.value
@@ -1,21 +1,10 @@
1
- import { Model } from '@nan0web/core'
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 {SpinnerData | any} [data]
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 {SpinnerSize|undefined} */ this.size
37
- /** @type {string|undefined} */ this.color
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
- // 2. AGNOSTIC LOGIC (Async Generator)
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: /** @type {any} */ (this),
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
+ }
@@ -0,0 +1,32 @@
1
+ import { Model } from '@nan0web/types'
2
+ import { StatsItemModel } from './StatsItemModel.js'
3
+
4
+ /**
5
+ * StatsModel — OLMUI Model-as-Schema
6
+ * A collection of stat items for dashboards and overview sections.
7
+ */
8
+ export class StatsModel extends Model {
9
+ static $id = '@nan0web/ui/StatsModel'
10
+
11
+ static title = {
12
+ help: 'Stats section title',
13
+ placeholder: 'Key Metrics',
14
+ default: '',
15
+ }
16
+ static items = {
17
+ help: 'Array of stat entries',
18
+ type: 'StatsItemModel[]',
19
+ hint: StatsItemModel,
20
+ default: [],
21
+ }
22
+
23
+ /**
24
+ * @param {Partial<StatsModel> | 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} Stats section title */ this.title
30
+ /** @type {StatsItemModel[]} Array of stat entries */ this.items
31
+ }
32
+ }
@@ -1,20 +1,10 @@
1
- import { Model } from '@nan0web/core'
2
-
3
- /**
4
- * @typedef {Object} TableData
5
- * @property {string[]} [columns]
6
- * @property {string[][]} [rows]
7
- */
1
+ import { Model } from '@nan0web/types'
8
2
 
9
3
  /**
10
4
  * Model-as-Schema for Table Data component.
11
5
  * Displays tabular string data in rows and columns.
12
6
  */
13
7
  export class TableModel extends Model {
14
- // ==========================================
15
- // 1. MODEL AS SCHEMA (Static Definition)
16
- // ==========================================
17
-
18
8
  static columns = {
19
9
  help: 'Array of column headers',
20
10
  type: 'string[]',
@@ -31,28 +21,25 @@ export class TableModel extends Model {
31
21
  }
32
22
 
33
23
  /**
34
- * @param {TableData | any} [data]
24
+ * @param {Partial<TableModel> | Record<string, any>} data Model input data.
25
+ * @param {object} [options] Extended options (db, etc.)
35
26
  */
36
- constructor(data = {}) {
37
- super(data)
38
- /** @type {string[]|undefined} */ this.columns
39
- /** @type {string[][]|undefined} */ this.rows
27
+ constructor(data = {}, options = {}) {
28
+ super(data, options)
29
+ /** @type {string[]} Array of column headers */ this.columns
30
+ /** @type {string[][]} 2D Array of table cells matching column length */ this.rows
40
31
  }
41
32
 
42
- // ==========================================
43
- // 2. AGNOSTIC LOGIC (Async Generator)
44
- // ==========================================
45
-
33
+ /**
34
+ * @returns {AsyncGenerator<any, any, any>}
35
+ */
46
36
  async *run() {
47
- // Tables are naturally result or log displays.
48
- // For an interactive flow, we could ask the user to 'select' a row,
49
- // but by default a table simply presents data.
50
37
  yield {
51
38
  type: 'log',
52
39
  level: 'info',
53
40
  message: `Displaying table with ${this.rows?.length || 0} rows`,
54
41
  component: 'Table',
55
- model: /** @type {any} */ (this),
42
+ model: this,
56
43
  }
57
44
 
58
45
  return { type: 'result', data: { rowsCount: this.rows?.length || 0 } }
@@ -0,0 +1,30 @@
1
+ import { Model } from '@nan0web/types'
2
+
3
+ /**
4
+ * TabsModel — OLMUI Model-as-Schema
5
+ * Tab container with selectable panels.
6
+ */
7
+ export class TabsModel extends Model {
8
+ static $id = '@nan0web/ui/TabsModel'
9
+
10
+ static active = {
11
+ help: 'Index of the currently active tab',
12
+ default: 0,
13
+ type: 'number',
14
+ }
15
+ static tabs = {
16
+ help: 'Tab definitions (label + content pairs)',
17
+ type: 'object[]',
18
+ default: [],
19
+ }
20
+
21
+ /**
22
+ * @param {Partial<TabsModel> | 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} Index of the currently active tab */ this.active
28
+ /** @type {Array<{label: string, content: string}>} Tab definitions */ this.tabs
29
+ }
30
+ }
@@ -0,0 +1,24 @@
1
+ import { CommentModel } from './CommentModel.js'
2
+
3
+ /**
4
+ * TestimonialModel — OLMUI Model-as-Schema
5
+ * Extends CommentModel with a rating field for testimonials/reviews.
6
+ */
7
+ export class TestimonialModel extends CommentModel {
8
+ static $id = '@nan0web/ui/TestimonialModel'
9
+
10
+ static rating = {
11
+ help: 'Rating from 1 to 5 stars',
12
+ default: 5,
13
+ type: 'number',
14
+ }
15
+
16
+ /**
17
+ * @param {Partial<TestimonialModel> | Record<string, any>} data Model input data.
18
+ * @param {object} [options] Extended options (db, etc.)
19
+ */
20
+ constructor(data = {}, options = {}) {
21
+ super(data, options)
22
+ /** @type {number} Rating from 1 to 5 stars */ this.rating
23
+ }
24
+ }
@@ -0,0 +1,38 @@
1
+ import { Model } from '@nan0web/types'
2
+
3
+ /**
4
+ * TimelineItemModel — OLMUI Model-as-Schema
5
+ * A single entry on a timeline (event, milestone, changelog).
6
+ */
7
+ export class TimelineItemModel extends Model {
8
+ static $id = '@nan0web/ui/TimelineItemModel'
9
+
10
+ static date = {
11
+ help: 'Date of the event (ISO 8601 or display string)',
12
+ placeholder: '2026-01-15',
13
+ default: '',
14
+ required: true,
15
+ }
16
+ static title = {
17
+ help: 'Event or milestone title',
18
+ placeholder: 'Product Launch',
19
+ default: '',
20
+ required: true,
21
+ }
22
+ static description = {
23
+ help: 'Detailed description of the event',
24
+ placeholder: 'We launched our new product...',
25
+ default: '',
26
+ }
27
+
28
+ /**
29
+ * @param {Partial<TimelineItemModel> | 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} Date of the event */ this.date
35
+ /** @type {string} Event or milestone title */ this.title
36
+ /** @type {string} Detailed description of the event */ this.description
37
+ }
38
+ }
@@ -0,0 +1,32 @@
1
+ import { Model } from '@nan0web/types'
2
+ import { TimelineItemModel } from './TimelineItemModel.js'
3
+
4
+ /**
5
+ * TimelineModel — OLMUI Model-as-Schema
6
+ * A collection of timeline events (changelog, roadmap, history).
7
+ */
8
+ export class TimelineModel extends Model {
9
+ static $id = '@nan0web/ui/TimelineModel'
10
+
11
+ static title = {
12
+ help: 'Timeline section title',
13
+ placeholder: 'Our Journey',
14
+ default: '',
15
+ }
16
+ static items = {
17
+ help: 'Array of timeline events',
18
+ type: 'TimelineItemModel[]',
19
+ hint: TimelineItemModel,
20
+ default: [],
21
+ }
22
+
23
+ /**
24
+ * @param {Partial<TimelineModel> | 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} Timeline section title */ this.title
30
+ /** @type {TimelineItemModel[]} Array of timeline events */ this.items
31
+ }
32
+ }
@@ -1,77 +1,50 @@
1
- import { Model } from '@nan0web/core'
1
+ import { Model } from '@nan0web/types'
2
2
 
3
3
  /**
4
- * @typedef {'success'|'error'|'info'|'warning'} ToastVariant
5
- * @typedef {Object} ToastData
6
- * @property {string} [message]
7
- * @property {ToastVariant} [variant]
8
- * @property {number} [duration]
9
- * @property {boolean} [open]
10
- */
11
-
12
- /**
13
- * Model-as-Schema for Toast notification component.
14
- * Represents a transient message displayed to the user.
4
+ * Model-as-Schema for Toast notification.
15
5
  */
16
6
  export class ToastModel extends Model {
17
- // ==========================================
18
- // 1. MODEL AS SCHEMA (Static Definition)
19
- // ==========================================
7
+ static variant = {
8
+ help: 'Notification color scheme',
9
+ default: 'info',
10
+ options: ['info', 'success', 'warn', 'error'],
11
+ }
20
12
 
21
13
  static message = {
22
- help: 'The message content of the toast',
23
- default: 'Saved successfully!',
14
+ help: 'Text content of the notification',
15
+ default: 'Notification message',
24
16
  type: 'string',
25
17
  }
26
18
 
27
- static variant = {
28
- help: 'Visual styling representing the message severity',
29
- default: 'success',
30
- options: ['success', 'error', 'info', 'warning'],
31
- }
32
-
33
19
  static duration = {
34
- help: 'Time in ms before auto-dismissal. 0 to keep open indefinitely.',
20
+ help: 'Auto-dismiss timeout (0 for manual only)',
35
21
  default: 3000,
36
22
  type: 'number',
37
23
  }
38
24
 
39
- static open = {
40
- help: 'Controls visibility state',
41
- default: true,
42
- type: 'boolean',
43
- }
44
-
45
25
  /**
46
- * @param {ToastData | any} [data]
26
+ * @param {Partial<ToastModel> | Record<string, any>} data Model input data.
27
+ * @param {object} [options] Extended options (db, etc.)
47
28
  */
48
- constructor(data = {}) {
49
- super(data)
50
- /** @type {string|undefined} */ this.message
51
- /** @type {ToastVariant|undefined} */ this.variant
52
- /** @type {number|undefined} */ this.duration
53
- /** @type {boolean|undefined} */ this.open
29
+ constructor(data = {}, options = {}) {
30
+ super(data, options)
31
+ /** @type {'info'|'success'|'warn'|'error'} Notification color scheme */ this.variant
32
+ /** @type {string} Text displayed in the toast */ this.message
33
+ /** @type {number} Auto-dismiss timeout in ms */ this.duration
54
34
  }
55
35
 
56
- // ==========================================
57
- // 2. AGNOSTIC LOGIC (Async Generator)
58
- // ==========================================
59
-
36
+ /**
37
+ * @returns {AsyncGenerator<any, any, any>}
38
+ */
60
39
  async *run() {
61
- // Maps naturally to the 'log' intent for OLMUI runners.
62
40
  yield {
63
41
  type: 'log',
64
- level: this.variant === 'error' ? 'error' : this.variant === 'warning' ? 'warn' : 'info',
42
+ level: this.variant === 'error' ? 'error' : 'info',
65
43
  message: this.message,
66
- component: 'Toast', // Hint for specific UI visual rendering
67
- model: /** @type {any} */ (this),
68
- }
69
-
70
- // Wait exactly 'duration' ms before completing (unless duration is 0)
71
- if (this.duration && this.duration > 0) {
72
- await new Promise((resolve) => setTimeout(resolve, this.duration))
44
+ component: 'Toast',
45
+ model: this,
73
46
  }
74
47
 
75
- return { type: 'result', data: { closed: true } }
48
+ return { type: 'result', data: { shown: true } }
76
49
  }
77
50
  }
@@ -1,26 +1,10 @@
1
- import { Model } from '@nan0web/core'
2
-
3
- /**
4
- * @typedef {Object} TreeNode
5
- * @property {string} label
6
- * @property {boolean} [expanded]
7
- * @property {TreeNode[]} [children]
8
- */
9
-
10
- /**
11
- * @typedef {Object} TreeData
12
- * @property {TreeNode[]} [data]
13
- */
1
+ import { Model } from '@nan0web/types'
14
2
 
15
3
  /**
16
4
  * Model-as-Schema for Tree component.
17
5
  * Represents a hierarchical selection or navigation structure.
18
6
  */
19
7
  export class TreeModel extends Model {
20
- // ==========================================
21
- // 1. MODEL AS SCHEMA (Static Definition)
22
- // ==========================================
23
-
24
8
  static data = {
25
9
  help: 'Tree nodes defining the hierarchy',
26
10
  type: 'TreeNode[]',
@@ -28,24 +12,24 @@ export class TreeModel extends Model {
28
12
  }
29
13
 
30
14
  /**
31
- * @param {TreeData | any} [data]
15
+ * @param {Partial<TreeModel> | Record<string, any>} data Model input data.
16
+ * @param {object} [options] Extended options (db, etc.)
32
17
  */
33
- constructor(data = {}) {
34
- super(data)
35
- /** @type {TreeNode[]|undefined} */ this.data
18
+ constructor(data = {}, options = {}) {
19
+ super(data, options)
20
+ /** @type {Array<{label: string, expanded?: boolean, children?: any[]}>} Tree nodes */ this.data
36
21
  }
37
22
 
38
- // ==========================================
39
- // 2. AGNOSTIC LOGIC (Async Generator)
40
- // ==========================================
41
-
23
+ /**
24
+ * @returns {AsyncGenerator<any, any, any>}
25
+ */
42
26
  async *run() {
43
27
  const response = yield {
44
28
  type: 'ask',
45
29
  field: 'selectedNode',
46
30
  schema: { help: 'Select a node from the tree' },
47
31
  component: 'Tree',
48
- model: /** @type {any} */ (this),
32
+ model: this,
49
33
  }
50
34
 
51
35
  return { type: 'result', data: { selected: response.value } }