neo.mjs 10.0.0-alpha.5 → 10.0.0-beta.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.
Files changed (188) hide show
  1. package/ServiceWorker.mjs +2 -2
  2. package/apps/colors/view/GridContainer.mjs +1 -1
  3. package/apps/covid/view/AttributionComponent.mjs +1 -1
  4. package/apps/covid/view/HeaderContainer.mjs +6 -6
  5. package/apps/covid/view/MainContainerController.mjs +5 -5
  6. package/apps/covid/view/TableContainerController.mjs +1 -1
  7. package/apps/covid/view/country/Gallery.mjs +13 -13
  8. package/apps/covid/view/country/Helix.mjs +13 -13
  9. package/apps/covid/view/country/HistoricalDataTable.mjs +1 -1
  10. package/apps/email/view/Viewport.mjs +2 -2
  11. package/apps/form/view/SideNavList.mjs +1 -1
  12. package/apps/portal/index.html +1 -1
  13. package/apps/portal/resources/data/examples_devmode.json +26 -27
  14. package/apps/portal/resources/data/examples_dist_dev.json +26 -27
  15. package/apps/portal/resources/data/examples_dist_esm.json +25 -26
  16. package/apps/portal/resources/data/examples_dist_prod.json +26 -27
  17. package/apps/portal/view/HeaderToolbar.mjs +3 -3
  18. package/apps/portal/view/about/Container.mjs +2 -2
  19. package/apps/portal/view/about/MemberContainer.mjs +3 -3
  20. package/apps/portal/view/blog/List.mjs +7 -7
  21. package/apps/portal/view/examples/List.mjs +4 -4
  22. package/apps/portal/view/home/ContentBox.mjs +2 -2
  23. package/apps/portal/view/home/FeatureSection.mjs +3 -3
  24. package/apps/portal/view/home/FooterContainer.mjs +7 -7
  25. package/apps/portal/view/home/parts/AfterMath.mjs +3 -3
  26. package/apps/portal/view/home/parts/MainNeo.mjs +3 -3
  27. package/apps/portal/view/home/parts/References.mjs +6 -6
  28. package/apps/portal/view/learn/ContentComponent.mjs +102 -111
  29. package/apps/portal/view/learn/PageSectionsContainer.mjs +1 -1
  30. package/apps/portal/view/learn/PageSectionsList.mjs +2 -2
  31. package/apps/portal/view/services/Component.mjs +16 -16
  32. package/apps/realworld/view/FooterComponent.mjs +1 -1
  33. package/apps/realworld/view/HeaderComponent.mjs +8 -8
  34. package/apps/realworld/view/HomeComponent.mjs +6 -6
  35. package/apps/realworld/view/article/CommentComponent.mjs +4 -4
  36. package/apps/realworld/view/article/Component.mjs +14 -14
  37. package/apps/realworld/view/article/CreateCommentComponent.mjs +3 -3
  38. package/apps/realworld/view/article/CreateComponent.mjs +3 -3
  39. package/apps/realworld/view/article/PreviewComponent.mjs +1 -1
  40. package/apps/realworld/view/article/TagListComponent.mjs +2 -2
  41. package/apps/realworld/view/user/ProfileComponent.mjs +8 -8
  42. package/apps/realworld/view/user/SettingsComponent.mjs +4 -4
  43. package/apps/realworld/view/user/SignUpComponent.mjs +4 -4
  44. package/apps/realworld2/view/FooterComponent.mjs +1 -1
  45. package/apps/realworld2/view/HomeContainer.mjs +3 -3
  46. package/apps/realworld2/view/article/DetailsContainer.mjs +1 -1
  47. package/apps/realworld2/view/article/PreviewComponent.mjs +7 -7
  48. package/apps/realworld2/view/article/TagListComponent.mjs +2 -2
  49. package/apps/realworld2/view/user/ProfileContainer.mjs +1 -1
  50. package/apps/route/view/center/CardAdministration.mjs +2 -2
  51. package/apps/route/view/center/CardAdministrationDenied.mjs +1 -1
  52. package/apps/route/view/center/CardContact.mjs +2 -2
  53. package/apps/route/view/center/CardHome.mjs +1 -1
  54. package/apps/route/view/center/CardSection1.mjs +1 -1
  55. package/apps/route/view/center/CardSection2.mjs +1 -1
  56. package/apps/sharedcovid/view/AttributionComponent.mjs +1 -1
  57. package/apps/sharedcovid/view/HeaderContainer.mjs +6 -6
  58. package/apps/sharedcovid/view/MainContainerController.mjs +5 -5
  59. package/apps/sharedcovid/view/TableContainerController.mjs +1 -1
  60. package/apps/sharedcovid/view/country/Gallery.mjs +13 -13
  61. package/apps/sharedcovid/view/country/Helix.mjs +13 -13
  62. package/apps/sharedcovid/view/country/HistoricalDataTable.mjs +1 -1
  63. package/apps/shareddialog/childapps/shareddialog2/view/MainContainer.mjs +1 -1
  64. package/apps/shareddialog/view/MainContainer.mjs +1 -1
  65. package/buildScripts/createApp.mjs +2 -2
  66. package/examples/table/cellEditing/MainContainer.mjs +1 -1
  67. package/examples/table/container/MainContainer.mjs +3 -3
  68. package/examples/table/nestedRecordFields/Viewport.mjs +6 -6
  69. package/examples/tableFiltering/MainContainer.mjs +1 -1
  70. package/examples/tablePerformance/MainContainer.mjs +1 -1
  71. package/examples/tablePerformance/MainContainer2.mjs +1 -1
  72. package/examples/tablePerformance/MainContainer3.mjs +2 -2
  73. package/examples/tableStore/MainContainer.mjs +2 -2
  74. package/learn/Glossary.md +261 -0
  75. package/learn/UsingTheseTopics.md +2 -2
  76. package/learn/benefits/ConfigSystem.md +538 -28
  77. package/learn/benefits/Effort.md +47 -2
  78. package/learn/benefits/Features.md +50 -32
  79. package/learn/benefits/FormsEngine.md +68 -38
  80. package/learn/benefits/MultiWindow.md +33 -7
  81. package/learn/benefits/OffTheMainThread.md +2 -2
  82. package/learn/benefits/Quick.md +45 -12
  83. package/learn/benefits/RPCLayer.md +75 -0
  84. package/learn/benefits/Speed.md +16 -11
  85. package/learn/gettingstarted/ComponentModels.md +4 -4
  86. package/learn/gettingstarted/Config.md +6 -6
  87. package/learn/gettingstarted/DescribingTheUI.md +4 -4
  88. package/learn/gettingstarted/Events.md +6 -6
  89. package/learn/gettingstarted/Extending.md +4 -4
  90. package/learn/gettingstarted/References.md +6 -6
  91. package/learn/gettingstarted/Workspaces.md +6 -6
  92. package/learn/guides/ApplicationBootstrap.md +26 -26
  93. package/learn/guides/ComponentsAndContainers.md +12 -12
  94. package/learn/guides/ConfigSystemDeepDive.md +280 -0
  95. package/learn/guides/CustomComponents.md +2 -2
  96. package/learn/guides/DeclarativeComponentTreesVsImperativeVdom.md +17 -17
  97. package/learn/guides/InstanceLifecycle.md +295 -1
  98. package/learn/guides/MainThreadAddons.md +475 -0
  99. package/learn/guides/PortalApp.md +2 -2
  100. package/learn/guides/StateProviders.md +12 -12
  101. package/learn/guides/WorkingWithVDom.md +14 -14
  102. package/learn/guides/events/CustomEvents.md +16 -16
  103. package/learn/guides/events/DomEvents.md +12 -12
  104. package/learn/javascript/ClassFeatures.md +3 -2
  105. package/learn/javascript/Classes.md +8 -8
  106. package/learn/javascript/NewNode.md +4 -4
  107. package/learn/javascript/Overrides.md +8 -8
  108. package/learn/javascript/Super.md +10 -8
  109. package/learn/tree.json +52 -51
  110. package/learn/tutorials/Earthquakes.md +54 -57
  111. package/learn/tutorials/TodoList.md +4 -4
  112. package/package.json +2 -2
  113. package/resources/scss/src/apps/portal/learn/ContentComponent.scss +12 -0
  114. package/resources/scss/src/table/{View.scss → Body.scss} +1 -1
  115. package/resources/scss/src/table/plugin/CellEditing.scss +1 -1
  116. package/resources/scss/theme-dark/table/{View.scss → Body.scss} +1 -1
  117. package/resources/scss/theme-light/table/{View.scss → Body.scss} +1 -1
  118. package/resources/scss/theme-neo-light/Global.scss +1 -2
  119. package/resources/scss/theme-neo-light/table/{View.scss → Body.scss} +1 -1
  120. package/src/DefaultConfig.mjs +2 -2
  121. package/src/Main.mjs +8 -7
  122. package/src/Neo.mjs +16 -2
  123. package/src/button/Base.mjs +2 -2
  124. package/src/calendar/view/SettingsContainer.mjs +2 -2
  125. package/src/calendar/view/YearComponent.mjs +9 -9
  126. package/src/calendar/view/calendars/ColorsList.mjs +1 -1
  127. package/src/calendar/view/calendars/List.mjs +1 -1
  128. package/src/calendar/view/month/Component.mjs +15 -15
  129. package/src/calendar/view/week/Component.mjs +12 -12
  130. package/src/calendar/view/week/EventDragZone.mjs +4 -4
  131. package/src/calendar/view/week/TimeAxisComponent.mjs +3 -3
  132. package/src/component/Base.mjs +17 -2
  133. package/src/component/Carousel.mjs +2 -2
  134. package/src/component/Chip.mjs +3 -3
  135. package/src/component/Circle.mjs +2 -2
  136. package/src/component/DateSelector.mjs +8 -8
  137. package/src/component/Helix.mjs +1 -1
  138. package/src/component/Label.mjs +3 -18
  139. package/src/component/Legend.mjs +3 -3
  140. package/src/component/MagicMoveText.mjs +6 -14
  141. package/src/component/Process.mjs +3 -3
  142. package/src/component/Progress.mjs +1 -1
  143. package/src/component/StatusBadge.mjs +2 -2
  144. package/src/component/Timer.mjs +2 -2
  145. package/src/component/Toast.mjs +5 -3
  146. package/src/container/AccordionItem.mjs +2 -2
  147. package/src/container/Base.mjs +1 -1
  148. package/src/core/Base.mjs +77 -14
  149. package/src/core/Util.mjs +14 -2
  150. package/src/date/DayViewComponent.mjs +2 -2
  151. package/src/date/SelectorContainer.mjs +1 -1
  152. package/src/draggable/grid/header/toolbar/SortZone.mjs +21 -21
  153. package/src/draggable/table/header/toolbar/SortZone.mjs +1 -1
  154. package/src/form/field/CheckBox.mjs +4 -4
  155. package/src/form/field/FileUpload.mjs +25 -39
  156. package/src/form/field/Range.mjs +1 -1
  157. package/src/form/field/Text.mjs +3 -3
  158. package/src/form/field/TextArea.mjs +2 -3
  159. package/src/grid/Body.mjs +8 -5
  160. package/src/grid/_export.mjs +1 -1
  161. package/src/list/Color.mjs +2 -2
  162. package/src/main/DeltaUpdates.mjs +157 -98
  163. package/src/main/addon/AmCharts.mjs +61 -84
  164. package/src/main/addon/Base.mjs +161 -42
  165. package/src/main/addon/GoogleMaps.mjs +9 -16
  166. package/src/main/addon/HighlightJS.mjs +2 -13
  167. package/src/main/addon/IntersectionObserver.mjs +21 -21
  168. package/src/main/addon/MonacoEditor.mjs +32 -64
  169. package/src/manager/ClassHierarchy.mjs +114 -0
  170. package/src/menu/List.mjs +1 -1
  171. package/src/plugin/Popover.mjs +2 -2
  172. package/src/sitemap/Component.mjs +1 -1
  173. package/src/table/{View.mjs → Body.mjs} +25 -22
  174. package/src/table/Container.mjs +43 -43
  175. package/src/table/_export.mjs +2 -2
  176. package/src/table/plugin/CellEditing.mjs +19 -19
  177. package/src/tooltip/Base.mjs +1 -6
  178. package/src/tree/Accordion.mjs +3 -3
  179. package/src/vdom/Helper.mjs +19 -22
  180. package/src/worker/App.mjs +1 -2
  181. package/src/worker/Base.mjs +7 -5
  182. package/src/worker/Canvas.mjs +2 -3
  183. package/src/worker/Data.mjs +5 -7
  184. package/src/worker/Task.mjs +2 -3
  185. package/src/worker/VDom.mjs +3 -4
  186. package/src/worker/mixin/RemoteMethodAccess.mjs +5 -2
  187. package/learn/guides/MainThreadAddonExample.md +0 -15
  188. package/learn/guides/MainThreadAddonIntro.md +0 -44
