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,122 @@
1
+ # Epic: Optimized VDOM Update Strategies
2
+
3
+ This epic outlines a series of surgical enhancements to the framework's VDOM update lifecycle. The goal is to improve the robustness and maintainability of the update mechanism by centralizing complex state for all collision scenarios, without altering the existing high-performance, real-time messaging architecture.
4
+
5
+ ## Core Problem: Distributed State
6
+ The current VDOM update logic is extremely fast, but the state management for aggregated updates is complex and distributed across component instances. This is true for two scenarios:
7
+ 1. **Pre-Flight Merges:** Multiple updates are queued in the same event loop tick and merged before a worker message is sent.
8
+ 2. **In-Flight Collisions:** A child requests an update while its parent's update is already in-flight to the worker.
9
+
10
+ In both cases, callbacks and post-update triggers are stored in scattered instance-level caches (`resolveUpdateCache`, `childUpdateCache`), making the lifecycle hard to debug and maintain.
11
+
12
+ ## Solution: Centralized Orchestration Manager
13
+
14
+ We will introduce a new manager to act as a central orchestrator for all collision-related state. This approach preserves the existing high-performance update engine while drastically simplifying the `VdomLifecycle` mixin.
15
+
16
+ ### 1. New Class: `Neo.manager.VDomUpdate` (Orchestrator)
17
+ - This new singleton manager will **not** schedule or delay updates.
18
+ - It will contain two maps to manage all collision scenarios:
19
+ - `mergedCallbackMap`: Stores callbacks and relevant update depth information for **pre-flight merges**.
20
+ - `postUpdateQueueMap`: Stores child components that need updating after an **in-flight collision**.
21
+ - It will expose methods to be called by the `VdomLifecycle` mixin:
22
+ - `registerMerged(ownerId, childId, callbacks, childUpdateDepth, distance)`: Stores the child's callbacks, its `updateDepth`, and its `distance` from the owner.
23
+ - `registerPostUpdate(ownerId, childId, resolve)`
24
+ - `executeCallbacks(ownerId)`: This method will also be responsible for calculating the maximum required `updateDepth` for the `ownerId` (parent) based on the `childUpdateDepth` and `distance` of all merged children. It will then set the `ownerId` component's `updateDepth` to this calculated maximum *before* the parent's `update()` method is called (if `needsVdomUpdate` is true).
25
+ - `triggerPostUpdates(ownerId)`
26
+
27
+ ### 2. `VdomLifecycle.mjs` Refactoring
28
+ - The core, high-performance update logic (`updateVdom`, collision detection) will remain.
29
+ - **Pre-Flight Merge:** When an update is merged (e.g., in `mergeIntoParentUpdate()`), it will now call `Neo.manager.VDomUpdate.registerMerged(parent.id, me.id, me.resolveUpdateCache, me.updateDepth, distance)` instead of manipulating local caches.
30
+ - **In-Flight Collision:** When an update collides with an in-flight parent (in `isParentUpdating()`), it will call `Neo.manager.VDomUpdate.registerPostUpdate(...)`. The child component will still set its own `needsVdomUpdate = true` and hold its own callback in its `resolveUpdateCache` for the update it will eventually run.
31
+ - **On Update Completion:** When a root update cycle finishes, its `then()` block will call both `manager.executeCallbacks(this.id)` and `manager.triggerPostUpdates(this.id)`.
32
+ - This change allows for the complete removal of the complex `childUpdateCache` property and simplifies the logic around `resolveUpdateCache`.
33
+
34
+ ### 3. Asymmetric VDOM Serialization (`ComponentManager.mjs`)
35
+ - This part of the plan remains crucial and unchanged.
36
+ - `getVdomTree()` and `getVnodeTree()` will be refactored to honor the `updateDepth` of each individual component.
37
+ - If a child component is excluded from an update, a lightweight placeholder object `{componentId: 'neo-ignore'}` will be inserted into the tree to preserve its structural integrity.
38
+
39
+ ### 4. VDOM Worker Enhancement (`vdom/Helper.mjs`)
40
+ - The VDOM worker's `createDeltas()` method will be enhanced to recognize the `neo-ignore` placeholder. When it encounters this node, it will skip the diffing process, leaving the corresponding DOM element untouched.
41
+
42
+ ### 5. Testing Strategy
43
+ Given the architectural significance of these changes, a comprehensive testing strategy is required. Since the test environment runs in a single thread (main), the strategy will be:
44
+
45
+ 1. **Unit Test Environment Setup:**
46
+ - The test suite will import all necessary classes directly into the main thread: `vdom.Helper`, `manager.VDomUpdate`, and all relevant components and containers.
47
+ - Components will be instantiated in a non-rendering mode (`preventDOM: true` or a similar mechanism) to avoid any interaction with the actual DOM.
48
+
49
+ 2. **Validation Points:**
50
+ - **Aggregation Logic:** Create complex scenarios with nested components triggering updates simultaneously to verify that the new `VDomUpdate` manager correctly handles both pre-flight and in-flight collisions.
51
+ - **Delta Correctness:** After a test update cycle, inspect the generated `deltas` array to ensure it is correct and that the `neo-ignore` placeholder is working as expected.
52
+ - **VNode Redistribution:** Verify that after an update, the new `vnode` is correctly passed down and synchronized to all relevant child components.
53
+ - **Callback Execution:** Ensure that all `resolve` callbacks from merged and queued updates are executed correctly and exactly once.
54
+
55
+ 3. **Benchmarking:**
56
+ - A dedicated feature branch will be used for this epic.
57
+ - Create a suite of performance tests that simulate high-frequency updates on complex component trees.
58
+ - Run these benchmarks on both the `main` branch (old implementation) and the feature branch (new implementation) to rigorously compare performance and ensure there are no regressions.
59
+
60
+ This final, refined approach provides the best of all worlds: it fixes the code complexity and maintainability issues by centralizing all collision-related state, while fully preserving the framework's proven, real-time performance characteristics.
61
+
62
+ ## Implementation Progress
63
+
64
+ **Status:** Foundational work complete. Documentation and a regression test suite are in place, and key framework APIs have been enhanced.
65
+
66
+ ### 1. Documentation & Test Suite
67
+
68
+ Two crucial files have been created to guide and validate this epic:
69
+
70
+ - **Epic Ticket (`.github/ticket-asymmetric-vdom-updates.md`):** This central document outlines the problem, defines the solution, and tracks our progress.
71
+ - **`VdomAsymmetricUpdates.mjs`:** A low-level unit test that directly validates the core logic of the new `VDomUpdate` manager and `TreeBuilder`. It simulates asymmetric updates with mock components to ensure the delta generation is correct.
72
+ - **`VdomRealWorldUpdates.mjs`:** A high-level integration test using real components to create a regression suite. It verifies that the framework's *existing* ability to merge updates from multiple component levels into a single, efficient cycle remains intact.
73
+
74
+ Key achievements of these tests:
75
+ - **Validates Current Logic:** It successfully tests the *existing* logic where updates from multiple component levels (e.g., a parent and a grandchild) within the same event loop tick are correctly merged into a single, efficient VDOM update cycle.
76
+ - **Pure VDOM Testing:** The test runs without a real DOM. It creates component instances, generates their initial `vnode` structure, and then programmatically triggers updates.
77
+ - **Asserts on Deltas:** Instead of inspecting the DOM, the test awaits the `promiseUpdate()` method (which was enhanced to resolve with the update data) and directly inspects the raw `deltas` array. This provides a precise and reliable way to verify that the update-merging logic is working as expected.
78
+
79
+ This test now serves as a critical regression suite, ensuring that the planned refactoring of the update mechanism will not alter this core, high-performance behavior.
80
+
81
+ ### 2. Framework API Enhancements
82
+
83
+ The process of building the test suite revealed opportunities to improve the core framework. The following enhancements have been implemented:
84
+
85
+ - **`Component.mountedPromise`:** A new, robust `mountedPromise` getter has been added to `component.Base`. This provides a clean, reusable, promise-based API for awaiting a component's mounted state. The implementation is resilient to the framework's full lifecycle, correctly handling unmounting and remounting, making it a valuable tool for both testing and application-level code.
86
+ - **`VdomLifecycle.promiseUpdate()` Enhancement:** The `promiseUpdate()` method was refactored to resolve with the full data object from `vdom.Helper.update()`, giving developers and tests access to the generated `deltas` and the new `vnode`.
87
+ - **Environment Robustness:** Several fixes were made to the `VdomLifecycle` mixin to ensure it works reliably in both multi-threaded (worker) and single-threaded (test) environments, particularly around `vdom.Helper` calls and `Neo.currentWorker` access.
88
+
89
+ - **`VdomLifecycle.promiseUpdate()` Enhancement:** The `promiseUpdate()` method was refactored to resolve with the full data object from `vdom.Helper.update()`, giving developers and tests access to the generated `deltas` and the new `vnode`.
90
+ - **Environment Robustness:** Several fixes were made to the `VdomLifecycle` mixin to ensure it works reliably in both multi-threaded (worker) and single-threaded (test) environments, particularly around `vdom.Helper` calls and `Neo.currentWorker` access.
91
+
92
+ ## Comparison with `dev` Branch (based on PR #7077)
93
+
94
+ This feature branch represents a major architectural enhancement to the VDOM update lifecycle. Here is a summary of the key changes compared to the `dev` branch:
95
+
96
+ - **New Update Orchestration Core:**
97
+ - `manager.VDomUpdate`: A new singleton manager has been introduced to centralize the state for both pre-flight update merges and in-flight update collisions.
98
+ - `util.vdom.TreeBuilder`: A new utility class for recursively building VDOM and VNode trees. It is the engine behind creating the *asymmetric* trees needed for optimized updates, correctly expanding component references based on a calculated `updateDepth`.
99
+
100
+ - **Core Framework Refactoring:**
101
+ - `mixin/VdomLifecycle.mjs`: This critical mixin has been significantly refactored. The complex, distributed state management (`childUpdateCache`) has been removed, and it now delegates all collision and merge logic to the new `VDomUpdate` manager.
102
+ The `executeVdomUpdate()` method has been modernized to use `async/await`, making the control flow more robust and readable, and ensuring deltas are correctly applied in non-worker environments.
103
+ - `vdom/Helper.mjs`: The diffing engine has been enhanced to support the new asymmetric update strategy.
104
+ - `component/Base.mjs`: The base component has been improved with a robust `mountedPromise` for easier async handling and other lifecycle enhancements to support the new update model.
105
+ - `manager/Component.mjs`: Has undergone significant refactoring to align with the new VDOM strategies.
106
+ - `functional/component/Base.mjs`: The base for functional components has been updated to align with the lifecycle changes in `component.Base`.
107
+
108
+ - **New Testing Infrastructure:**
109
+ - `test/siesta/tests/vdom/VdomAsymmetricUpdates.mjs`: A new low-level test suite that directly validates the logic of `VDomUpdate` and `TreeBuilder` using mock components.
110
+ - `test/siesta/tests/vdom/VdomRealWorldUpdates.mjs`: A new high-level integration test suite using real, nested components to serve as a regression test.
111
+ - `src/DefaultConfig.mjs`: The new `allowVdomUpdatesInTests: true` flag has been added to facilitate running VDOM-related tests in a unit test environment.
112
+ - `test/siesta/siesta.js`: The test runner has been updated to include these new test suites.
113
+
114
+ ### Remaining Work to Complete the Epic (as of this PR)
115
+
116
+ While the core architectural shift is complete, the following tasks remain to finalize the epic:
117
+
118
+ - **Finalize Cleanup:**
119
+ - The `childUpdateCache` property inside `src/component/Base.mjs` is now obsolete. It can be safely removed, as `VDomUpdate` has taken over its responsibilities.
120
+ - The `updateVdom()` method in `VdomLifecycle.mjs` still uses a `timeout` to handle updates on unmounted components. This can be refactored to use the new `mountedPromise`, creating a cleaner and more robust implementation.
121
+ - **Complete Asymmetric Logic:** The `TreeBuilder` and `vdom.Helper` still need the final logic to handle the `neo-ignore` placeholder. This will enable truly asymmetric updates where non-participating component sub-trees are completely skipped during the diffing process.
122
+ - **Performance Benchmarking:** Conduct rigorous performance tests to compare this branch against `dev` and ensure no regressions.
package/README.md CHANGED
@@ -84,9 +84,6 @@ That’s Neo.mjs in action — solving problems others can’t touch.
84
84
  * **Persistent Component Instances**: Components maintain their state and logic even when their DOM is removed or moved.
