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/worker/Base.mjs
CHANGED
@@ -9,6 +9,8 @@ import RemoteMethodAccess from './mixin/RemoteMethodAccess.mjs';
|
|
9
9
|
* The abstract base class for e.g. the App, Data & VDom worker
|
10
10
|
* @class Neo.worker.Base
|
11
11
|
* @extends Neo.core.Base
|
12
|
+
* @mixes Neo.core.Observable
|
13
|
+
* @mixes Neo.worker.mixin.RemoteMethodAccess
|
12
14
|
* @abstract
|
13
15
|
*/
|
14
16
|
class Worker extends Base {
|
package/src/worker/Manager.mjs
CHANGED
@@ -18,6 +18,8 @@ navigator.serviceWorker?.addEventListener('controllerchange', function() {
|
|
18
18
|
* Also, responsible for sending messages from the main thread to the different workers.
|
19
19
|
* @class Neo.worker.Manager
|
20
20
|
* @extends Neo.core.Base
|
21
|
+
* @mixes Neo.core.Observable
|
22
|
+
* @mixes Neo.worker.mixin.RemoteMethodAccess
|
21
23
|
* @singleton
|
22
24
|
*/
|
23
25
|
class Manager extends Base {
|
@@ -16,6 +16,7 @@ class ServiceBase extends Base {
|
|
16
16
|
className: 'Neo.worker.ServiceBase',
|
17
17
|
/**
|
18
18
|
* @member {String} cacheName_='neo-runtime'
|
19
|
+
* @reactive
|
19
20
|
*/
|
20
21
|
cacheName_: 'neo-runtime',
|
21
22
|
/**
|
@@ -26,6 +27,7 @@ class ServiceBase extends Base {
|
|
26
27
|
* Remote method access for other workers
|
27
28
|
* @member {Object} remote={app: [//...]}
|
28
29
|
* @protected
|
30
|
+
* @reactive
|
29
31
|
*/
|
30
32
|
remote: {
|
31
33
|
app: [
|
@@ -175,6 +177,8 @@ class ServiceBase extends Base {
|
|
175
177
|
* @param {ExtendableMessageEvent} event
|
176
178
|
*/
|
177
179
|
async onActivate(event) {
|
180
|
+
await globalThis.clients.claim();
|
181
|
+
|
178
182
|
console.log('onActivate', event);
|
179
183
|
|
180
184
|
let me = this,
|
@@ -229,7 +233,8 @@ class ServiceBase extends Base {
|
|
229
233
|
* @param {ExtendableMessageEvent} event
|
230
234
|
*/
|
231
235
|
onInstall(event) {
|
232
|
-
console.log('onInstall', event)
|
236
|
+
console.log('onInstall', event);
|
237
|
+
globalThis.skipWaiting();
|
233
238
|
}
|
234
239
|
|
235
240
|
/**
|
@@ -10,12 +10,7 @@ class RemoteMethodAccess extends Base {
|
|
10
10
|
* @member {String} className='Neo.worker.mixin.RemoteMethodAccess'
|
11
11
|
* @protected
|
12
12
|
*/
|
13
|
-
className: 'Neo.worker.mixin.RemoteMethodAccess'
|
14
|
-
/**
|
15
|
-
* @member {Boolean} mixin=true
|
16
|
-
* @protected
|
17
|
-
*/
|
18
|
-
mixin: true
|
13
|
+
className: 'Neo.worker.mixin.RemoteMethodAccess'
|
19
14
|
}
|
20
15
|
|
21
16
|
/**
|
package/test/siesta/siesta.js
CHANGED
@@ -48,7 +48,8 @@ project.plan(
|
|
48
48
|
group: 'state',
|
49
49
|
items: [
|
50
50
|
'tests/state/createHierarchicalDataProxy.mjs',
|
51
|
-
'tests/state/Provider.mjs'
|
51
|
+
'tests/state/Provider.mjs',
|
52
|
+
'tests/state/ProviderNestedDataConfigs.mjs'
|
52
53
|
]
|
53
54
|
},
|
54
55
|
'tests/CollectionBase.mjs',
|
@@ -69,7 +70,21 @@ project.plan(
|
|
69
70
|
'tests/vdom/table/Container.mjs'
|
70
71
|
]
|
71
72
|
},
|
72
|
-
|
73
|
+
'tests/vdom/Advanced.mjs',
|
74
|
+
'tests/vdom/VdomAsymmetricUpdates.mjs',
|
75
|
+
'tests/vdom/VdomRealWorldUpdates.mjs']
|
76
|
+
},
|
77
|
+
{
|
78
|
+
group: 'functional',
|
79
|
+
items: [
|
80
|
+
'tests/functional/Button.mjs'
|
81
|
+
]
|
82
|
+
},
|
83
|
+
{
|
84
|
+
group: 'classic',
|
85
|
+
items: [
|
86
|
+
'tests/classic/Button.mjs'
|
87
|
+
]
|
73
88
|
}
|
74
89
|
);
|
75
90
|
|
@@ -1,12 +1,16 @@
|
|
1
|
-
import Neo
|
2
|
-
import * as core
|
3
|
-
import NeoArray
|
4
|
-
import Style
|
5
|
-
import
|
6
|
-
import
|
1
|
+
import Neo from '../../../src/Neo.mjs';
|
2
|
+
import * as core from '../../../src/core/_export.mjs';
|
3
|
+
import NeoArray from '../../../src/util/Array.mjs';
|
4
|
+
import Style from '../../../src/util/Style.mjs';
|
5
|
+
import StringFromVnode from '../../../src/vdom/util/StringFromVnode.mjs';
|
6
|
+
import VdomHelper from '../../../src/vdom/Helper.mjs';
|
7
|
+
import VDomUtil from '../../../src/util/VDom.mjs';
|
7
8
|
|
8
9
|
let deltas, output, vdom, vnode;
|
9
10
|
|
11
|
+
// tests are designed for this rendering mode
|
12
|
+
Neo.config.useDomApiRenderer = false;
|
13
|
+
|
10
14
|
StartTest(t => {
|
11
15
|
t.it('Week view: Infinite Scrolling', t => {
|
12
16
|
vdom =
|
@@ -23,7 +27,7 @@ StartTest(t => {
|
|
23
27
|
{id: 'col-15'}
|
24
28
|
]};
|
25
29
|
|
26
|
-
vnode = VdomHelper.create(vdom);
|
30
|
+
let vnode = VdomHelper.create({vdom}).vnode;
|
27
31
|
|
28
32
|
vdom =
|
29
33
|
{id: 'neo-vnode-1', cn: [
|
@@ -105,7 +109,7 @@ StartTest(t => {
|
|
105
109
|
]}
|
106
110
|
]};
|
107
111
|
|
108
|
-
vnode = VdomHelper.create(vdom);
|
112
|
+
let vnode = VdomHelper.create({vdom}).vnode;
|
109
113
|
|
110
114
|
vdom =
|
111
115
|
{id: 'neo-calendar-week', cn: [
|
@@ -165,7 +169,7 @@ StartTest(t => {
|
|
165
169
|
]}
|
166
170
|
]};
|
167
171
|
|
168
|
-
vnode = VdomHelper.create(vdom);
|
172
|
+
let vnode = VdomHelper.create({vdom}).vnode;
|
169
173
|
|
170
174
|
vdom =
|
171
175
|
{id: 'neo-calendar-week', cn: [
|
@@ -216,7 +220,7 @@ StartTest(t => {
|
|
216
220
|
]}
|
217
221
|
]};
|
218
222
|
|
219
|
-
vnode = VdomHelper.create(vdom);
|
223
|
+
let vnode = VdomHelper.create({vdom}).vnode;
|
220
224
|
|
221
225
|
vdom =
|
222
226
|
{id: 'neo-calendar-week', cn: [
|
@@ -268,7 +272,7 @@ StartTest(t => {
|
|
268
272
|
{id: 'neo-column-3'}
|
269
273
|
]};
|
270
274
|
|
271
|
-
vnode = VdomHelper.create(vdom);
|
275
|
+
let vnode = VdomHelper.create({vdom}).vnode;
|
272
276
|
|
273
277
|
vdom =
|
274
278
|
{id: 'neo-calendar-week', cn: [
|
@@ -333,7 +337,7 @@ StartTest(t => {
|
|
333
337
|
vdom =
|
334
338
|
{id: 'neo-1'};
|
335
339
|
|
336
|
-
vnode = VdomHelper.create(vdom);
|
340
|
+
vnode = VdomHelper.create({vdom}).vnode;
|
337
341
|
|
338
342
|
vdom =
|
339
343
|
{id: 'neo-1', removeDom: true};
|
@@ -358,7 +362,7 @@ StartTest(t => {
|
|
358
362
|
]}
|
359
363
|
]};
|
360
364
|
|
361
|
-
vnode = VdomHelper.create(vdom);
|
365
|
+
vnode = VdomHelper.create({vdom}).vnode;
|
362
366
|
|
363
367
|
vdom =
|
364
368
|
{id: 'neo-calendar-week', cn: [
|
@@ -403,7 +407,7 @@ StartTest(t => {
|
|
403
407
|
]}
|
404
408
|
]};
|
405
409
|
|
406
|
-
vnode = VdomHelper.create(vdom);
|
410
|
+
vnode = VdomHelper.create({vdom}).vnode;
|
407
411
|
|
408
412
|
vdom =
|
409
413
|
{tag: 'ul', id: 'neo-calendar-calendars-list-1', cn: [
|
@@ -1696,7 +1700,7 @@ StartTest(t => {
|
|
1696
1700
|
}], tag: 'div'
|
1697
1701
|
}
|
1698
1702
|
|
1699
|
-
vnode = VdomHelper.create(vdom);
|
1703
|
+
let vnode = VdomHelper.create({vdom}).vnode;
|
1700
1704
|
|
1701
1705
|
vdom =
|
1702
1706
|
{cls: ['neo-c-m-scrollcontainer', 'neo-scroll-shadows', 'neo-is-scrolling'], id: 'neo-vnode-150', cn: [
|
@@ -1,13 +1,13 @@
|
|
1
|
-
import Neo
|
2
|
-
import * as core
|
3
|
-
import NeoArray
|
4
|
-
import Style
|
5
|
-
import
|
6
|
-
import
|
1
|
+
import Neo from '../../../src/Neo.mjs';
|
2
|
+
import * as core from '../../../src/core/_export.mjs';
|
3
|
+
import NeoArray from '../../../src/util/Array.mjs';
|
4
|
+
import Style from '../../../src/util/Style.mjs';
|
5
|
+
import StringFromVnode from '../../../src/vdom/util/StringFromVnode.mjs';
|
6
|
+
import VdomHelper from '../../../src/vdom/Helper.mjs';
|
7
|
+
import VDomUtil from '../../../src/util/VDom.mjs';
|
7
8
|
|
8
9
|
// tests are designed for this rendering mode
|
9
10
|
Neo.config.useDomApiRenderer = false;
|
10
|
-
VdomHelper.onNeoConfigChange({useDomApiRenderer: false})
|
11
11
|
|
12
12
|
let deltas, output, tmp, vdom, vnode;
|
13
13
|
|
@@ -0,0 +1,113 @@
|
|
1
|
+
import Neo from '../../../../src/Neo.mjs';
|
2
|
+
import * as core from '../../../../src/core/_export.mjs';
|
3
|
+
import Button from '../../../../src/button/Base.mjs';
|
4
|
+
import DomApiVnodeCreator from '../../../../src/vdom/util/DomApiVnodeCreator.mjs';
|
5
|
+
import VdomHelper from '../../../../src/vdom/Helper.mjs';
|
6
|
+
|
7
|
+
// IMPORTANT: This test file uses real components and expects them to render.
|
8
|
+
// We need to enable unitTestMode for isolation, but also allow VDOM updates.
|
9
|
+
Neo.config.unitTestMode = true;
|
10
|
+
Neo.config.allowVdomUpdatesInTests = true;
|
11
|
+
// This ensures that the VdomHelper uses the correct renderer for the assertions.
|
12
|
+
Neo.config.useDomApiRenderer = true;
|
13
|
+
|
14
|
+
// Create a mock application context, as the component lifecycle requires it for updates.
|
15
|
+
const appName = 'ClassicButtonTest';
|
16
|
+
Neo.apps = Neo.apps || {};
|
17
|
+
Neo.apps[appName] = {
|
18
|
+
name : appName,
|
19
|
+
fire : Neo.emptyFn,
|
20
|
+
isMounted: () => true,
|
21
|
+
rendering: false
|
22
|
+
};
|
23
|
+
|
24
|
+
StartTest(t => {
|
25
|
+
let button, vnode;
|
26
|
+
let testRun = 0;
|
27
|
+
|
28
|
+
t.beforeEach(async t => {
|
29
|
+
testRun++;
|
30
|
+
|
31
|
+
button = Neo.create(Button, {
|
32
|
+
appName,
|
33
|
+
id : 'my-button-' + testRun,
|
34
|
+
iconCls: 'fa fa-home',
|
35
|
+
text : 'Click me'
|
36
|
+
});
|
37
|
+
|
38
|
+
({vnode} = await button.render());
|
39
|
+
button.mounted = true; // Manually mount to enable updates in the test env
|
40
|
+
});
|
41
|
+
|
42
|
+
t.afterEach(t => {
|
43
|
+
button?.destroy();
|
44
|
+
button = null;
|
45
|
+
vnode = null;
|
46
|
+
});
|
47
|
+
|
48
|
+
t.it('should create initial vnode correctly', async t => {
|
49
|
+
t.expect(vnode.nodeName).toBe('button');
|
50
|
+
t.expect(vnode.className).toEqual(['neo-button', 'icon-left']);
|
51
|
+
t.expect(vnode.childNodes.length).toBe(2); // icon & text. badge & ripple have removeDom:true
|
52
|
+
|
53
|
+
const iconNode = vnode.childNodes[0];
|
54
|
+
t.expect(iconNode.className).toEqual(['neo-button-glyph', 'fa', 'fa-home']);
|
55
|
+
|
56
|
+
const textNode = vnode.childNodes[1];
|
57
|
+
t.expect(textNode.className).toEqual(['neo-button-text']);
|
58
|
+
t.expect(textNode.textContent).toBe('Click me');
|
59
|
+
});
|
60
|
+
|
61
|
+
t.it('should update vnode and create delta for a single config change', async t => {
|
62
|
+
const textNodeId = vnode.childNodes[1].id;
|
63
|
+
const {deltas} = await button.set({text: 'New Text'});
|
64
|
+
|
65
|
+
t.is(deltas.length, 1, 'Should generate exactly one delta');
|
66
|
+
const delta = deltas[0];
|
67
|
+
|
68
|
+
t.is(delta.id, textNodeId, 'Delta should target the text node');
|
69
|
+
t.is(delta.textContent, 'New Text', 'Delta textContent is correct');
|
70
|
+
});
|
71
|
+
|
72
|
+
t.it('should update vnode and create delta for multiple config changes', async t => {
|
73
|
+
const iconNodeId = vnode.childNodes[0].id;
|
74
|
+
const textNodeId = vnode.childNodes[1].id;
|
75
|
+
|
76
|
+
const {deltas} = await button.set({
|
77
|
+
iconCls: 'fa fa-user',
|
78
|
+
text : 'Submit'
|
79
|
+
});
|
80
|
+
|
81
|
+
t.is(deltas.length, 2, 'Should generate exactly two deltas');
|
82
|
+
|
83
|
+
const iconDelta = deltas.find(d => d.id === iconNodeId);
|
84
|
+
const textDelta = deltas.find(d => d.id === textNodeId);
|
85
|
+
|
86
|
+
t.ok(iconDelta, 'Should have a delta for the icon node');
|
87
|
+
t.isDeeply(iconDelta.cls.remove, ['fa-home'], 'Icon delta should remove old class');
|
88
|
+
t.isDeeply(iconDelta.cls.add, ['fa-user'], 'Icon delta should add new class');
|
89
|
+
|
90
|
+
t.ok(textDelta, 'Should have a delta for the text node');
|
91
|
+
t.is(textDelta.textContent, 'Submit', 'Text delta is correct');
|
92
|
+
});
|
93
|
+
|
94
|
+
t.it('should handle pressed state change', async t => {
|
95
|
+
t.notOk(vnode.className.includes('pressed'), 'Initial vnode should not have "pressed" class');
|
96
|
+
|
97
|
+
let updateData = await button.set({pressed: true});
|
98
|
+
|
99
|
+
t.is(updateData.deltas.length, 1, 'Should generate one delta for pressed: true');
|
100
|
+
let delta = updateData.deltas[0];
|
101
|
+
t.is(delta.id, button.id, 'Delta should target the button component root');
|
102
|
+
t.isDeeply(delta.cls.add, ['pressed'], 'Delta should add "pressed" class');
|
103
|
+
t.ok(updateData.vnode.className.includes('pressed'), 'Vnode should have "pressed" class');
|
104
|
+
|
105
|
+
updateData = await button.set({pressed: false});
|
106
|
+
|
107
|
+
t.is(updateData.deltas.length, 1, 'Should generate one delta for pressed: false');
|
108
|
+
delta = updateData.deltas[0];
|
109
|
+
t.is(delta.id, button.id, 'Delta should target the button component root');
|
110
|
+
t.isDeeply(delta.cls.remove, ['pressed'], 'Delta should remove "pressed" class');
|
111
|
+
t.notOk(updateData.vnode.className.includes('pressed'), 'Vnode should not have "pressed" class');
|
112
|
+
});
|
113
|
+
});
|
@@ -6,8 +6,8 @@ import Config from '../../../../src/core/Config.mjs';
|
|
6
6
|
|
7
7
|
StartTest(t => {
|
8
8
|
t.it('EffectManager should manage active effects', t => {
|
9
|
-
const effect1 = new Effect(
|
10
|
-
const effect2 = new Effect(
|
9
|
+
const effect1 = new Effect(() => {});
|
10
|
+
const effect2 = new Effect(() => {});
|
11
11
|
|
12
12
|
t.is(EffectManager.getActiveEffect(), null, 'No active effect initially');
|
13
13
|
|
@@ -38,13 +38,11 @@ StartTest(t => {
|
|
38
38
|
t.is(configB, configB, 'configB is strictly equal to itself');
|
39
39
|
t.isNot(configA, configB, 'configA is not strictly equal to configB');
|
40
40
|
|
41
|
-
const effect = new Effect({
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
t.pass(`Effect ran. Sum: ${sum}`);
|
47
|
-
}
|
41
|
+
const effect = new Effect(() => {
|
42
|
+
runCount++;
|
43
|
+
// Access configs to register them as dependencies
|
44
|
+
sum = configA.get() + configB.get();
|
45
|
+
t.pass(`Effect ran. Sum: ${sum}`);
|
48
46
|
});
|
49
47
|
|
50
48
|
t.is(runCount, 1, 'Effect function ran once on creation');
|
@@ -82,11 +80,9 @@ StartTest(t => {
|
|
82
80
|
const configY = new Config('Y');
|
83
81
|
|
84
82
|
// Initial effect: depends on configX
|
85
|
-
const effect = new Effect({
|
86
|
-
|
87
|
-
|
88
|
-
t.is(configX.get(), 'X', 'Effect ran (1st): configX value');
|
89
|
-
}
|
83
|
+
const effect = new Effect(() => {
|
84
|
+
runCount++;
|
85
|
+
t.is(configX.get(), 'X', 'Effect ran (1st): configX value');
|
90
86
|
});
|
91
87
|
|
92
88
|
t.is(runCount, 1, 'Effect ran once initially');
|
@@ -1,31 +1,30 @@
|
|
1
|
-
import Neo
|
2
|
-
import * as core
|
3
|
-
import Effect
|
4
|
-
import
|
1
|
+
import Neo from '../../../../src/Neo.mjs';
|
2
|
+
import * as core from '../../../../src/core/_export.mjs';
|
3
|
+
import Effect from '../../../../src/core/Effect.mjs';
|
4
|
+
import EffectManager from '../../../../src/core/EffectManager.mjs';
|
5
5
|
|
6
6
|
class TestComponent extends core.Base {
|
7
7
|
static config = {
|
8
8
|
className: 'Neo.Test.EffectBatchingComponent',
|
9
|
-
configA_: 0,
|
10
|
-
configB_: 0,
|
11
|
-
configC_: 0
|
9
|
+
configA_ : 0,
|
10
|
+
configB_ : 0,
|
11
|
+
configC_ : 0
|
12
12
|
}
|
13
13
|
}
|
14
|
+
|
14
15
|
Neo.setupClass(TestComponent);
|
15
16
|
|
16
17
|
StartTest(t => {
|
17
18
|
t.it('Effects should be batched during core.Base#set() operations', t => {
|
18
|
-
const instance
|
19
|
+
const instance = Neo.create(TestComponent);
|
19
20
|
let effectRunCount = 0;
|
20
|
-
let sum
|
21
|
-
|
22
|
-
const effect = new Effect({
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
t.pass(`Effect ran. Sum: ${sum}`);
|
28
|
-
}
|
21
|
+
let sum = 0;
|
22
|
+
|
23
|
+
const effect = new Effect(() => {
|
24
|
+
effectRunCount++;
|
25
|
+
// Access all props to make them dependencies
|
26
|
+
sum = instance.configA + instance.configB + instance.configC;
|
27
|
+
t.pass(`Effect ran. Sum: ${sum}`);
|
29
28
|
});
|
30
29
|
|
31
30
|
t.is(effectRunCount, 1, 'Effect ran once on initial creation');
|
@@ -49,7 +48,7 @@ StartTest(t => {
|
|
49
48
|
t.is(instance.configC, 3, 'configC should be updated');
|
50
49
|
|
51
50
|
// Test individual property change outside a batch
|
52
|
-
effectRunCount
|
51
|
+
effectRunCount = 0;
|
53
52
|
instance.configA = 10;
|
54
53
|
t.is(effectRunCount, 1, 'Effect should run immediately for individual property change outside a batch');
|
55
54
|
t.is(sum, 10 + 2 + 3, 'Sum should be 10 + 2 + 3 = 15 after individual configA change');
|
@@ -60,8 +59,8 @@ StartTest(t => {
|
|
60
59
|
// Update all configs to their previous values (no change)
|
61
60
|
instance.set({
|
62
61
|
configA: 10,
|
63
|
-
configB:
|
64
|
-
configC:
|
62
|
+
configB: 2,
|
63
|
+
configC: 3
|
65
64
|
});
|
66
65
|
|
67
66
|
t.is(effectRunCount, 0, 'Effect should not run.');
|
@@ -70,28 +69,28 @@ StartTest(t => {
|
|
70
69
|
instance.destroy();
|
71
70
|
});
|
72
71
|
|
73
|
-
t.it('
|
74
|
-
t.is(
|
72
|
+
t.it('EffectManager should correctly manage batch state via pause() and resume()', t => {
|
73
|
+
t.is(EffectManager.isPaused(), false, 'Batch should not be active initially');
|
75
74
|
|
76
|
-
|
77
|
-
t.is(
|
75
|
+
EffectManager.pause();
|
76
|
+
t.is(EffectManager.isPaused(), true, 'Batch should be active after pause()');
|
78
77
|
|
79
|
-
|
80
|
-
t.is(
|
78
|
+
EffectManager.pause(); // Nested batch
|
79
|
+
t.is(EffectManager.isPaused(), true, 'Batch should still be active for nested pause()');
|
81
80
|
|
82
|
-
|
83
|
-
t.is(
|
81
|
+
EffectManager.resume();
|
82
|
+
t.is(EffectManager.isPaused(), true, 'Batch should still be active after inner resume()');
|
84
83
|
|
85
|
-
|
86
|
-
t.is(
|
84
|
+
EffectManager.resume();
|
85
|
+
t.is(EffectManager.isPaused(), false, 'Batch should not be active after all resume() calls');
|
87
86
|
});
|
88
87
|
|
89
88
|
t.it('Effect should run when a dependency is changed inside an afterSet hook', t => {
|
90
89
|
class IndirectDependencyComponent extends core.Base {
|
91
90
|
static config = {
|
92
91
|
className: 'Neo.Test.IndirectDependencyComponent',
|
93
|
-
configA_: 'initialA',
|
94
|
-
configB_: 'initialB'
|
92
|
+
configA_ : 'initialA',
|
93
|
+
configB_ : 'initialB'
|
95
94
|
}
|
96
95
|
|
97
96
|
afterSetConfigA(newValue, oldValue) {
|
@@ -101,19 +100,18 @@ StartTest(t => {
|
|
101
100
|
}
|
102
101
|
}
|
103
102
|
}
|
103
|
+
|
104
104
|
Neo.setupClass(IndirectDependencyComponent);
|
105
105
|
|
106
|
-
const instance
|
106
|
+
const instance = Neo.create(IndirectDependencyComponent);
|
107
107
|
let effectRunCount = 0;
|
108
|
-
let effectValue
|
108
|
+
let effectValue = '';
|
109
109
|
|
110
110
|
// Effect depends only on configB
|
111
|
-
const effect = new Effect({
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
t.pass(`Effect ran. configB: ${effectValue}`);
|
116
|
-
}
|
111
|
+
const effect = new Effect(() => {
|
112
|
+
effectRunCount++;
|
113
|
+
effectValue = instance.configB;
|
114
|
+
t.pass(`Effect ran. configB: ${effectValue}`);
|
117
115
|
});
|
118
116
|
|
119
117
|
t.is(effectRunCount, 1, 'Effect ran once on initial creation');
|
@@ -139,8 +137,8 @@ StartTest(t => {
|
|
139
137
|
class BeforeSetDependencyComponent extends core.Base {
|
140
138
|
static config = {
|
141
139
|
className: 'Neo.Test.BeforeSetDependencyComponent',
|
142
|
-
configA_: 'initialA',
|
143
|
-
configC_: 'initialC' // configC will be changed by beforeSetConfigA
|
140
|
+
configA_ : 'initialA',
|
141
|
+
configC_ : 'initialC' // configC will be changed by beforeSetConfigA
|
144
142
|
}
|
145
143
|
|
146
144
|
beforeSetConfigA(newValue, oldValue) {
|
@@ -151,19 +149,18 @@ StartTest(t => {
|
|
151
149
|
return newValue; // Important: return newValue to allow configA to be set
|
152
150
|
}
|
153
151
|
}
|
152
|
+
|
154
153
|
Neo.setupClass(BeforeSetDependencyComponent);
|
155
154
|
|
156
|
-
const instance
|
155
|
+
const instance = Neo.create(BeforeSetDependencyComponent);
|
157
156
|
let effectRunCount = 0;
|
158
|
-
let effectValue
|
157
|
+
let effectValue = '';
|
159
158
|
|
160
159
|
// Effect depends only on configC
|
161
|
-
const effect = new Effect({
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
t.pass(`Effect ran. configC: ${effectValue}`);
|
166
|
-
}
|
160
|
+
const effect = new Effect(() => {
|
161
|
+
effectRunCount++;
|
162
|
+
effectValue = instance.configC;
|
163
|
+
t.pass(`Effect ran. configC: ${effectValue}`);
|
167
164
|
});
|
168
165
|
|
169
166
|
t.is(effectRunCount, 1, 'Effect ran once on initial creation');
|
@@ -189,9 +186,9 @@ StartTest(t => {
|
|
189
186
|
class CombinedDependencyComponent extends core.Base {
|
190
187
|
static config = {
|
191
188
|
className: 'Neo.Test.CombinedDependencyComponent',
|
192
|
-
configA_: 'initialA',
|
193
|
-
configB_: 'initialB', // Changed by afterSet
|
194
|
-
configC_: 'initialC' // Changed by beforeSet
|
189
|
+
configA_ : 'initialA',
|
190
|
+
configB_ : 'initialB', // Changed by afterSet
|
191
|
+
configC_ : 'initialC' // Changed by beforeSet
|
195
192
|
}
|
196
193
|
|
197
194
|
beforeSetConfigA(newValue, oldValue) {
|
@@ -207,30 +204,27 @@ StartTest(t => {
|
|
207
204
|
}
|
208
205
|
}
|
209
206
|
}
|
207
|
+
|
210
208
|
Neo.setupClass(CombinedDependencyComponent);
|
211
209
|
|
212
|
-
const instance
|
210
|
+
const instance = Neo.create(CombinedDependencyComponent);
|
213
211
|
let effectBRunCount = 0;
|
214
212
|
let effectCRunCount = 0;
|
215
|
-
let effectBValue
|
216
|
-
let effectCValue
|
213
|
+
let effectBValue = '';
|
214
|
+
let effectCValue = '';
|
217
215
|
|
218
216
|
// Effect for configB (changed by afterSet)
|
219
|
-
const effectB = new Effect({
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
t.pass(`EffectB ran. configB: ${effectBValue}`);
|
224
|
-
}
|
217
|
+
const effectB = new Effect(() => {
|
218
|
+
effectBRunCount++;
|
219
|
+
effectBValue = instance.configB;
|
220
|
+
t.pass(`EffectB ran. configB: ${effectBValue}`);
|
225
221
|
});
|
226
222
|
|
227
223
|
// Effect for configC (changed by beforeSet)
|
228
|
-
const effectC = new Effect({
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
t.pass(`EffectC ran. configC: ${effectCValue}`);
|
233
|
-
}
|
224
|
+
const effectC = new Effect(() => {
|
225
|
+
effectCRunCount++;
|
226
|
+
effectCValue = instance.configC;
|
227
|
+
t.pass(`EffectC ran. configC: ${effectCValue}`);
|
234
228
|
});
|
235
229
|
|
236
230
|
t.is(effectBRunCount, 1, 'EffectB ran once on initial creation');
|
@@ -267,9 +261,9 @@ StartTest(t => {
|
|
267
261
|
class SingleEffectCombinedDependencyComponent extends core.Base {
|
268
262
|
static config = {
|
269
263
|
className: 'Neo.Test.SingleEffectCombinedDependencyComponent',
|
270
|
-
configA_: 'initialA',
|
271
|
-
configB_: 'initialB', // Changed by afterSet
|
272
|
-
configC_: 'initialC' // Changed by beforeSet
|
264
|
+
configA_ : 'initialA',
|
265
|
+
configB_ : 'initialB', // Changed by afterSet
|
266
|
+
configC_ : 'initialC' // Changed by beforeSet
|
273
267
|
}
|
274
268
|
|
275
269
|
beforeSetConfigA(newValue, oldValue) {
|
@@ -285,19 +279,18 @@ StartTest(t => {
|
|
285
279
|
}
|
286
280
|
}
|
287
281
|
}
|
282
|
+
|
288
283
|
Neo.setupClass(SingleEffectCombinedDependencyComponent);
|
289
284
|
|
290
|
-
const instance
|
285
|
+
const instance = Neo.create(SingleEffectCombinedDependencyComponent);
|
291
286
|
let effectRunCount = 0;
|
292
|
-
let effectValue
|
287
|
+
let effectValue = '';
|
293
288
|
|
294
289
|
// Single Effect depends on both configB and configC
|
295
|
-
const effect = new Effect({
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
t.pass(`Effect ran. Combined: ${effectValue}`);
|
300
|
-
}
|
290
|
+
const effect = new Effect(() => {
|
291
|
+
effectRunCount++;
|
292
|
+
effectValue = `${instance.configB} | ${instance.configC}`;
|
293
|
+
t.pass(`Effect ran. Combined: ${effectValue}`);
|
301
294
|
});
|
302
295
|
|
303
296
|
t.is(effectRunCount, 1, 'Effect ran once on initial creation');
|