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.
Files changed (491) hide show
  1. package/.github/RELEASE_NOTES/v10.0.0-beta.1.md +20 -0
  2. package/.github/RELEASE_NOTES/v10.0.0-beta.2.md +73 -0
  3. package/.github/RELEASE_NOTES/v10.0.0-beta.3.md +39 -0
  4. package/.github/RELEASE_NOTES/v10.0.0-beta.5.md +70 -0
  5. package/.github/RELEASE_NOTES/v10.0.0-beta.6.md +48 -0
  6. package/.github/RELEASE_NOTES/v10.0.0.md +52 -0
  7. package/.github/epic-functional-components.md +498 -0
  8. package/.github/ticket-asymmetric-vdom-updates.md +122 -0
  9. package/README.md +0 -3
  10. package/ServiceWorker.mjs +2 -2
  11. package/apps/colors/store/Colors.mjs +1 -0
  12. package/apps/colors/view/GridContainer.mjs +3 -0
  13. package/apps/colors/view/HeaderToolbar.mjs +2 -0
  14. package/apps/colors/view/Viewport.mjs +3 -0
  15. package/apps/covid/view/FooterContainer.mjs +3 -0
  16. package/apps/covid/view/GalleryContainer.mjs +2 -0
  17. package/apps/covid/view/GalleryContainerController.mjs +1 -0
  18. package/apps/covid/view/HeaderContainer.mjs +2 -0
  19. package/apps/covid/view/HelixContainer.mjs +2 -0
  20. package/apps/covid/view/HelixContainerController.mjs +1 -0
  21. package/apps/covid/view/MainContainer.mjs +3 -0
  22. package/apps/covid/view/TableContainer.mjs +3 -0
  23. package/apps/covid/view/TableContainerController.mjs +1 -0
  24. package/apps/covid/view/WorldMapContainer.mjs +2 -0
  25. package/apps/covid/view/country/Gallery.mjs +3 -0
  26. package/apps/covid/view/country/Helix.mjs +8 -0
  27. package/apps/covid/view/country/HistoricalDataTable.mjs +1 -0
  28. package/apps/covid/view/country/Table.mjs +2 -0
  29. package/apps/covid/view/mapboxGl/Component.mjs +1 -0
  30. package/apps/covid/view/mapboxGl/Container.mjs +2 -0
  31. package/apps/email/EPIC_PLAN.md +58 -0
  32. package/apps/email/neo-config.json +2 -2
  33. package/apps/email/store/Emails.mjs +11 -1
  34. package/apps/email/view/ComposeView.mjs +44 -0
  35. package/apps/email/view/MainView.mjs +89 -0
  36. package/apps/email/view/Viewport.mjs +4 -33
  37. package/apps/email/view/ViewportStateProvider.mjs +3 -3
  38. package/apps/form/store/SideNav.mjs +1 -0
  39. package/apps/form/view/FormContainer.mjs +1 -0
  40. package/apps/form/view/FormPageContainer.mjs +2 -0
  41. package/apps/form/view/SideNavList.mjs +1 -0
  42. package/apps/form/view/Viewport.mjs +3 -0
  43. package/apps/portal/childapps/preview/MainContainer.mjs +1 -0
  44. package/apps/portal/index.html +1 -1
  45. package/apps/portal/store/BlogPosts.mjs +2 -0
  46. package/apps/portal/store/Content.mjs +1 -0
  47. package/apps/portal/store/ContentSections.mjs +1 -0
  48. package/apps/portal/store/Examples.mjs +1 -0
  49. package/apps/portal/view/HeaderToolbar.mjs +1 -0
  50. package/apps/portal/view/Viewport.mjs +5 -0
  51. package/apps/portal/view/ViewportController.mjs +11 -3
  52. package/apps/portal/view/about/Container.mjs +2 -0
  53. package/apps/portal/view/about/MemberContainer.mjs +7 -0
  54. package/apps/portal/view/blog/Container.mjs +2 -0
  55. package/apps/portal/view/blog/List.mjs +2 -0
  56. package/apps/portal/view/examples/List.mjs +29 -19
  57. package/apps/portal/view/examples/TabContainer.mjs +4 -0
  58. package/apps/portal/view/home/ContentBox.mjs +3 -0
  59. package/apps/portal/view/home/FeatureSection.mjs +8 -0
  60. package/apps/portal/view/home/FooterContainer.mjs +4 -1
  61. package/apps/portal/view/home/MainContainer.mjs +2 -0
  62. package/apps/portal/view/home/parts/AfterMath.mjs +2 -0
  63. package/apps/portal/view/home/parts/BaseContainer.mjs +1 -0
  64. package/apps/portal/view/home/parts/Colors.mjs +4 -0
  65. package/apps/portal/view/home/parts/Features.mjs +2 -0
  66. package/apps/portal/view/home/parts/Helix.mjs +5 -0
  67. package/apps/portal/view/home/parts/How.mjs +4 -0
  68. package/apps/portal/view/home/parts/MainNeo.mjs +1 -0
  69. package/apps/portal/view/home/parts/References.mjs +2 -0
  70. package/apps/portal/view/learn/ContentComponent.mjs +11 -5
  71. package/apps/portal/view/learn/ContentTreeList.mjs +2 -0
  72. package/apps/portal/view/learn/CubeLayoutButton.mjs +1 -0
  73. package/apps/portal/view/learn/MainContainer.mjs +4 -0
  74. package/apps/portal/view/learn/PageContainer.mjs +2 -0
  75. package/apps/portal/view/learn/PageSectionsContainer.mjs +3 -0
  76. package/apps/portal/view/learn/PageSectionsList.mjs +1 -0
  77. package/apps/portal/view/services/Component.mjs +1 -0
  78. package/apps/realworld/api/Base.mjs +1 -0
  79. package/apps/realworld/view/HeaderComponent.mjs +4 -0
  80. package/apps/realworld/view/HomeComponent.mjs +7 -0
  81. package/apps/realworld/view/MainContainer.mjs +2 -0
  82. package/apps/realworld/view/MainContainerController.mjs +2 -0
  83. package/apps/realworld/view/article/CommentComponent.mjs +3 -0
  84. package/apps/realworld/view/article/Component.mjs +17 -10
  85. package/apps/realworld/view/article/CreateCommentComponent.mjs +2 -0
  86. package/apps/realworld/view/article/CreateComponent.mjs +5 -0
  87. package/apps/realworld/view/article/PreviewComponent.mjs +9 -0
  88. package/apps/realworld/view/article/TagListComponent.mjs +2 -0
  89. package/apps/realworld/view/user/ProfileComponent.mjs +7 -0
  90. package/apps/realworld/view/user/SettingsComponent.mjs +5 -0
  91. package/apps/realworld/view/user/SignUpComponent.mjs +3 -0
  92. package/apps/realworld2/api/Base.mjs +1 -0
  93. package/apps/realworld2/view/FooterComponent.mjs +1 -0
  94. package/apps/realworld2/view/HeaderToolbar.mjs +3 -0
  95. package/apps/realworld2/view/HomeContainer.mjs +1 -0
  96. package/apps/realworld2/view/MainContainer.mjs +2 -0
  97. package/apps/realworld2/view/MainContainerController.mjs +1 -0
  98. package/apps/realworld2/view/article/Helix.mjs +1 -0
  99. package/apps/realworld2/view/article/PreviewComponent.mjs +9 -0
  100. package/apps/realworld2/view/article/PreviewList.mjs +1 -0
  101. package/apps/realworld2/view/article/TagListComponent.mjs +2 -0
  102. package/apps/route/view/CenterContainer.mjs +1 -0
  103. package/apps/route/view/MainView.mjs +1 -0
  104. package/apps/sharedcovid/childapps/sharedcovidchart/MainContainer.mjs +1 -0
  105. package/apps/sharedcovid/childapps/sharedcovidgallery/MainContainer.mjs +1 -0
  106. package/apps/sharedcovid/childapps/sharedcovidhelix/MainContainer.mjs +1 -0
  107. package/apps/sharedcovid/childapps/sharedcovidmap/MainContainer.mjs +1 -0
  108. package/apps/sharedcovid/view/FooterContainer.mjs +3 -0
  109. package/apps/sharedcovid/view/GalleryContainer.mjs +2 -0
  110. package/apps/sharedcovid/view/GalleryContainerController.mjs +1 -0
  111. package/apps/sharedcovid/view/HeaderContainer.mjs +2 -0
  112. package/apps/sharedcovid/view/HelixContainer.mjs +2 -0
  113. package/apps/sharedcovid/view/HelixContainerController.mjs +1 -0
  114. package/apps/sharedcovid/view/MainContainer.mjs +3 -0
  115. package/apps/sharedcovid/view/TableContainer.mjs +3 -0
  116. package/apps/sharedcovid/view/TableContainerController.mjs +1 -0
  117. package/apps/sharedcovid/view/WorldMapContainer.mjs +2 -0
  118. package/apps/sharedcovid/view/country/Gallery.mjs +3 -0
  119. package/apps/sharedcovid/view/country/Helix.mjs +8 -0
  120. package/apps/sharedcovid/view/country/HistoricalDataTable.mjs +1 -0
  121. package/apps/sharedcovid/view/country/Table.mjs +2 -0
  122. package/apps/sharedcovid/view/mapboxGl/Component.mjs +1 -0
  123. package/apps/sharedcovid/view/mapboxGl/Container.mjs +2 -0
  124. package/apps/shareddialog/childapps/shareddialog2/view/MainContainer.mjs +2 -0
  125. package/apps/shareddialog/view/DemoDialog.mjs +2 -0
  126. package/apps/shareddialog/view/MainContainer.mjs +2 -0
  127. package/apps/shareddialog/view/MainContainerController.mjs +1 -0
  128. package/buildScripts/addReactiveTags.mjs +191 -0
  129. package/buildScripts/checkReactiveTags.mjs +160 -0
  130. package/docs/app/store/Api.mjs +1 -0
  131. package/docs/app/store/Examples.mjs +1 -0
  132. package/docs/app/view/ApiTreeList.mjs +1 -0
  133. package/docs/app/view/ContentTabContainer.mjs +2 -0
  134. package/docs/app/view/ExamplesTreeList.mjs +2 -0
  135. package/docs/app/view/HeaderContainer.mjs +3 -0
  136. package/docs/app/view/MainContainer.mjs +5 -0
  137. package/docs/app/view/classdetails/HeaderComponent.mjs +1 -0
  138. package/docs/app/view/classdetails/MainContainer.mjs +3 -0
  139. package/docs/app/view/classdetails/MembersList.mjs +5 -0
  140. package/docs/app/view/classdetails/SourceViewComponent.mjs +2 -0
  141. package/examples/ConfigurationViewport.mjs +14 -8
  142. package/examples/calendar/weekview/MainContainer.mjs +4 -0
  143. package/examples/component/coronaGallery/CountryGallery.mjs +2 -0
  144. package/examples/component/coronaGallery/CountryStore.mjs +1 -0
  145. package/examples/component/coronaGallery/Viewport.mjs +3 -0
  146. package/examples/component/coronaGallery/ViewportController.mjs +1 -0
  147. package/examples/component/coronaHelix/CountryHelix.mjs +7 -0
  148. package/examples/component/coronaHelix/MainContainer.mjs +1 -0
  149. package/examples/component/gallery/ImageStore.mjs +1 -0
  150. package/examples/component/helix/ImageStore.mjs +1 -0
  151. package/examples/component/helix/Viewport.mjs +3 -0
  152. package/examples/component/helix/ViewportController.mjs +1 -0
  153. package/examples/component/multiWindowCoronaGallery/childapp/Viewport.mjs +1 -0
  154. package/examples/component/multiWindowHelix/childapp/Viewport.mjs +1 -0
  155. package/examples/component/wrapper/googleMaps/MapComponent.mjs +2 -0
  156. package/examples/core/config/MainContainer.mjs +2 -0
  157. package/examples/dialog/DemoDialog.mjs +2 -0
  158. package/examples/dialog/MainContainer.mjs +1 -0
  159. package/examples/form/field/color/MainStore.mjs +1 -0
  160. package/examples/functional/button/base/MainContainer.mjs +207 -0
  161. package/examples/functional/button/base/app.mjs +6 -0
  162. package/examples/functional/button/base/index.html +11 -0
  163. package/examples/functional/button/base/neo-config.json +6 -0
  164. package/examples/functional/defineComponent/Component.mjs +18 -0
  165. package/examples/functional/defineComponent/MainContainer.mjs +41 -0
  166. package/examples/functional/defineComponent/app.mjs +6 -0
  167. package/examples/functional/defineComponent/index.html +11 -0
  168. package/examples/functional/defineComponent/neo-config.json +6 -0
  169. package/examples/functional/hostComponent/Component.mjs +32 -0
  170. package/examples/functional/hostComponent/MainContainer.mjs +48 -0
  171. package/examples/functional/hostComponent/app.mjs +6 -0
  172. package/examples/functional/hostComponent/index.html +11 -0
  173. package/examples/functional/hostComponent/neo-config.json +6 -0
  174. package/examples/grid/animatedRowSorting/Viewport.mjs +1 -1
  175. package/examples/grid/bigData/ControlsContainer.mjs +3 -0
  176. package/examples/grid/bigData/GridContainer.mjs +4 -2
  177. package/examples/grid/bigData/MainContainer.mjs +2 -0
  178. package/examples/grid/bigData/MainModel.mjs +1 -0
  179. package/examples/grid/bigData/MainStore.mjs +3 -0
  180. package/examples/grid/cellEditing/MainContainer.mjs +1 -1
  181. package/examples/grid/container/MainContainer.mjs +1 -1
  182. package/examples/grid/covid/GridContainer.mjs +3 -0
  183. package/examples/grid/covid/MainContainer.mjs +2 -0
  184. package/examples/grid/covid/Store.mjs +1 -0
  185. package/examples/grid/nestedRecordFields/EditUserDialog.mjs +3 -0
  186. package/examples/grid/nestedRecordFields/Viewport.mjs +3 -1
  187. package/examples/list/animate/List.mjs +4 -0
  188. package/examples/list/animate/MainContainer.mjs +2 -0
  189. package/examples/list/circle/MainStore.mjs +1 -0
  190. package/examples/list/color/MainStore.mjs +1 -0
  191. package/examples/preloadingAssets/view/MainContainer.mjs +2 -0
  192. package/examples/stateProvider/advanced/MainContainer.mjs +1 -0
  193. package/examples/stateProvider/dialog/EditUserDialog.mjs +2 -0
  194. package/examples/stateProvider/dialog/MainContainer.mjs +1 -0
  195. package/examples/stateProvider/extendedClass/MainContainer.mjs +2 -0
  196. package/examples/stateProvider/inline/MainContainer.mjs +1 -0
  197. package/examples/stateProvider/inlineNoStateProvider/MainContainer.mjs +1 -0
  198. package/examples/stateProvider/inlineNoStateProvider/MainContainerController.mjs +2 -0
  199. package/examples/stateProvider/multiWindow/EditUserDialog.mjs +3 -0
  200. package/examples/stateProvider/multiWindow/MainContainer.mjs +1 -0
  201. package/examples/stateProvider/multiWindow/Viewport.mjs +1 -0
  202. package/examples/stateProvider/nestedData/MainContainer.mjs +1 -0
  203. package/examples/stateProvider/table/MainContainer.mjs +1 -0
  204. package/examples/table/covid/MainContainer.mjs +2 -0
  205. package/examples/table/covid/Store.mjs +1 -0
  206. package/examples/table/covid/TableContainer.mjs +3 -0
  207. package/examples/table/nestedRecordFields/EditUserDialog.mjs +3 -0
  208. package/examples/table/nestedRecordFields/Viewport.mjs +1 -0
  209. package/examples/todoList/version1/MainComponent.mjs +1 -1
  210. package/examples/toolbar/breadcrumb/view/MainContainer.mjs +2 -0
  211. package/examples/toolbar/paging/store/Users.mjs +1 -0
  212. package/examples/toolbar/paging/view/AddUserDialog.mjs +3 -0
  213. package/examples/toolbar/paging/view/MainContainer.mjs +3 -0
  214. package/examples/treeAccordion/MainContainer.mjs +2 -2
  215. package/examples/worker/task/MainContainer.mjs +1 -0
  216. package/learn/Glossary.md +1 -0
  217. package/learn/UsingTheseTopics.md +1 -0
  218. package/learn/benefits/ConfigSystem.md +2 -0
  219. package/learn/benefits/Effort.md +1 -0
  220. package/learn/benefits/Features.md +1 -0
  221. package/learn/benefits/FormsEngine.md +1 -0
  222. package/learn/benefits/FourEnvironments.md +2 -0
  223. package/learn/benefits/Introduction.md +2 -0
  224. package/learn/benefits/MultiWindow.md +3 -1
  225. package/learn/benefits/OffTheMainThread.md +2 -0
  226. package/learn/benefits/Quick.md +2 -0
  227. package/learn/benefits/RPCLayer.md +2 -0
  228. package/learn/benefits/Speed.md +2 -0
  229. package/learn/blog/v10-deep-dive-functional-components.md +293 -0
  230. package/learn/blog/v10-deep-dive-reactivity.md +522 -0
  231. package/learn/blog/v10-deep-dive-state-provider.md +432 -0
  232. package/learn/blog/v10-deep-dive-vdom-revolution.md +194 -0
  233. package/learn/blog/v10-post1-love-story.md +383 -0
  234. package/learn/comparisons/NeoVsAngular.md +90 -0
  235. package/learn/comparisons/NeoVsExtJs.md +178 -0
  236. package/learn/comparisons/NeoVsNextJs.md +124 -0
  237. package/learn/comparisons/NeoVsReact.md +95 -0
  238. package/learn/comparisons/NeoVsSolid.md +78 -0
  239. package/learn/comparisons/NeoVsVue.md +92 -0
  240. package/learn/comparisons/Overview.md +46 -0
  241. package/learn/gettingstarted/ComponentModels.md +2 -0
  242. package/learn/gettingstarted/Config.md +2 -0
  243. package/learn/gettingstarted/DescribingTheUI.md +2 -0
  244. package/learn/gettingstarted/Events.md +2 -0
  245. package/learn/gettingstarted/Extending.md +2 -0
  246. package/learn/gettingstarted/References.md +2 -0
  247. package/learn/gettingstarted/Setup.md +3 -2
  248. package/learn/gettingstarted/Workspaces.md +2 -0
  249. package/learn/guides/datahandling/Collections.md +1 -0
  250. package/learn/guides/datahandling/Records.md +1 -0
  251. package/learn/guides/datahandling/StateProviders.md +130 -16
  252. package/learn/guides/datahandling/Tables.md +1 -1
  253. package/learn/guides/fundamentals/ConfigSystemDeepDive.md +1 -0
  254. package/learn/guides/fundamentals/DeclarativeComponentTreesVsImperativeVdom.md +2 -0
  255. package/learn/guides/fundamentals/DeclarativeVDOMWithEffects.md +10 -8
  256. package/learn/guides/fundamentals/ExtendingNeoClasses.md +1 -0
  257. package/learn/guides/fundamentals/InstanceLifecycle.md +3 -1
  258. package/learn/guides/fundamentals/MainThreadAddons.md +2 -0
  259. package/learn/guides/specificfeatures/Mixins.md +3 -1
  260. package/learn/guides/specificfeatures/MultiWindow.md +3 -1
  261. package/learn/guides/specificfeatures/PortalApp.md +2 -0
  262. package/learn/guides/uibuildingblocks/ComponentsAndContainers.md +2 -0
  263. package/learn/guides/uibuildingblocks/CustomComponents.md +2 -0
  264. package/learn/guides/uibuildingblocks/Layouts.md +2 -0
  265. package/learn/guides/uibuildingblocks/WorkingWithVDom.md +28 -2
  266. package/learn/guides/userinteraction/Forms.md +2 -0
  267. package/learn/guides/userinteraction/events/CustomEvents.md +2 -1
  268. package/learn/guides/userinteraction/events/DomEvents.md +2 -0
  269. package/learn/javascript/ClassFeatures.md +4 -3
  270. package/learn/javascript/Classes.md +10 -13
  271. package/learn/javascript/Overrides.md +10 -6
  272. package/learn/javascript/Super.md +12 -8
  273. package/learn/tree.json +71 -64
  274. package/learn/tutorials/Earthquakes.md +2 -0
  275. package/learn/tutorials/RSP.md +3 -1
  276. package/learn/tutorials/TodoList.md +103 -7
  277. package/package.json +8 -6
  278. package/resources/scss/src/apps/email/ComposeView.scss +16 -0
  279. package/resources/scss/src/apps/email/MainView.scss +5 -0
  280. package/resources/scss/src/apps/portal/learn/ContentComponent.scss +5 -4
  281. package/src/DefaultConfig.mjs +12 -2
  282. package/src/Main.mjs +1 -0
  283. package/src/Neo.mjs +219 -166
  284. package/src/Xhr.mjs +1 -0
  285. package/src/button/Base.mjs +13 -0
  286. package/src/button/Effect.mjs +16 -2
  287. package/src/button/Split.mjs +2 -0
  288. package/src/calendar/store/Calendars.mjs +1 -0
  289. package/src/calendar/store/Colors.mjs +1 -0
  290. package/src/calendar/store/Events.mjs +1 -0
  291. package/src/calendar/view/DayComponent.mjs +2 -0
  292. package/src/calendar/view/EditEventContainer.mjs +4 -1
  293. package/src/calendar/view/MainContainer.mjs +13 -0
  294. package/src/calendar/view/MainContainerStateProvider.mjs +14 -28
  295. package/src/calendar/view/SettingsContainer.mjs +1 -0
  296. package/src/calendar/view/YearComponent.mjs +16 -0
  297. package/src/calendar/view/calendars/ColorsList.mjs +2 -0
  298. package/src/calendar/view/calendars/Container.mjs +2 -0
  299. package/src/calendar/view/calendars/EditContainer.mjs +1 -0
  300. package/src/calendar/view/month/Component.mjs +11 -0
  301. package/src/calendar/view/settings/GeneralContainer.mjs +1 -0
  302. package/src/calendar/view/settings/MonthContainer.mjs +1 -0
  303. package/src/calendar/view/settings/WeekContainer.mjs +1 -0
  304. package/src/calendar/view/settings/YearContainer.mjs +1 -0
  305. package/src/calendar/view/week/Component.mjs +15 -1
  306. package/src/calendar/view/week/TimeAxisComponent.mjs +4 -0
  307. package/src/code/LivePreview.mjs +51 -23
  308. package/src/collection/Base.mjs +7 -10
  309. package/src/collection/Filter.mjs +6 -0
  310. package/src/collection/Sorter.mjs +3 -0
  311. package/src/component/Abstract.mjs +412 -0
  312. package/src/component/Base.mjs +48 -1077
  313. package/src/component/Canvas.mjs +1 -0
  314. package/src/component/Chip.mjs +4 -0
  315. package/src/component/Circle.mjs +14 -0
  316. package/src/component/Clock.mjs +4 -0
  317. package/src/component/DateSelector.mjs +12 -0
  318. package/src/component/Gallery.mjs +11 -0
  319. package/src/component/Helix.mjs +24 -0
  320. package/src/component/Label.mjs +1 -0
  321. package/src/component/Legend.mjs +3 -0
  322. package/src/component/MagicMoveText.mjs +4 -0
  323. package/src/component/Progress.mjs +3 -0
  324. package/src/component/Splitter.mjs +3 -0
  325. package/src/component/StatusBadge.mjs +6 -0
  326. package/src/component/Timer.mjs +4 -0
  327. package/src/component/Toast.mjs +6 -0
  328. package/src/component/Video.mjs +1 -0
  329. package/src/component/mwc/Button.mjs +7 -0
  330. package/src/component/mwc/TextField.mjs +9 -0
  331. package/src/component/wrapper/AmChart.mjs +2 -0
  332. package/src/component/wrapper/GoogleMaps.mjs +3 -0
  333. package/src/component/wrapper/MapboxGL.mjs +5 -0
  334. package/src/component/wrapper/MonacoEditor.mjs +12 -0
  335. package/src/container/Accordion.mjs +2 -0
  336. package/src/container/Base.mjs +7 -3
  337. package/src/container/Panel.mjs +1 -0
  338. package/src/container/Viewport.mjs +1 -0
  339. package/src/controller/Application.mjs +1 -0
  340. package/src/controller/Base.mjs +1 -0
  341. package/src/controller/Component.mjs +1 -0
  342. package/src/core/Base.mjs +86 -33
  343. package/src/core/Compare.mjs +4 -7
  344. package/src/core/Config.mjs +65 -52
  345. package/src/core/Effect.mjs +86 -24
  346. package/src/core/EffectManager.mjs +117 -8
  347. package/src/core/IdGenerator.mjs +13 -44
  348. package/src/core/Observable.mjs +69 -65
  349. package/src/data/Model.mjs +2 -0
  350. package/src/data/Store.mjs +7 -0
  351. package/src/data/connection/WebSocket.mjs +2 -0
  352. package/src/date/DayViewComponent.mjs +2 -0
  353. package/src/date/SelectorContainer.mjs +14 -0
  354. package/src/dialog/Base.mjs +8 -0
  355. package/src/draggable/DragZone.mjs +5 -0
  356. package/src/draggable/tree/DragZone.mjs +1 -0
  357. package/src/filter/BooleanContainer.mjs +2 -0
  358. package/src/filter/NumberContainer.mjs +3 -0
  359. package/src/filter/ToggleOperatorsButton.mjs +2 -0
  360. package/src/form/Fieldset.mjs +6 -0
  361. package/src/form/field/Base.mjs +7 -0
  362. package/src/form/field/CheckBox.mjs +18 -0
  363. package/src/form/field/Chip.mjs +1 -0
  364. package/src/form/field/ComboBox.mjs +8 -0
  365. package/src/form/field/Country.mjs +1 -0
  366. package/src/form/field/Currency.mjs +2 -0
  367. package/src/form/field/Date.mjs +4 -0
  368. package/src/form/field/Display.mjs +1 -0
  369. package/src/form/field/Email.mjs +1 -0
  370. package/src/form/field/FileUpload.mjs +7 -0
  371. package/src/form/field/Hidden.mjs +1 -0
  372. package/src/form/field/Number.mjs +7 -0
  373. package/src/form/field/Password.mjs +1 -0
  374. package/src/form/field/Phone.mjs +3 -0
  375. package/src/form/field/Picker.mjs +2 -0
  376. package/src/form/field/Radio.mjs +1 -0
  377. package/src/form/field/Range.mjs +3 -0
  378. package/src/form/field/Search.mjs +2 -0
  379. package/src/form/field/Text.mjs +43 -5
  380. package/src/form/field/TextArea.mjs +7 -0
  381. package/src/form/field/Time.mjs +6 -0
  382. package/src/form/field/Url.mjs +3 -0
  383. package/src/form/field/ZipCode.mjs +2 -0
  384. package/src/form/field/trigger/Base.mjs +3 -0
  385. package/src/form/field/trigger/Clear.mjs +2 -0
  386. package/src/form/field/trigger/CopyToClipboard.mjs +2 -0
  387. package/src/form/field/trigger/Date.mjs +1 -0
  388. package/src/form/field/trigger/Picker.mjs +1 -0
  389. package/src/form/field/trigger/Search.mjs +1 -0
  390. package/src/form/field/trigger/SpinDown.mjs +2 -0
  391. package/src/form/field/trigger/SpinUp.mjs +1 -0
  392. package/src/form/field/trigger/Time.mjs +2 -0
  393. package/src/functional/_export.mjs +6 -0
  394. package/src/functional/button/Base.mjs +384 -0
  395. package/src/functional/component/Base.mjs +405 -0
  396. package/src/functional/defineComponent.mjs +102 -0
  397. package/src/functional/useConfig.mjs +52 -0
  398. package/src/functional/useEvent.mjs +43 -0
  399. package/src/grid/Body.mjs +20 -1
  400. package/src/grid/Container.mjs +50 -60
  401. package/src/grid/ScrollManager.mjs +2 -0
  402. package/src/grid/VerticalScrollbar.mjs +2 -0
  403. package/src/grid/column/Base.mjs +2 -0
  404. package/src/grid/header/Button.mjs +7 -0
  405. package/src/grid/header/Toolbar.mjs +6 -0
  406. package/src/grid/plugin/AnimateRows.mjs +2 -0
  407. package/src/layout/Base.mjs +3 -0
  408. package/src/layout/Card.mjs +1 -0
  409. package/src/layout/Cube.mjs +18 -4
  410. package/src/layout/Fit.mjs +1 -0
  411. package/src/layout/Flexbox.mjs +7 -0
  412. package/src/layout/Form.mjs +2 -0
  413. package/src/layout/Grid.mjs +1 -0
  414. package/src/layout/HBox.mjs +1 -0
  415. package/src/layout/VBox.mjs +1 -0
  416. package/src/list/Base.mjs +13 -0
  417. package/src/list/Chip.mjs +1 -0
  418. package/src/list/Circle.mjs +2 -0
  419. package/src/list/Color.mjs +1 -0
  420. package/src/list/plugin/Animate.mjs +2 -0
  421. package/src/main/DeltaUpdates.mjs +1 -0
  422. package/src/main/DomEvents.mjs +2 -0
  423. package/src/main/addon/CloneNode.mjs +1 -0
  424. package/src/main/addon/Cookie.mjs +1 -0
  425. package/src/main/addon/GoogleMaps.mjs +1 -0
  426. package/src/main/addon/LocalStorage.mjs +1 -0
  427. package/src/main/addon/MapboxGL.mjs +1 -0
  428. package/src/main/addon/Markdown.mjs +1 -0
  429. package/src/main/addon/Navigator.mjs +1 -0
  430. package/src/main/addon/Popover.mjs +1 -0
  431. package/src/main/addon/Stylesheet.mjs +1 -0
  432. package/src/main/addon/WindowPosition.mjs +1 -0
  433. package/src/manager/Component.mjs +0 -71
  434. package/src/manager/VDomUpdate.mjs +320 -0
  435. package/src/menu/List.mjs +6 -0
  436. package/src/menu/Model.mjs +1 -0
  437. package/src/menu/Panel.mjs +3 -0
  438. package/src/menu/Store.mjs +1 -0
  439. package/src/mixin/DomEvents.mjs +130 -0
  440. package/src/mixin/VdomLifecycle.mjs +670 -0
  441. package/src/plugin/Base.mjs +1 -0
  442. package/src/plugin/Resizable.mjs +2 -0
  443. package/src/selection/Model.mjs +15 -18
  444. package/src/selection/grid/BaseModel.mjs +1 -0
  445. package/src/sitemap/Component.mjs +1 -0
  446. package/src/state/Provider.mjs +129 -87
  447. package/src/state/createHierarchicalDataProxy.mjs +39 -25
  448. package/src/tab/Container.mjs +6 -0
  449. package/src/tab/Strip.mjs +1 -0
  450. package/src/tab/header/Button.mjs +2 -0
  451. package/src/tab/header/EffectButton.mjs +2 -0
  452. package/src/tab/header/Toolbar.mjs +1 -0
  453. package/src/table/Body.mjs +3 -0
  454. package/src/table/Container.mjs +10 -0
  455. package/src/table/header/Button.mjs +8 -0
  456. package/src/table/header/Toolbar.mjs +5 -0
  457. package/src/table/plugin/CellEditing.mjs +1 -0
  458. package/src/toolbar/Base.mjs +4 -0
  459. package/src/toolbar/Breadcrumb.mjs +3 -0
  460. package/src/toolbar/Paging.mjs +5 -0
  461. package/src/tooltip/Base.mjs +2 -0
  462. package/src/tree/List.mjs +3 -0
  463. package/src/util/HashHistory.mjs +1 -0
  464. package/src/util/KeyNavigation.mjs +2 -0
  465. package/src/util/Matrix.mjs +1 -0
  466. package/src/util/VDom.mjs +18 -5
  467. package/src/util/VNode.mjs +7 -1
  468. package/src/util/vdom/TreeBuilder.mjs +105 -0
  469. package/src/vdom/Helper.mjs +35 -23
  470. package/src/vdom/VNode.mjs +4 -6
  471. package/src/worker/App.mjs +1 -0
  472. package/src/worker/Base.mjs +2 -0
  473. package/src/worker/Manager.mjs +2 -0
  474. package/src/worker/ServiceBase.mjs +6 -1
  475. package/src/worker/mixin/RemoteMethodAccess.mjs +1 -6
  476. package/test/siesta/siesta.js +17 -2
  477. package/test/siesta/tests/VdomCalendar.mjs +19 -15
  478. package/test/siesta/tests/VdomHelper.mjs +7 -7
  479. package/test/siesta/tests/classic/Button.mjs +113 -0
  480. package/test/siesta/tests/core/Effect.mjs +10 -14
  481. package/test/siesta/tests/core/EffectBatching.mjs +72 -79
  482. package/test/siesta/tests/functional/Button.mjs +113 -0
  483. package/test/siesta/tests/state/ProviderNestedDataConfigs.mjs +314 -0
  484. package/test/siesta/tests/state/createHierarchicalDataProxy.mjs +42 -55
  485. package/test/siesta/tests/vdom/Advanced.mjs +14 -8
  486. package/test/siesta/tests/vdom/VdomAsymmetricUpdates.mjs +366 -0
  487. package/test/siesta/tests/vdom/VdomRealWorldUpdates.mjs +249 -0
  488. package/test/siesta/tests/vdom/layout/Cube.mjs +11 -7
  489. package/test/siesta/tests/vdom/table/Container.mjs +9 -5
  490. package/learn/javascript/NewNode.md +0 -31
  491. package/src/core/EffectBatchManager.mjs +0 -68