85
85
  No more wasteful re-creations – just surgical, efficient updates.
86
86
 
87
- * **Reactive State Management**: Built-in reactivity ensures dynamic, efficient updates between components and state providers,
88
- all handled off the main thread.
89
-
90
87
  * **Reactive State Management**: Leveraging `Neo.state.Provider`, Neo.mjs offers natively integrated, hierarchical state management.
91
88
  Components declare their data needs via a concise `bind` config. These `bind` functions act as powerful inline formulas, allowing
92
89
  Components to automatically react to changes and combine data from multiple state providers within the component hierarchy.
package/ServiceWorker.mjs CHANGED
@@ -20,9 +20,9 @@ class ServiceWorker extends ServiceBase {
20
20
  */
21
21
  singleton: true,
22
22
  /**
23
- * @member {String} version='10.0.0-beta.4'
23
+ * @member {String} version='10.0.0-beta.6'
24
24
  */
25
- version: '10.0.0-beta.4'
25
+ version: '10.0.0-beta.6'
26
26
  }
27
27
 
28
28
  /**
@@ -14,6 +14,7 @@ class Colors extends Store {
14
14
  className: 'Colors.store.Colors',
15
15
  /**
16
16
  * @member {Neo.data.Model} model=ColorModel
17
+ * @reactive
17
18
  */
