neo.mjs 10.0.0-beta.2 → 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/form/view/FormPageContainer.mjs +2 -3
- 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/ContentComponent.mjs +18 -11
- package/apps/portal/view/learn/MainContainerController.mjs +6 -6
- package/learn/README.md +9 -14
- package/learn/guides/datahandling/Collections.md +436 -0
- package/learn/guides/datahandling/Grids.md +621 -0
- package/learn/guides/datahandling/Records.md +287 -0
- package/learn/guides/{StateProviders.md → datahandling/StateProviders.md} +145 -1
- package/learn/guides/fundamentals/ExtendingNeoClasses.md +359 -0
- package/learn/guides/uibuildingblocks/CustomComponents.md +287 -0
- package/learn/guides/uibuildingblocks/Layouts.md +248 -0
- package/learn/guides/userinteraction/Forms.md +449 -0
- package/learn/guides/userinteraction/form_fields/ComboBox.md +241 -0
- package/learn/tree.json +63 -52
- package/package.json +2 -2
- package/resources/scss/src/apps/portal/learn/ContentComponent.scss +9 -0
- 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/form/field/ComboBox.mjs +6 -1
- package/src/util/Function.mjs +52 -5
- package/src/vdom/Helper.mjs +7 -5
- package/test/siesta/tests/ReactiveConfigs.mjs +112 -0
- package/learn/guides/CustomComponents.md +0 -45
- package/learn/guides/Forms.md +0 -1
- package/learn/guides/Layouts.md +0 -1
- /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/{WorkingWithVDom.md → uibuildingblocks/WorkingWithVDom.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
@@ -26,10 +26,9 @@ class FormPageContainer extends FormContainer {
|
|
26
26
|
*/
|
27
27
|
style: {overflow: 'auto'},
|
28
28
|
/**
|
29
|
-
* @member {
|
29
|
+
* @member {String} tag='div'
|
30
30
|
*/
|
31
|
-
|
32
|
-
{cn: []} // using a div instead of a form tag
|
31
|
+
tag: 'div' // using a div instead of a form tag
|
33
32
|
}
|
34
33
|
}
|
35
34
|
|
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
|
/**
|
@@ -3,11 +3,12 @@ import LivePreview from '../../../../src/code/LivePreview.mjs';
|
|
3
3
|
import {marked} from '../../../../node_modules/marked/lib/marked.esm.js';
|
4
4
|
|
5
5
|
const
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
6
|
+
regexInlineCode = /`([^`]+)`/g,
|
7
|
+
regexLabClose = /<!--\s*\/lab\s*-->/g,
|
8
|
+
regexLabOpen = /<!--\s*lab\s*-->/g,
|
9
|
+
regexLivePreview = /```(javascript|html|css|json)\s+live-preview\s*\n([\s\S]*?)\n\s*```/g,
|
10
|
+
regexNeoComponent = /```json\s+neo-component\s*\n([\s\S]*?)\n\s*```/g,
|
11
|
+
regexReadonly = /```(javascript|html|css|json)\s+readonly\s*\n([\s\S]*?)\n\s*```/g;
|
11
12
|
|
12
13
|
/**
|
13
14
|
* @class Portal.view.learn.ContentComponent
|
@@ -233,10 +234,10 @@ class ContentComponent extends Component {
|
|
233
234
|
*/
|
234
235
|
insertLabDivs(inputString) {
|
235
236
|
// Replace <!-- lab --> with <div class="lab">
|
236
|
-
inputString = inputString.replace(
|
237
|
+
inputString = inputString.replace(regexLabOpen, '<div class="lab">');
|
237
238
|
|
238
239
|
// Replace <!-- /lab --> with </div>
|
239
|
-
inputString = inputString.replace(
|
240
|
+
inputString = inputString.replace(regexLabClose, '</div>');
|
240
241
|
|
241
242
|
return inputString
|
242
243
|
}
|
@@ -307,7 +308,7 @@ class ContentComponent extends Component {
|
|
307
308
|
replacementPromises.push(
|
308
309
|
Neo.main.addon.HighlightJS.highlightAuto({html: code, windowId})
|
309
310
|
.then(highlightedHtml => ({
|
310
|
-
after: `<pre data-javascript id="pre-readonly-${Neo.core.IdGenerator.getId()}">${highlightedHtml}</pre>`,
|
311
|
+
after: `<pre data-javascript id="pre-readonly-${Neo.core.IdGenerator.getId()}">${highlightedHtml.trim()}</pre>`,
|
311
312
|
token: token
|
312
313
|
}))
|
313
314
|
);
|
@@ -336,7 +337,7 @@ class ContentComponent extends Component {
|
|
336
337
|
contentArray = content.split('\n'),
|
337
338
|
i = 1,
|
338
339
|
storeData = [],
|
339
|
-
tag;
|
340
|
+
headline, sideNavTitle, tag;
|
340
341
|
|
341
342
|
contentArray.forEach((line, index) => {
|
342
343
|
tag = null;
|
@@ -352,9 +353,15 @@ class ContentComponent extends Component {
|
|
352
353
|
}
|
353
354
|
|
354
355
|
if (tag) {
|
355
|
-
|
356
|
+
// Convert backticks to <code> tags for the article headline tags
|
357
|
+
headline = line.replace(regexInlineCode, '<code>$1</code>');
|
356
358
|
|
357
|
-
|
359
|
+
// Markdown titles can contain inline code, which we don't want to display inside PageSectionsList.
|
360
|
+
sideNavTitle = line.replaceAll('`', '');
|
361
|
+
|
362
|
+
storeData.push({id: i, name: sideNavTitle, sourceId: me.id, tag});
|
363
|
+
|
364
|
+
contentArray[index] = `<${tag} class="neo-${tag}" data-record-id="${i}">${headline}</${tag}>`;
|
358
365
|
|
359
366
|
i++
|
360
367
|
}
|
@@ -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
|
})
|
package/learn/README.md
CHANGED
@@ -16,7 +16,7 @@ Neo.mjs is the **first and only JavaScript framework** that achieves:
|
|
16
16
|
## 🌐 Best Learning Experience
|
17
17
|
|
18
18
|
**For the optimal learning experience, visit:**
|
19
|
-
**https://neomjs.com/dist/production/apps/portal/index.html#/learn**
|
19
|
+
**[neomjs.com#/learn](https://neomjs.com/dist/production/apps/portal/index.html#/learn)**
|
20
20
|
|
21
21
|
The web portal provides:
|
22
22
|
- ✨ **Enhanced Markdown rendering** with syntax highlighting
|
@@ -25,25 +25,20 @@ The web portal provides:
|
|
25
25
|
- 📱 **Responsive layout** optimized for learning
|
26
26
|
- 🔗 **Interactive navigation** between topics
|
27
27
|
|
28
|
-
## 📚 What's Inside
|
29
|
-
|
30
|
-
- **[Benefits](./benefits/)** - Why choose Neo.mjs and its revolutionary OMT advantages
|
31
|
-
- **[Getting Started](./gettingstarted/)** - Step-by-step introduction to Off-Main-Thread development
|
32
|
-
- **[Guides](./guides/)** - In-depth technical documentation on advanced concepts
|
33
|
-
- **[Tutorials](./tutorials/)** - Hands-on projects and practical examples
|
34
|
-
- **[JavaScript Classes](./javascript/)** - JavaScript fundamentals for Neo.mjs development
|
35
|
-
|
36
28
|
## 🎯 Learning Path
|
37
29
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
30
|
+
For a structured and effective learning experience, we recommend the following progression:
|
31
|
+
|
32
|
+
1. Start with [Benefits](./benefits/) to understand Neo.mjs's revolutionary OMT approach
|
33
|
+
2. Follow [Getting Started](./gettingstarted/) for Off-Main-Thread development basics
|
34
|
+
3. Explore [Guides](./guides/) for comprehensive technical knowledge
|
35
|
+
4. Practice with [Tutorials](./tutorials/) for hands-on experience
|
36
|
+
5. Review [JavaScript Classes](./javascript/) for JavaScript fundamentals relevant to Neo.mjs development
|
42
37
|
|
43
38
|
## 📖 Reading Options
|
44
39
|
|
45
40
|
- **🌐 Web Portal** (Recommended): Enhanced experience with live previews
|
46
|
-
→ [neomjs.com
|
41
|
+
→ [neomjs.com#/learn](https://neomjs.com/dist/production/apps/portal/index.html#/learn)
|
47
42
|
- **📁 GitHub**: Raw markdown files for quick reference or offline reading
|
48
43
|
- **💻 Local**: Clone the repo and browse files directly
|
49
44
|
|