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/table/Body.mjs
CHANGED
@@ -36,6 +36,7 @@ class TableBody extends Component {
|
|
36
36
|
containerId: null,
|
37
37
|
/**
|
38
38
|
* @member {Boolean} highlightModifiedCells_=false
|
39
|
+
* @reactive
|
39
40
|
*/
|
40
41
|
highlightModifiedCells_: false,
|
41
42
|
/**
|
@@ -49,6 +50,7 @@ class TableBody extends Component {
|
|
49
50
|
recordVnodeMap: {},
|
50
51
|
/**
|
51
52
|
* @member {Neo.selection.Model} selectionModel_=null
|
53
|
+
* @reactive
|
52
54
|
*/
|
53
55
|
selectionModel_: null,
|
54
56
|
/**
|
@@ -57,6 +59,7 @@ class TableBody extends Component {
|
|
57
59
|
selectedRecordField: 'annotations.selected',
|
58
60
|
/**
|
59
61
|
* @member {Neo.data.Store|null} store_=null
|
62
|
+
* @reactive
|
60
63
|
*/
|
61
64
|
store_: null,
|
62
65
|
/**
|
package/src/table/Container.mjs
CHANGED
@@ -34,11 +34,13 @@ class Container extends BaseContainer {
|
|
34
34
|
/**
|
35
35
|
* @member {String|null} bodyId_=null
|
36
36
|
* @protected
|
37
|
+
* @reactive
|
37
38
|
*/
|
38
39
|
bodyId_: null,
|
39
40
|
/**
|
40
41
|
* true uses table.plugin.CellEditing
|
41
42
|
* @member {Boolean} cellEditing_=false
|
43
|
+
* @reactive
|
42
44
|
*/
|
43
45
|
cellEditing_: false,
|
44
46
|
/**
|
@@ -48,6 +50,7 @@ class Container extends BaseContainer {
|
|
48
50
|
columnDefaults: null,
|
49
51
|
/**
|
50
52
|
* @member {Object[]} columns_=[]
|
53
|
+
* @reactive
|
51
54
|
*/
|
52
55
|
columns_: [],
|
53
56
|
/**
|
@@ -57,10 +60,12 @@ class Container extends BaseContainer {
|
|
57
60
|
headerToolbarConfig: null,
|
58
61
|
/**
|
59
62
|
* @member {String|null} headerToolbarId_=null
|
63
|
+
* @reactive
|
60
64
|
*/
|
61
65
|
headerToolbarId_: null,
|
62
66
|
/**
|
63
67
|
* @member {String} layout='base'
|
68
|
+
* @reactive
|
64
69
|
*/
|
65
70
|
layout: 'base',
|
66
71
|
/**
|
@@ -70,24 +75,29 @@ class Container extends BaseContainer {
|
|
70
75
|
scrollbarsCssApplied: false,
|
71
76
|
/**
|
72
77
|
* @member {Boolean} showHeaderFilters_=false
|
78
|
+
* @reactive
|
73
79
|
*/
|
74
80
|
showHeaderFilters_: false,
|
75
81
|
/**
|
76
82
|
* @member {Boolean} sortable_=true
|
83
|
+
* @reactive
|
77
84
|
*/
|
78
85
|
sortable_: true,
|
79
86
|
/**
|
80
87
|
* @member {Neo.data.Store} store_=null
|
88
|
+
* @reactive
|
81
89
|
*/
|
82
90
|
store_: null,
|
83
91
|
/**
|
84
92
|
* todo: only works for chrome & safari -> add a check
|
85
93
|
* @member {Boolean} useCustomScrollbars_=true
|
94
|
+
* @reactive
|
86
95
|
*/
|
87
96
|
useCustomScrollbars_: true,
|
88
97
|
/**
|
89
98
|
* @member {Array|null} items=null
|
90
99
|
* @protected
|
100
|
+
* @reactive
|
91
101
|
*/
|
92
102
|
items: null,
|
93
103
|
/**
|
@@ -34,6 +34,7 @@ class Button extends BaseButton {
|
|
34
34
|
/**
|
35
35
|
* Alignment of the matching table cells. Valid values are left, center, right
|
36
36
|
* @member {String} cellAlign_='left'
|
37
|
+
* @reactive
|
37
38
|
*/
|
38
39
|
cellAlign_: 'left',
|
39
40
|
/**
|
@@ -47,6 +48,7 @@ class Button extends BaseButton {
|
|
47
48
|
defaultSortDirection: 'ASC',
|
48
49
|
/**
|
49
50
|
* @member {Boolean} draggable_=true
|
51
|
+
* @reactive
|
50
52
|
*/
|
51
53
|
draggable_: true,
|
52
54
|
/**
|
@@ -64,20 +66,24 @@ class Button extends BaseButton {
|
|
64
66
|
filterField: null,
|
65
67
|
/**
|
66
68
|
* @member {String} iconCls='fa fa-arrow-circle-up'
|
69
|
+
* @reactive
|
67
70
|
*/
|
68
71
|
iconCls: 'fa fa-arrow-circle-up',
|
69
72
|
/**
|
70
73
|
* @member {String} iconPosition='right'
|
74
|
+
* @reactive
|
71
75
|
*/
|
72
76
|
iconPosition: 'right',
|
73
77
|
/**
|
74
78
|
* 'ASC', 'DESC' or null
|
75
79
|
* @member {String|null} isSorted_=null
|
76
80
|
* @protected
|
81
|
+
* @reactive
|
77
82
|
*/
|
78
83
|
isSorted_: null,
|
79
84
|
/**
|
80
85
|
* @member {Function|String|null} renderer_='cellRenderer'
|
86
|
+
* @reactive
|
81
87
|
*/
|
82
88
|
renderer_: 'cellRenderer',
|
83
89
|
/**
|
@@ -88,10 +94,12 @@ class Button extends BaseButton {
|
|
88
94
|
rendererScope: null,
|
89
95
|
/**
|
90
96
|
* @member {Boolean} showHeaderFilter_=false
|
97
|
+
* @reactive
|
91
98
|
*/
|
92
99
|
showHeaderFilter_: false,
|
93
100
|
/**
|
94
101
|
* @member {Boolean} sortable_=true
|
102
|
+
* @reactive
|
95
103
|
*/
|
96
104
|
sortable_: true,
|
97
105
|
/**
|
@@ -22,26 +22,31 @@ class Toolbar extends BaseToolbar {
|
|
22
22
|
baseCls: ['neo-table-header-toolbar'],
|
23
23
|
/**
|
24
24
|
* @member {Boolean} draggable_=true
|
25
|
+
* @reactive
|
25
26
|
*/
|
26
27
|
draggable_: true,
|
27
28
|
/**
|
28
29
|
* @member {String} layout='base'
|
30
|
+
* @reactive
|
29
31
|
*/
|
30
32
|
layout: 'base',
|
31
33
|
/**
|
32
34
|
* @member {Object} itemDefaults={ntype : 'table-header-button'}
|
35
|
+
* @reactive
|
33
36
|
*/
|
34
37
|
itemDefaults: {
|
35
38
|
ntype: 'table-header-button'
|
36
39
|
},
|
37
40
|
/**
|
38
41
|
* @member {Boolean} showHeaderFilters_=false
|
42
|
+
* @reactive
|
39
43
|
*/
|
40
44
|
showHeaderFilters_: false,
|
41
45
|
/**
|
42
46
|
* Convenience shortcut to pass sortable to all toolbar items.
|
43
47
|
* If set to true, header clicks will sort the matching column (ASC, DESC, null)
|
44
48
|
* @member {Boolean} sortable=true
|
49
|
+
* @reactive
|
45
50
|
*/
|
46
51
|
sortable: true,
|
47
52
|
/**
|
package/src/toolbar/Base.mjs
CHANGED
@@ -33,16 +33,19 @@ class Toolbar extends Container {
|
|
33
33
|
baseCls: ['neo-toolbar'],
|
34
34
|
/**
|
35
35
|
* @member {String|null} dock_=null
|
36
|
+
* @reactive
|
36
37
|
*/
|
37
38
|
dock_: null,
|
38
39
|
/**
|
39
40
|
* @member {Object} itemDefaults={ntype:'button'}
|
41
|
+
* @reactive
|
40
42
|
*/
|
41
43
|
itemDefaults: {
|
42
44
|
ntype: 'button'
|
43
45
|
},
|
44
46
|
/**
|
45
47
|
* @member {Object} layout={ntype:'flexbox',align:'center',direction: 'row', pack:'start'}
|
48
|
+
* @reactive
|
46
49
|
*/
|
47
50
|
layout: {
|
48
51
|
ntype : 'flexbox',
|
@@ -52,6 +55,7 @@ class Toolbar extends Container {
|
|
52
55
|
},
|
53
56
|
/**
|
54
57
|
* @member {Boolean} sortable_=false
|
58
|
+
* @reactive
|
55
59
|
*/
|
56
60
|
sortable_: false,
|
57
61
|
/**
|
@@ -21,6 +21,7 @@ class Breadcrumb extends Toolbar {
|
|
21
21
|
ntype: 'breadcrumb-toolbar',
|
22
22
|
/**
|
23
23
|
* @member {Number|String|null} activeKey_=null
|
24
|
+
* @reactive
|
24
25
|
*/
|
25
26
|
activeKey_: null,
|
26
27
|
/**
|
@@ -29,6 +30,7 @@ class Breadcrumb extends Toolbar {
|
|
29
30
|
baseCls: ['neo-breadcrumb-toolbar', 'neo-toolbar'],
|
30
31
|
/**
|
31
32
|
* @member {Object} itemDefaults={ntype:'button', ui: 'tertiary'}
|
33
|
+
* @reactive
|
32
34
|
*/
|
33
35
|
itemDefaults: {
|
34
36
|
ntype: 'button',
|
@@ -36,6 +38,7 @@ class Breadcrumb extends Toolbar {
|
|
36
38
|
},
|
37
39
|
/**
|
38
40
|
* @member {Neo.data.Store|Object} store_=null
|
41
|
+
* @reactive
|
39
42
|
*/
|
40
43
|
store_: null
|
41
44
|
}
|
package/src/toolbar/Paging.mjs
CHANGED
@@ -24,22 +24,27 @@ class Paging extends Toolbar {
|
|
24
24
|
baseCls: ['neo-paging-toolbar', 'neo-toolbar'],
|
25
25
|
/**
|
26
26
|
* @member {Number} currentPage_=1
|
27
|
+
* @reactive
|
27
28
|
*/
|
28
29
|
currentPage_: 1,
|
29
30
|
/**
|
30
31
|
* @member {Number} pageSize_=30
|
32
|
+
* @reactive
|
31
33
|
*/
|
32
34
|
pageSize_: 30,
|
33
35
|
/**
|
34
36
|
* @member {Function} pagesText_=me=>`Page: ${me.page} / ${me.getMaxPages()}`
|
37
|
+
* @reactive
|
35
38
|
*/
|
36
39
|
pagesText_: me => `Page ${me.currentPage} / ${me.getMaxPages()}`,
|
37
40
|
/**
|
38
41
|
* @member {Neo.data.Store|null} store_=null
|
42
|
+
* @reactive
|
39
43
|
*/
|
40
44
|
store_: null,
|
41
45
|
/**
|
42
46
|
* @member {Function} totalText_=count=>`Total: ${count} records`
|
47
|
+
* @reactive
|
43
48
|
*/
|
44
49
|
totalText_: count => `Total: ${count} rows`,
|
45
50
|
/**
|
package/src/tooltip/Base.mjs
CHANGED
@@ -27,6 +27,7 @@ class Tooltip extends Container {
|
|
27
27
|
/**
|
28
28
|
* A reference to the target component which is supposed to show this tooltip on mouseenter
|
29
29
|
* @member {String|null} componentId_=null
|
30
|
+
* @reactive
|
30
31
|
*/
|
31
32
|
componentId_: null,
|
32
33
|
/**
|
@@ -75,6 +76,7 @@ class Tooltip extends Container {
|
|
75
76
|
/**
|
76
77
|
* True prevents the tooltip from hiding while the mouse cursor is above it
|
77
78
|
* @member {Boolean|null} stayOnHover_=true
|
79
|
+
* @reactive
|
78
80
|
*/
|
79
81
|
stayOnHover_: true
|
80
82
|
}
|
package/src/tree/List.mjs
CHANGED
@@ -27,6 +27,7 @@ class Tree extends Base {
|
|
27
27
|
baseCls: ['neo-tree-list'],
|
28
28
|
/**
|
29
29
|
* @member {Boolean} disableSelection=false
|
30
|
+
* @reactive
|
30
31
|
*/
|
31
32
|
disableSelection: false,
|
32
33
|
/**
|
@@ -43,6 +44,7 @@ class Tree extends Base {
|
|
43
44
|
showCollapseExpandAllIcons: true,
|
44
45
|
/**
|
45
46
|
* @member {Boolean} sortable_=false
|
47
|
+
* @reactive
|
46
48
|
*/
|
47
49
|
sortable_: false,
|
48
50
|
/**
|
@@ -55,6 +57,7 @@ class Tree extends Base {
|
|
55
57
|
sortZoneConfig: null,
|
56
58
|
/**
|
57
59
|
* @member {String[]} wrapperCls=[]
|
60
|
+
* @reactive
|
58
61
|
*/
|
59
62
|
wrapperCls: [],
|
60
63
|
/**
|
package/src/util/HashHistory.mjs
CHANGED
@@ -20,6 +20,7 @@ class KeyNavigation extends Base {
|
|
20
20
|
/**
|
21
21
|
* Internally stores the component id inside _component
|
22
22
|
* @member {Neo.component.Base|null} component_=null
|
23
|
+
* @reactive
|
23
24
|
*/
|
24
25
|
component_: null,
|
25
26
|
/**
|
@@ -29,6 +30,7 @@ class KeyNavigation extends Base {
|
|
29
30
|
keyDownEventBubble: false,
|
30
31
|
/**
|
31
32
|
* @member {Array|null} keys_=null
|
33
|
+
* @reactive
|
32
34
|
*/
|
33
35
|
keys_: null
|
34
36
|
}
|
package/src/util/Matrix.mjs
CHANGED
package/src/util/VDom.mjs
CHANGED
@@ -261,7 +261,13 @@ class VDom extends Base {
|
|
261
261
|
*/
|
262
262
|
static getVdom(vdom) {
|
263
263
|
if (vdom.componentId) {
|
264
|
-
|
264
|
+
const component = ComponentManager.get(vdom.componentId);
|
265
|
+
|
266
|
+
if (!component) {
|
267
|
+
throw new Error(`util.VDom.getVdom: Component not found for id: ${vdom.componentId}`)
|
268
|
+
}
|
269
|
+
|
270
|
+
vdom = component.vdom
|
265
271
|
}
|
266
272
|
|
267
273
|
return vdom
|
@@ -385,16 +391,23 @@ class VDom extends Base {
|
|
385
391
|
vdom.id = vnode.id
|
386
392
|
}
|
387
393
|
} else {
|
388
|
-
//
|
389
|
-
//
|
390
|
-
|
394
|
+
// We only want to add an ID if the vdom node does not already have one.
|
395
|
+
// This preserves developer-provided IDs while allowing the framework
|
396
|
+
// to assign IDs to nodes that need them for reconciliation.
|
397
|
+
// Also think of adding and removing nodes in parallel.
|
398
|
+
if (vnode.id && (!vdom.id || vdom.id.startsWith('neo-vnode-'))) {
|
391
399
|
vdom.id = vnode.id
|
392
400
|
}
|
393
401
|
}
|
394
402
|
|
395
403
|
if (childNodes) {
|
396
404
|
cn = childNodes.map(item => VDom.getVdom(item));
|
397
|
-
|
405
|
+
// The vnode.childNodes array is already filtered by the worker.
|
406
|
+
// We must filter the component's vdom.cn array identically to ensure
|
407
|
+
// both arrays are structurally aligned for the sync loop.
|
408
|
+
// The boolean check `item &&` is critical to remove falsy values
|
409
|
+
// from conditional rendering and prevent runtime errors.
|
410
|
+
cn = cn.filter(item => item && item.removeDom !== true);
|
398
411
|
i = 0;
|
399
412
|
len = cn?.length || 0;
|
400
413
|
|
package/src/util/VNode.mjs
CHANGED
@@ -168,7 +168,13 @@ class VNode extends Base {
|
|
168
168
|
*/
|
169
169
|
static getVnode(vnode) {
|
170
170
|
if (vnode.componentId) {
|
171
|
-
|
171
|
+
const component = ComponentManager.get(vnode.componentId);
|
172
|
+
|
173
|
+
if (!component) {
|
174
|
+
throw new Error(`util.VNode.getVnode: Component not found for id: ${vnode.componentId}`)
|
175
|
+
}
|
176
|
+
|
177
|
+
vnode = component.vnode
|
172
178
|
}
|
173
179
|
|
174
180
|
return vnode
|
@@ -0,0 +1,105 @@
|
|
1
|
+
import Base from '../../core/Base.mjs';
|
2
|
+
import ComponentManager from '../../manager/Component.mjs';
|
3
|
+
|
4
|
+
/**
|
5
|
+
* A singleton utility class responsible for recursively building VDOM and VNode trees.
|
6
|
+
* It can expand component references within a tree structure into their full VDOM/VNode representations,
|
7
|
+
* supporting selective (asymmetric) tree expansion for optimized updates.
|
8
|
+
* @class Neo.util.vdom.TreeBuilder
|
9
|
+
* @extends Neo.core.Base
|
10
|
+
* @singleton
|
11
|
+
*/
|
12
|
+
class TreeBuilder extends Base {
|
13
|
+
static config = {
|
14
|
+
/**
|
15
|
+
* @member {String} className='Neo.util.vdom.TreeBuilder'
|
16
|
+
* @protected
|
17
|
+
*/
|
18
|
+
className: 'Neo.util.vdom.TreeBuilder',
|
19
|
+
/**
|
20
|
+
* @member {Boolean} singleton=true
|
21
|
+
* @protected
|
22
|
+
*/
|
23
|
+
singleton: true
|
24
|
+
}
|
25
|
+
|
26
|
+
/**
|
27
|
+
* Private helper to recursively build a tree, abstracting the child node key.
|
28
|
+
* @param {Object} node The vdom or vnode to process.
|
29
|
+
* @param {Number} depth The current recursion depth.
|
30
|
+
* @param {Set<String>|null} mergedChildIds A set of component IDs to selectively expand.
|
31
|
+
* @param {String} childKey The property name for child nodes ('cn' or 'childNodes').
|
32
|
+
* @returns {Object}
|
33
|
+
* @private
|
34
|
+
*/
|
35
|
+
#buildTree(node, depth, mergedChildIds, childKey) {
|
36
|
+
// We can not use Neo.isObject() here, since inside unit-test scenarios, we will import vdom.Helper into main threads.
|
37
|
+
// Inside this scenario, Neo.isObject() returns false for VNode instances
|
38
|
+
if (typeof node !== 'object' || node === null) {
|
39
|
+
return node
|
40
|
+
}
|
41
|
+
|
42
|
+
let output = {...node}; // Shallow copy
|
43
|
+
|
44
|
+
if (node[childKey]) {
|
45
|
+
output[childKey] = [];
|
46
|
+
|
47
|
+
node[childKey].forEach(item => {
|
48
|
+
let currentItem = item,
|
49
|
+
childDepth;
|
50
|
+
|
51
|
+
if (currentItem.componentId) {
|
52
|
+
// Prune the branch only if we are at the boundary AND the child is not part of a merged update
|
53
|
+
if (depth === 1 && !mergedChildIds?.has(currentItem.componentId)) {
|
54
|
+
output[childKey].push({componentId: 'neo-ignore', id: item.id || item.componentId});
|
55
|
+
return // Stop processing this branch
|
56
|
+
}
|
57
|
+
// Expand the branch if it's part of a merged update, or if the depth requires it
|
58
|
+
else if (depth > 1 || depth === -1 || mergedChildIds?.has(currentItem.componentId)) {
|
59
|
+
const component = ComponentManager.get(currentItem.componentId);
|
60
|
+
// Use the correct tree type based on the childKey
|
61
|
+
const componentTree = childKey === 'cn' ? component?.vdom : component?.vnode;
|
62
|
+
if (componentTree) {
|
63
|
+
currentItem = componentTree
|
64
|
+
}
|
65
|
+
}
|
66
|
+
}
|
67
|
+
|
68
|
+
if (item.componentId) {
|
69
|
+
childDepth = (depth === -1) ? -1 : Math.max(0, depth - 1)
|
70
|
+
} else {
|
71
|
+
childDepth = depth
|
72
|
+
}
|
73
|
+
|
74
|
+
output[childKey].push(this.#buildTree(currentItem, childDepth, mergedChildIds, childKey))
|
75
|
+
})
|
76
|
+
}
|
77
|
+
|
78
|
+
return output
|
79
|
+
}
|
80
|
+
|
81
|
+
|
82
|
+
/**
|
83
|
+
* Copies a given vdom tree and replaces child component references with their vdom.
|
84
|
+
* @param {Object} vdom
|
85
|
+
* @param {Number} [depth=-1]
|
86
|
+
* @param {Set<String>|null} [mergedChildIds=null]
|
87
|
+
* @returns {Object}
|
88
|
+
*/
|
89
|
+
getVdomTree(vdom, depth=-1, mergedChildIds=null) {
|
90
|
+
return this.#buildTree(vdom, depth, mergedChildIds, 'cn')
|
91
|
+
}
|
92
|
+
|
93
|
+
/**
|
94
|
+
* Copies a given vnode tree and replaces child component references with their vnode.
|
95
|
+
* @param {Object} vnode
|
96
|
+
* @param {Number} [depth=-1]
|
97
|
+
* @param {Set<String>|null} [mergedChildIds=null]
|
98
|
+
* @returns {Object}
|
99
|
+
*/
|
100
|
+
getVnodeTree(vnode, depth=-1, mergedChildIds=null) {
|
101
|
+
return this.#buildTree(vnode, depth, mergedChildIds, 'childNodes')
|
102
|
+
}
|
103
|
+
}
|
104
|
+
|
105
|
+
export default Neo.setupClass(TreeBuilder);
|
package/src/vdom/Helper.mjs
CHANGED
@@ -23,6 +23,7 @@ class Helper extends Base {
|
|
23
23
|
* Remote method access for other workers
|
24
24
|
* @member {Object} remote={app:['create','update']}
|
25
25
|
* @protected
|
26
|
+
* @reactive
|
26
27
|
*/
|
27
28
|
remote: {
|
28
29
|
app: [
|
@@ -47,19 +48,21 @@ class Helper extends Base {
|
|
47
48
|
* @protected
|
48
49
|
*/
|
49
50
|
compareAttributes({deltas, oldVnode, vnode, vnodeMap}) {
|
50
|
-
//
|
51
|
-
|
52
|
-
|
51
|
+
// If either vnode is a component placeholder (indicated by the presence of componentId),
|
52
|
+
// we must not compare element attributes.
|
53
|
+
if (vnode.componentId || oldVnode.componentId) {
|
54
|
+
return deltas;
|
53
55
|
}
|
54
56
|
|
55
|
-
let
|
57
|
+
let delta = {},
|
58
|
+
attributes, value, keys, styles, add, remove;
|
56
59
|
|
57
|
-
if (vnode.vtype === 'text' && vnode.
|
60
|
+
if (vnode.vtype === 'text' && vnode.textContent !== oldVnode.textContent) {
|
58
61
|
deltas.default.push({
|
59
62
|
action : 'updateVtext',
|
60
63
|
id : vnode.id,
|
61
64
|
parentId: vnodeMap.get(vnode.id).parentNode.id,
|
62
|
-
value : vnode.
|
65
|
+
value : vnode.textContent
|
63
66
|
})
|
64
67
|
} else {
|
65
68
|
keys = Object.keys(vnode);
|
@@ -77,7 +80,6 @@ class Helper extends Base {
|
|
77
80
|
});
|
78
81
|
|
79
82
|
keys.forEach(prop => {
|
80
|
-
delta = {};
|
81
83
|
value = vnode[prop];
|
82
84
|
|
83
85
|
switch (prop) {
|
@@ -143,12 +145,12 @@ class Helper extends Base {
|
|
143
145
|
}
|
144
146
|
break
|
145
147
|
}
|
148
|
+
});
|
146
149
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
})
|
150
|
+
if (Object.keys(delta).length > 0) {
|
151
|
+
delta.id = vnode.id;
|
152
|
+
deltas.default.push(delta)
|
153
|
+
}
|
152
154
|
}
|
153
155
|
|
154
156
|
return deltas
|
@@ -200,12 +202,11 @@ class Helper extends Base {
|
|
200
202
|
*/
|
201
203
|
createDeltas(config) {
|
202
204
|
let {deltas={default: [], remove: []}, oldVnode, vnode} = config,
|
203
|
-
|
204
|
-
vnodeId = vnode?.id;
|
205
|
+
vnodeId = vnode?.id;
|
205
206
|
|
206
207
|
// Edge case: setting `removeDom: true` on a top-level vdom node
|
207
|
-
if (!vnode &&
|
208
|
-
deltas.remove.push({action: 'removeNode', id:
|
208
|
+
if (!vnode && (oldVnode?.id || oldVnode?.componentId)) {
|
209
|
+
deltas.remove.push({action: 'removeNode', id: oldVnode.id || oldVnode.componentId});
|
209
210
|
return deltas
|
210
211
|
}
|
211
212
|
|
@@ -213,8 +214,10 @@ class Helper extends Base {
|
|
213
214
|
return deltas
|
214
215
|
}
|
215
216
|
|
216
|
-
|
217
|
-
|
217
|
+
// The top-level nodes passed to createDeltas must be the same logical node. The VdomLifecycle
|
218
|
+
// mixin ensures symmetric trees, so IDs and types (component vs element) must match.
|
219
|
+
if (vnode.id !== oldVnode.id || vnode.componentId !== oldVnode.componentId) {
|
220
|
+
throw new Error(`createDeltas() must be called for the same node. new: {id: ${vnode.id}, cId: ${vnode.componentId}}, old: {id: ${oldVnode.id}, cId: ${oldVnode.componentId}}`);
|
218
221
|
}
|
219
222
|
|
220
223
|
let me = this,
|
@@ -243,11 +246,19 @@ class Helper extends Base {
|
|
243
246
|
break
|
244
247
|
}
|
245
248
|
|
246
|
-
//
|
249
|
+
// A "match" requires nodes to be of the same type (placeholder or element) and have
|
250
|
+
// the same identifier. The VdomLifecycle mixin ensures that both the old (vnode)
|
251
|
+
// and new (vdom) trees are expanded to the same symmetric depth before diffing.
|
247
252
|
if (childNode && oldChildNode && (
|
248
|
-
|
249
|
-
(childNode.componentId &&
|
250
|
-
|
253
|
+
// Case 1: Both nodes are elements with the same ID
|
254
|
+
(!childNode.componentId && !oldChildNode.componentId && childNode.id === oldChildNode.id) ||
|
255
|
+
// Case 2: Both nodes are placeholders for the same component
|
256
|
+
(childNode.componentId && childNode.componentId === oldChildNode.componentId)
|
257
|
+
)) {
|
258
|
+
if (childNode.componentId === 'neo-ignore') {
|
259
|
+
continue
|
260
|
+
}
|
261
|
+
|
251
262
|
me.createDeltas({deltas, oldVnode: oldChildNode, oldVnodeMap, vnode: childNode, vnodeMap});
|
252
263
|
continue
|
253
264
|
}
|
@@ -334,7 +345,7 @@ class Helper extends Base {
|
|
334
345
|
|
335
346
|
newValue = [];
|
336
347
|
|
337
|
-
value.forEach(item => {
|
348
|
+
value.filter(Boolean).forEach(item => {
|
338
349
|
if (item.removeDom !== true) {
|
339
350
|
delete item.removeDom; // could be false
|
340
351
|
potentialNode = me.createVnode(item);
|
@@ -371,6 +382,7 @@ class Helper extends Base {
|
|
371
382
|
case 'componentId':
|
372
383
|
case 'id':
|
373
384
|
case 'static':
|
385
|
+
case 'vtype':
|
374
386
|
node[key] = value;
|
375
387
|
break
|
376
388
|
case 'style':
|
package/src/vdom/VNode.mjs
CHANGED
@@ -71,8 +71,9 @@ class VNode {
|
|
71
71
|
});
|
72
72
|
|
73
73
|
if (isVText) {
|
74
|
-
//
|
75
|
-
|
74
|
+
// A vtext node represents a pure text node. It should not be created from an innerHTML property.
|
75
|
+
// For XSS Security, we escape the content when using the string-based renderer.
|
76
|
+
me.textContent = Neo.config.useDomApiRenderer ? textContent : StringUtil.escapeHtml(textContent);
|
76
77
|
} else {
|
77
78
|
Object.assign(me, {
|
78
79
|
attributes: config.attributes || {},
|
@@ -135,7 +136,4 @@ function normalizeClassName(classNameInput) {
|
|
135
136
|
return [...new Set(normalizedClasses)]
|
136
137
|
}
|
137
138
|
|
138
|
-
|
139
|
-
ns.VNode = VNode;
|
140
|
-
|
141
|
-
export default VNode;
|
139
|
+
export default Neo.gatekeep(VNode, 'Neo.vdom.VNode');
|