neo.mjs 10.0.0-beta.4 → 10.0.0-beta.6

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 (485) hide show
  1. package/.github/RELEASE_NOTES/v10.0.0-beta.4.md +2 -2
  2. package/.github/RELEASE_NOTES/v10.0.0-beta.5.md +70 -0
  3. package/.github/RELEASE_NOTES/v10.0.0-beta.6.md +48 -0
  4. package/.github/epic-functional-components.md +498 -0
  5. package/.github/ticket-asymmetric-vdom-updates.md +122 -0
  6. package/README.md +0 -3
  7. package/ServiceWorker.mjs +2 -2
  8. package/apps/colors/store/Colors.mjs +1 -0
  9. package/apps/colors/view/GridContainer.mjs +3 -0
  10. package/apps/colors/view/HeaderToolbar.mjs +2 -0
  11. package/apps/colors/view/Viewport.mjs +3 -0
  12. package/apps/covid/view/FooterContainer.mjs +3 -0
  13. package/apps/covid/view/GalleryContainer.mjs +2 -0
  14. package/apps/covid/view/GalleryContainerController.mjs +1 -0
  15. package/apps/covid/view/HeaderContainer.mjs +2 -0
  16. package/apps/covid/view/HelixContainer.mjs +2 -0
  17. package/apps/covid/view/HelixContainerController.mjs +1 -0
  18. package/apps/covid/view/MainContainer.mjs +3 -0
  19. package/apps/covid/view/TableContainer.mjs +3 -0
  20. package/apps/covid/view/TableContainerController.mjs +1 -0
  21. package/apps/covid/view/WorldMapContainer.mjs +2 -0
  22. package/apps/covid/view/country/Gallery.mjs +3 -0
  23. package/apps/covid/view/country/Helix.mjs +8 -0
  24. package/apps/covid/view/country/HistoricalDataTable.mjs +1 -0
  25. package/apps/covid/view/country/Table.mjs +2 -0
  26. package/apps/covid/view/mapboxGl/Component.mjs +1 -0
  27. package/apps/covid/view/mapboxGl/Container.mjs +2 -0
  28. package/apps/email/EPIC_PLAN.md +58 -0
  29. package/apps/email/neo-config.json +2 -2
  30. package/apps/email/store/Emails.mjs +11 -1
  31. package/apps/email/view/ComposeView.mjs +44 -0
  32. package/apps/email/view/MainView.mjs +89 -0
  33. package/apps/email/view/Viewport.mjs +4 -33
  34. package/apps/email/view/ViewportStateProvider.mjs +3 -3
  35. package/apps/form/store/SideNav.mjs +1 -0
  36. package/apps/form/view/FormContainer.mjs +1 -0
  37. package/apps/form/view/FormPageContainer.mjs +2 -0
  38. package/apps/form/view/SideNavList.mjs +1 -0
  39. package/apps/form/view/Viewport.mjs +3 -0
  40. package/apps/portal/childapps/preview/MainContainer.mjs +1 -0
  41. package/apps/portal/index.html +1 -1
  42. package/apps/portal/store/BlogPosts.mjs +2 -0
  43. package/apps/portal/store/Content.mjs +1 -0
  44. package/apps/portal/store/ContentSections.mjs +1 -0
  45. package/apps/portal/store/Examples.mjs +1 -0
  46. package/apps/portal/view/HeaderToolbar.mjs +1 -0
  47. package/apps/portal/view/Viewport.mjs +5 -0
  48. package/apps/portal/view/ViewportController.mjs +8 -2
  49. package/apps/portal/view/about/Container.mjs +2 -0
  50. package/apps/portal/view/about/MemberContainer.mjs +7 -0
  51. package/apps/portal/view/blog/Container.mjs +2 -0
  52. package/apps/portal/view/blog/List.mjs +2 -0
  53. package/apps/portal/view/examples/List.mjs +1 -0
  54. package/apps/portal/view/examples/TabContainer.mjs +4 -0
  55. package/apps/portal/view/home/ContentBox.mjs +3 -0
  56. package/apps/portal/view/home/FeatureSection.mjs +8 -0
  57. package/apps/portal/view/home/FooterContainer.mjs +4 -1
  58. package/apps/portal/view/home/MainContainer.mjs +2 -0
  59. package/apps/portal/view/home/parts/AfterMath.mjs +2 -0
  60. package/apps/portal/view/home/parts/BaseContainer.mjs +1 -0
  61. package/apps/portal/view/home/parts/Colors.mjs +4 -0
  62. package/apps/portal/view/home/parts/Features.mjs +2 -0
  63. package/apps/portal/view/home/parts/Helix.mjs +5 -0
  64. package/apps/portal/view/home/parts/How.mjs +4 -0
  65. package/apps/portal/view/home/parts/MainNeo.mjs +1 -0
  66. package/apps/portal/view/home/parts/References.mjs +2 -0
  67. package/apps/portal/view/learn/ContentComponent.mjs +11 -5
  68. package/apps/portal/view/learn/ContentTreeList.mjs +2 -0
  69. package/apps/portal/view/learn/CubeLayoutButton.mjs +1 -0
  70. package/apps/portal/view/learn/MainContainer.mjs +4 -0
  71. package/apps/portal/view/learn/PageContainer.mjs +2 -0
  72. package/apps/portal/view/learn/PageSectionsContainer.mjs +3 -0
  73. package/apps/portal/view/learn/PageSectionsList.mjs +1 -0
  74. package/apps/portal/view/services/Component.mjs +1 -0
  75. package/apps/realworld/api/Base.mjs +1 -0
  76. package/apps/realworld/view/HeaderComponent.mjs +4 -0
  77. package/apps/realworld/view/HomeComponent.mjs +7 -0
  78. package/apps/realworld/view/MainContainer.mjs +2 -0
  79. package/apps/realworld/view/MainContainerController.mjs +2 -0
  80. package/apps/realworld/view/article/CommentComponent.mjs +3 -0
  81. package/apps/realworld/view/article/Component.mjs +17 -10
  82. package/apps/realworld/view/article/CreateCommentComponent.mjs +2 -0
  83. package/apps/realworld/view/article/CreateComponent.mjs +5 -0
  84. package/apps/realworld/view/article/PreviewComponent.mjs +9 -0
  85. package/apps/realworld/view/article/TagListComponent.mjs +2 -0
  86. package/apps/realworld/view/user/ProfileComponent.mjs +7 -0
  87. package/apps/realworld/view/user/SettingsComponent.mjs +5 -0
  88. package/apps/realworld/view/user/SignUpComponent.mjs +3 -0
  89. package/apps/realworld2/api/Base.mjs +1 -0
  90. package/apps/realworld2/view/FooterComponent.mjs +1 -0
  91. package/apps/realworld2/view/HeaderToolbar.mjs +3 -0
  92. package/apps/realworld2/view/HomeContainer.mjs +1 -0
  93. package/apps/realworld2/view/MainContainer.mjs +2 -0
  94. package/apps/realworld2/view/MainContainerController.mjs +1 -0
  95. package/apps/realworld2/view/article/Helix.mjs +1 -0
  96. package/apps/realworld2/view/article/PreviewComponent.mjs +9 -0
  97. package/apps/realworld2/view/article/PreviewList.mjs +1 -0
  98. package/apps/realworld2/view/article/TagListComponent.mjs +2 -0
  99. package/apps/route/view/CenterContainer.mjs +1 -0
  100. package/apps/route/view/MainView.mjs +1 -0
  101. package/apps/sharedcovid/childapps/sharedcovidchart/MainContainer.mjs +1 -0
  102. package/apps/sharedcovid/childapps/sharedcovidgallery/MainContainer.mjs +1 -0
  103. package/apps/sharedcovid/childapps/sharedcovidhelix/MainContainer.mjs +1 -0
  104. package/apps/sharedcovid/childapps/sharedcovidmap/MainContainer.mjs +1 -0
  105. package/apps/sharedcovid/view/FooterContainer.mjs +3 -0
  106. package/apps/sharedcovid/view/GalleryContainer.mjs +2 -0
  107. package/apps/sharedcovid/view/GalleryContainerController.mjs +1 -0
  108. package/apps/sharedcovid/view/HeaderContainer.mjs +2 -0
  109. package/apps/sharedcovid/view/HelixContainer.mjs +2 -0
  110. package/apps/sharedcovid/view/HelixContainerController.mjs +1 -0
  111. package/apps/sharedcovid/view/MainContainer.mjs +3 -0
  112. package/apps/sharedcovid/view/TableContainer.mjs +3 -0
  113. package/apps/sharedcovid/view/TableContainerController.mjs +1 -0
  114. package/apps/sharedcovid/view/WorldMapContainer.mjs +2 -0
  115. package/apps/sharedcovid/view/country/Gallery.mjs +3 -0
  116. package/apps/sharedcovid/view/country/Helix.mjs +8 -0
  117. package/apps/sharedcovid/view/country/HistoricalDataTable.mjs +1 -0
  118. package/apps/sharedcovid/view/country/Table.mjs +2 -0
  119. package/apps/sharedcovid/view/mapboxGl/Component.mjs +1 -0
  120. package/apps/sharedcovid/view/mapboxGl/Container.mjs +2 -0
  121. package/apps/shareddialog/childapps/shareddialog2/view/MainContainer.mjs +2 -0
  122. package/apps/shareddialog/view/DemoDialog.mjs +2 -0
  123. package/apps/shareddialog/view/MainContainer.mjs +2 -0
  124. package/apps/shareddialog/view/MainContainerController.mjs +1 -0
  125. package/buildScripts/addReactiveTags.mjs +191 -0
  126. package/buildScripts/checkReactiveTags.mjs +160 -0
  127. package/docs/app/store/Api.mjs +1 -0
  128. package/docs/app/store/Examples.mjs +1 -0
  129. package/docs/app/view/ApiTreeList.mjs +1 -0
  130. package/docs/app/view/ContentTabContainer.mjs +2 -0
  131. package/docs/app/view/ExamplesTreeList.mjs +2 -0
  132. package/docs/app/view/HeaderContainer.mjs +3 -0
  133. package/docs/app/view/MainContainer.mjs +5 -0
  134. package/docs/app/view/classdetails/HeaderComponent.mjs +1 -0
  135. package/docs/app/view/classdetails/MainContainer.mjs +3 -0
  136. package/docs/app/view/classdetails/MembersList.mjs +5 -0
  137. package/docs/app/view/classdetails/SourceViewComponent.mjs +2 -0
  138. package/examples/ConfigurationViewport.mjs +14 -8
  139. package/examples/button/effect/MainContainer.mjs +207 -0
  140. package/examples/button/effect/app.mjs +6 -0
  141. package/examples/button/effect/index.html +11 -0
  142. package/examples/button/effect/neo-config.json +6 -0
  143. package/examples/calendar/weekview/MainContainer.mjs +4 -0
  144. package/examples/component/coronaGallery/CountryGallery.mjs +2 -0
  145. package/examples/component/coronaGallery/CountryStore.mjs +1 -0
  146. package/examples/component/coronaGallery/Viewport.mjs +3 -0
  147. package/examples/component/coronaGallery/ViewportController.mjs +1 -0
  148. package/examples/component/coronaHelix/CountryHelix.mjs +7 -0
  149. package/examples/component/coronaHelix/MainContainer.mjs +1 -0
  150. package/examples/component/gallery/ImageStore.mjs +1 -0
  151. package/examples/component/helix/ImageStore.mjs +1 -0
  152. package/examples/component/helix/Viewport.mjs +3 -0
  153. package/examples/component/helix/ViewportController.mjs +1 -0
  154. package/examples/component/multiWindowCoronaGallery/childapp/Viewport.mjs +1 -0
  155. package/examples/component/multiWindowHelix/childapp/Viewport.mjs +1 -0
  156. package/examples/component/wrapper/googleMaps/MapComponent.mjs +2 -0
  157. package/examples/core/config/MainContainer.mjs +2 -0
  158. package/examples/dialog/DemoDialog.mjs +2 -0
  159. package/examples/dialog/MainContainer.mjs +1 -0
  160. package/examples/form/field/color/MainStore.mjs +1 -0
  161. package/examples/functional/defineComponent/Component.mjs +18 -0
  162. package/examples/functional/defineComponent/MainContainer.mjs +41 -0
  163. package/examples/functional/defineComponent/app.mjs +6 -0
  164. package/examples/functional/defineComponent/index.html +11 -0
  165. package/examples/functional/defineComponent/neo-config.json +6 -0
  166. package/examples/functional/hostComponent/Component.mjs +32 -0
  167. package/examples/functional/hostComponent/MainContainer.mjs +48 -0
  168. package/examples/functional/hostComponent/app.mjs +6 -0
  169. package/examples/functional/hostComponent/index.html +11 -0
  170. package/examples/functional/hostComponent/neo-config.json +6 -0
  171. package/examples/grid/animatedRowSorting/Viewport.mjs +1 -1
  172. package/examples/grid/bigData/ControlsContainer.mjs +3 -0
  173. package/examples/grid/bigData/GridContainer.mjs +4 -2
  174. package/examples/grid/bigData/MainContainer.mjs +2 -0
  175. package/examples/grid/bigData/MainModel.mjs +1 -0
  176. package/examples/grid/bigData/MainStore.mjs +3 -0
  177. package/examples/grid/cellEditing/MainContainer.mjs +1 -1
  178. package/examples/grid/container/MainContainer.mjs +1 -1
  179. package/examples/grid/covid/GridContainer.mjs +3 -0
  180. package/examples/grid/covid/MainContainer.mjs +2 -0
  181. package/examples/grid/covid/Store.mjs +1 -0
  182. package/examples/grid/nestedRecordFields/EditUserDialog.mjs +3 -0
  183. package/examples/grid/nestedRecordFields/Viewport.mjs +3 -1
  184. package/examples/list/animate/List.mjs +4 -0
  185. package/examples/list/animate/MainContainer.mjs +2 -0
  186. package/examples/list/circle/MainStore.mjs +1 -0
  187. package/examples/list/color/MainStore.mjs +1 -0
  188. package/examples/preloadingAssets/view/MainContainer.mjs +2 -0
  189. package/examples/stateProvider/advanced/MainContainer.mjs +1 -0
  190. package/examples/stateProvider/dialog/EditUserDialog.mjs +2 -0
  191. package/examples/stateProvider/dialog/MainContainer.mjs +1 -0
  192. package/examples/stateProvider/extendedClass/MainContainer.mjs +2 -0
  193. package/examples/stateProvider/inline/MainContainer.mjs +1 -0
  194. package/examples/stateProvider/inlineNoStateProvider/MainContainer.mjs +1 -0
  195. package/examples/stateProvider/inlineNoStateProvider/MainContainerController.mjs +2 -0
  196. package/examples/stateProvider/multiWindow/EditUserDialog.mjs +3 -0
  197. package/examples/stateProvider/multiWindow/MainContainer.mjs +1 -0
  198. package/examples/stateProvider/multiWindow/Viewport.mjs +1 -0
  199. package/examples/stateProvider/nestedData/MainContainer.mjs +1 -0
  200. package/examples/stateProvider/table/MainContainer.mjs +1 -0
  201. package/examples/table/covid/MainContainer.mjs +2 -0
  202. package/examples/table/covid/Store.mjs +1 -0
  203. package/examples/table/covid/TableContainer.mjs +3 -0
  204. package/examples/table/nestedRecordFields/EditUserDialog.mjs +3 -0
  205. package/examples/table/nestedRecordFields/Viewport.mjs +1 -0
  206. package/examples/todoList/version1/MainComponent.mjs +1 -1
  207. package/examples/toolbar/breadcrumb/view/MainContainer.mjs +2 -0
  208. package/examples/toolbar/paging/store/Users.mjs +1 -0
  209. package/examples/toolbar/paging/view/AddUserDialog.mjs +3 -0
  210. package/examples/toolbar/paging/view/MainContainer.mjs +3 -0
  211. package/examples/treeAccordion/MainContainer.mjs +2 -2
  212. package/examples/worker/task/MainContainer.mjs +1 -0
  213. package/learn/Glossary.md +1 -0
  214. package/learn/UsingTheseTopics.md +1 -0
  215. package/learn/benefits/ConfigSystem.md +2 -0
  216. package/learn/benefits/Effort.md +1 -0
  217. package/learn/benefits/Features.md +1 -0
  218. package/learn/benefits/FormsEngine.md +1 -0
  219. package/learn/benefits/FourEnvironments.md +2 -0
  220. package/learn/benefits/Introduction.md +2 -0
  221. package/learn/benefits/MultiWindow.md +3 -1
  222. package/learn/benefits/OffTheMainThread.md +2 -0
  223. package/learn/benefits/Quick.md +2 -0
  224. package/learn/benefits/RPCLayer.md +2 -0
  225. package/learn/benefits/Speed.md +2 -0
  226. package/learn/comparisons/NeoVsAngular.md +90 -0
  227. package/learn/comparisons/NeoVsExtJs.md +178 -0
  228. package/learn/comparisons/NeoVsNextJs.md +124 -0
  229. package/learn/comparisons/NeoVsReact.md +95 -0
  230. package/learn/comparisons/NeoVsSolid.md +78 -0
  231. package/learn/comparisons/NeoVsVue.md +92 -0
  232. package/learn/comparisons/Overview.md +46 -0
  233. package/learn/gettingstarted/ComponentModels.md +2 -0
  234. package/learn/gettingstarted/Config.md +2 -0
  235. package/learn/gettingstarted/DescribingTheUI.md +2 -0
  236. package/learn/gettingstarted/Events.md +2 -0
  237. package/learn/gettingstarted/Extending.md +2 -0
  238. package/learn/gettingstarted/References.md +2 -0
  239. package/learn/gettingstarted/Setup.md +3 -2
  240. package/learn/gettingstarted/Workspaces.md +2 -0
  241. package/learn/guides/datahandling/Collections.md +1 -0
  242. package/learn/guides/datahandling/Records.md +1 -0
  243. package/learn/guides/datahandling/StateProviders.md +131 -16
  244. package/learn/guides/datahandling/Tables.md +1 -1
  245. package/learn/guides/fundamentals/ConfigSystemDeepDive.md +1 -0
  246. package/learn/guides/fundamentals/DeclarativeComponentTreesVsImperativeVdom.md +2 -0
  247. package/learn/guides/fundamentals/DeclarativeVDOMWithEffects.md +168 -0
  248. package/learn/guides/fundamentals/ExtendingNeoClasses.md +1 -0
  249. package/learn/guides/fundamentals/InstanceLifecycle.md +3 -1
  250. package/learn/guides/fundamentals/MainThreadAddons.md +2 -0
  251. package/learn/guides/specificfeatures/Mixins.md +3 -1
  252. package/learn/guides/specificfeatures/MultiWindow.md +3 -1
  253. package/learn/guides/specificfeatures/PortalApp.md +2 -0
  254. package/learn/guides/uibuildingblocks/ComponentsAndContainers.md +2 -0
  255. package/learn/guides/uibuildingblocks/CustomComponents.md +2 -0
  256. package/learn/guides/uibuildingblocks/Layouts.md +2 -0
  257. package/learn/guides/uibuildingblocks/WorkingWithVDom.md +2 -0
  258. package/learn/guides/userinteraction/Forms.md +2 -0
  259. package/learn/guides/userinteraction/events/CustomEvents.md +2 -1
  260. package/learn/guides/userinteraction/events/DomEvents.md +2 -0
  261. package/learn/javascript/ClassFeatures.md +4 -3
  262. package/learn/javascript/Classes.md +10 -13
  263. package/learn/javascript/Overrides.md +10 -6
  264. package/learn/javascript/Super.md +12 -8
  265. package/learn/tree.json +71 -63
  266. package/learn/tutorials/Earthquakes.md +2 -0
  267. package/learn/tutorials/RSP.md +3 -1
  268. package/learn/tutorials/TodoList.md +103 -7
  269. package/package.json +6 -4
  270. package/resources/scss/src/apps/email/ComposeView.scss +16 -0
  271. package/resources/scss/src/apps/email/MainView.scss +5 -0
  272. package/resources/scss/src/apps/portal/learn/ContentComponent.scss +5 -4
  273. package/src/DefaultConfig.mjs +12 -2
  274. package/src/Main.mjs +1 -0
  275. package/src/Neo.mjs +377 -178
  276. package/src/Xhr.mjs +1 -0
  277. package/src/button/Base.mjs +13 -0
  278. package/src/button/Effect.mjs +449 -0
  279. package/src/button/Split.mjs +2 -0
  280. package/src/calendar/store/Calendars.mjs +1 -0
  281. package/src/calendar/store/Colors.mjs +1 -0
  282. package/src/calendar/store/Events.mjs +1 -0
  283. package/src/calendar/view/DayComponent.mjs +2 -0
  284. package/src/calendar/view/EditEventContainer.mjs +4 -1
  285. package/src/calendar/view/MainContainer.mjs +13 -0
  286. package/src/calendar/view/MainContainerStateProvider.mjs +14 -28
  287. package/src/calendar/view/SettingsContainer.mjs +1 -0
  288. package/src/calendar/view/YearComponent.mjs +16 -0
  289. package/src/calendar/view/calendars/ColorsList.mjs +2 -0
  290. package/src/calendar/view/calendars/Container.mjs +2 -0
  291. package/src/calendar/view/calendars/EditContainer.mjs +1 -0
  292. package/src/calendar/view/month/Component.mjs +11 -0
  293. package/src/calendar/view/settings/GeneralContainer.mjs +1 -0
  294. package/src/calendar/view/settings/MonthContainer.mjs +1 -0
  295. package/src/calendar/view/settings/WeekContainer.mjs +1 -0
  296. package/src/calendar/view/settings/YearContainer.mjs +1 -0
  297. package/src/calendar/view/week/Component.mjs +15 -1
  298. package/src/calendar/view/week/TimeAxisComponent.mjs +4 -0
  299. package/src/code/LivePreview.mjs +51 -23
  300. package/src/collection/Base.mjs +14 -12
  301. package/src/collection/Filter.mjs +6 -0
  302. package/src/collection/Sorter.mjs +3 -0
  303. package/src/component/Base.mjs +156 -802
  304. package/src/component/Canvas.mjs +1 -0
  305. package/src/component/Chip.mjs +4 -0
  306. package/src/component/Circle.mjs +14 -0
  307. package/src/component/Clock.mjs +4 -0
  308. package/src/component/DateSelector.mjs +12 -0
  309. package/src/component/Gallery.mjs +11 -0
  310. package/src/component/Helix.mjs +24 -0
  311. package/src/component/Label.mjs +1 -0
  312. package/src/component/Legend.mjs +3 -0
  313. package/src/component/MagicMoveText.mjs +4 -0
  314. package/src/component/Progress.mjs +3 -0
  315. package/src/component/Splitter.mjs +3 -0
  316. package/src/component/StatusBadge.mjs +6 -0
  317. package/src/component/Timer.mjs +4 -0
  318. package/src/component/Toast.mjs +6 -0
  319. package/src/component/Video.mjs +1 -0
  320. package/src/component/mwc/Button.mjs +7 -0
  321. package/src/component/mwc/TextField.mjs +9 -0
  322. package/src/component/wrapper/AmChart.mjs +2 -0
  323. package/src/component/wrapper/GoogleMaps.mjs +3 -0
  324. package/src/component/wrapper/MapboxGL.mjs +5 -0
  325. package/src/component/wrapper/MonacoEditor.mjs +12 -0
  326. package/src/container/Accordion.mjs +2 -0
  327. package/src/container/Base.mjs +34 -26
  328. package/src/container/Panel.mjs +1 -0
  329. package/src/container/Viewport.mjs +1 -0
  330. package/src/controller/Application.mjs +1 -0
  331. package/src/controller/Base.mjs +1 -0
  332. package/src/controller/Component.mjs +1 -0
  333. package/src/core/Base.mjs +193 -22
  334. package/src/core/Compare.mjs +4 -7
  335. package/src/core/Config.mjs +137 -33
  336. package/src/core/Effect.mjs +193 -0
  337. package/src/core/EffectBatchManager.mjs +67 -0
  338. package/src/core/EffectManager.mjs +60 -0
  339. package/src/core/IdGenerator.mjs +13 -44
  340. package/src/data/Model.mjs +2 -0
  341. package/src/data/Store.mjs +7 -0
  342. package/src/data/connection/WebSocket.mjs +2 -0
  343. package/src/date/DayViewComponent.mjs +2 -0
  344. package/src/date/SelectorContainer.mjs +14 -0
  345. package/src/dialog/Base.mjs +8 -0
  346. package/src/draggable/DragZone.mjs +5 -0
  347. package/src/draggable/tree/DragZone.mjs +1 -0
  348. package/src/filter/BooleanContainer.mjs +2 -0
  349. package/src/filter/NumberContainer.mjs +3 -0
  350. package/src/filter/ToggleOperatorsButton.mjs +2 -0
  351. package/src/form/Fieldset.mjs +6 -0
  352. package/src/form/field/Base.mjs +7 -0
  353. package/src/form/field/CheckBox.mjs +18 -0
  354. package/src/form/field/Chip.mjs +1 -0
  355. package/src/form/field/ComboBox.mjs +8 -0
  356. package/src/form/field/Country.mjs +1 -0
  357. package/src/form/field/Currency.mjs +2 -0
  358. package/src/form/field/Date.mjs +4 -0
  359. package/src/form/field/Display.mjs +1 -0
  360. package/src/form/field/Email.mjs +1 -0
  361. package/src/form/field/FileUpload.mjs +7 -0
  362. package/src/form/field/Hidden.mjs +1 -0
  363. package/src/form/field/Number.mjs +7 -0
  364. package/src/form/field/Password.mjs +1 -0
  365. package/src/form/field/Phone.mjs +3 -0
  366. package/src/form/field/Picker.mjs +2 -0
  367. package/src/form/field/Radio.mjs +1 -0
  368. package/src/form/field/Range.mjs +3 -0
  369. package/src/form/field/Search.mjs +2 -0
  370. package/src/form/field/Text.mjs +32 -0
  371. package/src/form/field/TextArea.mjs +7 -0
  372. package/src/form/field/Time.mjs +6 -0
  373. package/src/form/field/Url.mjs +3 -0
  374. package/src/form/field/ZipCode.mjs +2 -0
  375. package/src/form/field/trigger/Base.mjs +3 -0
  376. package/src/form/field/trigger/Clear.mjs +2 -0
  377. package/src/form/field/trigger/CopyToClipboard.mjs +2 -0
  378. package/src/form/field/trigger/Date.mjs +1 -0
  379. package/src/form/field/trigger/Picker.mjs +1 -0
  380. package/src/form/field/trigger/Search.mjs +1 -0
  381. package/src/form/field/trigger/SpinDown.mjs +2 -0
  382. package/src/form/field/trigger/SpinUp.mjs +1 -0
  383. package/src/form/field/trigger/Time.mjs +2 -0
  384. package/src/functional/_export.mjs +6 -0
  385. package/src/functional/component/Base.mjs +499 -0
  386. package/src/functional/defineComponent.mjs +102 -0
  387. package/src/functional/useConfig.mjs +52 -0
  388. package/src/functional/useEvent.mjs +43 -0
  389. package/src/grid/Body.mjs +20 -1
  390. package/src/grid/Container.mjs +57 -63
  391. package/src/grid/ScrollManager.mjs +2 -0
  392. package/src/grid/VerticalScrollbar.mjs +2 -0
  393. package/src/grid/column/Base.mjs +2 -0
  394. package/src/grid/column/Component.mjs +1 -1
  395. package/src/grid/header/Button.mjs +7 -0
  396. package/src/grid/header/Toolbar.mjs +6 -0
  397. package/src/grid/plugin/AnimateRows.mjs +2 -0
  398. package/src/layout/Base.mjs +3 -0
  399. package/src/layout/Card.mjs +1 -0
  400. package/src/layout/Cube.mjs +11 -1
  401. package/src/layout/Fit.mjs +1 -0
  402. package/src/layout/Flexbox.mjs +7 -0
  403. package/src/layout/Form.mjs +2 -0
  404. package/src/layout/Grid.mjs +1 -0
  405. package/src/layout/HBox.mjs +1 -0
  406. package/src/layout/VBox.mjs +1 -0
  407. package/src/list/Base.mjs +13 -0
  408. package/src/list/Chip.mjs +1 -0
  409. package/src/list/Circle.mjs +2 -0
  410. package/src/list/Color.mjs +1 -0
  411. package/src/list/plugin/Animate.mjs +2 -0
  412. package/src/main/DeltaUpdates.mjs +1 -0
  413. package/src/main/DomEvents.mjs +2 -0
  414. package/src/main/addon/CloneNode.mjs +1 -0
  415. package/src/main/addon/Cookie.mjs +1 -0
  416. package/src/main/addon/GoogleMaps.mjs +1 -0
  417. package/src/main/addon/LocalStorage.mjs +1 -0
  418. package/src/main/addon/MapboxGL.mjs +1 -0
  419. package/src/main/addon/Markdown.mjs +1 -0
  420. package/src/main/addon/Navigator.mjs +1 -0
  421. package/src/main/addon/Popover.mjs +1 -0
  422. package/src/main/addon/Stylesheet.mjs +1 -0
  423. package/src/main/addon/WindowPosition.mjs +1 -0
  424. package/src/manager/Component.mjs +0 -71
  425. package/src/manager/VDomUpdate.mjs +235 -0
  426. package/src/menu/List.mjs +6 -0
  427. package/src/menu/Model.mjs +1 -0
  428. package/src/menu/Panel.mjs +3 -0
  429. package/src/menu/Store.mjs +1 -0
  430. package/src/mixin/DomEvents.mjs +130 -0
  431. package/src/mixin/VdomLifecycle.mjs +667 -0
  432. package/src/plugin/Base.mjs +1 -0
  433. package/src/plugin/Resizable.mjs +2 -0
  434. package/src/selection/Model.mjs +15 -18
  435. package/src/selection/grid/BaseModel.mjs +1 -0
  436. package/src/sitemap/Component.mjs +1 -0
  437. package/src/state/Provider.mjs +376 -457
  438. package/src/state/createHierarchicalDataProxy.mjs +138 -0
  439. package/src/tab/Container.mjs +6 -0
  440. package/src/tab/Strip.mjs +1 -0
  441. package/src/tab/header/Button.mjs +2 -0
  442. package/src/tab/header/EffectButton.mjs +77 -0
  443. package/src/tab/header/Toolbar.mjs +1 -0
  444. package/src/table/Body.mjs +3 -0
  445. package/src/table/Container.mjs +10 -0
  446. package/src/table/header/Button.mjs +8 -0
  447. package/src/table/header/Toolbar.mjs +5 -0
  448. package/src/table/plugin/CellEditing.mjs +1 -0
  449. package/src/toolbar/Base.mjs +4 -0
  450. package/src/toolbar/Breadcrumb.mjs +3 -0
  451. package/src/toolbar/Paging.mjs +5 -0
  452. package/src/tooltip/Base.mjs +2 -0
  453. package/src/tree/List.mjs +3 -0
  454. package/src/util/HashHistory.mjs +1 -0
  455. package/src/util/KeyNavigation.mjs +2 -0
  456. package/src/util/Matrix.mjs +1 -0
  457. package/src/util/VDom.mjs +7 -1
  458. package/src/util/VNode.mjs +7 -1
  459. package/src/util/vdom/TreeBuilder.mjs +129 -0
  460. package/src/vdom/Helper.mjs +44 -33
  461. package/src/vdom/VNode.mjs +5 -7
  462. package/src/worker/App.mjs +1 -5
  463. package/src/worker/Base.mjs +2 -0
  464. package/src/worker/Manager.mjs +2 -0
  465. package/src/worker/ServiceBase.mjs +6 -1
  466. package/test/siesta/siesta.js +36 -1
  467. package/test/siesta/tests/CollectionBase.mjs +10 -10
  468. package/test/siesta/tests/VdomCalendar.mjs +13 -9
  469. package/test/siesta/tests/VdomHelper.mjs +22 -59
  470. package/test/siesta/tests/config/AfterSetConfig.mjs +100 -0
  471. package/test/siesta/tests/{ReactiveConfigs.mjs → config/Basic.mjs} +58 -21
  472. package/test/siesta/tests/config/CircularDependencies.mjs +166 -0
  473. package/test/siesta/tests/config/CustomFunctions.mjs +69 -0
  474. package/test/siesta/tests/config/Hierarchy.mjs +94 -0
  475. package/test/siesta/tests/config/MemoryLeak.mjs +92 -0
  476. package/test/siesta/tests/config/MultiLevelHierarchy.mjs +85 -0
  477. package/test/siesta/tests/core/Effect.mjs +127 -0
  478. package/test/siesta/tests/core/EffectBatching.mjs +310 -0
  479. package/test/siesta/tests/neo/MixinStaticConfig.mjs +138 -0
  480. package/test/siesta/tests/state/Provider.mjs +537 -0
  481. package/test/siesta/tests/state/ProviderNestedDataConfigs.mjs +255 -0
  482. package/test/siesta/tests/state/createHierarchicalDataProxy.mjs +204 -0
  483. package/test/siesta/tests/vdom/VdomAsymmetricUpdates.mjs +366 -0
  484. package/test/siesta/tests/vdom/VdomRealWorldUpdates.mjs +249 -0
  485. package/learn/javascript/NewNode.md +0 -31
