neo.mjs 10.0.0-beta.3 → 10.0.0-beta.4
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/.github/RELEASE_NOTES/v10.0.0-beta.4.md +41 -0
- package/ServiceWorker.mjs +2 -2
- package/apps/portal/index.html +1 -1
- package/apps/portal/view/ViewportController.mjs +1 -1
- package/apps/portal/view/home/FooterContainer.mjs +1 -1
- package/apps/portal/view/learn/MainContainerController.mjs +6 -6
- package/learn/guides/{Collections.md → datahandling/Collections.md} +6 -6
- package/learn/guides/datahandling/Grids.md +621 -0
- package/learn/guides/{Records.md → datahandling/Records.md} +4 -3
- package/learn/guides/{StateProviders.md → datahandling/StateProviders.md} +145 -1
- package/learn/guides/fundamentals/ExtendingNeoClasses.md +359 -0
- package/learn/guides/{Layouts.md → uibuildingblocks/Layouts.md} +40 -38
- package/learn/guides/{form_fields → userinteraction/form_fields}/ComboBox.md +3 -3
- package/learn/tree.json +63 -57
- package/package.json +2 -2
- package/src/DefaultConfig.mjs +2 -2
- package/src/Neo.mjs +37 -29
- package/src/collection/Base.mjs +29 -2
- package/src/component/Base.mjs +6 -16
- package/src/controller/Base.mjs +87 -63
- package/src/core/Base.mjs +72 -17
- package/src/core/Compare.mjs +3 -13
- package/src/core/Config.mjs +139 -0
- package/src/core/ConfigSymbols.mjs +3 -0
- package/src/core/Util.mjs +3 -18
- package/src/data/RecordFactory.mjs +22 -3
- package/src/util/Function.mjs +52 -5
- package/test/siesta/tests/ReactiveConfigs.mjs +112 -0
- package/learn/guides/ExtendingNeoClasses.md +0 -331
- /package/learn/guides/{Tables.md → datahandling/Tables.md} +0 -0
- /package/learn/guides/{ApplicationBootstrap.md → fundamentals/ApplicationBootstrap.md} +0 -0
- /package/learn/guides/{ConfigSystemDeepDive.md → fundamentals/ConfigSystemDeepDive.md} +0 -0
- /package/learn/guides/{DeclarativeComponentTreesVsImperativeVdom.md → fundamentals/DeclarativeComponentTreesVsImperativeVdom.md} +0 -0
- /package/learn/guides/{InstanceLifecycle.md → fundamentals/InstanceLifecycle.md} +0 -0
- /package/learn/guides/{MainThreadAddons.md → fundamentals/MainThreadAddons.md} +0 -0
- /package/learn/guides/{Mixins.md → specificfeatures/Mixins.md} +0 -0
- /package/learn/guides/{MultiWindow.md → specificfeatures/MultiWindow.md} +0 -0
- /package/learn/guides/{PortalApp.md → specificfeatures/PortalApp.md} +0 -0
- /package/learn/guides/{ComponentsAndContainers.md → uibuildingblocks/ComponentsAndContainers.md} +0 -0
- /package/learn/guides/{CustomComponents.md → uibuildingblocks/CustomComponents.md} +0 -0
- /package/learn/guides/{WorkingWithVDom.md → uibuildingblocks/WorkingWithVDom.md} +0 -0
- /package/learn/guides/{Forms.md → userinteraction/Forms.md} +0 -0
- /package/learn/guides/{events → userinteraction/events}/CustomEvents.md +0 -0
- /package/learn/guides/{events → userinteraction/events}/DomEvents.md +0 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
## Neo.mjs v10.0.0-beta.4 Release Notes
|
2
|
+
|
3
|
+
This beta release introduces a powerful, opt-in **Reactive Config System**, a foundational architectural enhancement that enables fine-grained, cross-instance state management and significantly improves the developer experience for building complex, interactive applications.
|
4
|
+
|
5
|
+
### Core Framework & Features
|
6
|
+
|
7
|
+
The centerpiece of this release is the new reactive config system, internally named "Config Atoms". This system is fully opt-in and backward compatible, ensuring that existing applications continue to work without any changes.
|
8
|
+
|
9
|
+
* **New Reactive Config System ("Config Atoms")**:
|
10
|
+
* **Opt-in Reactivity**: By adding a trailing underscore (`_`) to a config property in its `static config` block (e.g., `myValue_`), the property becomes "reactive." It is automatically wrapped in a `Neo.core.Config` instance, which acts as an observable container for its value.
|
11
|
+
* **Cross-Instance State Sharing**: The new system exposes a `subscribe()` method on each reactive config, allowing components to listen for changes to a config on any other component instance. This enables a clean, decoupled, and highly efficient way to implement cross-component state synchronization.
|
12
|
+
```javascript
|
13
|
+
// In ComponentA
|
14
|
+
const componentB = Neo.get('b');
|
15
|
+
|
16
|
+
// Subscribe to changes in componentB's 'items' config
|
17
|
+
this.cleanup = componentB.getConfig('items').subscribe((newValue, oldValue) => {
|
18
|
+
this.someOtherProperty = newValue; // Reactively update
|
19
|
+
});
|
20
|
+
|
21
|
+
// In ComponentA's destroy() method:
|
22
|
+
this.cleanup?.(); // Simple, clean, and prevents memory leaks.
|
23
|
+
```
|
24
|
+
* **Fine-Grained Control (Future Foundation)**: While not fully implemented in this beta, the groundwork is laid for using config descriptors to define custom `mergeStrategy` and `isEqual` functions, which will provide even more control over config behavior in a future release.
|
25
|
+
* **Transactional Consistency**: The new system fully integrates with Neo.mjs's existing transactional update mechanism (`set()`), ensuring that `afterSet` hooks always have a consistent view of all pending config changes within a single operation.
|
26
|
+
|
27
|
+
### Developer Experience
|
28
|
+
|
29
|
+
* **Simplified State Management**: The `subscribe()` API drastically simplifies the logic required for components to react to state changes in other parts of the application, reducing boilerplate and the need for complex event chains.
|
30
|
+
* **Improved Debugging**: The observable nature of reactive configs makes it easier to trace how and when state changes occur throughout your application.
|
31
|
+
|
32
|
+
---
|
33
|
+
|
34
|
+
This release marks a significant step forward in the evolution of the Neo.mjs architecture. The new reactive config system provides a robust foundation for building the next generation of highly interactive and state-driven web applications.
|
35
|
+
|
36
|
+
### Call To Action
|
37
|
+
|
38
|
+
We are incredibly excited for you to start experimenting with this powerful new feature!
|
39
|
+
|
40
|
+
* **Try Reactive Configs**: Start by making a config reactive by adding a `_` to its name in the `static config` block and explore the new possibilities with `getConfig().subscribe()`.
|
41
|
+
* **Share Your Feedback**: This is a foundational change, and your feedback is more critical than ever. Please share your experiences, report any issues, or suggest improvements via [GitHub Issues](https://github.com/neomjs/neo/issues) or our [Slack Channel](https://join.slack.com/t/neomjs/shared_invite/zt-6c50ueeu-3E1~M4T9xkNnb~M_prEEOA).
|
package/ServiceWorker.mjs
CHANGED
package/apps/portal/index.html
CHANGED
@@ -50,7 +50,7 @@ class ViewportController extends Controller {
|
|
50
50
|
'/examples/{itemId}': 'onExamplesRoute',
|
51
51
|
'/home' : 'onHomeRoute',
|
52
52
|
'/learn' : 'onLearnRoute',
|
53
|
-
'/learn/{itemId}'
|
53
|
+
'/learn/{*itemId}' : 'onLearnRoute',
|
54
54
|
'/services' : 'onServicesRoute'
|
55
55
|
},
|
56
56
|
/**
|
@@ -17,8 +17,8 @@ class MainContainerController extends Controller {
|
|
17
17
|
* @member {Object} routes
|
18
18
|
*/
|
19
19
|
routes: {
|
20
|
-
'/learn'
|
21
|
-
'/learn/{itemId}': 'onRouteLearnItem'
|
20
|
+
'/learn' : 'onRouteDefault',
|
21
|
+
'/learn/{*itemId}': 'onRouteLearnItem'
|
22
22
|
}
|
23
23
|
}
|
24
24
|
|
@@ -118,7 +118,7 @@ class MainContainerController extends Controller {
|
|
118
118
|
*/
|
119
119
|
onRouteDefault(data) {
|
120
120
|
if (!this.getStateProvider().data.currentPageRecord) {
|
121
|
-
this.onRouteLearnItem({itemId: 'benefits
|
121
|
+
this.onRouteLearnItem({itemId: 'benefits/Introduction'})
|
122
122
|
}
|
123
123
|
}
|
124
124
|
|
@@ -126,15 +126,15 @@ class MainContainerController extends Controller {
|
|
126
126
|
* @param {Object} data
|
127
127
|
* @param {String} data.itemId
|
128
128
|
*/
|
129
|
-
onRouteLearnItem(
|
129
|
+
onRouteLearnItem({itemId}) {
|
130
130
|
let stateProvider = this.getStateProvider(),
|
131
131
|
store = stateProvider.getStore('contentTree');
|
132
132
|
|
133
133
|
if (store.getCount() > 0) {
|
134
|
-
stateProvider.data.currentPageRecord = store.get(
|
134
|
+
stateProvider.data.currentPageRecord = store.get(itemId)
|
135
135
|
} else {
|
136
136
|
store.on({
|
137
|
-
load : () => {stateProvider.data.currentPageRecord = store.get(
|
137
|
+
load : () => {stateProvider.data.currentPageRecord = store.get(itemId)},
|
138
138
|
delay: 10,
|
139
139
|
once : true
|
140
140
|
})
|
@@ -95,7 +95,7 @@ The `sourceId` concept provides an elegant solution:
|
|
95
95
|
Set its `sourceId` to the ID of your primary store. This combobox store can then apply its own filters (e.g., based on
|
96
96
|
user input in the combobox field) and sorters, completely independently of the grid store or the primary store.
|
97
97
|
|
98
|
-
```javascript
|
98
|
+
```javascript readonly
|
99
99
|
import Collection from '../../src/collection/Base.mjs';
|
100
100
|
import Filter from '../../src/collection/Filter.mjs';
|
101
101
|
|
@@ -161,7 +161,7 @@ application to work with synchronized data while maintaining their own independe
|
|
161
161
|
|
162
162
|
### Example: Basic Collection Usage
|
163
163
|
|
164
|
-
```javascript
|
164
|
+
```javascript readonly
|
165
165
|
import Collection from '../../src/collection/Base.mjs';
|
166
166
|
|
167
167
|
const myCollection = Neo.create(Collection, {
|
@@ -198,7 +198,7 @@ instances based on the store's model definition.
|
|
198
198
|
|
199
199
|
### Example: Adding and Removing
|
200
200
|
|
201
|
-
```javascript
|
201
|
+
```javascript readonly
|
202
202
|
import Collection from '../../src/collection/Base.mjs';
|
203
203
|
|
204
204
|
const users = Neo.create(Collection, {
|
@@ -253,7 +253,7 @@ instances.**
|
|
253
253
|
|
254
254
|
### Example: Filtering a Collection
|
255
255
|
|
256
|
-
```javascript
|
256
|
+
```javascript readonly
|
257
257
|
import Collection from '../../src/collection/Base.mjs';
|
258
258
|
import Filter from '../../src/collection/Filter.mjs';
|
259
259
|
|
@@ -323,7 +323,7 @@ instances.**
|
|
323
323
|
|
324
324
|
### Example: Sorting a Collection
|
325
325
|
|
326
|
-
```javascript
|
326
|
+
```javascript readonly
|
327
327
|
import Collection from '../../src/collection/Base.mjs';
|
328
328
|
import Sorter from '../../src/collection/Sorter.mjs';
|
329
329
|
|
@@ -364,7 +364,7 @@ any operation that changes the collection's items.
|
|
364
364
|
|
365
365
|
### Example: Listening to Collection Events
|
366
366
|
|
367
|
-
```javascript
|
367
|
+
```javascript readonly
|
368
368
|
import Collection from '../../src/collection/Base.mjs';
|
369
369
|
|
370
370
|
const tasks = Neo.create(Collection, {
|