@@ -1,16 +1,27 @@
1
+ A Declarative Approach to Application Building
2
+
1
3
  ## Introduction
2
4
 
3
5
  Modern JavaScript frameworks have revolutionized front-end development by providing declarative ways to build
4
6
  user interfaces, primarily centered around enhancing HTML with custom syntax like JSX or Angular directives.
5
7
  However, the complexity of applications extends far beyond the Document Object Model (DOM), encompassing crucial
6
8
  non-DOM entities such as data stores, state providers, routers, view controllers, selection models, and layouts.
9
+
7
10
  While existing frameworks offer solutions for managing these aspects, they often lack a truly consistent, declarative,
8
11
  and nested approach to their configuration, a gap that a class config system aims to fill.
9
12
 
10
- ## A bad example
11
- I recently found this Angular code snippet (new public API draft) on LinkedIn:
13
+ ### The Problem with Disparate Configuration
14
+
15
+ Currently, the configuration and management of these non-DOM entities can feel somewhat disparate across different
16
+ frameworks. State management, for instance, might involve dedicated libraries (like Redux or Vuex), routing is handled
17
+ by router-specific configurations, and layouts might be defined through a mix of component composition and potentially
18
+ separate layout configurations. While these solutions are functional, they don't always present a unified configuration
19
+ tree that mirrors the nested, hierarchical structure often used for describing the UI. The syntax and patterns for
20
+ configuring a data store can be quite different from those used to define a route or a view controller.
12
21
 