@@ -0,0 +1,667 @@
1
+ import Base from '../core/Base.mjs';
2
+ import ComponentManager from '../manager/Component.mjs';
3
+ import NeoArray from '../util/Array.mjs';
4
+ import TreeBuilder from '../util/vdom/TreeBuilder.mjs';
5
+ import VDomUtil from '../util/VDom.mjs';
6
+ import VDomUpdate from '../manager/VDomUpdate.mjs';
7
+ import VNodeUtil from '../util/VNode.mjs';
8
+ import {isDescriptor} from '../core/ConfigSymbols.mjs';
9
+
10
+ const {currentWorker} = Neo;
11
+
12
+ /**
13
+ * @class Neo.mixin.VdomLifecycle
14
+ * @extends Neo.core.Base
15
+ */
16
+ class VdomLifecycle extends Base {
17
+ static config = {
18
+ /**
19
+ * @member {String} className='Neo.mixin.VdomLifecycle'
20
+ * @protected
21
+ */
22
+ className: 'Neo.mixin.VdomLifecycle',
23
+ /**
24
+ * True automatically mounts a component after being rendered.
25
+ * Use this for the top level component of your app.
26
+ * @member {Boolean} autoMount=false
27
+ * @tutorial 02_ClassSystem
28
+ */
29
+ autoMount: false,
30
+ /**
31
+ * True automatically renders a component after being created inside the init call.
32
+ * Use this for the top level component of your app.
33
+ * @member {Boolean} autoRender=false
34
+ * @see {@link Neo.component.Base#init init}
35
+ * @tutorial 02_ClassSystem
36
+ */
37
+ autoRender: false,
38
+ /**
39
+ * Internal flag for vdom changes after a component got unmounted
40
+ * (delta updates can no longer get applied & a new render call is required before re-mounting)
41
+ * @member {Boolean} hasUnmountedVdomChanges_=false
42
+ * @protected
43
+ * @reactive
44
+ */
45
+ hasUnmountedVdomChanges_: false,
46
+ /**
47
+ * Internal flag which will get set to true while an update request (worker messages) is in progress
48
+ * @member {Boolean} isVdomUpdating_=false
49
+ * @protected
50
+ * @reactive
51
+ */
52
+ isVdomUpdating_: false,
53
+ /**
54
+ * True in case the component is mounted to the DOM
55
+ * @member {Boolean} mounted_=false
56
+ * @protected
57
+ * @reactive
58
+ */
59
+ mounted_: false,
60
+ /**
61
+ * Internal flag which will get set to true in case an update call arrives while another update is running
62
+ * @member {Boolean} needsVdomUpdate_=false
63
+ * @protected
64
+ * @reactive
65
+ */
66
+ needsVdomUpdate_: false,
67
+ /**
68
+ * True in case the component is rendering the vnode
69
+ * @member {Boolean} rendering_=false
70
+ * @protected
71
+ * @reactive
72
+ */
73
+ rendering_: false,
74
+ /**
75
+ * Set this to true for bulk updates. Ensure to set it back to false afterwards.
76
+ * Internally the value will get saved as a number to ensure that child methods won't stop the silent mode too early.
77
+ * @member {Boolean} silentVdomUpdate_=false
78
+ * @reactive
79
+ */
80
+ silentVdomUpdate_: false,
81
+ /**
82
+ * Defines the depth of the vdom tree for the next update cycle.
83
+ * - The value 1 will only send the current vdom structure as it is
84
+ * - The value of 2 will include the vdom of direct children
85
+ * - The value of 3 will include the vdom of grandchildren
86
+ * - The value of -1 will include the full tree of any depth
87
+ * @member {Number} updateDepth_=1
88
+ * @reactive
89
+ */
90
+ updateDepth_: 1,
91
+ /**
92
+ * The component vnode tree. Available after the component got rendered.
93
+ * @member {Object} vnode_=={[isDescriptor]: true, value: null, isEqual: (a, b) => a === b,}
94
+ * @protected
95
+ * @reactive
96
+ */
97
+ vnode_: {
98
+ [isDescriptor]: true,
99
+ clone : 'none',
100
+ cloneOnGet : 'none',
101
+ isEqual : (a, b) => a === b, // vnode trees can be huge, and will get compared by the vdom worker.
102
+ value : null,
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Triggered after the hasUnmountedVdomChanges config got changed
108
+ * @param {Boolean} value
109
+ * @param {Boolean} oldValue
110
+ * @protected
111
+ */
112
+ afterSetHasUnmountedVdomChanges(value, oldValue) {
113
+ if (value || (!value && oldValue)) {
114
+ let parentIds = ComponentManager.getParentIds(this),
115
+ i = 0,
116
+ len = parentIds.length,
117
+ parent;
118
+
119
+ for (; i < len; i++) {
120
+ parent = Neo.getComponent(parentIds[i]);
121
+
122
+ if (parent) {
123
+ parent._hasUnmountedVdomChanges = value // silent update
124
+ }
125
+ }
126
+ }
127
+ }
128
+
129
+ /**
130
+ * Triggered after the vdom pseudo-config got changed
131
+ * @param {Object} value
132
+ * @param {Object|null} oldValue
133
+ * @protected
134
+ */
135
+ afterSetVdom(value, oldValue) {
136
+ this.updateVdom()
137
+ }
138
+
139
+ /**
140
+ * Triggered after the vnode config got changed
141
+ * @param {Object} value
142
+ * @param {Object|null} oldValue
143
+ * @protected
144
+ */
145
+ afterSetVnode(value, oldValue) {
146
+ oldValue !== undefined && this.syncVnodeTree()
147
+ }
148
+
149
+ /**
150
+ * Creates a lightweight, serializable placeholder for this component, intended for injection
151
+ * into the VDOM of other components.
152
+ *
153
+ * This is the **only recommended way** to nest a component within another component's VDOM tree.
154
+ * Directly embedding one component's full `vdom` object into another's is an anti-pattern
155
+ * that violates the principle of scoped VDOM, leading to unpredictable rendering behavior
156
+ * and making updates inefficient.
157
+ *
158
+ * At its core, the returned object contains a `componentId` that uniquely identifies the
159
+ * component instance. In cases where a component's structure is wrapped by another element
160
+ * (e.g., a Button in a Table Header being wrapped by a `<td>`), the reference will also
161
+ * include the wrapper's `id`. This happens when a component uses `getVdomRoot()` to
162
+ * designate a deeper node as its logical root, causing the component's `id` and its
163
+ * VDOM root's `id` to differ. The framework uses this dual-ID reference to correctly
164
+ * assemble the final VDOM tree.
165
+ *
166
+ * @returns {{componentId: String, id: String|undefined}} The VDOM reference object.
167
+ */
168
+ createVdomReference() {
169
+ let me = this,
170
+ reference = {componentId: me.id},
171
+ vdomId = me.vdom.id;
172
+
173
+ if (vdomId && me.id !== vdomId) {
174
+ reference.id = vdomId
175
+ }
176
+
177
+ return reference
178
+ }
179
+
180
+ /**
181
+ * Internal method to send update requests to the vdom worker
182
+ * @param {function} [resolve] used by promiseUpdate()
183
+ * @param {function} [reject] used by promiseUpdate()
184
+ * @private
185
+ */
186
+ async executeVdomUpdate(resolve, reject) {
187
+ let me = this;
188
+
189
+ resolve && VDomUpdate.addPromiseCallback(me.id, resolve);
190
+
191
+ me.isVdomUpdating = true;
192
+ // Centralize in-flight state
193
+ VDomUpdate.registerInFlightUpdate(me.id, me.updateDepth);
194
+
195
+ try {
196
+ const
197
+ {vdom, vnode} = me,
198
+ mergedChildIds = VDomUpdate.getMergedChildIds(me.id),
199
+ opts = {
200
+ vdom : TreeBuilder.getVdomTree(vdom, me.updateDepth, mergedChildIds),
201
+ vnode: TreeBuilder.getVnodeTree(vnode, me.updateDepth, mergedChildIds)
202
+ };
203
+
204
+ if (currentWorker?.isSharedWorker) {
205
+ opts.appName = me.appName;
206
+ opts.windowId = me.windowId;
207
+ }
208
+
209
+ // We cannot set the config directly => it could already be false,
210
+ // and we still want to pass it further into subtrees
211
+ me._needsVdomUpdate = false;
212
+ me.afterSetNeedsVdomUpdate?.(false, true);
213
+
214
+ // Reset the updateDepth to the default value for the next update cycle
215
+ me._updateDepth = me.constructor.config.updateDepth;
216
+
217
+ const data = await Promise.resolve(Neo.vdom.Helper.update(opts));
218
+
219
+ // Component could be destroyed while the update is running
220
+ if (me.id) {
221
+ // It is crucial to delegate the vnode tree before resolving the cycle
222
+ me.vnode = data.vnode;
223
+
224
+ // When not using a VdomWorker, we need to apply the deltas inside the App worker
225
+ if (!Neo.config.useVdomWorker && data.deltas?.length > 0) {
226
+ await Neo.applyDeltas(me.appName, data.deltas)
227
+ }
228
+
229
+ me.isVdomUpdating = false;
230
+ me.resolveVdomUpdate(data)
231
+ }
232
+ } catch (err) {
233
+ me.isVdomUpdating = false;
234
+ // Ensure state is cleaned up on error
235
+ VDomUpdate.unregisterInFlightUpdate(me.id);
236
+ reject?.(err)
237
+ }
238
+ }
239
+
240
+ /**
241
+ * Honors different item roots for mount / render OPs
242
+ * @returns {String}
243
+ */
244
+ getMountedParentId() {
245
+ let parentId = this.parentId,
246
+ parent = Neo.getComponent(parentId),
247
+ itemsRoot = parent?.getVdomItemsRoot?.();
248
+
249
+ return itemsRoot ? itemsRoot.id : parentId
250
+ }
251
+
252
+ /**
253
+ * Calculate the real parentIndex inside the DOM
254
+ * @returns {Number|undefined}
255
+ */
256
+ getMountedParentIndex() {
257
+ let parent = this.parent,
258
+ items = parent?.items || [],
259
+ i = 0,
260
+ index = 0,
261
+ len = items.length,
262
+ item;
263
+
264
+ for (; i < len; i++) {
265
+ item = items[i];
266
+
267
+ if (item === this) {
268
+ return index
269
+ }
270
+
271
+ if (!item.hidden && item.hideMode === 'removeDom') {
272
+ index++
273
+ }
274
+ }
275
+ }
276
+
277
+ /**
278
+ * Search a vdom child node by id for a given vdom tree
279
+ * @param {String} id
280
+ * @param {Object} vdom=this.vdom
281
+ * @returns {Object}
282
+ */
283
+ getVdomChild(id, vdom=this.vdom) {
284
+ return VDomUtil.find(vdom, id)?.vdom
285
+ }
286
+
287
+ /**
288
+ * Specify a different vdom root if needed to apply the top level style attributes on a different level.
289
+ * Make sure to use getVnodeRoot() as well, to keep the vdom & vnode trees in sync.
290
+ * @returns {Object} The new vdom root
291
+ */
292
+ getVdomRoot() {
293
+ return this.vdom
294
+ }
295
+
296
+ /**
297
+ * Specify a different vnode root if needed to apply the top level style attributes on a different level.
298
+ * Make sure to use getVdomRoot() as well, to keep the vdom & vnode trees in sync.
299
+ * @returns {Object} The new vnode root
300
+ */
301
+ getVnodeRoot() {
302
+ return this.vnode
303
+ }
304
+
305
+ /**
306
+ * Checks if a given updateDepth & distance would result in an update collision
307
+ * @param {Number} updateDepth
308
+ * @param {Number} distance
309
+ * @returns {Boolean}
310
+ */
311
+ hasUpdateCollision(updateDepth, distance) {
312
+ return updateDepth === -1 ? true : distance < updateDepth
313
+ }
314
+
315
+ /**
316
+ * Checks for vdom updates inside the parent chain and if found.
317
+ * Registers the component for a vdom update once done.
318
+ * @param {String} parentId=this.parentId
319
+ * @param {Function} [resolve] Gets passed by updateVdom()
320
+ * @param {Number} distance=1 Distance inside the component tree
321
+ * @returns {Boolean}
322
+ */
323
+ isParentUpdating(parentId=this.parentId, resolve, distance=1) {
324
+ if (parentId !== 'document.body') {
325
+ let me = this,
326
+ parent = Neo.getComponent(parentId);
327
+
328
+ if (parent) {
329
+ if (parent.isVdomUpdating) {
330
+ // Get the in-flight update depth from the central manager
331
+ const parentUpdateDepth = VDomUpdate.getInFlightUpdateDepth(parent.id);
332
+
333
+ if (me.hasUpdateCollision(parentUpdateDepth, distance)) {
334
+ if (Neo.config.logVdomUpdateCollisions) {
335
+ console.warn('vdom parent update conflict with:', parent, 'for:', me)
336
+ }
337
+
338
+ VDomUpdate.registerPostUpdate(parent.id, me.id, resolve);
339
+ return true
340
+ }
341
+
342
+ // If an update is running and does not have a collision, we do not need to check further parents
343
+ return false
344
+ }
345
+
346
+ return me.isParentUpdating(parent.parentId, resolve, distance+1)
347
+ }
348
+ }
349
+
350
+ return false
351
+ }
352
+
353
+ /**
354
+ * Checks the needsVdomUpdate config inside the parent tree
355
+ * @param {String} parentId=this.parentId
356
+ * @param {Function} [resolve] gets passed by updateVdom()
357
+ * @param {Number} distance=1 Distance inside the component tree
358
+ * @returns {Boolean}
359
+ */
360
+ mergeIntoParentUpdate(parentId=this.parentId, distance=1) {
361
+ if (parentId !== 'document.body') {
362
+ let me = this,
363
+ parent = Neo.getComponent(parentId);
364
+
365
+ if (parent) {
366
+ // We are checking for parent.updateDepth, since we care about the depth of the next update cycle
367
+ if (parent.needsVdomUpdate && me.hasUpdateCollision(parent.updateDepth, distance)) {
368
+ VDomUpdate.registerMerged(parent.id, me.id, me.updateDepth, distance);
369
+ return true
370
+ }
371
+
372
+ return me.mergeIntoParentUpdate(parent.parentId, distance+1)
373
+ }
374
+ }
375
+
376
+ return false
377
+ }
378
+
379
+ /**
380
+ * Gets called from the render() promise success handler
381
+ * @param {Object} vnode
382
+ * @param {Boolean} autoMount Mount the DOM after the vnode got created
383
+ * @protected
384
+ */
385
+ onRender(vnode, autoMount) {
386
+ let me = this,
387
+ {app} = me;
388
+
389
+ me.rendering = false;
390
+
391
+ // if app is a check to see if the Component got destroyed while rendering => before onRender got triggered
392
+ if (app) {
393
+ if (!app.rendered) {
394
+ app.rendering = false;
395
+ app.rendered = true;
396
+ app.fire('render')
397
+ }
398
+
399
+ me.vnode = vnode;
400
+
401
+ let childIds = ComponentManager.getChildIds(vnode),
402
+ i = 0,
403
+ len = childIds.length,
404
+ child;
405
+
406
+ for (; i < len; i++) {
407
+ child = Neo.getComponent(childIds[i]);
408
+
409
+ if (child) {
410
+ child.rendered = true
411
+ }
412
+ }
413
+
414
+ me._rendered = true; // silent update
415
+ me.fire('rendered', me.id);
416
+
417
+ if (autoMount) {
418
+ me.mounted = true;
419
+
420
+ if (!app.mounted) {
421
+ app.mounted = true;
422
+ app.fire('mounted')
423
+ }
424
+ }
425
+ }
426
+ }
427
+
428
+ /**
429
+ * Promise based vdom update
430
+ * @returns {Promise<any>}
431
+ */
432
+ promiseUpdate() {
433
+ return new Promise((resolve, reject) => {
434
+ this.updateVdom(resolve, reject)
435
+ })
436
+ }
437
+
438
+ /**
439
+ * Creates the vnode tree for this component and mounts the component in case
440
+ * - you pass true for the mount param
441
+ * - or the autoMount config is set to true
442
+ * @param {Boolean} [mount] Mount the DOM after the vnode got created
443
+ */
444
+ async render(mount) {
445
+ let me = this,
446
+ autoMount = mount || me.autoMount,
447
+ {app} = me,
448
+ {allowVdomUpdatesInTests, unitTestMode, useVdomWorker} = Neo.config;
449
+
450
+ if (unitTestMode && !allowVdomUpdatesInTests) return;
451
+
452
+ // Verify that the critical rendering path => CSS files for the new tree is in place
453
+ if (!unitTestMode && autoMount && currentWorker.countLoadingThemeFiles !== 0) {
454
+ currentWorker.on('themeFilesLoaded', function() {
455
+ !me.mounted && me.render(mount)
456
+ }, me, {once: true});
457
+
458
+ return
459
+ }
460
+
461
+ me.rendering = true;
462
+
463
+ if (!app.rendered) {
464
+ app.rendering = true
465
+ }
466
+
467
+ if (me.vdom) {
468
+ me.isVdomUpdating = true;
469
+
470
+ delete me.vdom.removeDom;
471
+
472
+ me._needsVdomUpdate = false;
473
+ me.afterSetNeedsVdomUpdate?.(false, true);
474
+
475
+ const data = await Promise.resolve(Neo.vdom.Helper.create({
476
+ appName : me.appName,
477
+ autoMount,
478
+ parentId : autoMount ? me.getMountedParentId() : undefined,
479
+ parentIndex: autoMount ? me.getMountedParentIndex() : undefined,
480
+ vdom : TreeBuilder.getVdomTree(me.vdom, -1),
481
+ windowId : me.windowId
482
+ }));
483
+
484
+ me.onRender(data.vnode, useVdomWorker ? autoMount : false);
485
+ me.isVdomUpdating = false;
486
+
487
+ autoMount && !useVdomWorker && me.mount();
488
+
489
+ me.resolveVdomUpdate()
490
+ }
491
+ }
492
+
493
+ /**
494
+ * Internal helper fn to resolve the Promise for updateVdom()
495
+ * @param {Object} [data] The return value of vdom.Helper.update()
496
+ * @protected
497
+ */
498
+ resolveVdomUpdate(data) {
499
+ let me = this;
500
+
501
+ // Execute callbacks for merged updates
502
+ VDomUpdate.executeCallbacks(me.id, data);
503
+
504
+ // The update is no longer in-flight
505
+ VDomUpdate.unregisterInFlightUpdate(me.id);
506
+
507
+ // Trigger updates for components that were in-flight
508
+ VDomUpdate.triggerPostUpdates(me.id);
509
+
510
+ if (me.needsVdomUpdate) {
511
+ // any new promise callbacks will get picked up by the next update cycle
512
+ me.update()
513
+ }
514
+ }
515
+
516
+ /**
517
+ * Placeholder method for util.VDom.syncVdomIds to allow overriding (disabling) it
518
+ * @param {Neo.vdom.VNode} [vnode=this.vnode]
519
+ * @param {Object} [vdom=this.vdom]
520
+ * @param {Boolean} force=false
521
+ */
522
+ syncVdomIds(vnode=this.vnode, vdom=this.vdom, force=false) {
523
+ VDomUtil.syncVdomIds(vnode, vdom, force)
524
+ }
525
+
526
+ /**
527
+ * In case a component receives a new vnode, we want to do:
528
+ * - sync the vdom ids
529
+ * - setting rendered to true for child components
530
+ * - updating the parent component to ensure that the vnode tree stays persistent
531
+ * @param {Neo.vdom.VNode} [vnode=this.vnode]
532
+ */
533
+ syncVnodeTree(vnode=this.vnode) {
534
+ let me = this,
535
+ childComponents = ComponentManager.getChildren(me),
536
+ debug = false,
537
+ map = {},
538
+ childVnode, start;
539
+
540
+ if (debug) {
541
+ start = performance.now()
542
+ }
543
+
544
+ me.syncVdomIds();
545
+
546
+ if (vnode && me.id !== vnode.id) {
547
+ ComponentManager.registerWrapperNode(vnode.id, me)
548
+ }
549
+
550
+ // we need one separate iteration first to ensure all wrapper nodes get registered
551
+ childComponents.forEach(component => {
552
+ childVnode = VNodeUtil.find(me.vnode, component.vdom.id)?.vnode;
553
+
554
+ if (childVnode) {
555
+ map[component.id] = childVnode;
556
+
557
+ if (component.id !== childVnode.id) {
558
+ ComponentManager.registerWrapperNode(childVnode.id, component)
559
+ }
560
+ }
561
+ });
562
+
563
+ // delegate the latest node updates to all possible child components found inside the vnode tree
564
+ childComponents.forEach(component => {
565
+ childVnode = map[component.id];
566
+
567
+ if (childVnode) {
568
+ // silent update
569
+ component._vnode = ComponentManager.addVnodeComponentReferences(childVnode, component.id);
570
+
571
+ if (!component.rendered) {
572
+ component._rendered = true;
573
+ component.fire('rendered', component.id)
574
+ }
575
+
576
+ component.mounted = true
577
+ } else {
578
+ console.warn('syncVnodeTree: Could not replace the child vnode for', component.id)
579
+ }
580
+ });
581
+
582
+ // silent update
583
+ me._vnode = vnode ? ComponentManager.addVnodeComponentReferences(vnode, me.id) : null;
584
+
585
+ debug && console.log('syncVnodeTree', me.id, performance.now() - start)
586
+ }
587
+
588
+ /**
589
+ *
590
+ */
591
+ update() {
592
+ this.afterSetVdom(this.vdom, null)
593
+ }
594
+
595
+ /**
596
+ * Gets called after the vdom config gets changed in case the component is already mounted (delta updates).
597
+ * @param {function} [resolve] used by promiseUpdate()
598
+ * @param {function} [reject] used by promiseUpdate()
599
+ * @protected
600
+ */
601
+ updateVdom(resolve, reject) {
602
+ if (!this.isConstructed) {
603
+ resolve?.();
604
+ return
605
+ }
606
+
607
+ if (Neo.config.unitTestMode && !Neo.config.allowVdomUpdatesInTests) {
608
+ reject?.();
609
+ return
610
+ }
611
+
612
+ let me = this,
613
+ {mounted, parentId, vnode} = me;
614
+
615
+ if (me.isVdomUpdating || me.silentVdomUpdate) {
616
+ resolve && VDomUpdate.addPromiseCallback(me.id, resolve);
617
+ me.needsVdomUpdate = true
618
+ } else {
619
+ // If there's a promise, register it against this component's ID immediately.
620
+ // The manager will ensure it's called when the appropriate update cycle completes.
621
+ resolve && VDomUpdate.addPromiseCallback(me.id, resolve);
622
+
623
+ // If an update is triggered on an unmounted component, we must wait for it to be mounted.
624
+ if (!mounted) {
625
+ // Use a flag to prevent setting up multiple `then` listeners for subsequent updates
626
+ // that might arrive before the component is mounted.
627
+ if (!me.isAwaitingMount) {
628
+ me.isAwaitingMount = true;
629
+ me.mountedPromise.then(() => {
630
+ me.isAwaitingMount = false;
631
+ // After mounting, re-trigger the update cycle. The cached callbacks will be picked up.
632
+ me.vnode && me.update();
633
+ });
634
+ }
635
+ } else {
636
+ if (
637
+ !me.mergeIntoParentUpdate(parentId)
638
+ && !me.isParentUpdating(parentId, resolve)
639
+ && mounted
640
+ && vnode
641
+ ) {
642
+ // Check for merged child updates and adjust the update depth accordingly
643
+ let adjustedDepth = VDomUpdate.getAdjustedUpdateDepth(me.id);
644
+
645
+ if (adjustedDepth !== null) {
646
+ me.updateDepth = adjustedDepth;
647
+ }
648
+
649
+ // Verify that the critical rendering path => CSS files for the new tree is in place
650
+ if (!Neo.config.unitTestMode && currentWorker.countLoadingThemeFiles !== 0) {
651
+ currentWorker.on('themeFilesLoaded', function() {
652
+ me.updateVdom(resolve, reject)
653
+ }, me, {once: true})
654
+ } else {
655
+ me.executeVdomUpdate(null, reject)
656
+ }
657
+ }
658
+ }
659
+ }
660
+
661
+ me.hasUnmountedVdomChanges = !mounted && me.hasBeenMounted
662
+ }
663
+ }
664
+
665
+ Neo.setupClass(VdomLifecycle);
666
+
667
+ export default VdomLifecycle;
@@ -27,6 +27,7 @@ class Plugin extends Base {
27
27
  owner: null,
28
28
  /**
29
29
  * @member {Number|null} windowId_=null
30
+ * @reactive
30
31
  */
31
32
  windowId_: null
32
33
  }
@@ -49,6 +49,7 @@ class Resizable extends Plugin {
49
49
  /**
50
50
  * The name of the App this instance belongs to
51
51
  * @member {String|null} appName_=null
52
+ * @reactive
52
53
  */
53
54
  appName_: null,
54
55
  /**
@@ -74,6 +75,7 @@ class Resizable extends Plugin {
74
75
  /**
75
76
  * Directions into which you want to drag => resize
76
77
  * @member {String[]} directions_=['b','bl','br','l','r','t','tl','tr']
78
+ * @reactive
77
79
  */
78
80
  directions_: ['b', 'bl', 'br', 'l', 'r', 't', 'tl', 'tr'],
79
81
  /**