18
19
  model: ColorModel
19
20
  }
@@ -13,10 +13,12 @@ class GridContainer extends BaseGridContainer {
13
13
  className: 'Colors.view.GridContainer',
14
14
  /**
15
15
  * @member {Number|null} amountColumns_=null
16
+ * @reactive
16
17
  */
17
18
  amountColumns_: null,
18
19
  /**
19
20
  * @member {Number|null} amountRows_=null
21
+ * @reactive
20
22
  */
21
23
  amountRows_: null,
22
24
  /**
@@ -29,6 +31,7 @@ class GridContainer extends BaseGridContainer {
29
31
  },
30
32
  /**
31
33
  * @member {String[]} cls=['colors-grid-container']
34
+ * @reactive
32
35
  */
33
36
  cls: ['colors-grid-container']
34
37
  }
@@ -16,10 +16,12 @@ class HeaderToolbar extends Toolbar {
16
16
  className: 'Colors.view.HeaderToolbar',
17
17
  /**
18
18
  * @member {String[]} cls=['colors-header-toolbar']
19
+ * @reactive
19
20
  */
20
21
  cls: ['colors-header-toolbar'],
21
22
  /**
22
23
  * @member {Object} layout={ntype:'hbox',align:'stretch',wrap:'wrap'}
24
+ * @reactive
23
25
  */
24
26
  layout: {ntype: 'hbox', align: 'center', pack: 'start', wrap: 'wrap'},
25
27
  /**
@@ -19,10 +19,12 @@ class Viewport extends BaseViewport {
19
19
  className: 'Colors.view.Viewport',
20
20
  /**
21
21
  * @member {String[]} cls=['colors-viewport']
22
+ * @reactive
22
23
  */
23
24
  cls: ['colors-viewport'],
24
25
  /**
25
26
  * @member {Neo.controller.Component} controller=ViewportController
27
+ * @reactive
26
28
  */
27
29
  controller: ViewportController,
28
30
  /**
@@ -49,6 +51,7 @@ class Viewport extends BaseViewport {
49
51
  }],
50
52
  /**
51
53
  * @member {Neo.state.Provider} stateProvider=ViewportStateProvider
54
+ * @reactive
52
55
  */
53
56
  stateProvider: ViewportStateProvider
54
57
  }