13
- <pre data-code-readonly>
22
+ Consider this Angular code snippet (from a new public API draft):
23
+
24
+ ```javascript readonly
14
25
  // MyComponent with an attribute
15
26
  <MyComponent myAttribute="someValue" />
16
27
 
@@ -25,40 +36,539 @@ I recently found this Angular code snippet (new public API draft) on LinkedIn:
25
36
 
26
37
  // Scoped inputs for MyDirective
27
38
  <MyComponent @MyDirective(input1="someString" [input2]="mySignal()") />
28
- </pre>
39
+ ```
29
40
 
30
- Now you might wonder why I think that this is not a good way to create apps.
41
+ This example illustrates how various aspects (attributes, input bindings, directives, host elements, scoped inputs) are
42
+ configured using distinct syntax patterns. While functional, this variety can increase the cognitive load on developers,
43
+ requiring them to constantly context-switch between different configuration paradigms for different elements.
31
44
 
32
- Currently, the configuration and management of these non-DOM entities can feel somewhat disparate across different
33
- frameworks. State management, for instance, might involve dedicated libraries (like Redux or Vuex), routing is
34
- handled by router-specific configurations, and layouts might be defined through a mix of component composition and
35
- potentially separate layout configurations. While these solutions are functional, they don't always present a
36
- unified configuration tree that mirrors the nested, hierarchical structure often used for describing the UI.
37
- The syntax and patterns for configuring a data store can be quite different from those used to define a route or
38
- a view controller.
39
-
40
- This is where the benefit of a class config system becomes apparent. The vision is a system that allows developers
41
- to describe the desired state and relationships of all application components, regardless of whether they directly
42
- interact with the DOM, using a consistent, declarative, and nested configuration structure.
43
-
44
- Imagine defining your application's data stores, their initial states, and how they relate to each other, alongside
45
- the routes of your application, the view controllers responsible for handling those routes, and the layouts they will
46
- use – all within a unified configuration syntax. This nested structure would clearly illustrate the dependencies and
45
+ More importantly, the entire syntax is strictly limited to DOM-based entities.
46
+
47
+ ### Neo.mjs's Solution: A Unified Class Config System
48
+
49
+ This is where the benefit of a class config system becomes apparent. The vision in Neo.mjs is a system that allows
50
+ developers to describe the desired state and relationships of all application components—regardless of whether they
51
+ directly interact with the DOM—using a consistent, declarative, and nested configuration structure.
52
+
53
+ Imagine defining your application's data stores, their initial states, and how they relate to each other, alongside the
54
+ routes of your application, the view controllers responsible for handling those routes, and the layouts they will
55
+ use all within a unified configuration syntax. This nested structure clearly illustrates the dependencies and
47
56
  composition of the application's various parts, offering a holistic view that is often obscured when non-DOM elements
48
57
  are configured in isolation using different mechanisms.
49
58
 
50
- ## Key advantages
59
+ Neo.mjs achieves this by leveraging a powerful static config object pattern. You define properties and their default
60
+ values directly within your class definitions. When you create an instance of that class using Neo.create(), you can
61
+ override these defaults, and the framework automatically processes these configurations to instantiate and configure
62
+ components, data models, routes, and more. This mechanism applies consistently across all Neo.mjs classes.
63
+
64
+ ## Key Advantages
65
+
51
66
  A class config system, by treating all application entities as configurable classes within a unified hierarchy,