@@ -19,6 +19,7 @@ class VBox extends Flexbox {
19
19
  /**
20
20
  * @member {String} direction='column'
21
21
  * @protected
22
+ * @reactive
22
23
  */
23
24
  direction: 'column'
24
25
  }
package/src/list/Base.mjs CHANGED
@@ -22,6 +22,7 @@ class List extends Component {
22
22
  ntype: 'list',
23
23
  /**
24
24
  * @member {Boolean} animate_=false
25
+ * @reactive
25
26
  */
26
27
  animate_: false,
27
28
  /**
@@ -41,6 +42,7 @@ class List extends Component {
41
42
  disabledField: 'disabled',
42
43
  /**
43
44
  * @member {Boolean} disableSelection_=false
45
+ * @reactive
44
46
  */
45
47
  disableSelection_: false,
46
48
  /**
@@ -49,6 +51,7 @@ class List extends Component {
49
51
  displayField: 'name',
50
52
  /**
51
53
  * @member {Boolean} draggable_=false
54
+ * @reactive
52
55
  */
53
56
  draggable_: false,
54
57
  /**
@@ -63,12 +66,14 @@ class List extends Component {
63
66
  * Keeps track of the focussed item index and allows bindings and programmatic changes.
64
67
  * You can either pass the index or the related record
65
68
  * @member {Number|Object|null} focusIndex_=null
69
+ * @reactive
66
70
  */
67
71
  focusIndex_: null,
68
72
  /**
69
73
  * In case we are using list item headers and want to bind list item indexes to e.g. a card layout
70
74
  * for e.g. a sidenav, this config comes in handy.
71
75
  * @member {Number|null} headerlessSelectedIndex_=null
76
+ * @reactive
72
77
  */
73
78
  headerlessSelectedIndex_: null,
74
79
  /**
@@ -82,6 +87,7 @@ class List extends Component {
82
87
  /**
83
88
  * Defaults to px
84
89
  * @member {Number|null} itemHeight_=null
90
+ * @reactive
85
91
  */
86
92
  itemHeight_: null,
87
93
  /**
@@ -92,6 +98,7 @@ class List extends Component {
92
98
  /**
93
99
  * Defaults to px
94
100
  * @member {Number|null} itemWidth_=null
101
+ * @reactive
95
102
  */
96
103
  itemWidth_: null,
97
104
  /**
@@ -117,11 +124,13 @@ class List extends Component {
117
124
  /**
118
125
  * Keeps track of the selected item index and allows bindings and programmatic changes
119
126
  * @member {Number|null} selectedIndex_=null
127
+ * @reactive
120
128
  */
121
129
  selectedIndex_: null,
122
130
  /**
123
131
  * Either pass a selection.Model module, an instance or a config object
124
132
  * @member {Object|Neo.selection.Model} selectionModel_=null
133
+ * @reactive
125
134
  */
126
135
  selectionModel_: null,
127
136
  /**
@@ -136,21 +145,25 @@ class List extends Component {
136
145
  silentSelect: false,
137
146
  /**
138
147
  * @member {Neo.data.Store|null} store_=null
148
+ * @reactive
139
149
  */
140
150
  store_: null,
141
151
  /**
142
152
  * True will add a checkbox in front of each list item
143
153
  * @member {Boolean} stacked_=true
154
+ * @reactive
144
155
  */
145
156
  useCheckBoxes_: false,
146
157
  /**
147
158
  * Setting this config to true will switch to dl, dt & dd tags instead of using ul & li.
148
159
  * Use the {Boolean} model field isHeader.
149
160
  * @member {Boolean} useHeaders_=false
161
+ * @reactive
150
162
  */
151
163
  useHeaders_: false,
152
164
  /**
153
165
  * @member {Boolean} useWrapperNode_=false
166
+ * @reactive
154
167
  */
155
168
  useWrapperNode_: false,
156
169
  /**
package/src/list/Chip.mjs CHANGED
@@ -41,6 +41,7 @@ class Chip extends ComponentList {
41
41
  /**
42
42
  * True will flex each list item horizontally
43
43
  * @member {Boolean} stacked_=true
44
+ * @reactive
44
45
  */
45
46
  stacked_: true,
46
47
  /**
@@ -30,11 +30,13 @@ class Circle extends ComponentList {
30
30
  /**
31
31
  * Defaults to px
32
32
  * @member {Number|null} itemHeight=300
33
+ * @reactive
33
34
  */
34
35
  itemHeight: 300,
35
36
  /**
36
37
  * Defaults to px
37
38
  * @member {Number|null} itemWidth=300
39
+ * @reactive
38
40
  */
39
41
  itemWidth: 300,
40
42
  /**
@@ -23,6 +23,7 @@ class Color extends List {
23
23
  /**
24
24
  * The data.Model field which contains the color value
25
25
  * @member {String} colorField_='name'
26
+ * @reactive
26
27
  */
27
28
  colorField_: 'name',
28
29
  /**
@@ -47,12 +47,14 @@ class Animate extends Base {
47
47
  /**
48
48
  * Time in ms. Please ensure to match the CSS based value, in case you change the default.
49
49
  * @member {Number} transitionDuration_=500
50
+ * @reactive
50
51
  */
51
52
  transitionDuration_: 500,
52
53
  /**
53
54
  * The easing used for fadeIn, fadeOut and position changes.
54
55
  * Valid values: 'ease','ease-in','ease-out','ease-in-out','linear'
55
56
  * @member {String} transitionEasing_='ease-in-out'
57
+ * @reactive
56
58
  */
57
59
  transitionEasing_: 'ease-in-out',
58
60
  /**
@@ -41,6 +41,7 @@ class DeltaUpdates extends Base {
41
41
  /**
42
42
  * @member {Boolean} renderCountDeltas_=false
43
43
  * @protected
44
+ * @reactive
44
45
  */
45
46
  renderCountDeltas_: false,
46
47
  /**
@@ -70,6 +70,8 @@ const
70
70
  /**
71
71
  * @class Neo.main.DomEvents
72
72
  * @extends Neo.core.Base
73
+ * @mixes Neo.core.Observable
74
+ * @mixes Neo.main.mixin.TouchDomEvents
73
75
  * @singleton
74
76
  */
75
77
  class DomEvents extends Base {
@@ -23,6 +23,7 @@ class CloneNode extends Base {
23
23
  * Remote method access for other workers
24
24
  * @member {Object} remote={app: [//...]}
25
25
  * @protected
26
+ * @reactive
26
27
  */
27
28
  remote: {
28
29
  app: [
@@ -16,6 +16,7 @@ class Cookie extends Base {
16
16
  * Remote method access for other workers
17
17
  * @member {Object} remote={app: [//...]}
18
18
  * @protected
19
+ * @reactive
19
20
  */
20
21
  remote: {
21
22
  app: [
@@ -6,6 +6,7 @@ import Observable from '../../core/Observable.mjs';
6
6
  /**
7
7
  * @class Neo.main.addon.GoogleMaps
8
8
  * @extends Neo.main.addon.Base
9
+ * @mixes Neo.core.Observable
9
10
  */
10
11
  class GoogleMaps extends Base {
11
12
  /**
@@ -16,6 +16,7 @@ class LocalStorage extends Base {
16
16
  * Remote method access for other workers
17
17
  * @member {Object} remote={app: [//...]}
18
18
  * @protected
19
+ * @reactive
19
20
  */
20
21
  remote: {
21
22
  app: [
@@ -71,6 +71,7 @@ class MapboxGL extends Base {
71
71
  /**
72
72
  * @member {Boolean} scriptsLoaded_=true
73
73
  * @protected
74
+ * @reactive
74
75
  */
75
76
  scriptsLoaded_: false,
76
77
  /**
@@ -20,6 +20,7 @@ class Markdown extends Base {
20
20
  * Remote method access for other workers
21
21
  * @member {Object} remote={app: [//...]}
22
22
  * @protected
23
+ * @reactive
23
24
  */
24
25
  remote: {
25
26
  app: [
@@ -26,6 +26,7 @@ class Navigator extends Base {
26
26
  * Remote method access for other workers
27
27
  * @member {Object} remote={app: [//...]}
28
28
  * @protected
29
+ * @reactive
29
30
  */
30
31
  remote: {
31
32
  app: [
@@ -17,6 +17,7 @@ class Popover extends Base {
17
17
  * Remote method access for other workers
18
18
  * @member {Object} remote={app: [//...]}
19
19
  * @protected
20
+ * @reactive
20
21
  */
21
22
  remote: {
22
23
  app: [
@@ -23,6 +23,7 @@ class Stylesheet extends Base {
23
23
  * Remote method access for other workers
24
24
  * @member {Object} remote={app: [//...]}
25
25
  * @protected
26
+ * @reactive
26
27
  */
27
28
  remote: {
28
29
  app: [
@@ -25,6 +25,7 @@ class WindowPosition extends Base {
25
25
  intervalTime: 20,
26
26
  /**
27
27
  * @member {Boolean} observeResize_=false
28
+ * @reactive
28
29
  */
29
30
  observeResize_: false,
30
31
  /**
@@ -394,77 +394,6 @@ class Component extends Manager {
394
394
  return parents
395
395
  }
396
396
 
397
- /**
398
- * Copies a given vdom tree and replaces child component references with the vdom of their matching components
399
- * @param {Object} vdom
400
- * @param {Number} depth=-1
401
- * The component replacement depth.
402
- * -1 will parse the full tree, 1 top level only, 2 include children, 3 include grandchildren
403
- * @returns {Object}
404
- */
405
- getVdomTree(vdom, depth=-1) {
406
- let output = {...vdom}, // shallow copy
407
- childDepth;
408
-
409
- if (vdom.cn) {
410
- output.cn = [];
411
-
412
- vdom.cn.forEach(item => {
413
- childDepth = depth;
414
-
415
- if (item.componentId) {
416
- childDepth = depth === -1 ? -1 : depth > 1 ? depth-1 : 1;
417
-
418
- if (depth === -1 || depth > 1) {
419
- item = this.get(item.componentId).vdom
420
- }
421
- }
422
-
423
- output.cn.push(this.getVdomTree(item, childDepth))
424
- })
425
- }
426
-
427
- return output
428
- }
429
-
430
- /**
431
- * Copies a given vnode tree and replaces child component references with the vnode of their matching components
432
- * @param {Object} vnode
433
- * @param {Number} depth=-1
434
- * The component replacement depth.
435
- * -1 will parse the full tree, 1 top level only, 2 include children, 3 include grandchildren
436
- * @returns {Object}
437
- */
438
- getVnodeTree(vnode, depth=-1) {
439
- let output = {...vnode}, // shallow copy
440
- childDepth, component;
441
-
442
- if (vnode.childNodes) {
443
- output.childNodes = [];
444
-
445
- vnode.childNodes.forEach(item => {
446
- childDepth = depth;
447
-
448
- if (item.componentId) {
449
- childDepth = depth === -1 ? -1 : depth > 1 ? depth-1 : 1;
450
-
451
- if (depth === -1 || depth > 1) {
452
- component = this.get(item.componentId);
453
-
454
- // keep references in case there is no vnode (cmp not mounted)
455
- if (component?.vnode) {
456
- item = component.vnode
457
- }
458
- }
459
- }
460
-
461
- output.childNodes.push(this.getVnodeTree(item, childDepth))
462
- })
463
- }
464
-
465
- return output
466
- }
467
-
468
397
  /**
469
398
  * Check if the component had a property of any value somewhere in the Prototype chain
470
399
  *
@@ -0,0 +1,320 @@
1
+ import Collection from '../collection/Base.mjs';
2
+
3
+ /**
4
+ * The VDomUpdate manager is a singleton responsible for orchestrating and optimizing
5
+ * component VDOM updates within the Neo.mjs framework. It acts as a central coordinator
6
+ * to optimize the VDOM update process. Its primary goal is to reduce the amount of
7
+ * message roundtrips between the application and VDOM workers by aggregating multiple
8
+ * component updates into a single, optimized VDOM tree.
9
+ *
10
+ * Key Responsibilities:
11
+ * 1. **Update Merging & Aggregation:** Allows a parent component to absorb the update
12
+ * requests of its children. Instead of each child triggering a separate VDOM update
13
+ * message to the VDOM worker, the parent sends a single, aggregated VDOM tree. This
14
+ * significantly reduces the overhead of worker communication and can result in smaller,
15
+ * more focused data for the VDOM worker to process. While the amount of final DOM
16
+ * modifications remains the same, this aggregation is key to performance.
17
+ *
18
+ * 2. **Asynchronous Flow Control:** Manages the asynchronous nature of VDOM updates, which
19
+ * are often processed in a worker thread. It ensures that code awaiting an update
20
+ * (e.g., via a returned Promise) is correctly notified upon completion.
21
+ *
22
+ * 3. **Dependency Chaining:** Provides a "post-update" queue, allowing one component's
23
+ * update to be declaratively chained to another's, ensuring a predictable order of
24
+ * operations.
25
+ *
26
+ * 4. **State Tracking:** Keeps track of updates that are "in-flight" (i.e., currently
27
+ * being processed), which helps to avoid race conditions and redundant work.
28
+ *
29
+ * By centralizing these concerns, VDomUpdate plays a critical role in the framework's
30
+ * performance and rendering efficiency.
31
+ *
32
+ * @class Neo.manager.VDomUpdate
33
+ * @extends Neo.collection.Base
34
+ * @singleton
35
+ */
36
+ class VDomUpdate extends Collection {
37
+ static config = {
38
+ /**
39
+ * @member {String} className='Neo.manager.VDomUpdate'
40
+ * @protected
41
+ */
42
+ className: 'Neo.manager.VDomUpdate',
43
+ /**
44
+ * A collection that maps a parent component's ID (`ownerId`) to the set of child
45
+ * components whose VDOM updates have been merged into that parent's update cycle.
46
+ *
47
+ * The structure for each entry is:
48
+ * `{ ownerId: 'parent-id', children: Map<'child-id', {childUpdateDepth, distance}> }`
49
+ *
50
+ * - `ownerId`: The `id` of the parent component taking responsibility for the update.
51
+ * - `children`: A Map where keys are the `id`s of the merged children and values
52
+ * are objects containing metadata needed to calculate the total update scope.
53
+ *
54
+ * @member {Neo.collection.Base|null} mergedCallbackMap=null
55
+ * @protected
56
+ */
57
+ mergedCallbackMap: null,
58
+ /**
59
+ * A collection that queues components that need to be updated immediately after
60
+ * another component's update cycle completes. This is used to handle rendering
61
+ * dependencies.
62
+ *
63
+ * The structure for each entry is:
64
+ * `{ ownerId: 'component-id', children: [{childId, resolve}] }`
65
+ *
66
+ * - `ownerId`: The `id` of the component whose update completion will trigger the queued updates.
67
+ * - `children`: An array of objects, where `childId` is the component to update and
68
+ * `resolve` is the Promise resolver to call after that subsequent update is done.
69
+ *
70
+ * @member {Neo.collection.Base|null} postUpdateQueueMap=null
71
+ * @protected
72
+ */
73
+ postUpdateQueueMap: null,
74
+ /**
75
+ * @member {Boolean} singleton=true
76
+ * @protected
77
+ */
78
+ singleton: true
79
+ }
80
+
81
+ /**
82
+ * A Map that tracks VDOM updates that have been dispatched to the VDOM worker but
83
+ * have not yet completed. This prevents redundant updates for the same component.
84
+ *
85
+ * The structure is: `Map<'component-id', updateDepth>`
86
+ *
87
+ * @member {Map|null} inFlightUpdateMap=null
88
+ * @protected
89
+ */
90
+ inFlightUpdateMap = null;
91
+ /**
92
+ * A Map that stores Promise `resolve` functions associated with a component's update.
93
+ * When a component's VDOM update is finalized, the callbacks for its ID are executed,
94
+ * resolving the Promise returned by the component's `update()` method.
95
+ *
96
+ * The structure is: `Map<'component-id', [callback1, callback2, ...]>`
97
+ *
98
+ * @member {Map|null} promiseCallbackMap=null
99
+ * @protected
100
+ */
101
+ promiseCallbackMap = null;
102
+
103
+ /**
104
+ * Initializes the manager's internal collections and maps.
105
+ * This is called automatically when the singleton instance is created.
106
+ * @param {Object} config
107
+ */
108
+ construct(config) {
109
+ super.construct(config);
110
+
111
+ const me = this;
112
+
113
+ me.inFlightUpdateMap = new Map();
114
+ me.mergedCallbackMap = Neo.create(Collection, {keyProperty: 'ownerId'});
115
+ me.postUpdateQueueMap = Neo.create(Collection, {keyProperty: 'ownerId'});
116
+ me.promiseCallbackMap = new Map();
117
+ }
118
+
119
+ /**
120
+ * Registers a callback function to be executed when a specific component's
121
+ * VDOM update completes. This is the mechanism that resolves the Promise
122
+ * returned by `Component#update()`.
123
+ * @param {String} ownerId The `id` of the component owning the update.
124
+ * @param {Function} callback The function to execute upon completion.
125
+ */
126
+ addPromiseCallback(ownerId, callback) {
127
+ let me = this;
128
+
129
+ if (!me.promiseCallbackMap.has(ownerId)) {
130
+ me.promiseCallbackMap.set(ownerId, [])
131
+ }
132
+
133
+ me.promiseCallbackMap.get(ownerId).push(callback)
134
+ }
135
+
136
+ /**
137
+ * Executes all callbacks associated with a completed VDOM update for a given `ownerId`.
138
+ * This method first processes callbacks for any children that were merged into this
139
+ * update cycle, then executes the callbacks for the `ownerId` itself.
140
+ * @param {String} ownerId The `id` of the component whose update has just completed.
141
+ * @param {Object} [data] Optional data to pass to the callbacks.
142
+ */
143
+ executeCallbacks(ownerId, data) {
144
+ let me = this,
145
+ item = me.mergedCallbackMap.get(ownerId),
146
+ callbackData = data ? [data] : [];
147
+
148
+ if (item) {
149
+ item.children.forEach((value, key) => {
150
+ me.executePromiseCallbacks(key, ...callbackData)
151
+ });
152
+ me.mergedCallbackMap.remove(item);
153
+ }
154
+
155
+ me.executePromiseCallbacks(ownerId, ...callbackData)
156
+ }
157
+
158
+ /**
159
+ * A helper method that invokes all registered promise callbacks for a given
160
+ * component ID and then clears them from the queue.
161
+ * @param {String} ownerId The `id` of the component.
162
+ * @param {Object} [data] Optional data to pass to the callbacks.
163
+ */
164
+ executePromiseCallbacks(ownerId, data) {
165
+ let me = this,
166
+ callbacks = me.promiseCallbackMap.get(ownerId);
167
+
168
+ callbacks?.forEach(callback => callback(data));
169
+ me.promiseCallbackMap.delete(ownerId);
170
+ }
171
+
172
+ /**
173
+ * Calculates the required `updateDepth` for a parent component based on its own
174
+ * needs and the needs of all child components whose updates have been merged into it.
175
+ * The final depth is the maximum required depth to ensure all changes are rendered.
176
+ *
177
+ * For example, if a parent needs to update its direct content (`updateDepth: 1`) but
178
+ * a merged child 3 levels down needs a full subtree update (`childUpdateDepth: -1`),
179
+ * this method will return -1, signaling a full recursive update from the parent.
180
+ *
181
+ * This method is called by the parent component right before it dispatches its VDOM update.
182
+ * @param {String} ownerId The `id` of the parent component.
183
+ * @returns {Number|null} The adjusted update depth, or `null` if no merged children exist.
184
+ */
185
+ getAdjustedUpdateDepth(ownerId) {
186
+ let me = this,
187
+ owner = Neo.getComponent(ownerId),
188
+ item = me.mergedCallbackMap.get(ownerId),
189
+ maxDepth = owner?.updateDepth ?? 1,
190
+ newDepth;
191
+
192
+ if (item) {
193
+ item.children.forEach(value => {
194
+ if (value.childUpdateDepth === -1) {
195
+ newDepth = -1
196
+ } else {
197
+ // The new depth is the distance to the child plus the child's own required update depth.
198
+ newDepth = value.distance + value.childUpdateDepth
199
+ }
200
+
201
+ if (newDepth === -1) {
202
+ maxDepth = -1
203
+ } else if (maxDepth !== -1) {
204
+ maxDepth = Math.max(maxDepth, newDepth)
205
+ }
206
+ });
207
+
208
+ return maxDepth
209
+ }
210
+
211
+ return null
212
+ }
213
+
214
+ /**
215
+ * Retrieves the `updateDepth` for a component's update that is currently in-flight.
216
+ * @param {String} ownerId The `id` of the component owning the update.
217
+ * @returns {Number|undefined} The update depth, or `undefined` if no update is in-flight.
218
+ */
219
+ getInFlightUpdateDepth(ownerId) {
220
+ return this.inFlightUpdateMap.get(ownerId)
221
+ }
222
+
223
+ /**
224
+ * Returns a Set of child component IDs that have been merged into a parent's update cycle.
225
+ * This is used by the parent to know which children it is responsible for updating.
226
+ * @param {String} ownerId The `id` of the parent component.
227
+ * @returns {Set<String>|null} A Set containing the IDs of the merged children, or `null`.
228
+ */
229
+ getMergedChildIds(ownerId) {
230
+ const item = this.mergedCallbackMap.get(ownerId);
231
+ if (item) {
232
+ return new Set(item.children.keys())
233
+ }
234
+ return null
235
+ }
236
+
237
+ /**
238
+ * Marks a component's VDOM update as "in-flight," meaning it has been sent to the
239
+ * worker for processing.
240
+ * @param {String} ownerId The `id` of the component owning the update.
241
+ * @param {Number} updateDepth The depth of the in-flight update.
242
+ */
243
+ registerInFlightUpdate(ownerId, updateDepth) {
244
+ this.inFlightUpdateMap.set(ownerId, updateDepth)
245
+ }
246
+
247
+ /**
248
+ * Registers a child's update request to be merged into its parent's update cycle.
249
+ * This is called by a child component when it determines it can delegate its update
250
+ * to an ancestor.
251
+ * @param {String} ownerId The `id` of the parent component that will own the merged update.
252
+ * @param {String} childId The `id` of the child component requesting the merge.
253
+ * @param {Number} childUpdateDepth The update depth required by the child.
254
+ * @param {Number} distance The component tree distance (number of levels) between the parent and child.
255
+ */
256
+ registerMerged(ownerId, childId, childUpdateDepth, distance) {
257
+ let me = this,
258
+ item = me.mergedCallbackMap.get(ownerId);
259
+
260
+ if (!item) {
261
+ item = {ownerId, children: new Map()};
262
+ me.mergedCallbackMap.add(item)
263
+ }
264
+
265
+ item.children.set(childId, {childUpdateDepth, distance})
266
+ }
267
+
268
+ /**
269
+ * Queues a component update to be executed after another component's update is complete.
270
+ * @param {String} ownerId The `id` of the component to wait for.
271
+ * @param {String} childId The `id` of the component to update afterward.
272
+ * @param {Function} [resolve] The Promise resolver to be called when the `childId`'s subsequent update finishes.
273
+ */
274
+ registerPostUpdate(ownerId, childId, resolve) {
275
+ let me = this,
276
+ item = me.postUpdateQueueMap.get(ownerId);
277
+
278
+ if (!item) {
279
+ item = {ownerId, children: []};
280
+ me.postUpdateQueueMap.add(item)
281
+ }
282
+
283
+ item.children.push({childId, resolve})
284
+ }
285
+
286
+ /**
287
+ * Triggers all pending updates that were queued to run after the specified `ownerId`'s
288
+ * update has completed.
289
+ * @param {String} ownerId The `id` of the component whose update has just finished.
290
+ */
291
+ triggerPostUpdates(ownerId) {
292
+ let me = this,
293
+ item = me.postUpdateQueueMap.get(ownerId),
294
+ component;
295
+
296
+ if (item) {
297
+ item.children.forEach(entry => {
298
+ component = Neo.getComponent(entry.childId);
299
+
300
+ if (component) {
301
+ entry.resolve && me.addPromiseCallback(component.id, entry.resolve);
302
+ component.update()
303
+ }
304
+ });
305
+
306
+ me.postUpdateQueueMap.remove(item)
307
+ }
308
+ }
309
+
310
+ /**
311
+ * Removes a component's update from the "in-flight" registry. This is called after
312
+ * the VDOM worker confirms the update has been processed.
313
+ * @param {String} ownerId The `id` of the component owning the update.
314
+ */
315
+ unregisterInFlightUpdate(ownerId) {
316
+ this.inFlightUpdateMap.delete(ownerId)
317
+ }
318
+ }
319
+
320
+ export default Neo.setupClass(VDomUpdate);