neo.mjs 10.1.1 → 10.2.1
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.2.0.md +34 -0
- package/.github/RELEASE_NOTES/v10.2.1.md +17 -0
- package/ServiceWorker.mjs +2 -2
- package/apps/covid/view/GalleryContainer.mjs +1 -1
- package/apps/covid/view/HelixContainer.mjs +1 -1
- package/apps/covid/view/WorldMapContainer.mjs +4 -4
- package/apps/covid/view/country/Gallery.mjs +1 -1
- package/apps/covid/view/country/Helix.mjs +1 -1
- package/apps/covid/view/country/Table.mjs +27 -29
- package/apps/portal/index.html +1 -1
- package/apps/portal/resources/data/blog.json +12 -0
- package/apps/portal/view/home/FooterContainer.mjs +1 -1
- package/apps/sharedcovid/view/GalleryContainer.mjs +1 -1
- package/apps/sharedcovid/view/HelixContainer.mjs +1 -1
- package/apps/sharedcovid/view/WorldMapContainer.mjs +4 -4
- package/apps/sharedcovid/view/country/Gallery.mjs +1 -1
- package/apps/sharedcovid/view/country/Helix.mjs +1 -1
- package/apps/sharedcovid/view/country/Table.mjs +22 -22
- package/examples/grid/bigData/ControlsContainer.mjs +14 -0
- package/examples/stateProvider/inline/MainContainer.mjs +1 -1
- package/examples/stateProvider/twoWay/MainContainer.mjs +2 -2
- package/examples/treeAccordion/MainContainer.mjs +1 -1
- package/learn/blog/v10-deep-dive-functional-components.md +107 -97
- package/learn/blog/v10-deep-dive-reactivity.md +3 -3
- package/learn/blog/v10-deep-dive-state-provider.md +42 -137
- package/learn/blog/v10-deep-dive-vdom-revolution.md +35 -61
- package/learn/blog/v10-post1-love-story.md +3 -3
- package/learn/gettingstarted/DescribingTheUI.md +108 -33
- package/learn/guides/fundamentals/ConfigSystemDeepDive.md +118 -18
- package/learn/guides/fundamentals/InstanceLifecycle.md +121 -84
- package/learn/tree.json +1 -0
- package/learn/tutorials/CreatingAFunctionalButton.md +179 -0
- package/package.json +3 -3
- package/src/DefaultConfig.mjs +2 -2
- package/src/button/Base.mjs +13 -4
- package/src/container/Base.mjs +9 -2
- package/src/data/Store.mjs +8 -3
- package/src/date/SelectorContainer.mjs +2 -2
- package/src/form/field/Base.mjs +15 -1
- package/src/form/field/ComboBox.mjs +5 -15
- package/src/functional/component/Base.mjs +26 -0
- package/src/functional/util/html.mjs +75 -0
- package/src/state/Provider.mjs +7 -4
- package/src/tree/Accordion.mjs +1 -1
- package/test/siesta/siesta.js +8 -1
- package/test/siesta/tests/form/field/AfterSetValueSequence.mjs +106 -0
- package/test/siesta/tests/functional/HtmlTemplateComponent.mjs +92 -0
- package/test/siesta/tests/state/FeedbackLoop.mjs +159 -0
- package/test/siesta/tests/state/Provider.mjs +56 -0
@@ -186,6 +186,62 @@ StartTest(t => {
|
|
186
186
|
component.destroy();
|
187
187
|
});
|
188
188
|
|
189
|
+
t.it('Two-way binding should handle nested data properties', t => {
|
190
|
+
let userEffectRuns = 0;
|
191
|
+
|
192
|
+
const component = Neo.create(MockComponent, {
|
193
|
+
stateProvider: {
|
194
|
+
data: {
|
195
|
+
user: {
|
196
|
+
name: 'initial'
|
197
|
+
}
|
198
|
+
}
|
199
|
+
},
|
200
|
+
bind: {
|
201
|
+
testConfig: { key: 'user.name', twoWay: true },
|
202
|
+
// Add a separate binding to the parent object to test reactivity bubbling
|
203
|
+
userObject: 'user'
|
204
|
+
}
|
205
|
+
});
|
206
|
+
const provider = component.getStateProvider();
|
207
|
+
|
208
|
+
// Effect to monitor changes on the parent 'user' object
|
209
|
+
const userEffect = new Neo.core.Effect(() => {
|
210
|
+
userEffectRuns++;
|
211
|
+
return provider.getData('user');
|
212
|
+
});
|
213
|
+
|
214
|
+
t.is(userEffectRuns, 1, 'User effect should run once initially');
|
215
|
+
t.is(component.testConfig, 'initial', 'Component config should be initialized from nested state provider property');
|
216
|
+
t.is(provider.getData('user.name'), 'initial', 'State provider data should be correct initially');
|
217
|
+
|
218
|
+
// 1. Update component config => should update provider state
|
219
|
+
component.testConfig = 'updated from component';
|
220
|
+
|
221
|
+
t.is(provider.getData('user.name'), 'updated from component', 'Nested state provider data should update from component config change');
|
222
|
+
t.is(userEffectRuns, 2, 'User effect should run again after nested property change (bubbling)');
|
223
|
+
|
224
|
+
// 2. Update provider state => should update component config
|
225
|
+
provider.setData('user.name', 'updated from provider');
|
226
|
+
|
227
|
+
t.is(component.testConfig, 'updated from provider', 'Component config should update from nested state provider data change');
|
228
|
+
t.is(userEffectRuns, 3, 'User effect should run again after direct state change');
|
229
|
+
|
230
|
+
// 3. Verify the parent object reference has changed
|
231
|
+
const initialUserObject = component.userObject;
|
232
|
+
provider.setData('user.name', 'another update');
|
233
|
+
const newUserObject = component.userObject;
|
234
|
+
|
235
|
+
t.is(component.testConfig, 'another update', 'Component config updated again');
|
236
|
+
t.is(provider.getData('user.name'), 'another update', 'Provider data updated again');
|
237
|
+
t.is(userEffectRuns, 4, 'User effect should run again');
|
238
|
+
t.isNot(newUserObject, initialUserObject, 'Parent user object reference should change to trigger reactivity');
|
239
|
+
t.is(newUserObject.name, 'another update', 'New user object has the correct name property');
|
240
|
+
|
241
|
+
userEffect.destroy();
|
242
|
+
component.destroy();
|
243
|
+
});
|
244
|
+
|
189
245
|
t.it('Formulas should calculate correctly and react to dependencies', t => {
|
190
246
|
const component = Neo.create(MockComponent, {
|
191
247
|
stateProvider: {
|