52
67
  offers several key advantages:
53
68
 
54
- * ***Consistency***: Provides a single, predictable way to configure any part of the application, reducing the cognitive load on developers who would otherwise need to learn and context-switch between different configuration paradigms for DOM and non-DOM elements.
55
- * ***Declarative Clarity***: Enables developers to declare the desired state and relationships of their application's components in a clear and concise manner, rather than writing imperative code to set up and connect these entities. This improves readability and maintainability.
56
- * ***Nested Structure***: Allows for the natural expression of hierarchical relationships between components, whether they are parent-child UI elements or a router managing various routes, each with associated view controllers and data requirements. This mirrors the often tree-like structure of applications.
57
- * ***Improved Maintainability***: Changes to the application's structure or behavior can be made in a centralized and organized configuration, rather than spread across various imperative code snippets and disparate configuration files.
58
- * ***Enhanced Tooling and Abstraction***: A unified system provides a solid foundation for building powerful development tools, such as visual editors or automatic documentation generators, that can understand and manipulate the entire application's structure. It also allows for higher levels of abstraction, potentially simplifying the definition of complex application patterns.
59
- * ***Reactive Configuration***: Similar to how UI frameworks react to state changes and update the DOM, a reactive class config system can react to changes in the configuration itself (in a development context, for example) to facilitate hot module replacement or dynamic updates of non-DOM entities.
69
+ * **Consistency**: Provides a single, predictable way to configure any part of the application, reducing the cognitive
70
+ load on developers who would otherwise need to learn and context-switch between different configuration paradigms for DOM and non-DOM elements.
71
+
72
+ * **Declarative Clarity**: Enables developers to declare the desired state and relationships of their application's
73
+ components in a clear and concise manner, rather than writing imperative code to set up and connect these entities.
74
+ This significantly improves readability and maintainability.
75
+
76
+ * **Nested Structure**: Allows for the natural expression of hierarchical relationships between components, whether they
77
+ are parent-child UI elements or a router managing various routes, each with associated view controllers and data requirements.
78
+ This mirrors the often tree-like structure of applications.
79
+
80
+ * **Improved Maintainability**: Changes to the application's structure or behavior can be made in a centralized and
81
+ organized configuration, rather than spread across various imperative code snippets and disparate configuration files.
82
+ This leads to a more predictable and manageable codebase.
83
+
84
+ * **Enhanced Tooling and Abstraction**: A unified system provides a solid foundation for building powerful development tools,
85
+ such as visual editors or automatic documentation generators, that can understand and manipulate the entire application's
86
+ structure. It also allows for higher levels of abstraction, potentially simplifying the definition of complex application patterns.
87
+
88
+ * **Reactive Configuration & Lifecycle Hooks:**: Neo.mjs configs are inherently reactive. Similar to how UI frameworks
89
+ react to state changes and update the DOM, Neo.mjs's reactive class config system automatically updates views when config
90
+ values change. For instance, simply assigning a new value to a config directly:
91
+
92
+ ```javascript readonly
93
+ myButton.text = 'New Button Text'; // UI will update automatically
94
+ myButton.iconCls = 'fa fa-check'; // UI will update automatically
95
+ ```
96
+
97
+ For optimal performance when changing multiple configs simultaneously, it's recommended to use the `set()` method.
98
+ This ensures all changes are processed within a single, efficient update cycle, avoiding unnecessary redraws.
99
+
100
+ Furthermore, any config defined with a trailing underscore (e.g., `myConfig_`) automatically gains optional lifecycle hooks:
101
+ * `beforeGetMyConfig(value)`
102
+ * `beforeSetMyConfig(value, oldValue)`
103
+ * `afterSetMyConfig(value, oldValue)`
104
+
105
+ These powerful hooks allow you to intercept, validate,
106
+ transform, or react to config changes, providing fine-grained control over data flow and enabling clean side effects.
107
+
108
+ * **Direct DevTools Interaction**: The declarative and accessible nature of Neo.mjs class configs allows developers to
109
+ easily inspect, modify, and experiment with component and application state directly within the browser's developer
110
+ tools console. This live interaction capability significantly streamlines debugging, prototyping, and understanding
111
+ complex application behavior.
60
112
 
61
113
  While existing frameworks have made significant strides in declarative UI development, the concept of extending this
62
114
  declarative, nested configuration approach consistently to all aspects of an application, particularly the non-DOM realm,
63
- represents a powerful next step. A class config system holds the promise of a more unified, maintainable, and
115
+ represents a powerful next step. Neo.mjs's class config system holds the promise of a more unified, maintainable, and
64
116
  understandable way to build complex modern web applications.
