neo.mjs 10.0.0-beta.5 → 10.0.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.
- package/.github/RELEASE_NOTES/v10.0.0-beta.1.md +20 -0
- package/.github/RELEASE_NOTES/v10.0.0-beta.2.md +73 -0
- package/.github/RELEASE_NOTES/v10.0.0-beta.3.md +39 -0
- package/.github/RELEASE_NOTES/v10.0.0-beta.5.md +70 -0
- package/.github/RELEASE_NOTES/v10.0.0-beta.6.md +48 -0
- package/.github/RELEASE_NOTES/v10.0.0.md +52 -0
- package/.github/epic-functional-components.md +498 -0
- package/.github/ticket-asymmetric-vdom-updates.md +122 -0
- package/README.md +0 -3
- package/ServiceWorker.mjs +2 -2
- package/apps/colors/store/Colors.mjs +1 -0
- package/apps/colors/view/GridContainer.mjs +3 -0
- package/apps/colors/view/HeaderToolbar.mjs +2 -0
- package/apps/colors/view/Viewport.mjs +3 -0
- package/apps/covid/view/FooterContainer.mjs +3 -0
- package/apps/covid/view/GalleryContainer.mjs +2 -0
- package/apps/covid/view/GalleryContainerController.mjs +1 -0
- package/apps/covid/view/HeaderContainer.mjs +2 -0
- package/apps/covid/view/HelixContainer.mjs +2 -0
- package/apps/covid/view/HelixContainerController.mjs +1 -0
- package/apps/covid/view/MainContainer.mjs +3 -0
- package/apps/covid/view/TableContainer.mjs +3 -0
- package/apps/covid/view/TableContainerController.mjs +1 -0
- package/apps/covid/view/WorldMapContainer.mjs +2 -0
- package/apps/covid/view/country/Gallery.mjs +3 -0
- package/apps/covid/view/country/Helix.mjs +8 -0
- package/apps/covid/view/country/HistoricalDataTable.mjs +1 -0
- package/apps/covid/view/country/Table.mjs +2 -0
- package/apps/covid/view/mapboxGl/Component.mjs +1 -0
- package/apps/covid/view/mapboxGl/Container.mjs +2 -0
- package/apps/email/EPIC_PLAN.md +58 -0
- package/apps/email/neo-config.json +2 -2
- package/apps/email/store/Emails.mjs +11 -1
- package/apps/email/view/ComposeView.mjs +44 -0
- package/apps/email/view/MainView.mjs +89 -0
- package/apps/email/view/Viewport.mjs +4 -33
- package/apps/email/view/ViewportStateProvider.mjs +3 -3
- package/apps/form/store/SideNav.mjs +1 -0
- package/apps/form/view/FormContainer.mjs +1 -0
- package/apps/form/view/FormPageContainer.mjs +2 -0
- package/apps/form/view/SideNavList.mjs +1 -0
- package/apps/form/view/Viewport.mjs +3 -0
- package/apps/portal/childapps/preview/MainContainer.mjs +1 -0
- package/apps/portal/index.html +1 -1
- package/apps/portal/store/BlogPosts.mjs +2 -0
- package/apps/portal/store/Content.mjs +1 -0
- package/apps/portal/store/ContentSections.mjs +1 -0
- package/apps/portal/store/Examples.mjs +1 -0
- package/apps/portal/view/HeaderToolbar.mjs +1 -0
- package/apps/portal/view/Viewport.mjs +5 -0
- package/apps/portal/view/ViewportController.mjs +11 -3
- package/apps/portal/view/about/Container.mjs +2 -0
- package/apps/portal/view/about/MemberContainer.mjs +7 -0
- package/apps/portal/view/blog/Container.mjs +2 -0
- package/apps/portal/view/blog/List.mjs +2 -0
- package/apps/portal/view/examples/List.mjs +29 -19
- package/apps/portal/view/examples/TabContainer.mjs +4 -0
- package/apps/portal/view/home/ContentBox.mjs +3 -0
- package/apps/portal/view/home/FeatureSection.mjs +8 -0
- package/apps/portal/view/home/FooterContainer.mjs +4 -1
- package/apps/portal/view/home/MainContainer.mjs +2 -0
- package/apps/portal/view/home/parts/AfterMath.mjs +2 -0
- package/apps/portal/view/home/parts/BaseContainer.mjs +1 -0
- package/apps/portal/view/home/parts/Colors.mjs +4 -0
- package/apps/portal/view/home/parts/Features.mjs +2 -0
- package/apps/portal/view/home/parts/Helix.mjs +5 -0
- package/apps/portal/view/home/parts/How.mjs +4 -0
- package/apps/portal/view/home/parts/MainNeo.mjs +1 -0
- package/apps/portal/view/home/parts/References.mjs +2 -0
- package/apps/portal/view/learn/ContentComponent.mjs +11 -5
- package/apps/portal/view/learn/ContentTreeList.mjs +2 -0
- package/apps/portal/view/learn/CubeLayoutButton.mjs +1 -0
- package/apps/portal/view/learn/MainContainer.mjs +4 -0
- package/apps/portal/view/learn/PageContainer.mjs +2 -0
- package/apps/portal/view/learn/PageSectionsContainer.mjs +3 -0
- package/apps/portal/view/learn/PageSectionsList.mjs +1 -0
- package/apps/portal/view/services/Component.mjs +1 -0
- package/apps/realworld/api/Base.mjs +1 -0
- package/apps/realworld/view/HeaderComponent.mjs +4 -0
- package/apps/realworld/view/HomeComponent.mjs +7 -0
- package/apps/realworld/view/MainContainer.mjs +2 -0
- package/apps/realworld/view/MainContainerController.mjs +2 -0
- package/apps/realworld/view/article/CommentComponent.mjs +3 -0
- package/apps/realworld/view/article/Component.mjs +17 -10
- package/apps/realworld/view/article/CreateCommentComponent.mjs +2 -0
- package/apps/realworld/view/article/CreateComponent.mjs +5 -0
- package/apps/realworld/view/article/PreviewComponent.mjs +9 -0
- package/apps/realworld/view/article/TagListComponent.mjs +2 -0
- package/apps/realworld/view/user/ProfileComponent.mjs +7 -0
- package/apps/realworld/view/user/SettingsComponent.mjs +5 -0
- package/apps/realworld/view/user/SignUpComponent.mjs +3 -0
- package/apps/realworld2/api/Base.mjs +1 -0
- package/apps/realworld2/view/FooterComponent.mjs +1 -0
- package/apps/realworld2/view/HeaderToolbar.mjs +3 -0
- package/apps/realworld2/view/HomeContainer.mjs +1 -0
- package/apps/realworld2/view/MainContainer.mjs +2 -0
- package/apps/realworld2/view/MainContainerController.mjs +1 -0
- package/apps/realworld2/view/article/Helix.mjs +1 -0
- package/apps/realworld2/view/article/PreviewComponent.mjs +9 -0
- package/apps/realworld2/view/article/PreviewList.mjs +1 -0
- package/apps/realworld2/view/article/TagListComponent.mjs +2 -0
- package/apps/route/view/CenterContainer.mjs +1 -0
- package/apps/route/view/MainView.mjs +1 -0
- package/apps/sharedcovid/childapps/sharedcovidchart/MainContainer.mjs +1 -0
- package/apps/sharedcovid/childapps/sharedcovidgallery/MainContainer.mjs +1 -0
- package/apps/sharedcovid/childapps/sharedcovidhelix/MainContainer.mjs +1 -0
- package/apps/sharedcovid/childapps/sharedcovidmap/MainContainer.mjs +1 -0
- package/apps/sharedcovid/view/FooterContainer.mjs +3 -0
- package/apps/sharedcovid/view/GalleryContainer.mjs +2 -0
- package/apps/sharedcovid/view/GalleryContainerController.mjs +1 -0
- package/apps/sharedcovid/view/HeaderContainer.mjs +2 -0
- package/apps/sharedcovid/view/HelixContainer.mjs +2 -0
- package/apps/sharedcovid/view/HelixContainerController.mjs +1 -0
- package/apps/sharedcovid/view/MainContainer.mjs +3 -0
- package/apps/sharedcovid/view/TableContainer.mjs +3 -0
- package/apps/sharedcovid/view/TableContainerController.mjs +1 -0
- package/apps/sharedcovid/view/WorldMapContainer.mjs +2 -0
- package/apps/sharedcovid/view/country/Gallery.mjs +3 -0
- package/apps/sharedcovid/view/country/Helix.mjs +8 -0
- package/apps/sharedcovid/view/country/HistoricalDataTable.mjs +1 -0
- package/apps/sharedcovid/view/country/Table.mjs +2 -0
- package/apps/sharedcovid/view/mapboxGl/Component.mjs +1 -0
- package/apps/sharedcovid/view/mapboxGl/Container.mjs +2 -0
- package/apps/shareddialog/childapps/shareddialog2/view/MainContainer.mjs +2 -0
- package/apps/shareddialog/view/DemoDialog.mjs +2 -0
- package/apps/shareddialog/view/MainContainer.mjs +2 -0
- package/apps/shareddialog/view/MainContainerController.mjs +1 -0
- package/buildScripts/addReactiveTags.mjs +191 -0
- package/buildScripts/checkReactiveTags.mjs +160 -0
- package/docs/app/store/Api.mjs +1 -0
- package/docs/app/store/Examples.mjs +1 -0
- package/docs/app/view/ApiTreeList.mjs +1 -0
- package/docs/app/view/ContentTabContainer.mjs +2 -0
- package/docs/app/view/ExamplesTreeList.mjs +2 -0
- package/docs/app/view/HeaderContainer.mjs +3 -0
- package/docs/app/view/MainContainer.mjs +5 -0
- package/docs/app/view/classdetails/HeaderComponent.mjs +1 -0
- package/docs/app/view/classdetails/MainContainer.mjs +3 -0
- package/docs/app/view/classdetails/MembersList.mjs +5 -0
- package/docs/app/view/classdetails/SourceViewComponent.mjs +2 -0
- package/examples/ConfigurationViewport.mjs +14 -8
- package/examples/calendar/weekview/MainContainer.mjs +4 -0
- package/examples/component/coronaGallery/CountryGallery.mjs +2 -0
- package/examples/component/coronaGallery/CountryStore.mjs +1 -0
- package/examples/component/coronaGallery/Viewport.mjs +3 -0
- package/examples/component/coronaGallery/ViewportController.mjs +1 -0
- package/examples/component/coronaHelix/CountryHelix.mjs +7 -0
- package/examples/component/coronaHelix/MainContainer.mjs +1 -0
- package/examples/component/gallery/ImageStore.mjs +1 -0
- package/examples/component/helix/ImageStore.mjs +1 -0
- package/examples/component/helix/Viewport.mjs +3 -0
- package/examples/component/helix/ViewportController.mjs +1 -0
- package/examples/component/multiWindowCoronaGallery/childapp/Viewport.mjs +1 -0
- package/examples/component/multiWindowHelix/childapp/Viewport.mjs +1 -0
- package/examples/component/wrapper/googleMaps/MapComponent.mjs +2 -0
- package/examples/core/config/MainContainer.mjs +2 -0
- package/examples/dialog/DemoDialog.mjs +2 -0
- package/examples/dialog/MainContainer.mjs +1 -0
- package/examples/form/field/color/MainStore.mjs +1 -0
- package/examples/functional/button/base/MainContainer.mjs +207 -0
- package/examples/functional/button/base/app.mjs +6 -0
- package/examples/functional/button/base/index.html +11 -0
- package/examples/functional/button/base/neo-config.json +6 -0
- package/examples/functional/defineComponent/Component.mjs +18 -0
- package/examples/functional/defineComponent/MainContainer.mjs +41 -0
- package/examples/functional/defineComponent/app.mjs +6 -0
- package/examples/functional/defineComponent/index.html +11 -0
- package/examples/functional/defineComponent/neo-config.json +6 -0
- package/examples/functional/hostComponent/Component.mjs +32 -0
- package/examples/functional/hostComponent/MainContainer.mjs +48 -0
- package/examples/functional/hostComponent/app.mjs +6 -0
- package/examples/functional/hostComponent/index.html +11 -0
- package/examples/functional/hostComponent/neo-config.json +6 -0
- package/examples/grid/animatedRowSorting/Viewport.mjs +1 -1
- package/examples/grid/bigData/ControlsContainer.mjs +3 -0
- package/examples/grid/bigData/GridContainer.mjs +4 -2
- package/examples/grid/bigData/MainContainer.mjs +2 -0
- package/examples/grid/bigData/MainModel.mjs +1 -0
- package/examples/grid/bigData/MainStore.mjs +3 -0
- package/examples/grid/cellEditing/MainContainer.mjs +1 -1
- package/examples/grid/container/MainContainer.mjs +1 -1
- package/examples/grid/covid/GridContainer.mjs +3 -0
- package/examples/grid/covid/MainContainer.mjs +2 -0
- package/examples/grid/covid/Store.mjs +1 -0
- package/examples/grid/nestedRecordFields/EditUserDialog.mjs +3 -0
- package/examples/grid/nestedRecordFields/Viewport.mjs +3 -1
- package/examples/list/animate/List.mjs +4 -0
- package/examples/list/animate/MainContainer.mjs +2 -0
- package/examples/list/circle/MainStore.mjs +1 -0
- package/examples/list/color/MainStore.mjs +1 -0
- package/examples/preloadingAssets/view/MainContainer.mjs +2 -0
- package/examples/stateProvider/advanced/MainContainer.mjs +1 -0
- package/examples/stateProvider/dialog/EditUserDialog.mjs +2 -0
- package/examples/stateProvider/dialog/MainContainer.mjs +1 -0
- package/examples/stateProvider/extendedClass/MainContainer.mjs +2 -0
- package/examples/stateProvider/inline/MainContainer.mjs +1 -0
- package/examples/stateProvider/inlineNoStateProvider/MainContainer.mjs +1 -0
- package/examples/stateProvider/inlineNoStateProvider/MainContainerController.mjs +2 -0
- package/examples/stateProvider/multiWindow/EditUserDialog.mjs +3 -0
- package/examples/stateProvider/multiWindow/MainContainer.mjs +1 -0
- package/examples/stateProvider/multiWindow/Viewport.mjs +1 -0
- package/examples/stateProvider/nestedData/MainContainer.mjs +1 -0
- package/examples/stateProvider/table/MainContainer.mjs +1 -0
- package/examples/table/covid/MainContainer.mjs +2 -0
- package/examples/table/covid/Store.mjs +1 -0
- package/examples/table/covid/TableContainer.mjs +3 -0
- package/examples/table/nestedRecordFields/EditUserDialog.mjs +3 -0
- package/examples/table/nestedRecordFields/Viewport.mjs +1 -0
- package/examples/todoList/version1/MainComponent.mjs +1 -1
- package/examples/toolbar/breadcrumb/view/MainContainer.mjs +2 -0
- package/examples/toolbar/paging/store/Users.mjs +1 -0
- package/examples/toolbar/paging/view/AddUserDialog.mjs +3 -0
- package/examples/toolbar/paging/view/MainContainer.mjs +3 -0
- package/examples/treeAccordion/MainContainer.mjs +2 -2
- package/examples/worker/task/MainContainer.mjs +1 -0
- package/learn/Glossary.md +1 -0
- package/learn/UsingTheseTopics.md +1 -0
- package/learn/benefits/ConfigSystem.md +2 -0
- package/learn/benefits/Effort.md +1 -0
- package/learn/benefits/Features.md +1 -0
- package/learn/benefits/FormsEngine.md +1 -0
- package/learn/benefits/FourEnvironments.md +2 -0
- package/learn/benefits/Introduction.md +2 -0
- package/learn/benefits/MultiWindow.md +3 -1
- package/learn/benefits/OffTheMainThread.md +2 -0
- package/learn/benefits/Quick.md +2 -0
- package/learn/benefits/RPCLayer.md +2 -0
- package/learn/benefits/Speed.md +2 -0
- package/learn/blog/v10-deep-dive-functional-components.md +293 -0
- package/learn/blog/v10-deep-dive-reactivity.md +522 -0
- package/learn/blog/v10-deep-dive-state-provider.md +432 -0
- package/learn/blog/v10-deep-dive-vdom-revolution.md +194 -0
- package/learn/blog/v10-post1-love-story.md +383 -0
- package/learn/comparisons/NeoVsAngular.md +90 -0
- package/learn/comparisons/NeoVsExtJs.md +178 -0
- package/learn/comparisons/NeoVsNextJs.md +124 -0
- package/learn/comparisons/NeoVsReact.md +95 -0
- package/learn/comparisons/NeoVsSolid.md +78 -0
- package/learn/comparisons/NeoVsVue.md +92 -0
- package/learn/comparisons/Overview.md +46 -0
- package/learn/gettingstarted/ComponentModels.md +2 -0
- package/learn/gettingstarted/Config.md +2 -0
- package/learn/gettingstarted/DescribingTheUI.md +2 -0
- package/learn/gettingstarted/Events.md +2 -0
- package/learn/gettingstarted/Extending.md +2 -0
- package/learn/gettingstarted/References.md +2 -0
- package/learn/gettingstarted/Setup.md +3 -2
- package/learn/gettingstarted/Workspaces.md +2 -0
- package/learn/guides/datahandling/Collections.md +1 -0
- package/learn/guides/datahandling/Records.md +1 -0
- package/learn/guides/datahandling/StateProviders.md +130 -16
- package/learn/guides/datahandling/Tables.md +1 -1
- package/learn/guides/fundamentals/ConfigSystemDeepDive.md +1 -0
- package/learn/guides/fundamentals/DeclarativeComponentTreesVsImperativeVdom.md +2 -0
- package/learn/guides/fundamentals/DeclarativeVDOMWithEffects.md +10 -8
- package/learn/guides/fundamentals/ExtendingNeoClasses.md +1 -0
- package/learn/guides/fundamentals/InstanceLifecycle.md +3 -1
- package/learn/guides/fundamentals/MainThreadAddons.md +2 -0
- package/learn/guides/specificfeatures/Mixins.md +3 -1
- package/learn/guides/specificfeatures/MultiWindow.md +3 -1
- package/learn/guides/specificfeatures/PortalApp.md +2 -0
- package/learn/guides/uibuildingblocks/ComponentsAndContainers.md +2 -0
- package/learn/guides/uibuildingblocks/CustomComponents.md +2 -0
- package/learn/guides/uibuildingblocks/Layouts.md +2 -0
- package/learn/guides/uibuildingblocks/WorkingWithVDom.md +28 -2
- package/learn/guides/userinteraction/Forms.md +2 -0
- package/learn/guides/userinteraction/events/CustomEvents.md +2 -1
- package/learn/guides/userinteraction/events/DomEvents.md +2 -0
- package/learn/javascript/ClassFeatures.md +4 -3
- package/learn/javascript/Classes.md +10 -13
- package/learn/javascript/Overrides.md +10 -6
- package/learn/javascript/Super.md +12 -8
- package/learn/tree.json +71 -64
- package/learn/tutorials/Earthquakes.md +2 -0
- package/learn/tutorials/RSP.md +3 -1
- package/learn/tutorials/TodoList.md +103 -7
- package/package.json +8 -6
- package/resources/scss/src/apps/email/ComposeView.scss +16 -0
- package/resources/scss/src/apps/email/MainView.scss +5 -0
- package/resources/scss/src/apps/portal/learn/ContentComponent.scss +5 -4
- package/src/DefaultConfig.mjs +12 -2
- package/src/Main.mjs +1 -0
- package/src/Neo.mjs +219 -166
- package/src/Xhr.mjs +1 -0
- package/src/button/Base.mjs +13 -0
- package/src/button/Effect.mjs +16 -2
- package/src/button/Split.mjs +2 -0
- package/src/calendar/store/Calendars.mjs +1 -0
- package/src/calendar/store/Colors.mjs +1 -0
- package/src/calendar/store/Events.mjs +1 -0
- package/src/calendar/view/DayComponent.mjs +2 -0
- package/src/calendar/view/EditEventContainer.mjs +4 -1
- package/src/calendar/view/MainContainer.mjs +13 -0
- package/src/calendar/view/MainContainerStateProvider.mjs +14 -28
- package/src/calendar/view/SettingsContainer.mjs +1 -0
- package/src/calendar/view/YearComponent.mjs +16 -0
- package/src/calendar/view/calendars/ColorsList.mjs +2 -0
- package/src/calendar/view/calendars/Container.mjs +2 -0
- package/src/calendar/view/calendars/EditContainer.mjs +1 -0
- package/src/calendar/view/month/Component.mjs +11 -0
- package/src/calendar/view/settings/GeneralContainer.mjs +1 -0
- package/src/calendar/view/settings/MonthContainer.mjs +1 -0
- package/src/calendar/view/settings/WeekContainer.mjs +1 -0
- package/src/calendar/view/settings/YearContainer.mjs +1 -0
- package/src/calendar/view/week/Component.mjs +15 -1
- package/src/calendar/view/week/TimeAxisComponent.mjs +4 -0
- package/src/code/LivePreview.mjs +51 -23
- package/src/collection/Base.mjs +7 -10
- package/src/collection/Filter.mjs +6 -0
- package/src/collection/Sorter.mjs +3 -0
- package/src/component/Abstract.mjs +412 -0
- package/src/component/Base.mjs +48 -1077
- package/src/component/Canvas.mjs +1 -0
- package/src/component/Chip.mjs +4 -0
- package/src/component/Circle.mjs +14 -0
- package/src/component/Clock.mjs +4 -0
- package/src/component/DateSelector.mjs +12 -0
- package/src/component/Gallery.mjs +11 -0
- package/src/component/Helix.mjs +24 -0
- package/src/component/Label.mjs +1 -0
- package/src/component/Legend.mjs +3 -0
- package/src/component/MagicMoveText.mjs +4 -0
- package/src/component/Progress.mjs +3 -0
- package/src/component/Splitter.mjs +3 -0
- package/src/component/StatusBadge.mjs +6 -0
- package/src/component/Timer.mjs +4 -0
- package/src/component/Toast.mjs +6 -0
- package/src/component/Video.mjs +1 -0
- package/src/component/mwc/Button.mjs +7 -0
- package/src/component/mwc/TextField.mjs +9 -0
- package/src/component/wrapper/AmChart.mjs +2 -0
- package/src/component/wrapper/GoogleMaps.mjs +3 -0
- package/src/component/wrapper/MapboxGL.mjs +5 -0
- package/src/component/wrapper/MonacoEditor.mjs +12 -0
- package/src/container/Accordion.mjs +2 -0
- package/src/container/Base.mjs +7 -3
- package/src/container/Panel.mjs +1 -0
- package/src/container/Viewport.mjs +1 -0
- package/src/controller/Application.mjs +1 -0
- package/src/controller/Base.mjs +1 -0
- package/src/controller/Component.mjs +1 -0
- package/src/core/Base.mjs +86 -33
- package/src/core/Compare.mjs +4 -7
- package/src/core/Config.mjs +65 -52
- package/src/core/Effect.mjs +86 -24
- package/src/core/EffectManager.mjs +117 -8
- package/src/core/IdGenerator.mjs +13 -44
- package/src/core/Observable.mjs +69 -65
- package/src/data/Model.mjs +2 -0
- package/src/data/Store.mjs +7 -0
- package/src/data/connection/WebSocket.mjs +2 -0
- package/src/date/DayViewComponent.mjs +2 -0
- package/src/date/SelectorContainer.mjs +14 -0
- package/src/dialog/Base.mjs +8 -0
- package/src/draggable/DragZone.mjs +5 -0
- package/src/draggable/tree/DragZone.mjs +1 -0
- package/src/filter/BooleanContainer.mjs +2 -0
- package/src/filter/NumberContainer.mjs +3 -0
- package/src/filter/ToggleOperatorsButton.mjs +2 -0
- package/src/form/Fieldset.mjs +6 -0
- package/src/form/field/Base.mjs +7 -0
- package/src/form/field/CheckBox.mjs +18 -0
- package/src/form/field/Chip.mjs +1 -0
- package/src/form/field/ComboBox.mjs +8 -0
- package/src/form/field/Country.mjs +1 -0
- package/src/form/field/Currency.mjs +2 -0
- package/src/form/field/Date.mjs +4 -0
- package/src/form/field/Display.mjs +1 -0
- package/src/form/field/Email.mjs +1 -0
- package/src/form/field/FileUpload.mjs +7 -0
- package/src/form/field/Hidden.mjs +1 -0
- package/src/form/field/Number.mjs +7 -0
- package/src/form/field/Password.mjs +1 -0
- package/src/form/field/Phone.mjs +3 -0
- package/src/form/field/Picker.mjs +2 -0
- package/src/form/field/Radio.mjs +1 -0
- package/src/form/field/Range.mjs +3 -0
- package/src/form/field/Search.mjs +2 -0
- package/src/form/field/Text.mjs +43 -5
- package/src/form/field/TextArea.mjs +7 -0
- package/src/form/field/Time.mjs +6 -0
- package/src/form/field/Url.mjs +3 -0
- package/src/form/field/ZipCode.mjs +2 -0
- package/src/form/field/trigger/Base.mjs +3 -0
- package/src/form/field/trigger/Clear.mjs +2 -0
- package/src/form/field/trigger/CopyToClipboard.mjs +2 -0
- package/src/form/field/trigger/Date.mjs +1 -0
- package/src/form/field/trigger/Picker.mjs +1 -0
- package/src/form/field/trigger/Search.mjs +1 -0
- package/src/form/field/trigger/SpinDown.mjs +2 -0
- package/src/form/field/trigger/SpinUp.mjs +1 -0
- package/src/form/field/trigger/Time.mjs +2 -0
- package/src/functional/_export.mjs +6 -0
- package/src/functional/button/Base.mjs +384 -0
- package/src/functional/component/Base.mjs +405 -0
- package/src/functional/defineComponent.mjs +102 -0
- package/src/functional/useConfig.mjs +52 -0
- package/src/functional/useEvent.mjs +43 -0
- package/src/grid/Body.mjs +20 -1
- package/src/grid/Container.mjs +50 -60
- package/src/grid/ScrollManager.mjs +2 -0
- package/src/grid/VerticalScrollbar.mjs +2 -0
- package/src/grid/column/Base.mjs +2 -0
- package/src/grid/header/Button.mjs +7 -0
- package/src/grid/header/Toolbar.mjs +6 -0
- package/src/grid/plugin/AnimateRows.mjs +2 -0
- package/src/layout/Base.mjs +3 -0
- package/src/layout/Card.mjs +1 -0
- package/src/layout/Cube.mjs +18 -4
- package/src/layout/Fit.mjs +1 -0
- package/src/layout/Flexbox.mjs +7 -0
- package/src/layout/Form.mjs +2 -0
- package/src/layout/Grid.mjs +1 -0
- package/src/layout/HBox.mjs +1 -0
- package/src/layout/VBox.mjs +1 -0
- package/src/list/Base.mjs +13 -0
- package/src/list/Chip.mjs +1 -0
- package/src/list/Circle.mjs +2 -0
- package/src/list/Color.mjs +1 -0
- package/src/list/plugin/Animate.mjs +2 -0
- package/src/main/DeltaUpdates.mjs +1 -0
- package/src/main/DomEvents.mjs +2 -0
- package/src/main/addon/CloneNode.mjs +1 -0
- package/src/main/addon/Cookie.mjs +1 -0
- package/src/main/addon/GoogleMaps.mjs +1 -0
- package/src/main/addon/LocalStorage.mjs +1 -0
- package/src/main/addon/MapboxGL.mjs +1 -0
- package/src/main/addon/Markdown.mjs +1 -0
- package/src/main/addon/Navigator.mjs +1 -0
- package/src/main/addon/Popover.mjs +1 -0
- package/src/main/addon/Stylesheet.mjs +1 -0
- package/src/main/addon/WindowPosition.mjs +1 -0
- package/src/manager/Component.mjs +0 -71
- package/src/manager/VDomUpdate.mjs +320 -0
- package/src/menu/List.mjs +6 -0
- package/src/menu/Model.mjs +1 -0
- package/src/menu/Panel.mjs +3 -0
- package/src/menu/Store.mjs +1 -0
- package/src/mixin/DomEvents.mjs +130 -0
- package/src/mixin/VdomLifecycle.mjs +670 -0
- package/src/plugin/Base.mjs +1 -0
- package/src/plugin/Resizable.mjs +2 -0
- package/src/selection/Model.mjs +15 -18
- package/src/selection/grid/BaseModel.mjs +1 -0
- package/src/sitemap/Component.mjs +1 -0
- package/src/state/Provider.mjs +129 -87
- package/src/state/createHierarchicalDataProxy.mjs +39 -25
- package/src/tab/Container.mjs +6 -0
- package/src/tab/Strip.mjs +1 -0
- package/src/tab/header/Button.mjs +2 -0
- package/src/tab/header/EffectButton.mjs +2 -0
- package/src/tab/header/Toolbar.mjs +1 -0
- package/src/table/Body.mjs +3 -0
- package/src/table/Container.mjs +10 -0
- package/src/table/header/Button.mjs +8 -0
- package/src/table/header/Toolbar.mjs +5 -0
- package/src/table/plugin/CellEditing.mjs +1 -0
- package/src/toolbar/Base.mjs +4 -0
- package/src/toolbar/Breadcrumb.mjs +3 -0
- package/src/toolbar/Paging.mjs +5 -0
- package/src/tooltip/Base.mjs +2 -0
- package/src/tree/List.mjs +3 -0
- package/src/util/HashHistory.mjs +1 -0
- package/src/util/KeyNavigation.mjs +2 -0
- package/src/util/Matrix.mjs +1 -0
- package/src/util/VDom.mjs +18 -5
- package/src/util/VNode.mjs +7 -1
- package/src/util/vdom/TreeBuilder.mjs +105 -0
- package/src/vdom/Helper.mjs +35 -23
- package/src/vdom/VNode.mjs +4 -6
- package/src/worker/App.mjs +1 -0
- package/src/worker/Base.mjs +2 -0
- package/src/worker/Manager.mjs +2 -0
- package/src/worker/ServiceBase.mjs +6 -1
- package/src/worker/mixin/RemoteMethodAccess.mjs +1 -6
- package/test/siesta/siesta.js +17 -2
- package/test/siesta/tests/VdomCalendar.mjs +19 -15
- package/test/siesta/tests/VdomHelper.mjs +7 -7
- package/test/siesta/tests/classic/Button.mjs +113 -0
- package/test/siesta/tests/core/Effect.mjs +10 -14
- package/test/siesta/tests/core/EffectBatching.mjs +72 -79
- package/test/siesta/tests/functional/Button.mjs +113 -0
- package/test/siesta/tests/state/ProviderNestedDataConfigs.mjs +314 -0
- package/test/siesta/tests/state/createHierarchicalDataProxy.mjs +42 -55
- package/test/siesta/tests/vdom/Advanced.mjs +14 -8
- package/test/siesta/tests/vdom/VdomAsymmetricUpdates.mjs +366 -0
- package/test/siesta/tests/vdom/VdomRealWorldUpdates.mjs +249 -0
- package/test/siesta/tests/vdom/layout/Cube.mjs +11 -7
- package/test/siesta/tests/vdom/table/Container.mjs +9 -5
- package/learn/javascript/NewNode.md +0 -31
- package/src/core/EffectBatchManager.mjs +0 -68
package/src/selection/Model.mjs
CHANGED
@@ -1,10 +1,12 @@
|
|
1
|
-
import Base
|
2
|
-
import NeoArray
|
3
|
-
import Observable
|
1
|
+
import Base from '../core/Base.mjs';
|
2
|
+
import NeoArray from '../util/Array.mjs';
|
3
|
+
import Observable from '../core/Observable.mjs';
|
4
|
+
import {isDescriptor} from '../core/ConfigSymbols.mjs';
|
4
5
|
|
5
6
|
/**
|
6
7
|
* @class Neo.selection.Model
|
7
8
|
* @extends Neo.core.Base
|
9
|
+
* @mixes Neo.core.Observable
|
8
10
|
*/
|
9
11
|
class Model extends Base {
|
10
12
|
/**
|
@@ -32,10 +34,17 @@ class Model extends Base {
|
|
32
34
|
*/
|
33
35
|
cls: null,
|
34
36
|
/**
|
35
|
-
* @member {Array} items_
|
37
|
+
* @member {Array} items_
|
36
38
|
* @protected
|
39
|
+
* @reactive
|
37
40
|
*/
|
38
|
-
items_:
|
41
|
+
items_: {
|
42
|
+
[isDescriptor]: true,
|
43
|
+
clone : 'shallow',
|
44
|
+
cloneOnGet : 'none',
|
45
|
+
isEqual : () => false,
|
46
|
+
value : []
|
47
|
+
},
|
39
48
|
/**
|
40
49
|
* @member {String} selectedCls='selected'
|
41
50
|
*/
|
@@ -48,23 +57,11 @@ class Model extends Base {
|
|
48
57
|
* Internally saves the view id, but the getter will return the matching instance
|
49
58
|
* @member {Object} view_=null
|
50
59
|
* @protected
|
60
|
+
* @reactive
|
51
61
|
*/
|
52
62
|
view_: null
|
53
63
|
}
|
54
64
|
|
55
|
-
/**
|
56
|
-
* Gets triggered before getting the value of the items config
|
57
|
-
* @param {Array|null} value
|
58
|
-
* @returns {Array}
|
59
|
-
*/
|
60
|
-
beforeGetItems(value) {
|
61
|
-
if (!value) {
|
62
|
-
this._items = value = []
|
63
|
-
}
|
64
|
-
|
65
|
-
return value
|
66
|
-
}
|
67
|
-
|
68
65
|
/**
|
69
66
|
* Gets triggered before getting the value of the view config
|
70
67
|
* @param {String} value
|
@@ -34,6 +34,7 @@ class Component extends Base {
|
|
34
34
|
* Valid values: removeDom, visibility
|
35
35
|
* Defines if the component items should use css visibility:'hidden' or vdom:removeDom
|
36
36
|
* @member {String} hideMode_='removeDom'
|
37
|
+
* @reactive
|
37
38
|
*/
|
38
39
|
itemHideMode_: 'removeDom',
|
39
40
|
/*
|
package/src/state/Provider.mjs
CHANGED
@@ -2,6 +2,7 @@ import Base from '../core/Base.mjs';
|
|
2
2
|
import ClassSystemUtil from '../util/ClassSystem.mjs';
|
3
3
|
import Config from '../core/Config.mjs';
|
4
4
|
import Effect from '../core/Effect.mjs';
|
5
|
+
import EffectManager from '../core/EffectManager.mjs';
|
5
6
|
import Observable from '../core/Observable.mjs';
|
6
7
|
import {createHierarchicalDataProxy} from './createHierarchicalDataProxy.mjs';
|
7
8
|
import {isDescriptor} from '../core/ConfigSymbols.mjs';
|
@@ -12,6 +13,7 @@ const twoWayBindingSymbol = Symbol.for('twoWayBinding');
|
|
12
13
|
* An optional component state provider for adding bindings to configs
|
13
14
|
* @class Neo.state.Provider
|
14
15
|
* @extends Neo.core.Base
|
16
|
+
* @mixes Neo.core.Observable
|
15
17
|
*/
|
16
18
|
class Provider extends Base {
|
17
19
|
/**
|
@@ -55,6 +57,7 @@ class Provider extends Base {
|
|
55
57
|
* theme: 'dark'
|
56
58
|
* }
|
57
59
|
* }
|
60
|
+
* @reactive
|
58
61
|
*/
|
59
62
|
data_: {
|
60
63
|
[isDescriptor]: true,
|
@@ -79,10 +82,12 @@ class Provider extends Base {
|
|
79
82
|
* // Accessing parent data (assuming a parent provider has a 'taxRate' property)
|
80
83
|
* totalWithTax: (data) => data.total * (1 + data.taxRate)
|
81
84
|
* }
|
85
|
+
* @reactive
|
82
86
|
*/
|
83
87
|
formulas_: null,
|
84
88
|
/**
|
85
89
|
* @member {Neo.state.Provider|null} parent_=null
|
90
|
+
* @reactive
|
86
91
|
*/
|
87
92
|
parent_: null,
|
88
93
|
/**
|
@@ -104,6 +109,7 @@ class Provider extends Base {
|
|
104
109
|
* autoLoad: true
|
105
110
|
* }
|
106
111
|
* }
|
112
|
+
* @reactive
|
107
113
|
*/
|
108
114
|
stores_: null
|
109
115
|
}
|
@@ -161,21 +167,16 @@ class Provider extends Base {
|
|
161
167
|
|
162
168
|
if (value) {
|
163
169
|
Object.entries(value).forEach(([formulaKey, formulaFn]) => {
|
164
|
-
// Create a new Effect
|
170
|
+
// Create a new lazy Effect. It will not run until explicitly told to.
|
165
171
|
const effect = new Effect({
|
166
172
|
fn: () => {
|
167
173
|
const
|
168
|
-
hierarchicalData = me.getHierarchyData(),
|
169
|
-
result = formulaFn(hierarchicalData);
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
me.setData(formulaKey, null)
|
175
|
-
} else {
|
176
|
-
me.setData(formulaKey, result)
|
177
|
-
}
|
178
|
-
}
|
174
|
+
hierarchicalData = me.getHierarchyData(),
|
175
|
+
result = formulaFn(hierarchicalData);
|
176
|
+
|
177
|
+
me.setData(formulaKey, result);
|
178
|
+
},
|
179
|
+
lazy: true
|
179
180
|
});
|
180
181
|
|
181
182
|
me.#formulaEffects.set(formulaKey, effect)
|
@@ -223,24 +224,22 @@ class Provider extends Base {
|
|
223
224
|
* @param {String} configKey The component config to bind (e.g., 'text').
|
224
225
|
* @param {String|Function} formatter The function that computes the value.
|
225
226
|
*/
|
226
|
-
createBinding(componentId, configKey,
|
227
|
+
createBinding(componentId, configKey, formatter) {
|
227
228
|
const
|
228
229
|
me = this,
|
229
|
-
effect = new Effect({
|
230
|
-
fn: () => {
|
230
|
+
effect = new Effect(() => {
|
231
231
|
const component = Neo.get(componentId);
|
232
232
|
|
233
233
|
if (component && !component.isDestroyed) {
|
234
234
|
const
|
235
235
|
hierarchicalData = me.getHierarchyData(),
|
236
|
-
newValue = Neo.isFunction(
|
236
|
+
newValue = Neo.isFunction(formatter) ? formatter.call(me, hierarchicalData) : hierarchicalData[formatter];
|
237
237
|
|
238
238
|
component._skipTwoWayPush = configKey;
|
239
239
|
component[configKey] = newValue;
|
240
240
|
delete component._skipTwoWayPush
|
241
241
|
}
|
242
|
-
}
|
243
|
-
});
|
242
|
+
});
|
244
243
|
|
245
244
|
me.#bindingEffects.set(componentId, effect);
|
246
245
|
|
@@ -262,7 +261,8 @@ class Provider extends Base {
|
|
262
261
|
* @param {Neo.component.Base} component The component instance whose bindings are to be created.
|
263
262
|
*/
|
264
263
|
createBindings(component) {
|
265
|
-
let
|
264
|
+
let me = this,
|
265
|
+
hasTwoWayBinding = false;
|
266
266
|
|
267
267
|
Object.entries(component.bind || {}).forEach(([configKey, value]) => {
|
268
268
|
let key = value;
|
@@ -276,12 +276,12 @@ class Provider extends Base {
|
|
276
276
|
}
|
277
277
|
|
278
278
|
// Determine if it's a store binding or a data binding.
|
279
|
-
if (
|
279
|
+
if (me.isStoreValue(key)) {
|
280
280
|
// For store bindings, resolve the store and assign it to the component config.
|
281
|
-
|
281
|
+
me.resolveStore(component, configKey, key.substring(7)) // remove the "stores." prefix
|
282
282
|
} else {
|
283
283
|
// For data bindings, create an Effect to keep the component config in sync with the data.
|
284
|
-
|
284
|
+
me.createBinding(component.id, configKey, key, value.twoWay)
|
285
285
|
}
|
286
286
|
});
|
287
287
|
|
@@ -435,52 +435,45 @@ class Provider extends Base {
|
|
435
435
|
* @returns {String[]}
|
436
436
|
*/
|
437
437
|
getTopLevelDataKeys(path) {
|
438
|
-
const
|
439
|
-
|
438
|
+
const
|
439
|
+
keys = new Set(),
|
440
|
+
pathPrefix = path ? `${path}.` : '';
|
440
441
|
|
441
442
|
for (const fullPath in this.#dataConfigs) {
|
442
443
|
if (fullPath.startsWith(pathPrefix)) {
|
443
|
-
const
|
444
|
-
|
444
|
+
const
|
445
|
+
relativePath = fullPath.substring(pathPrefix.length),
|
446
|
+
topLevelKey = relativePath.split('.')[0];
|
447
|
+
|
445
448
|
if (topLevelKey) {
|
446
|
-
keys.add(topLevelKey)
|
449
|
+
keys.add(topLevelKey)
|
447
450
|
}
|
448
451
|
}
|
449
452
|
}
|
450
|
-
|
453
|
+
|
454
|
+
return Array.from(keys)
|
451
455
|
}
|
452
456
|
|
453
457
|
/**
|
454
|
-
*
|
455
|
-
*
|
458
|
+
* This is the core method for setting data, providing a single entry point for all data modifications.
|
459
|
+
* It handles multiple scenarios:
|
460
|
+
* 1. **Object-based updates:** If `key` is an object, it recursively calls itself for each key-value pair.
|
461
|
+
* 2. **Data Records:** If `value` is a `Neo.data.Record`, it is treated as an atomic value and set directly.
|
462
|
+
* 3. **Bubbling Reactivity:** For a given key (e.g., 'user.name'), it sets the leaf value and then "bubbles up"
|
463
|
+
* the change, creating new parent objects (e.g., 'user') to ensure that effects depending on any part
|
464
|
+
* of the path are triggered.
|
456
465
|
*
|
457
|
-
*
|
458
|
-
*
|
466
|
+
* All updates are batched by the public `setData` methods to ensure effects run only once.
|
467
|
+
* Use `setData()` or `setDataAtSameLevel()` instead of calling this method directly.
|
459
468
|
*
|
460
|
-
*
|
461
|
-
*
|
462
|
-
*
|
463
|
-
* @param {Object|String} key
|
464
|
-
* @param {*} value
|
465
|
-
* @param {Neo.state.Provider} [originStateProvider]
|
469
|
+
* @param {Object|String} key The property to set, or an object of key-value pairs.
|
470
|
+
* @param {*} value The new value.
|
471
|
+
* @param {Neo.state.Provider} [originStateProvider] The provider to start the search from for hierarchical updates.
|
466
472
|
* @protected
|
467
473
|
*/
|
468
474
|
internalSetData(key, value, originStateProvider) {
|
469
475
|
const me = this;
|
470
476
|
|
471
|
-
// If the value is a Neo.data.Record, treat it as an atomic value
|
472
|
-
// and set it directly without further recursive processing of its properties.
|
473
|
-
if (Neo.isObject(value) && value.isRecord) {
|
474
|
-
const
|
475
|
-
ownerDetails = me.getOwnerOfDataProperty(key),
|
476
|
-
targetProvider = ownerDetails ? ownerDetails.owner : (originStateProvider || me);
|
477
|
-
|
478
|
-
me.#setConfigValue(targetProvider, key, value, null);
|
479
|
-
return
|
480
|
-
}
|
481
|
-
|
482
|
-
// If the key is an object, iterate over its entries and recursively call internalSetData.
|
483
|
-
// This handles setting multiple properties at once (e.g., setData({prop1: val1, prop2: val2})).
|
484
477
|
if (Neo.isObject(key)) {
|
485
478
|
Object.entries(key).forEach(([dataKey, dataValue]) => {
|
486
479
|
me.internalSetData(dataKey, dataValue, originStateProvider)
|
@@ -488,33 +481,52 @@ class Provider extends Base {
|
|
488
481
|
return
|
489
482
|
}
|
490
483
|
|
491
|
-
//
|
484
|
+
// Now 'key' is a string path.
|
485
|
+
// If 'value' is a plain object, we need to drill down further.
|
486
|
+
// If the value is a Neo.data.Record, treat it as an atomic value => it will not enter this block.
|
487
|
+
if (Neo.typeOf(value) === 'Object') {
|
488
|
+
Object.entries(value).forEach(([nestedKey, nestedValue]) => {
|
489
|
+
const fullPath = `${key}.${nestedKey}`;
|
490
|
+
me.internalSetData(fullPath, nestedValue, originStateProvider);
|
491
|
+
});
|
492
|
+
return // We've delegated the setting to deeper paths.
|
493
|
+
}
|
494
|
+
|
492
495
|
const
|
493
496
|
ownerDetails = me.getOwnerOfDataProperty(key),
|
494
|
-
targetProvider = ownerDetails ? ownerDetails.owner : (originStateProvider || me)
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
497
|
+
targetProvider = ownerDetails ? ownerDetails.owner : (originStateProvider || me);
|
498
|
+
|
499
|
+
me.#setConfigValue(targetProvider, key, value, null);
|
500
|
+
|
501
|
+
// This is the "reactivity bubbling" logic. When a leaf property like 'user.name' changes,
|
502
|
+
// we must also trigger effects that depend on the parent object 'user'. We do this by
|
503
|
+
// creating a new object reference for each parent in the path. The spread syntax
|
504
|
+
// `{ ...oldParentValue, [leafKey]: latestValue }` is key, as it creates a new
|
505
|
+
// object, which the reactivity system detects as a change.
|
506
|
+
let path = key,
|
507
|
+
latestValue = value;
|
508
|
+
|
509
|
+
while (path.includes('.')) {
|
510
|
+
const leafKey = path.split('.').pop();
|
511
|
+
path = path.substring(0, path.lastIndexOf('.'));
|
512
|
+
|
513
|
+
const parentConfig = targetProvider.getDataConfig(path);
|
514
|
+
|
515
|
+
if (parentConfig) {
|
516
|
+
const oldParentValue = parentConfig.get();
|
517
|
+
if (Neo.isObject(oldParentValue)) {
|
518
|
+
const newParentValue = { ...oldParentValue, [leafKey]: latestValue };
|
519
|
+
parentConfig.set(newParentValue);
|
520
|
+
latestValue = newParentValue;
|
521
|
+
} else {
|
522
|
+
break // Stop if parent is not an object
|
517
523
|
}
|
524
|
+
} else {
|
525
|
+
// If the parent config doesn't exist, we need to create it to support bubbling.
|
526
|
+
// This is crucial for creating new nested data structures at runtime.
|
527
|
+
const newParentValue = {[leafKey]: latestValue};
|
528
|
+
me.#setConfigValue(targetProvider, path, newParentValue);
|
529
|
+
latestValue = newParentValue
|
518
530
|
}
|
519
531
|
}
|
520
532
|
}
|
@@ -528,6 +540,18 @@ class Provider extends Base {
|
|
528
540
|
return Neo.isString(value) && value.startsWith('stores.')
|
529
541
|
}
|
530
542
|
|
543
|
+
/**
|
544
|
+
* Gets called after all constructors & configs are applied.
|
545
|
+
* @protected
|
546
|
+
*/
|
547
|
+
onConstructed() {
|
548
|
+
super.onConstructed();
|
549
|
+
|
550
|
+
// After the provider is fully constructed and initial data is set,
|
551
|
+
// run the formula effects for the first time to compute their initial values.
|
552
|
+
this.#formulaEffects.forEach(effect => effect.run())
|
553
|
+
}
|
554
|
+
|
531
555
|
/**
|
532
556
|
* @param {String} key
|
533
557
|
* @param {*} value
|
@@ -552,22 +576,22 @@ class Provider extends Base {
|
|
552
576
|
|
553
577
|
// Ensure a Config instance exists for the current fullPath
|
554
578
|
if (me.#dataConfigs[fullPath]) {
|
555
|
-
me.#dataConfigs[fullPath].set(value)
|
579
|
+
me.#dataConfigs[fullPath].set(value)
|
556
580
|
} else {
|
557
|
-
me.#dataConfigs[fullPath] = new Config(value)
|
581
|
+
me.#dataConfigs[fullPath] = new Config(value)
|
558
582
|
}
|
559
583
|
|
560
584
|
// If the value is a plain object, recursively process its properties
|
561
585
|
if (Neo.typeOf(value) === 'Object') {
|
562
|
-
me.processDataObject(value, fullPath)
|
586
|
+
me.processDataObject(value, fullPath)
|
563
587
|
}
|
564
588
|
});
|
565
589
|
}
|
566
590
|
|
567
591
|
/**
|
568
592
|
* @param {Neo.component.Base} component
|
569
|
-
* @param {String}
|
570
|
-
* @param {String}
|
593
|
+
* @param {String} configName
|
594
|
+
* @param {String} storeName
|
571
595
|
*/
|
572
596
|
resolveStore(component, configName, storeName) {
|
573
597
|
let store = this.getStore(storeName);
|
@@ -582,9 +606,9 @@ class Provider extends Base {
|
|
582
606
|
* This method creates a new Config instance if one doesn't exist for the given path,
|
583
607
|
* or updates an existing one. It also triggers binding effects and calls onDataPropertyChange.
|
584
608
|
* @param {Neo.state.Provider} provider The StateProvider instance owning the config.
|
585
|
-
* @param {String}
|
586
|
-
* @param {*}
|
587
|
-
* @param {*}
|
609
|
+
* @param {String} path The full path of the data property (e.g., 'user.firstname').
|
610
|
+
* @param {*} newValue The new value to set.
|
611
|
+
* @param {*} [oldVal] The old value (optional, used for initial setup).
|
588
612
|
* @private
|
589
613
|
*/
|
590
614
|
#setConfigValue(provider, path, newValue, oldVal) {
|
@@ -608,21 +632,39 @@ class Provider extends Base {
|
|
608
632
|
/**
|
609
633
|
* The method will assign all values to the closest stateProvider where it finds an existing key.
|
610
634
|
* In case no match is found inside the parent chain, a new data property will get generated.
|
635
|
+
*
|
636
|
+
* All updates within a single call are batched to ensure that reactive effects (bindings and formulas)
|
637
|
+
* are run only once.
|
638
|
+
*
|
611
639
|
* @param {Object|String} key
|
612
|
-
* @param {*}
|
640
|
+
* @param {*} value
|
613
641
|
*/
|
614
642
|
setData(key, value) {
|
615
|
-
|
643
|
+
EffectManager.pause();
|
644
|
+
try {
|
645
|
+
this.internalSetData(key, value, this)
|
646
|
+
} finally {
|
647
|
+
EffectManager.resume()
|
648
|
+
}
|
616
649
|
}
|
617
650
|
|
618
651
|
/**
|
619
652
|
* Use this method instead of setData() in case you want to enforce
|
620
653
|
* setting all keys on this instance instead of looking for matches inside parent stateProviders.
|
654
|
+
*
|
655
|
+
* All updates within a single call are batched to ensure that reactive effects (bindings and formulas)
|
656
|
+
* are run only once.
|
657
|
+
*
|
621
658
|
* @param {Object|String} key
|
622
|
-
* @param {*}
|
659
|
+
* @param {*} value
|
623
660
|
*/
|
624
661
|
setDataAtSameLevel(key, value) {
|
625
|
-
|
662
|
+
EffectManager.pause();
|
663
|
+
try {
|
664
|
+
this.internalSetData(key, value)
|
665
|
+
} finally {
|
666
|
+
EffectManager.resume()
|
667
|
+
}
|
626
668
|
}
|
627
669
|
}
|
628
670
|
|
@@ -22,7 +22,7 @@ function createNestedProxy(rootProvider, path) {
|
|
22
22
|
// Handle internal properties that might be set directly on the proxy's target
|
23
23
|
// or are expected by the environment (like Siesta's __REFADR__).
|
24
24
|
if (typeof property === 'symbol' || property === '__REFADR__' || property === 'inspect' || property === 'then') {
|
25
|
-
return Reflect.get(currentTarget, property)
|
25
|
+
return Reflect.get(currentTarget, property)
|
26
26
|
}
|
27
27
|
|
28
28
|
// Only allow string or number properties to proceed as data paths.
|
@@ -30,6 +30,20 @@ function createNestedProxy(rootProvider, path) {
|
|
30
30
|
return undefined; // For other non-string/non-number properties, return undefined.
|
31
31
|
}
|
32
32
|
|
33
|
+
// Special handling for the 'stores' property at the root level
|
34
|
+
if (path === '' && property === 'stores') {
|
35
|
+
return new Proxy({}, {
|
36
|
+
get(target, storeName) {
|
37
|
+
if (typeof storeName === 'symbol' || storeName === '__REFADR__') {
|
38
|
+
return Reflect.get(target, storeName)
|
39
|
+
}
|
40
|
+
// Delegate to the StateProvider's getStore method for hierarchical resolution
|
41
|
+
// Accessing store.count later will register the dependency via the Config system
|
42
|
+
return rootProvider.getStore(storeName)
|
43
|
+
}
|
44
|
+
})
|
45
|
+
}
|
46
|
+
|
33
47
|
const fullPath = path ? `${path}.${property}` : property;
|
34
48
|
|
35
49
|
// 1. Check if the full path corresponds to an actual data property.
|
@@ -41,17 +55,15 @@ function createNestedProxy(rootProvider, path) {
|
|
41
55
|
config = owner.getDataConfig(propertyName);
|
42
56
|
|
43
57
|
if (config) {
|
44
|
-
|
45
|
-
if (activeEffect) {
|
46
|
-
activeEffect.addDependency(config);
|
47
|
-
}
|
58
|
+
EffectManager.getActiveEffect()?.addDependency(config);
|
48
59
|
|
49
60
|
const value = config.get();
|
50
61
|
// If the value is an object, return a new proxy for it to ensure nested accesses are also proxied.
|
51
|
-
if (Neo.
|
62
|
+
if (Neo.isObject(value)) {
|
52
63
|
return createNestedProxy(rootProvider, fullPath)
|
53
64
|
}
|
54
|
-
|
65
|
+
|
66
|
+
return value
|
55
67
|
}
|
56
68
|
}
|
57
69
|
|
@@ -62,52 +74,54 @@ function createNestedProxy(rootProvider, path) {
|
|
62
74
|
return createNestedProxy(rootProvider, fullPath)
|
63
75
|
}
|
64
76
|
|
65
|
-
// 3. If it's neither a data property nor a path to one, it doesn't exist
|
66
|
-
|
77
|
+
// 3. If it's neither a data property nor a path to one, it doesn't exist.
|
78
|
+
// Returning undefined ensures that chained accesses (e.g., data.nonexistent.property) fail gracefully.
|
67
79
|
},
|
68
80
|
|
69
81
|
set(currentTarget, property, value) {
|
70
82
|
// Allow internal properties (like Symbols or specific strings) to be set directly on the target.
|
71
83
|
if (typeof property === 'symbol' || property === '__REFADR__') {
|
72
|
-
return Reflect.set(currentTarget, property, value)
|
84
|
+
return Reflect.set(currentTarget, property, value)
|
73
85
|
}
|
74
86
|
|
75
|
-
const
|
76
|
-
|
77
|
-
|
87
|
+
const
|
88
|
+
fullPath = path ? `${path}.${property}` : property,
|
89
|
+
ownerDetails = rootProvider.getOwnerOfDataProperty(fullPath);
|
78
90
|
let targetProvider;
|
91
|
+
|
79
92
|
if (ownerDetails) {
|
80
|
-
targetProvider = ownerDetails.owner
|
93
|
+
targetProvider = ownerDetails.owner
|
81
94
|
} else {
|
82
95
|
// If no owner is found, set it on the rootProvider (the one that created this proxy)
|
83
|
-
targetProvider = rootProvider
|
96
|
+
targetProvider = rootProvider
|
84
97
|
}
|
85
98
|
|
86
99
|
targetProvider.setData(fullPath, value);
|
87
|
-
return true
|
100
|
+
return true // Indicate that the assignment was successful
|
88
101
|
},
|
89
102
|
|
90
103
|
ownKeys(currentTarget) {
|
91
|
-
return rootProvider.getTopLevelDataKeys(path)
|
104
|
+
return rootProvider.getTopLevelDataKeys(path)
|
92
105
|
},
|
93
106
|
|
94
107
|
getOwnPropertyDescriptor(currentTarget, property) {
|
95
|
-
const
|
96
|
-
|
108
|
+
const
|
109
|
+
fullPath = path ? `${path}.${property}` : property,
|
110
|
+
ownerDetails = rootProvider.getOwnerOfDataProperty(fullPath);
|
97
111
|
|
98
112
|
if (ownerDetails) {
|
99
113
|
const config = ownerDetails.owner.getDataConfig(ownerDetails.propertyName);
|
114
|
+
|
100
115
|
if (config) {
|
101
116
|
const value = config.get();
|
102
117
|
return {
|
103
|
-
value: Neo.isObject(value) ? createNestedProxy(rootProvider, fullPath) : value,
|
104
|
-
writable: true,
|
105
|
-
enumerable: true,
|
106
|
-
configurable: true
|
107
|
-
}
|
118
|
+
value : Neo.isObject(value) ? createNestedProxy(rootProvider, fullPath) : value,
|
119
|
+
writable : true,
|
120
|
+
enumerable : true,
|
121
|
+
configurable: true
|
122
|
+
}
|
108
123
|
}
|
109
124
|
}
|
110
|
-
return undefined; // Property not found
|
111
125
|
}
|
112
126
|
})
|
113
127
|
}
|
package/src/tab/Container.mjs
CHANGED
@@ -32,6 +32,7 @@ class Container extends BaseContainer {
|
|
32
32
|
/**
|
33
33
|
* You can use null to not render any items initially
|
34
34
|
* @member {Number|null} activeIndex_=0
|
35
|
+
* @reactive
|
35
36
|
*/
|
36
37
|
activeIndex_: 0,
|
37
38
|
/**
|
@@ -60,11 +61,13 @@ class Container extends BaseContainer {
|
|
60
61
|
headerToolbar: null,
|
61
62
|
/**
|
62
63
|
* @member {Object|null} layout=null
|
64
|
+
* @reactive
|
63
65
|
*/
|
64
66
|
layout: null,
|
65
67
|
/**
|
66
68
|
* True to not apply a background effect to the tab header container
|
67
69
|
* @member {Boolean} plain_=true
|
70
|
+
* @reactive
|
68
71
|
*/
|
69
72
|
plain_: true,
|
70
73
|
/*
|
@@ -77,6 +80,7 @@ class Container extends BaseContainer {
|
|
77
80
|
* true enables sorting tabs via drag&drop.
|
78
81
|
* The config gets passed to the header toolbar
|
79
82
|
* @member {Boolean} sortable_=false
|
83
|
+
* @reactive
|
80
84
|
*/
|
81
85
|
sortable_: false,
|
82
86
|
/**
|
@@ -96,6 +100,7 @@ class Container extends BaseContainer {
|
|
96
100
|
* The position of the tab header toolbar.
|
97
101
|
* Valid values are top, right, bottom, left.
|
98
102
|
* @member {String} tabBarPosition_='top'
|
103
|
+
* @reactive
|
99
104
|
*/
|
100
105
|
tabBarPosition_: 'top',
|
101
106
|
/**
|
@@ -105,6 +110,7 @@ class Container extends BaseContainer {
|
|
105
110
|
tabContainerCls: 'neo-tab-container',
|
106
111
|
/**
|
107
112
|
* @member {Boolean} useActiveTabIndicator_=true
|
113
|
+
* @reactive
|
108
114
|
*/
|
109
115
|
useActiveTabIndicator_: true
|
110
116
|
}
|
package/src/tab/Strip.mjs
CHANGED
@@ -23,10 +23,12 @@ class Button extends BaseButton {
|
|
23
23
|
/**
|
24
24
|
* Specify a role tag attribute for the vdom root.
|
25
25
|
* @member {String|null} role='tab'
|
26
|
+
* @reactive
|
26
27
|
*/
|
27
28
|
role: 'tab',
|
28
29
|
/**
|
29
30
|
* @member {Boolean} useActiveTabIndicator_=true
|
31
|
+
* @reactive
|
30
32
|
*/
|
31
33
|
useActiveTabIndicator_: true,
|
32
34
|
/**
|
@@ -23,10 +23,12 @@ class EffectTabButton extends EffectButton {
|
|
23
23
|
/**
|
24
24
|
* Specify a role tag attribute for the vdom root.
|
25
25
|
* @member {String|null} role='tab'
|
26
|
+
* @reactive
|
26
27
|
*/
|
27
28
|
role: 'tab',
|
28
29
|
/**
|
29
30
|
* @member {Boolean} useActiveTabIndicator_=true
|
31
|
+
* @reactive
|
30
32
|
*/
|
31
33
|
useActiveTabIndicator_: true
|
32
34
|
}
|