@@ -13,14 +13,17 @@ class FooterContainer extends Container {
13
13
  className: 'Covid.view.FooterContainer',
14
14
  /**
15
15
  * @member {Number} height=20
16
+ * @reactive
16
17
  */
17
18
  height: 25,
18
19
  /**
19
20
  * @member {Object} layout={ntype: 'hbox'}
21
+ * @reactive
20
22
  */
21
23
  layout: {ntype: 'hbox'},
22
24
  /**
23
25
  * @member {String} reference='footer'
26
+ * @reactive
24
27
  */
25
28
  reference: 'footer',
26
29
  /**
@@ -22,6 +22,7 @@ class GalleryContainer extends Container {
22
22
  baseCls: ['neo-gallery-maincontainer', 'neo-viewport'],
23
23
  /**
24
24
  * @member {Neo.controller.Component|null} controller=GalleryContainerController
25
+ * @reactive
25
26
  */
26
27
  controller: GalleryContainerController,
27
28
  /**
@@ -34,6 +35,7 @@ class GalleryContainer extends Container {
34
35
  galleryConfig: null,
35
36
  /**
36
37
  * @member {Object|null} layout={ntype: 'hbox', align: 'stretch'}
38
+ * @reactive
37
39
  */
38
40
  layout: {ntype: 'hbox', align: 'stretch'},
39
41
  /**
@@ -14,6 +14,7 @@ class GalleryContainerController extends ComponentController {
14
14
  /**
15
15
  * @member {Neo.component.Gallery|null} gallery_=null
16
16
  * @protected
17
+ * @reactive
17
18
  */
18
19
  gallery_: null
19
20
  }