117
+
118
+ ## Unifying Creation and Updates: The Consistent Config Experience
119
+
120
+ A particularly powerful aspect of the Neo.mjs config system's "unified" nature lies in its consistent application
121
+ across object creation and dynamic updates. The same declarative `static config` block that defines your class's properties
122
+ also serves as the blueprint for its instances.
123
+
124
+ When you initially create a component or any Neo.mjs class using `Neo.create()`, you pass a config object that directly
125
+ leverages this blueprint. Crucially, when you later need to change properties of an existing instance
126
+ (e.g., `myButton.set({ text: 'New Text' })` or `myButton.text = 'New Text'`),
127
+ you use the **exact same declarative config syntax**.
128
+ This consistency means developers only need to learn one powerful way to interact with an object's properties,
129
+ whether for initial setup or reactive modifications throughout its lifecycle. This predictability significantly
130
+ streamlines development, reduces cognitive load, and enhances code readability,
131
+ making the entire application more intuitive to manage.
132
+
133
+ ## The static config Block: Your Declarative Blueprint
134
+
135
+ Every Neo.mjs class, from UI components to data models and utility classes, can define a `static config` object.
136
+ This object serves as the blueprint for instances of that class, declaring their properties, default values,
137
+ and how they interact.
138
+
139
+ ### 1. Basic Component Configuration: The Neo.mjs Button
140
+
141
+ Let's start with a simple example: configuring a button. In Neo.mjs, even fundamental UI elements like buttons
142
+ are highly configurable classes.
143
+
144
+ Consider the `Neo.button.Base class`
145
+ [[Source: button.Base.mjs](https://github.com/neomjs/neo/blob/dev/src/button/Base.mjs)],
146
+ Its static config block defines all the properties you can set to customize a button's appearance and behavior:
147
+
148
+ ```javascript readonly
149
+ // From: Neo.button.Base
150
+ class Button extends Component {
151
+ static config = {
152
+ className: 'Neo.button.Base',
153
+ ntype : 'button',
154
+ text : null, // The text displayed on the button
155
+ iconCls_ : null, // The CSS class to use for an icon, e.g. 'fa fa-home'
156
+ handler_ : null, // Shortcut for domListeners={click:handler}
157
+ route_ : null, // Change the browser hash value on click.
158
+
159
+ // The virtual DOM structure of the button
160
+ // (not used parts will not show up inside the live DOM)
161
+ _vdom: {
162
+ tag: 'button', type: 'button', cn: [
163
+ {tag: 'span', cls: ['neo-button-glyph']},
164
+ {tag: 'span', cls: ['neo-button-text']},
165
+ {cls: ['neo-button-badge']},
166
+ {cls: ['neo-button-ripple-wrapper'], cn: [
167
+ {cls: ['neo-button-ripple']}
168
+ ]}
169
+ ]
170
+ }
171
+ // ... many other properties like badgeText_, iconPosition_, menu_, pressed_, etc.
172
+ }
173
+ // ... rest of the class definition
174
+ }
175
+ ```
176
+
177
+ ### Instantiating and Configuring a Button
178
+
179
+ To create an instance of this button and apply your desired configuration, you use `Neo.create()` or `Neo.ntype()`:
180
+
181
+ ```javascript readonly
182
+ import Button fron '../../src/button/Base.mjs';
183
+
184
+ // A simple button
185
+ Neo.create({
186
+ module : Button,
187
+ text : 'Click Me',
188
+ handler: () => alert('Button clicked!')
189
+ });
190
+
191
+ // A button with an icon and route
192
+ Neo.ntype({
193
+ ntype : 'button',
194
+ text : 'Go Home',
195
+ iconCls : 'fa fa-home', // Uses Font Awesome icon
196
+ iconPosition: 'left', // Icon on the left
197
+ route : '#main/home' // Changes browser hash to #main/home on click
198
+ });
199
+ ```
200
+
201
+ Notice how `text`, `iconCls`, `iconPosition`, and `route` are simply properties passed into the configuration object.
202
+ The framework takes care of applying these values to the button instance and rendering its virtual DOM (`_vdom) accordingly.
203
+
204
+ ### 2. Nested Component Configuration: Containers and the items Property
205
+
206
+ Neo.mjs components can be nested to create complex UIs, forming a hierarchical tree structure. This is managed consistently
207
+ through container components and their `items` configuration.
208
+
209
+ The `Neo.container.Base` class
210
+ [[Source: container.Base.mjs](https://github.com/neomjs/neo/blob/dev/src/container/Base.mjs)],
211
+ is fundamental for building UIs with multiple child components. It provides a `static config`
212
+ property called `items_`, which is an array or object containing configurations for its children. It also includes a `layout_`
213
+ property to define how these items are arranged.
214
+
215
+ Here's a simplified look at the relevant parts of `Neo.container.Base`'s config:
216
+
217
+ ```javascript readonly
218
+ // From: Neo.container.Base
219
+ class Container extends Component {
220
+ static config = {
221
+ className: 'Neo.container.Base',
222
+ ntype: 'container',
223
+ // ... other properties
224
+ /**
225
+ * Defines the layout manager for the container's items.
226
+ * @member {Object|String|null} layout_={ntype: 'vbox', align: 'stretch'}
227
+ */
228
+ layout_: {
229
+ ntype: 'vbox',
230
+ align: 'stretch'
231
+ },
232
+ /**
233
+ * An array or an object of config objects|instances|modules for each child component
234
+ * @member {Object[]} items_=[]
235
+ */
236
+ items_: [],
237
+ // ... other properties
238
+ }
239
+ // ... rest of the class definition
240
+ }
241
+ ```
242
+
243
+ The `items_` config allows for flexible ways to define children:
244
+
245
+ * **By ntype**: A string alias for the component's className.
246
+ * **By imported module**: Directly referencing the imported class.
247
+ * **By instance**: Passing an already created Neo.mjs component instance.
248
+
249
+ ### Example: A Container with Nested Buttons
250
+
251
+ Let's create a container with a vertical box layout and several buttons inside it,
252
+ demonstrating different ways to configure items:
253
+
254
+ ```javascript readonly
255
+ import Button from '../../src/button/Base.mjs'; // Assuming Button is imported correctly
256
+
257
+ Neo.ntype({
258
+ ntype: 'container',
259
+ layout: {
260
+ ntype: 'vbox', // Vertical box layout
261
+ align: 'center' // Center items horizontally
262
+ },
263
+ items: [ // Define child components within the 'items' array
264
+ { // Configured by ntype
265
+ ntype: 'button',
266
+ text : 'Button 1 (by ntype)'
267
+ },
268
+ { // Configured by imported module
269
+ module: Button,
270
+ text : 'Button 2 (by module)'
271
+ },
272
+ Neo.create({ // Configured by instance
273
+ module: Button,
274
+ text : 'Button 3 (by instance)'
275
+ }),
276
+ { // Another button with a handler
277
+ className: 'Neo.button.Base',
278
+ text : 'Hello Alert',
279
+ handler : () => console.log('Hello from a nested button!')
280
+ }
281
+ ]
282
+ });
283
+ ```
284
+
285
+ This example clearly shows how the `items` config allows for a declarative, nested structure, effectively building a UI tree.
286
+ The `layout` config further specifies how these children are arranged within the container,
287
+ all using the same consistent configuration syntax.
288
+
289
+ Note: While this section demonstrates container configuration, a comprehensive guide on Neo.mjs containers and their
290
+ various layouts (e.g., `vbox`, `hbox`, `fit`, `card`, `grid`) will be provided in a separate, dedicated guide to maintain
291
+ a sharp focus on the core class config system here.
292
+
293
+ ### 3. Non-DOM Entity Configuration: Data Stores and Models
294
+
295
+ Beyond UI components, the class config system extends seamlessly to non-DOM entities like data stores and models,
296
+ allowing for a unified declarative approach to your application's data layer.
297
+
298
+ **Defining a Data Store** (`Neo.data.Store`)
299
+
300
+ A `Neo.data.Store` manages collections of data records, often fetched from a server or generated client-side.
301
+ The `static config` for a store allows you to define its associated data model, filters, and other properties.
302
+
303
+ Here's an example from `Neo.examples.grid.bigData.MainStore`
304
+ [[Source: MainStore.mjs](https://github.com/neomjs/neo/blob/dev/examples/grid/bigData/MainStore.mjs)]:
305
+
306
+ ```javascript readonly
307
+ import Model from './MainModel.mjs'; // Assuming MainModel.mjs defines a Neo.data.Model
308
+ import Store from '../../../src/data/Store.mjs';
309
+
310
+ class MainStore extends Store {
311
+ static config = {
312
+ className : 'Neo.examples.grid.bigData.MainStore',
313
+ ntype : 'mainstore', // Custom ntype for easy referencing
314
+ amountColumns_: 50,
315
+ amountRows_ : 1000,
316
+
317
+ // Define default filters declaratively
318
+ filters: [{
319
+ property: 'firstname',
320
+ operator: 'like',
321
+ value : null
322
+ }, {
323
+ property: 'lastname',
324
+ operator: 'like',
325
+ value : null
326
+ }],
327
+ model: Model // Associate a data model with this store
328
+ }
329
+ // ... other properties and methods like firstnames, lastnames, generateData, etc.
330
+ }
331
+
332
+ export default Neo.setupClass(MainStore);
333
+ ```
334
+
335
+ In this example:
336
+
337
+ * `amountColumns_` and `amountRows_` define initial data dimensions.
338
+ * The `filters` array declaratively sets up default filtering rules.
339
+ * The `model` property specifies which `Neo.data.Model` class instances in this store will adhere to.
340
+ This creates a powerful, type-safe data structure.
341
+
342
+ **Connecting a Store to a Grid**
343
+
344
+ One common use case is connecting a data store to a UI component like a grid. `The Neo.grid.Container`
345
+ (which GridContainer extends) also uses the class config system to specify its data `store`.
346
+
347
+ Here's how `Neo.examples.grid.bigData.GridContainer`
348
+ [[Source: GridContainer.mjs](https://github.com/neomjs/neo/blob/dev/examples/grid/bigData/GridContainer.mjs)]
349
+ connects to the `MainStore`:
350
+
351
+ ```javascript readonly
352
+ import BaseGridContainer from '../../../src/grid/Container.mjs';
353
+ import Button from '../../../src/button/Base.mjs';
354
+ import MainStore from './MainStore.mjs';
355
+
356
+ class GridContainer extends BaseGridContainer {
357
+ static config = {
358
+ className: 'Neo.examples.grid.bigData.GridContainer',
359
+ // ... other grid-specific configurations
360
+ store: MainStore // The grid declaratively specifies which store to use
361
+ }
362
+ // ...
363
+ }
364
+
365
+ export default Neo.setupClass(GridContainer);
366
+ ```
367
+
368
+ By simply assigning `MainStore` to the `store` config property, the `GridContainer` instance will automatically use the data
369
+ provided and managed by `MainStore`. This demonstrates the seamless integration of non-DOM data logic with DOM-rendering
370
+ components through a consistent declarative config system.
371
+
372
+ **Note**: This section focuses on how grid's `store config property integrates with the class config system. A detailed
373
+ explanation of all grid features, column configurations, and data handling methods will be covered in a
374
+ separate Grid Component guide.
375
+
376
+ ### 4. Configuring Controllers and State Providers for Application Logic
377
+
378
+ Neo.mjs's declarative configuration extends to application logic components such as controllers and state providers,
379
+ allowing you to define their association and initial properties directly within the `static config` of your views or other classes.
380
+ This offers significant flexibility in how these non-DOM entities are managed.
381
+
382
+ **Important Best Practice**:
383
+
384
+ It's a core Neo.mjs best practice that controllers and state providers are typically associated with non-leaf (container)
385
+ components, such as `Viewport`s or other top-level application containers, rather than individual leaf-node UI components
386
+ (like a `Button` or `Label`). This promotes a clear separation of concerns, keeping complex logic centralized and allowing
387
+ leaf components to remain focused on their rendering responsibilities. A `Viewport`, for example, often manages overall
388
+ application state, routing, and user interactions, making it a natural home for a controller and state provider.
389
+
390
+ Consider the `Portal.view.Viewport` class
391
+ [[Source: Viewport.mjs](https://github.com/neomjs/neo/blob/dev/apps/portal/view/Viewport.mjs)],
392
+ which effectively utilizes both a controller and a state provider for application-level concerns:
393
+
394
+ ```javascript readonly
395
+ import ViewportController from './ViewportController.mjs';
396
+ import ViewportStateProvider from './ViewportStateProvider.mjs';
397
+
398
+ class Viewport extends BaseViewport {
399
+ static config = {
400
+ className : 'Portal.view.Viewport',
401
+ controller : ViewportController, // Option 1: Direct module reference
402
+ // ... layout, items
403
+ stateProvider: ViewportStateProvider // Option 1: Direct module reference
404
+ }
405
+ // ... rest of the class
406
+ }
407
+ ```
408
+
409
+ Neo.mjs provides several ways to configure these entities within the `static config` block:
410
+
411
+ 1. **Direct Module Reference (Most Common)**</br>
412
+ You can directly provide the imported class module to the controller or stateProvider config.
413
+ Neo.mjs will automatically create an instance of that class and assign it to the property.
414
+ This is the simplest and most common approach, as seen in the Viewport example above.
415
+
416
+ ```javascript readonly
417
+ // In MyContainer.mjs (a non-leaf component)
418
+ import MyController from './MyController.mjs';
419
+
420
+ class MyContainer extends Container {
421
+ static config = {
422
+ controller: MyController // Neo.mjs will instantiate MyController
423
+ }
424
+ }
425
+ ```
426
+
427
+ 2. **Config Object with `module`**</br>
428
+ If you need to pass additional configuration properties to the controller or state provider at the time of its creation,
429
+ you can provide a config object that includes the `module` property along with any other desired properties.
430
+ Neo.mjs will use this full config object to create the instance.
431
+
432
+ ```javascript readonly
433
+ // In MyContainer.mjs
434
+ import MyController from './MyController.mjs';
435
+
436
+ class MyContainer extends Container {
437
+ static config = {
438
+ controller: {
439
+ module : MyController,
440
+ myCustomProperty: 'initialValue',
441
+ anotherSetting : true
442
+ }
443
+ }
444
+ }
445
+ ```
446
+
447
+ 3. **Inline Class Definition (for tightly coupled cases)** </br>
448
+ For very specific or small controllers/state providers that are tightly coupled to a single component and don't
449
+ require external reusability, you can define them inline as a nested configuration object within the component's config.
450
+ While this reduces external reusability, it keeps highly related code together and maintains the declarative paradigm.
451
+
452
+ ```javascript readonly
453
+ // In MyContainer.mjs
454
+ class MyContainer extends Container {
455
+ static config = {
456
+ stateProvider: {
457
+ data: {
458
+ foo: 'bar'
459
+ }
460
+ }
461
+ }
462
+ }
463
+ ```
464
+
465
+ This approach allows you to fully define the state provider's behavior and dependencies directly within the container's configuration.
466
+
467
+ These options provide a powerful and consistent way to inject behavior and state management into your components,
468
+ all within the unified class config system, further demonstrating its versatility for both UI and non-UI logic.
469
+
470
+ **Note**: This section focuses on the configuration methods for controllers and state providers. Detailed explanations of
471
+ controller methods, state management patterns, and specific API functionalities will be covered in dedicated guides on
472
+ Controllers and State Management.
473
+
474
+ ### 5. Non-DOM Entity Configuration: Routing with routes
475
+
476
+ Neo.mjs enables declarative routing directly within the static config of your controllers (or other relevant classes), often a ViewportController for top-level application navigation. This allows you to define URL hash patterns and map them to specific controller methods, creating a clear, maintainable routing system.
477
+
478
+ Consider the ViewportController.mjs
479
+ [[Source: ViewportController.mjs](https://github.com/neomjs/neo/blob/dev/apps/portal/view/ViewportController.mjs)]:
480
+
481
+ ```javascript readonly
482
+ // From: Portal.view.ViewportController
483
+ import Controller from '../../../src/controller/Component.mjs';
484
+ // ... other imports
485
+
486
+ class ViewportController extends Controller {
487
+ static config = {
488
+ className: 'Portal.view.ViewportController',
489
+ ntype : 'viewport-controller',
490
+ // ... other configurations
491
+ /**
492
+ * @member {Object} routes
493
+ */
494
+ routes: {
495
+ '/about-us' : 'onAboutUsRoute',
496
+ '/blog' : 'onBlogRoute',
497
+ '/docs' : 'onDocsRoute',
498
+ '/examples' : 'onExamplesRoute',
499
+ '/examples/{itemId}': 'onExamplesRoute',
500
+ '/home' : 'onHomeRoute',
501
+ '/learn' : 'onLearnRoute',
502
+ '/learn/{itemId}' : 'onLearnRoute',
503
+ '/services' : 'onServicesRoute'
504
+ },
505
+ // ... other configurations
506
+ }
507
+ // ... controller methods like onAboutUsRoute, onBlogRoute, etc.
508
+ }
509
+ ```
510
+
511
+ In this `ViewportController`'s `static config`:
512
+
513
+ * The `routes` object maps URL hash patterns (keys) to controller method names (values).
514
+ * For example, when the browser's hash changes to `#/home`, the `onHomeRoute` method within `ViewportController` is automatically invoked.
515
+ * Routes can include dynamic parameters using curly braces, like `/examples/{itemId}`. When such a route is matched
516
+ (e.g., `#/examples/my-component`), the `onExamplesRoute` method will be called, and the `itemId` value (`my-component`)
517
+ will be passed as a parameter to the method.
518
+ * This declarative setup centralizes your application's routing logic, making it easy to understand the application's
519
+ navigation paths and their corresponding actions at a glance.
520
+ * The controller methods, such as `onHomeRoute`, then typically manage the application's UI state based on the route,
521
+ for instance, by setting the `activeIndex` of a card layout container to display the correct view:
522
+
523
+ ```javascript readonly
524
+ // From: Portal.view.ViewportController
525
+ // ...
526
+ /**
527
+ * @param {Object} params
528
+ * @param {Object} value
529
+ * @param {Object} oldValue
530
+ */
531
+ onHomeRoute(params, value, oldValue) {
532
+ this.setMainContentIndex(0)
533
+ }
534
+
535
+ /**
536
+ * @param {Number} index
537
+ */
538
+ async setMainContentIndex(index) {
539
+ let me = this,
540
+ {activeIndex, mainContentLayout} = me,
541
+ container = me.getReference('main-content');
542
+ // ... logic to update the main content container's activeIndex
543
+ if (index !== activeIndex) {
544
+ me.activeIndex = index;
545
+ // ... more complex layout transition logic
546
+ container.layout.activeIndex = index;
547
+ }
548
+ }
549
+ ```
550
+
551
+ This demonstrates a complete declarative flow: the `static config` defines the routes, which then trigger methods within
552
+ the same controller to update the UI, all within a consistent declarative pattern.
553
+
554
+ **Note**: This section focuses on how routes are defined and linked to controller methods through the `static config`.
555
+ A comprehensive guide on Neo.mjs routing, including advanced features like route guards, nested routes, and router
556
+ history management, will be provided in a separate, dedicated guide.
557
+
558
+ ## Conclusion: Empowering Declarative Development with Neo.mjs Configs
559
+
560
+ The Neo.mjs Unified Class Config System is a cornerstone of the framework's design, extending the power of declarative
561
+ programming beyond traditional UI elements to encompass every aspect of your application. By providing a consistent,
562
+ intuitive, and hierarchical way to define and manage properties for all classes — from UI components to data stores,
563
+ controllers, and routers—Neo.mjs significantly reduces cognitive load and enhances maintainability.
564
+
565
+ This system empowers developers to describe the desired state and behavior of their applications in a clear, concise,
566
+ and unified manner. The inherent reactivity of configs, coupled with powerful lifecycle hooks like beforeGet, beforeSet,
567
+ and afterSet, offers unparalleled control and flexibility, enabling dynamic updates and sophisticated data flow management.
568
+
569
+ Ultimately, the Neo.mjs config system streamlines application development, making it easier to build complex,
570
+ high-performance, and maintainable web applications. It's a testament to Neo.mjs's commitment to providing a truly
571
+ unified and developer-friendly experience.
572
+
573
+ For a detailed understanding of the internal mechanics, advanced usage patterns, and the full power of config lifecycle
574
+ hooks, please refer to the [Config System Deep Dive guide](#/learn/guides.ConfigSystemDeepDive).
@@ -1,3 +1,48 @@
1
- WIth Neo.mjs applications, the relationship between complexity and effort is nearly linear. In a typical frameworks, trivial applications are simple to implement, but complex applications can be very expensive and difficult to implement.
2
1
 
3
- <img width="85%" src="https://s3.amazonaws.com/mjs.neo.learning.images/whyneo/ComplexityAndEffort.png"></img>
2
+ ## A Strategic Investment
3
+
4
+ In the world of web development, the relationship between application complexity and the effort required to build and
5
+ maintain it is rarely linear. As the chart below illustrates, traditional JavaScript frameworks and even vanilla JavaScript
6
+ often lead to an exponential increase in effort as applications grow in features, data, and user interactions.
7
+
8
+ <img width="85%" src="https://raw.githubusercontent.com/neomjs/pages/main/resources_pub/website/learn/ComplexityAndEffort.png"></img>
9
+
10
+ ### The Neo.mjs Advantage: A Linear Path to Scalability
11
+
12
+ Neo.mjs presents a fundamentally different curve. While there might be a slightly higher initial learning curve or setup
13
+ effort compared to starting with a trivial vanilla JavaScript website, this upfront investment is a strategic advantage.
14
+ Developers typically get "up to speed" with Neo.mjs within about a week, grasping its core concepts and unique architecture.
15
+
16
+ This initial effort is quickly recouped, leading to a significant "turning point" where developer productivity skyrockets.
17
+ Once familiar with the Neo.mjs paradigm, the effort required to implement increasingly complex features scales almost
18
+ linearly. This is a stark contrast to other frameworks where complexity often translates into spiraling costs,
19
+ diminishing returns, and a constant battle against technical debt.
20
+
21
+ ### Why Neo.mjs Maintains Linearity:
22
+
23
+ Neo.mjs achieves this remarkable linearity through a combination of architectural innovations and developer-centric design:
24
+
25
+ 1. **Unified Config System**: All aspects of your application—from UI components and layouts to data models, controllers,
26
+ and routing—are defined declaratively through a consistent, hierarchical configuration. This eliminates the need to learn
27
+ disparate configuration paradigms, significantly reducing cognitive load and development time as complexity increases.
28
+
29
+ 2. **Off-Main-Thread Architecture (OMT)**: By offloading business logic and data processing to Web Workers, Neo.mjs ensures
30
+ the main thread remains responsive, even in highly complex, data-intensive applications. This inherent separation of
31
+ concerns prevents UI freezes and simplifies debugging, as performance bottlenecks are isolated and easier to identify.
32
+ The multi-threaded nature also inherently supports technical scaling by distributing computational load across CPU cores.
33
+
34
+ 3. **Predictable Component Lifecycle**: The well-defined and consistent lifecycle of Neo.mjs components, from creation
35
+ to destruction, provides clear hooks for managing state and resources. This predictability reduces the likelihood of
36
+ memory leaks and unexpected behavior, making complex applications more stable and easier to maintain.
37
+
38
+ 4. **Modular and Scalable Design**: Neo.mjs encourages a modular approach, allowing developers to build complex
39
+ applications from smaller, self-contained, and reusable components. This design philosophy, combined with features like
40
+ intelligent lazy loading, ensures that even massive enterprise applications remain manageable and performant.
41
+
42
+ 5. **Reduced Build Tooling Overhead**: The zero-build development mode and native ES module support minimize reliance
43
+ on complex build configurations and transpilation steps. This accelerates the development feedback loop, allowing
44
+ developers to iterate faster and focus on writing application logic rather than wrestling with tooling.
45
+
46
+ This linear relationship translates directly into tangible benefits: faster development cycles, lower maintenance costs,
47
+ and a more predictable path to scaling your applications, regardless of their eventual complexity. For decision-makers,
48
+ this means a more efficient use of development resources and a higher return on investment for web application projects.