@@ -19,10 +19,12 @@ class HeaderContainer extends Container {
19
19
  baseCls: ['covid-header-container'],
20
20
  /**
21
21
  * @member {Number} height=70
22
+ * @reactive
22
23
  */
23
24
  height: 120,
24
25
  /**
25
26
  * @member {Object} layout={ntype: 'hbox', align: 'stretch'}
27
+ * @reactive
26
28
  */
27
29
  layout: {ntype: 'hbox', align: 'stretch'},
28
30
  /**
@@ -22,6 +22,7 @@ class HelixContainer extends Container {
22
22
  baseCls: ['neo-helix-maincontainer', 'neo-viewport'],
23
23
  /**
24
24
  * @member {Neo.controller.Component|null} controller=HelixContainerController
25
+ * @reactive
25
26
  */
26
27
  controller: HelixContainerController,
27
28
  /**
@@ -34,6 +35,7 @@ class HelixContainer extends Container {
34
35
  helixConfig: null,
35
36
  /**
36
37
  * @member {Object|null} layout={ntype: 'hbox', align: 'stretch'}
38
+ * @reactive
37
39
  */
38
40
  layout: {ntype: 'hbox', align: 'stretch'},
39
41
  /**
@@ -14,6 +14,7 @@ class HelixContainerController extends ComponentController {
14
14
  /**
15
15
  * @member {Neo.component.Helix|null} helix_=null
16
16
  * @protected
17
+ * @reactive
17
18
  */
18
19
  helix_: null
19
20
  }
@@ -22,6 +22,7 @@ class MainContainer extends Viewport {
22
22
  baseCls: ['covid-viewport', 'neo-viewport'],
23
23
  /**
24
24
  * @member {Neo.controller.Component} controller=MainContainerController
25
+ * @reactive
25
26
  */
26
27
  controller: MainContainerController,
27
28
  /**
@@ -83,10 +84,12 @@ class MainContainer extends Viewport {
83
84
  }, FooterContainer],
84
85
  /**
85
86
  * @member {Object} layout={ntype: 'vbox', align: 'stretch'}
87
+ * @reactive
86
88
  */
87
89
  layout: {ntype: 'vbox', align: 'stretch'},
88
90
  /**
89
91
  * @member {Neo.state.Provider} stateProvider=MainContainerStateProvider
92
+ * @reactive
90
93
  */
91
94
  stateProvider: MainContainerStateProvider
92
95
  }
@@ -27,10 +27,12 @@ class TableContainer extends Container {
27
27
  },
28
28
  /**
29
29
  * @member {Neo.controller.Component|null} controller=TableContainerController
30
+ * @reactive
30
31
  */
31
32
  controller: TableContainerController,
32
33
  /**
33
34
  * @member {Object} countryRecord_=null
35
+ * @reactive
34
36
  */
35
37
  countryRecord_: null,
36
38
  /**
@@ -48,6 +50,7 @@ class TableContainer extends Container {
48
50
  tableConfig: null,
49
51
  /**
50
52
  * @member {Object|null} layout={ntype: 'hbox', align: 'stretch'}
53
+ * @reactive
51
54
  */
52
55
  layout: {ntype: 'hbox', align: 'stretch'},
53
56
  /**
@@ -45,6 +45,7 @@ class TableContainerController extends ComponentController {
45
45
  /**
46
46
  * @member {Neo.table.Container|null} table_=null
47
47
  * @protected
48
+ * @reactive
48
49
  */
49
50
  table_: null
50
51
  }
@@ -17,10 +17,12 @@ class WorldMapContainer extends Container {
17
17
  className: 'Covid.view.WorldMapContainer',
18
18
  /**
19
19
  * @member {Neo.controller.Component} controller=WorldMapContainerController
20
+ * @reactive
20
21
  */
21
22
  controller: WorldMapContainerController,
22
23
  /**
23
24
  * @member {Object} layout={ntype: 'vbox', align: 'stretch'}
25
+ * @reactive
24
26
  */
25
27
  layout: {ntype: 'vbox', align: 'stretch'},
26
28
  /**
@@ -25,6 +25,7 @@ class CountryGallery extends Gallery {
25
25
  },
26
26
  /**
27
27
  * @member {String|null} country_=null
28
+ * @reactive
28
29
  */
29
30
  country_: null,
30
31
  /**
@@ -34,6 +35,7 @@ class CountryGallery extends Gallery {
34
35
  itemHeight: 280,
35
36
  /**
36
37
  * @member {Object} itemTpl_
38
+ * @reactive
37
39
  */
38
40
  itemTpl:
39
41
  {cls: ['neo-gallery-item', 'image-wrap', 'view', 'neo-transition-1000'], tabIndex: '-1', cn: [
@@ -86,6 +88,7 @@ class CountryGallery extends Gallery {
86
88
  selectOnMount: false,
87
89
  /**
88
90
  * @member {Neo.data.Store} store=CountryStore
91
+ * @reactive
89
92
  */
90
93
  store: CountryStore
91
94
  }
@@ -25,15 +25,18 @@ class CountryHelix extends Helix {
25
25
  },
26
26
  /**
27
27
  * @member {String|null} country_=null
28
+ * @reactive
28
29
  */
29
30
  country_: null,
30
31
  /**
31
32
  * The vertical delta between each helix item (increasing this value will create a spiral)
32
33
  * @member {Number} deltaY=1.2
34
+ * @reactive
33
35
  */
34
36
  deltaY: 1.2,
35
37
  /**
36
38
  * @member {Object} itemTpl_
39
+ * @reactive
37
40
  */
38
41
  itemTpl:
39
42
  {cls: ['surface', 'neo-helix-item'], style: {}, tabIndex: '-1', cn: [
@@ -77,11 +80,13 @@ class CountryHelix extends Helix {
77
80
  /**
78
81
  * The radius of the Helix in px
79
82
  * @member {Number} radius=2500
83
+ * @reactive
80
84
  */
81
85
  radius: 2500,
82
86
  /**
83
87
  * The rotationAngle of the Helix in degrees
84
88
  * @member {Number} rotationAngle=720
89
+ * @reactive
85
90
  */
86
91
  rotationAngle: 720,
87
92
  /**
@@ -91,16 +96,19 @@ class CountryHelix extends Helix {
91
96
  showCloneInfo: false,
92
97
  /**
93
98
  * @member {Neo.data.Store} store=CountryStore
99
+ * @reactive
94
100
  */
95
101
  store: CountryStore,
96
102
  /**
97
103
  * The translateX value gets included into each helix item
98
104
  * @member {Number} translateY=500
105
+ * @reactive
99
106
  */
100
107
  translateY: 500,
101
108
  /**
102
109
  * The translateX value gets included into each helix item
103
110
  * @member {Number} translateZ_=-2300
111
+ * @reactive
104
112
  */
105
113
  translateZ: -2300
106
114
  }
@@ -80,6 +80,7 @@ class HistoricalDataTable extends Container {
80
80
  }],
81
81
  /**
82
82
  * @member {Neo.data.Store} store=HistoricalData
83
+ * @reactive
83
84
  */
84
85
  store: HistoricalData
85
86
  }
@@ -104,10 +104,12 @@ class Table extends Container {
104
104
  }],
105
105
  /**
106
106
  * @member {String|null} country_=null
107
+ * @reactive
107
108
  */
108
109
  country_: null,
109
110
  /**
110
111
  * @member {Neo.data.Store} store=CountryStore
112
+ * @reactive
111
113
  */
112
114
  store: CountryStore
113
115
  }
@@ -17,6 +17,7 @@ class Component extends BaseComponent {
17
17
  accessToken: 'pk.eyJ1IjoidG9iaXUiLCJhIjoiY2s4dTlsdHA5MDRmYzNtcGxlczFpcGVncyJ9.qcmzDjpdyQeLtz9z7d7CkA',
18
18
  /**
19
19
  * @member {Object} center={lat: 40, lng: 20}
20
+ * @reactive
20
21
  */
21
22
  center: {lat: 40, lng: 20},
22
23
  /**
@@ -22,6 +22,7 @@ class Container extends BaseContainer {
22
22
  ntype: 'covid-mapboxgl-container',
23
23
  /**
24
24
  * @member {Neo.controller.Component} controller=ContainerController
25
+ * @reactive
25
26
  */
26
27
  controller: ContainerController,
27
28
  /**
@@ -88,6 +89,7 @@ class Container extends BaseContainer {
88
89
  }],
89
90
  /**
90
91
  * @member {Object} layout={ntype: 'fit'}
92
+ * @reactive
91
93
  */
92
94
  layout: {ntype: 'fit'},
93
95
 
@@ -0,0 +1,58 @@
1
+ # EPIC: Refactor and Enhance the Email App
2
+
3
+ This document outlines the plan for refactoring the `apps/email` application into a showcase for the Neo.mjs functional component architecture and multi-window capabilities.
4
+
5
+ ## Architectural Milestones & Key Learnings
6
+
7
+ This epic has driven significant architectural improvements to the functional component system. For a full understanding of the current state, review this ticket:
8
+
9
+ - **[#ticket-functional-recursive-config-diffing.md](/.github/ticket-functional-recursive-config-diffing.md):** A plan for a future enhancement to make the diffing logic recursive, allowing for deep, declarative control over nested component configurations.
10
+
11
+ ---
12
+
13
+ ## Phase 1: Foundation and Basic Layout (Completed)
14
+
15
+ **Goal:** Implement the main 3-pane layout as a functional `MainView` component and set it as the content of the existing classic `Viewport`.
16
+
17
+ **Learnings & Decisions:**
18
+ - **Interoperability:** Kept the classic `Viewport` and embedded the new functional `MainView` component, showcasing seamless integration.
19
+ - **Naming:** Renamed `Main.mjs` to `MainView.mjs` for clarity.
20
+
21
+ ---
22
+
23
+ ## Phase 2: Email List View (Completed)
24
+
25
+ **Goal:** Implement the email list pane using a `Neo.grid.Container`.
26
+
27
+ **Learnings & Decisions:**
28
+ - **Complex Component Integration:** Discovered that complex classic components require specific configs (e.g., `wrapperStyle`) to manage their own layout when nested inside functional components.
29
+ - **Stateful Child Problem:** Uncovered the core issue of stateful children (stores, columns) being re-created on every parent render. This led directly to the architectural work on VDOM diffing.
30
+
31
+ ---
32
+
33
+ ## Phase 3: Email Detail View (Completed)
34
+
35
+ **Goal:** Display the content of a selected email from the grid.
36
+ - Implemented a `selection.RowModel` on the grid and used a `useConfig` state variable (`selectedEmail`) to drive a conditional render of the detail pane.
37
+
38
+ ---
39
+
40
+ ## Phase 4: Compose Email Functionality (Next)
41
+
42
+ **Goal:** Implement the ability to compose a new email, initially within the main window.
43
+
44
+ **Proposed Plan:**
45
+ 1. **Compose Button:** Add a `Neo.button.Base` to the "Folders" pane.
46
+ 2. **State Management:** Use `useConfig` in `MainView` to manage an `isComposing` boolean state.
47
+ 3. **Compose View:** Create a new functional component, `view/ComposeView.mjs`, containing the form for the new email.
48
+ 4. **Conditional Rendering:** Use the `isComposing` flag to conditionally render the `ComposeView` as an overlay on top of the main view.
49
+ 5. **Event Handling:** The "Compose" button will set `isComposing` to `true`. The `ComposeView` will have a "Close" button that sets it back to `false`.
50
+ 6. **Overlay Implementation:** We will build a custom functional overlay for this, as it's a good exercise and provides maximum flexibility.
51
+
52
+ ---
53
+
54
+ ## Phase 5: Multi-Window Detach
55
+
56
+ **Goal:** Implement the "detach" functionality to move the compose view into a separate browser window.
57
+ **Sub-Tasks:** *(To be defined)*
58
+
@@ -4,6 +4,6 @@
4
4
  "environment": "development",
5
5
  "mainPath": "./Main.mjs",
6
6
  "themes": [
7
- "neo-theme-light"
7
+ "neo-theme-dark"
8
8
  ]
9
- }
9
+ }
@@ -15,7 +15,17 @@ class Emails extends Store {
15
15
  /**
16
16
  * @member {Neo.data.Model} model=Email
17
17
  */
18
- model: EmailModel
18
+ model: EmailModel,
19
+ /**
20
+ * @member {Object[]} data
21
+ */
22
+ data: [
23
+ {id: 1, sender: 'John Doe', title: 'Hello World!', content: 'This is the first email.', dateSent: '2025-07-15T10:00:00Z'},
24
+ {id: 2, sender: 'Jane Smith', title: 'Re: Project Update', content: 'Here is the project update you requested.', dateSent: '2025-07-15T11:30:00Z'},
25
+ {id: 3, sender: 'Peter Jones', title: 'Lunch tomorrow?', content: 'Are we still on for lunch tomorrow at 12:30?', dateSent: '2025-07-15T12:15:00Z'},
26
+ {id: 4, sender: 'Mary Williams', title: 'Your order has shipped', content: 'Your order #12345 has shipped and will arrive in 3-5 business days.', dateSent: '2025-07-14T15:45:00Z'},
27
+ {id: 5, sender: 'David Brown', title: 'Quick question', content: 'I have a quick question about the new feature.', dateSent: '2025-07-14T09:20:00Z'}
28
+ ]
19
29
  }
20
30
  }
21
31
 
@@ -0,0 +1,44 @@
1
+ import Button from '../../../src/button/Base.mjs';
2
+ import TextField from '../../../src/form/field/Text.mjs';
3
+ import TextAreaField from '../../../src/form/field/TextArea.mjs';
4
+ import {defineComponent} from '../../../src/functional/_export.mjs';
5
+
6
+ export default defineComponent({
7
+ config: {
8
+ className: 'Email.view.ComposeView',
9
+ cls : ['email-compose-view']
10
+ },
11
+ createVdom({onClose}) {
12
+ const fieldStyle = {
13
+ marginBottom: '10px'
14
+ };
15
+
16
+ return {
17
+ cn: [{
18
+ module : TextField,
19
+ id : 'compose-to',
20
+ labelText : 'To:',
21
+ labelWidth: 80,
22
+ style : fieldStyle
23
+ }, {
24
+ module : TextField,
25
+ id : 'compose-subject',
26
+ labelText : 'Subject:',
27
+ labelWidth: 80,
28
+ style : fieldStyle
29
+ }, {
30
+ module : TextAreaField,
31
+ id : 'compose-body',
32
+ labelText: 'Body:',
33
+ height : 200,
34
+ style : fieldStyle
35
+ }, {
36
+ module : Button,
37
+ handler: onClose,
38
+ id : 'compose-close-button',
39
+ style : {alignSelf: 'flex-end'},
40
+ text : 'Close'
41
+ }]
42
+ }
43
+ }
44
+ });