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
@@ -1,3 +1,5 @@
1
+ # Shared Bindable Data (State Providers)
2
+
1
3
  While Components can manage their own state using the Class Config System,
2
4
  you want to use VMs as soon as you want to share data properties with multiple child Components.
3
5
 
@@ -8,6 +10,60 @@ Rules of thumb:
8
10
 
9
11
  Other libraries or frameworks often call state providers "Stores".
10
12
 
13
+ ## How Reactivity Works: The Effects-Based System
14
+
15
+ Neo.mjs State Providers implement a powerful effects-based reactivity system,
16
+ which automatically tracks dependencies and re-evaluates computations when
17
+ their underlying data changes. This system is built around two core concepts:
18
+
19
+ ### 1. The `Neo.core.Effect` Class
20
+
21
+ At the heart of the reactivity is the `Neo.core.Effect` class. An `Effect`
22
+ is a mechanism that encapsulates a function (its "effect function") and
23
+ automatically re-runs this function whenever any of the reactive data
24
+ properties it accesses change.
25
+
26
+ * **Implicit Dependency Tracking:** When your effect function (e.g., a formula
27
+ or a binding formatter) reads a reactive data property (e.g., `data.user.firstName`),
28
+ the `Effect` automatically "subscribes" to changes in that property.
29
+ * **Automatic Re-evaluation:** If `data.user.firstName` changes, the `Effect`
30
+ detects this and automatically re-executes its effect function, ensuring
31
+ that any dependent computations or UI updates are performed.
32
+
33
+ ### 2. The Hierarchical Data Proxy
34
+
35
+ When you access data within a State Provider (e.g., in a `bind` configuration
36
+ or a `formula`), you are interacting with a special `Proxy` object. This proxy
37
+ is created by `Neo.state.createHierarchicalDataProxy` and provides a unified
38
+ view of data across the entire State Provider hierarchy (current provider and
39
+ all its parents).
40
+
41
+ * **Seamless Data Access:** You can access any data property, whether it lives
42
+ in the current State Provider or a parent, using simple dot notation (e.g.,
43
+ `data.myProperty` or `data.user.address.street`).
44
+ * **Enabling Dependency Tracking:** This proxy works in conjunction with
45
+ `Neo.core.Effect` to enable implicit dependency tracking. When an `Effect`
46
+ reads a property through this proxy, the proxy notifies the `Effect` about
47
+ the access, allowing the `Effect` to register that property as a dependency.
48
+
49
+ ### How Bindings and Formulas Utilize Effects
50
+
51
+ * **Bindings (`bind` config):** When you define a `bind` configuration for a
52
+ component (e.g., `bind: {text: data => data.hello}`), Neo.mjs creates an
53
+ `Effect`. The effect function is your formatter (`data => data.hello`).
54
+ Whenever `data.hello` changes, the `Effect` re-runs, re-evaluates the
55
+ formatter, and updates the component's `text` config.
56
+
57
+ * **Formulas (`formulas` config):** These are effect-based computed properties. Each formula function is wrapped in an `Effect`. When the
58
+ formula accesses data (e.g., `data.a + data.b`), the `Effect` tracks `data.a`
59
+ and `data.b` as dependencies. If either changes, the `Effect` re-runs the
60
+ formula, and its computed result is automatically updated in the State Provider's
61
+ data.
62
+
63
+ This effects-based system significantly reduces boilerplate, making state
64
+ management intuitive and efficient by handling dependency tracking and updates
65
+ automatically.
66
+
11
67
  ## Inline State Providers
12
68
  ### Direct Bindings
13
69
  ```javascript live-preview
@@ -111,9 +167,9 @@ Inside the Container are 3 Labels which bind their `text` config to a combinatio
111
167
 
112
168
  We are showcasing 3 different ways how you can define your binding (resulting in the same output).
113
169
 
114
- In case any of the bound data props changes, all bound Configs will check for an update.
170
+ In case any of the bound data props changes, the underlying `Effect` for that binding will re-evaluate, and all bound Configs will update.
115
171
 
116
- Important: The Config setter will only trigger in case there is a real change for the bound output.
172
+ Important: The Config setter will only trigger in case there is a real change for the bound output, ensuring efficient updates.
117
173
 
118
174
  We also added 2 Buttons to change the value of each data prop, so that we can see that the bound Label texts
119
175
  update right away.
@@ -252,17 +308,82 @@ which contains the nested props `firstname` and `lastname`.
252
308
  We can bind to these nested props like before:</br>
253
309
  `bind: {text: data => data.user.firstname + ' ' + data.user.lastname}`
254
310
 
255
- Any change of a nested data prop will directly get reflected into the bound components.
311
+ Any change of a nested data prop will directly trigger the associated `Effect` and get reflected into the bound components.
256
312
 
257
313
  We can update a nested data prop with passing its path:</br>
258
314
  `data => data.component.setState({'user.lastname': 'Rahder'})`
259
315
 
260
316
  Or we can directly pass the object containing the change(s):</br>
261
- `data => data.component.setState({user: {firstname: 'Max'}})`
317
+ `data => data.component.setState({user: {firstname: 'Max'}})`</br>
318
+ **Hint:** This will not override left out nested data props (lastname in this case).</br>
319
+ **Hint:** This is the recommended way for bulk state changes.
320
+
321
+ ***You can also directly change state data***
322
+
323
+ `data => data.component.setStateProvider().data.user.firstname = 'Max'`
324
+
325
+ Shorthand syntax:</br>
326
+ `data => data.component.data.user.firstname = 'Max'`
327
+
328
+ ### Formulas in Action
329
+
330
+ ```javascript live-preview
331
+ import Button from '../button/Base.mjs';
332
+ import Container from '../container/Base.mjs';
333
+ import Label from '../component/Label.mjs';
334
+
335
+ class MainView extends Container {
336
+ static config = {
337
+ className: 'Guides.vmFormula.MainView',
338
+ stateProvider: {
339
+ data: {
340
+ price : 10,
341
+ quantity: 2
342
+ },
343
+ formulas: {
344
+ total : data => data.price * data.quantity,
345
+ discountedTotal: data => data.total * 0.9 // 10% discount
346
+ }
347
+ },
348
+ itemDefaults: {
349
+ module: Label,
350
+ style : {margin: '.5em 1em'}
351
+ },
352
+ items: [{
353
+ bind: {text: data => `Price: ${data.price}`}
354
+ }, {
355
+ bind: {text: data => `Quantity: ${data.quantity}`}
356
+ }, {
357
+ bind: {text: data => `Total: ${data.total}`}
358
+ }, {
359
+ bind: {text: data => `Discounted Total (10% off): ${data.discountedTotal.toFixed(2)}`}
360
+ }, {
361
+ module : Button,
362
+ handler: event => event.component.getStateProvider().data.price++,
363
+ text : 'Increase Price'
364
+ }, {
365
+ module : Button,
366
+ // Shorthand syntax. Less descriptive, but works fine too.
367
+ handler: event => event.component.data.quantity++,
368
+ text : 'Increase Quantity'
369
+ }],
370
+ layout: {ntype: 'vbox', align: 'start'}
371
+ }
372
+ }
373
+ MainView = Neo.setupClass(MainView);
374
+ ```
375
+ This example demonstrates how formulas automatically react to changes in their dependencies.
376
+
377
+ * We define `price` and `quantity` in the `data` config.
378
+ The `total` formula computes `data.price * data.quantity`.
379
+ The `discountedTotal` formula then computes `data.total * 0.9`.
262
380
 
263
- Hint: This will not override left out nested data props (lastname in this case).
381
+ * When you click the "Increase Price" or "Increase Quantity" buttons, you'll observe that
382
+ `Total` and `Discounted Total` labels update automatically, showcasing the
383
+ effect-based reactivity of formulas.
264
384
 
265
385
  ### Dialog connecting to a Container
386
+
266
387
  ```javascript live-preview
267
388
  import Controller from '../controller/Component.mjs';
268
389
  import Dialog from '../dialog/Base.mjs';
@@ -321,6 +442,7 @@ class MainContainerController extends Controller {
321
442
  animateTargetId: me.getReference('edit-user-button').id,
322
443
  appName : me.component.appName,
323
444
  closeAction : 'hide',
445
+ modal : true,
324
446
 
325
447
  stateProvider: {
326
448
  parent: me.getStateProvider()
@@ -382,9 +504,11 @@ MainView = Neo.setupClass(MainView);
382
504
  ```
383
505
 
384
506
  ## Class based State Providers
507
+
385
508
  When your stateProviders contain many data props or need custom logic, you can easily move them into their own classes.
386
509
 
387
510
  ### Direct Bindings
511
+
388
512
  ```javascript live-preview
389
513
  import Button from '../button/Base.mjs';
390
514
  import Container from '../container/Base.mjs';
@@ -497,15 +621,10 @@ class MainViewStateProvider extends StateProvider {
497
621
  static config = {
498
622
  className: 'Guides.vm7.MainViewStateProvider',
499
623
 
500
- data: {
501
- myStoreCount: 0
502
- },
503
-
504
624
  stores: {
505
625
  // Define a store using a class reference
506
626
  mySharedStore: {
507
- module : MyDataStore,
508
- listeners: {countChange: 'onMyStoreCountChange'}
627
+ module : MyDataStore
509
628
  },
510
629
  // Define another store using an inline configuration
511
630
  anotherStore: {
@@ -523,10 +642,6 @@ class MainViewStateProvider extends StateProvider {
523
642
  }
524
643
  }
525
644
  }
526
-
527
- onMyStoreCountChange(data) {
528
- this.data.myStoreCount = data.value // Reactive
529
- }
530
645
  }
531
646
  MainViewStateProvider = Neo.setupClass(MainViewStateProvider);
532
647
 
@@ -556,7 +671,7 @@ class MainView extends Container {
556
671
  module: Label,
557
672
  style : {margin: 'auto'},
558
673
  bind: {
559
- text: data => `Count: ${data.myStoreCount}`
674
+ text: data => `Count: ${data.stores.mySharedStore.count}`
560
675
  }
561
676
  }, {
562
677
  module: Button,
@@ -1 +1 @@
1
- ## todo
1
+ # Tables (Stores)
@@ -1,3 +1,4 @@
1
+ # Config System Deep Dive
1
2
 
2
3
  **Pre-requisite:** It is highly recommended to study [The Unified Class Config System](#/learn/benefits.ConfigSystem)
3
4
  first to understand the foundational concepts and benefits.
@@ -1,3 +1,5 @@
1
+ # Declarative Component Trees VS Imperative Vdom
2
+
1
3
  ## Overview
2
4
 
3
5
  Neo.mjs employs a unique two-tier architecture that separates **declarative component configuration** from **imperative
@@ -0,0 +1,168 @@
1
+ # Declarative VDOM with Effects
2
+
3
+ ## A New Approach: Declarative VDOM with Effects
4
+
5
+ Neo.mjs v10 introduces a powerful new declarative pattern for defining a component's internal Virtual DOM (VDOM), serving as an alternative to the traditional imperative hook-based system. This approach, which leverages the new `Neo.core.Effect` class, allows developers to define a component's entire VDOM structure in a single, reactive function, similar to the `render()` method in React.
6
+
7
+ This guide will walk you through the new pattern, compare it to the classic approach, and explain when to use each.
8
+
9
+ ## The Classic Pattern: Imperative Hooks
10
+
11
+ Let's look at the traditional way a component like `Neo.button.Base` defines and updates its VDOM.
12
+
13
+ **1. Initial VDOM Structure:**
14
+ The base structure is defined in the `_vdom` config.
15
+
16
+ ```javascript readonly
17
+ // Neo.button.Base
18
+ class Button extends Component {
19
+ static config = {
20
+ _vdom: {
21
+ tag: 'button', type: 'button', cn: [
22
+ {tag: 'span', cls: ['neo-button-glyph']},
23
+ {tag: 'span', cls: ['neo-button-text']},
24
+ // ... and so on
25
+ ]
26
+ }
27
+ }
28
+ }
29
+ ```
30
+
31
+ **2. Imperative Updates:**
32
+ To make the component reactive, developers must implement specific `afterSet` hooks for each config that affects the UI. The logic is imperative and fragmented.
33
+
34
+ ```javascript readonly
35
+ // Neo.button.Base - internal framework code
36
+ afterSetIconCls(value, oldValue) {
37
+ let {iconNode} = this;
38
+ // Imperative: Manually add/remove classes
39
+ NeoArray.remove(iconNode.cls, oldValue);
40
+ NeoArray.add(iconNode.cls, value);
41
+ this.update();
42
+ }
43
+
44
+ afterSetText(value, oldValue) {
45
+ let {textNode} = this;
46
+ // Imperative: Manually set properties
47
+ textNode.removeDom = !value;
48
+ textNode.text = value;
49
+ this.update();
50
+ }
51
+
52
+ afterSetPressed(value, oldValue) {
53
+ // Imperative: Manually toggle a class
54
+ NeoArray.toggle(this.cls, 'pressed', value);
55
+ this.update();
56
+ }
57
+ ```
58
+
59
+ **Pros:**
60
+ * **Performance:** Updates are surgical and extremely fast. Only the code for the changed property is executed.
61
+
62
+ **Cons:**
63
+ * **High Cognitive Load:** To understand the component's full rendering logic, a developer must find and read multiple, separate methods.
64
+ * **Error-Prone:** Forgetting to implement a hook for a new config is a common source of bugs.
65
+
66
+ ## The New Pattern: Declarative VDOM with `Effect`
67
+
68
+ The new `EffectButton` PoC demonstrates a more modern, declarative approach.
69
+
70
+ **1. A Single, Reactive Render Function:**
71
+ Instead of fragmented hooks, the entire VDOM is generated within a `Neo.core.Effect`. This effect automatically tracks its dependencies (like `this.text` or `this.pressed`) and re-runs whenever they change.
72
+
73
+ ```javascript readonly
74
+ // button.Effect - The "Template Method"
75
+ createVdomEffect() {
76
+ return new Effect(() => {
77
+ // The effect's only job is to get the config and trigger an update.
78
+ this._vdom = this.getVdomConfig();
79
+ this.update();
80
+ });
81
+ }
82
+
83
+ // The main VDOM builder
84
+ getVdomConfig() {
85
+ return {
86
+ tag: this.pressed ? 'a' : 'button', // Declarative logic
87
+ cls: this.getVdomCls(),
88
+ cn: this.getVdomChildren()
89
+ // ... and so on
90
+ };
91
+ }
92
+ ```
93
+
94
+ **2. Centralized Logic:**
95
+ All VDOM logic is co-located, making it easy to read and understand at a glance.
96
+
97
+ ```javascript readonly
98
+ // button.Effect - Centralized class and child generation
99
+ getVdomCls() {
100
+ let vdomCls = [...this.baseCls, ...this.cls];
101
+ // Declarative: Describe what the classes should be based on state
102
+ NeoArray.toggle(vdomCls, 'no-text', !this.text);
103
+ NeoArray.toggle(vdomCls, 'pressed', this.pressed);
104
+ vdomCls.push('icon-' + this.iconPosition);
105
+ return vdomCls;
106
+ }
107
+
108
+ getVdomChildren() {
109
+ return [
110
+ // Declarative: Describe the children based on state
111
+ {tag: 'span', cls: ['neo-button-glyph', ...this._iconCls || []], removeDom: !this.iconCls},
112
+ {tag: 'span', cls: ['neo-button-text'], removeDom: !this.text, text: this.text},
113
+ // ... and so on
114
+ ];
115
+ }
116
+ ```
117
+
118
+ ## The Power of Inheritance
119
+
120
+ A key challenge with a single render function is extensibility. The new pattern solves this by using a "Template Method" design. The main effect calls smaller, overridable builder methods.
121
+
122
+ This allows a subclass like `tab.header.EffectButton` to easily extend the VDOM without duplicating code.
123
+
124
+ ```javascript readonly
125
+ // tab.header.EffectButton
126
+ class EffectTabButton extends EffectButton {
127
+ // Override to add the indicator child node
128
+ getVdomChildren() {
129
+ // Get the standard button children from the parent class
130
+ let children = super.getVdomChildren();
131
+
132
+ // Add the new indicator node
133
+ children.push({
134
+ cls: ['neo-tab-button-indicator'],
135
+ removeDom: !this.useActiveTabIndicator
136
+ });
137
+
138
+ return children;
139
+ }
140
+
141
+ // Override to add accessibility attributes
142
+ getVdomConfig() {
143
+ let vdomConfig = super.getVdomConfig();
144
+ vdomConfig.role = this.role;
145
+ if (this.pressed) {
146
+ vdomConfig['aria-selected'] = true;
147
+ }
148
+ return vdomConfig;
149
+ }
150
+ }
151
+ ```
152
+
153
+ ## When to Use Each Pattern: A Hybrid Approach
154
+
155
+ Neo.mjs v10 does not force you to choose one pattern over the other. Instead, it empowers you to use the right tool for the job.
156
+
157
+ **Use the Declarative `Effect` Pattern when (Recommended Default):**
158
+ * Building most of your application components.
159
+ * You value developer experience, readability, and maintainability.
160
+ * The component's VDOM structure can be expressed as a pure function of its state.
161
+
162
+ **Use the Imperative `afterSet` Pattern when:**
163
+ * You are building a highly complex, performance-critical component (e.g., a virtualized data grid or a canvas-based chart).
164
+ * You need to perform surgical, hand-tuned VDOM manipulations for maximum performance, bypassing a full recalculation.
165
+
166
+ ## Conclusion
167
+
168
+ The new declarative VDOM pattern is a major leap forward for component development in Neo.mjs. It provides a more modern, readable, and robust way to build components, while the classic imperative pattern remains a powerful tool for fine-grained performance optimization. By understanding both, you can build sophisticated, high-performance applications with an exceptional developer experience.
@@ -1,3 +1,4 @@
1
+ # Extending Neo Classes
1
2
 
2
3
  Neo.mjs is built upon a robust and consistent class system. Understanding how to extend framework classes is fundamental
3
4
  to building custom functionality, whether you're creating new UI components, defining data structures, or implementing
@@ -1,3 +1,5 @@
1
+ # Instance Lifecycle
2
+
1
3
  Understanding the lifecycle of a class instance in Neo.mjs is crucial for building robust and predictable
2
4
  applications. The framework provides a series of well-defined hooks that allow you to tap into different stages of an
3
5
  instance's life, from its creation to its destruction.
@@ -292,4 +294,4 @@ With this pattern, the `columnPositions` collection is **not** created during th
292
294
  instantiated the very first time some other code calls `this.columnPositions`.
293
295
 
294
296
  Use the get-driven approach for non-essential or heavy nested instances to optimize performance and memory usage,
295
- especially if they are only used in specific scenarios.
297
+ especially if they are only used in specific scenarios.
@@ -1,3 +1,5 @@
1
+ # Main Thread Addons: Interacting with the Browser
2
+
1
3
  Neo.mjs is multi-threaded. There are worker threads that handle data access, application logic, and
2
4
  keeping track of DOM updates. Practically all your application logic is run in parallel in these
3
5
  threads. However, anything that needs to actually reference or update the DOM (`window.document`),
@@ -1 +1,3 @@
1
- ## todo
1
+ # Mixins
2
+
3
+ todo
@@ -1 +1,3 @@
1
- ## todo
1
+ # Multi-Window Applications
2
+
3
+ todo
@@ -1,3 +1,5 @@
1
+ # Portal App
2
+
1
3
  ## Study the Code
2
4
 
3
5
  As you hopefully have noticed by now, this entire multi-window app is created based on Neo.mjs.
@@ -1,3 +1,5 @@
1
+ # Component and Container Basics
2
+
1
3
  Neo.mjs views are made up of components and containers.
2
4
 
3
5
  A component is a visual widget, such as a button, label, or text field. A container is a visual
@@ -1,3 +1,5 @@
1
+ # Custom Components
2
+
1
3
  ## Introduction
2
4
 
3
5
  A major strength of Neo.mjs is its extensive library of components. In most cases, you can build sophisticated
@@ -1,3 +1,5 @@
1
+ # Layouts
2
+
1
3
  ## Understanding Layouts in Neo.mjs
2
4
 
3
5
  Layouts are fundamental to arranging components within your application's user interface. In Neo.mjs, layouts are
@@ -1,3 +1,5 @@
1
+ # Working with VDom
2
+
1
3
  ## A Comprehensive Guide to Custom Component Development
2
4
 
3
5
  **Target Audience**: Developers building custom Neo.mjs components who need to work directly with the VDom layer for performance optimization, complex animations, or advanced UI patterns.
@@ -1,3 +1,5 @@
1
+ # User Input (Forms)
2
+
1
3
  The Neo.mjs Forms Engine provides a powerful and flexible way to build
2
4
  user interfaces for data input and validation. This guide will walk you
3
5
  through the core concepts and practical usage of forms in Neo.mjs,
@@ -1,5 +1,6 @@
1
- As you read in the <a href="#/learn/Events">Getting Started > Events</a> topic, components, stores, and many other objects fire events.
1
+ # Custom Events
2
2
 
3
+ As you read in the <a href="#/learn/Events">Getting Started > Events</a> topic, components, stores, and many other objects fire events.
3
4
 
4
5
  ```javascript live-preview
5
6
  import Container from '../container/Base.mjs';
@@ -1,3 +1,5 @@
1
+ # DOM Events
2
+
1
3
  ## Delegated global DOM Events
2
4
 
3
5
  By default, Neo.mjs will attach DOM event listeners for all common events to the `document.body`.
@@ -1,5 +1,6 @@
1
- Neo.mjs uses standard modular JavaScript, so you're free to use other class
2
- features, like private members.
1
+ # Other JavaScript Class Features
2
+
3
+ Neo.mjs uses standard modular JavaScript, so you're free to use other class features, like private members.
3
4
 
4
5
  ```javascript readonly
5
6
  class Human extends Mammal {
@@ -27,7 +28,7 @@ class Human extends Mammal {
27
28
  }
28
29
  }
29
30
 
30
- Neo.setupClass(Human);
31
+ Human = Neo.setupClass(Human);
31
32
 
32
33
  const myPerson = Neo.create(Human, {
33
34
  name: 'Herbert'
@@ -1,3 +1,5 @@
1
+ # Classes, Properties, and Methods
2
+
1
3
  Neo.mjs classes are standard JavaScript classes. Every source file
2
4
  you write will be a class definition, extending some Neo.mjs
3
5
  class.
@@ -13,8 +15,8 @@ class Mammal extends Base {
13
15
 
14
16
  const myMammal = Neo.create(Mammal);
15
17
 
16
- Neo.setupClass(Mammal); // Where Neo.mjs initializes the class config.
17
- export default Mammal; // Makes the class available elsewhere.
18
+ // Where Neo.mjs initializes the class and makes the class available elsewhere.
19
+ export default Neo.setupClass(Mammal);
18
20
  ```
19
21
 
20
22
  In the example above, we're extending the Neo.mjs base class. The static
@@ -40,16 +42,14 @@ class Mammal extends Base {
40
42
  }
41
43
 
42
44
  const myMammal = Neo.create(Mammal);
43
- console.log(myMammal.name); // Logs "Anonymous"
45
+ console.log(myMammal.name); // Logs "Anonymous"
44
46
  myMammal.name = 'Herbert';
45
- console.log(myMammal.name); // Logs "Herbert"
46
-
47
- Neo.setupClass(Mammal);
47
+ console.log(myMammal.name); // Logs "Herbert"
48
48
 
49
- export default Mammal;
49
+ export default Neo.setupClass(Mammal);
50
50
  ```
51
51
 
52
- In Neo.mjs, instance properties are usually added in the `static config` block.
52
+ In Neo.mjs, instance properties are usually added in the `static config` block.</br>
53
53
  The `static config` block does two things:
54
54
  - It formally describes the properties API for your class.
55
55
  - It lets Neo.mjs manage the initialization and lifecycle of those properties.
@@ -65,10 +65,9 @@ the instance, using the second argument to the `create` method.
65
65
  const myMammal = Neo.create(Mammal, {
66
66
  name: 'Creature'
67
67
  });
68
- console.log(myMammal.name); // Logs "Creature"
68
+ console.log(myMammal.name); // Logs "Creature"
69
69
  ```
70
70
 
71
-
72
71
  Since _you_ define those properties, you can
73
72
  look for them in class methods and use them as needed.
74
73
  Let's add a `speak()` method that uses the `name` property.
@@ -93,9 +92,7 @@ const myMammal = Neo.create(Mammal, {
93
92
 
94
93
  myMammal.speak(); // Logs "Creature is grunting."
95
94
 
96
- Neo.setupClass(Mammal);
97
-
98
- export default Mammal;
95
+ export default Neo.setupClass(Mammal);
99
96
  ```
100
97
 
101
98
 
@@ -1,3 +1,5 @@
1
+ # Overriding Methods
2
+
1
3
  In Neo.mjs you sub-class and override methods in the usual way.
2
4
 
3
5
  Here, we'll extend `Mammal` and override the `speak()` method.
@@ -14,7 +16,7 @@ class Mammal extends Base {
14
16
  console.log(`(${this.name} is grunting)`);
15
17
  }
16
18
  }
17
- Neo.setupClass(Mammal);
19
+ export default Neo.setupClass(Mammal);
18
20
  ```
19
21
 
20
22
  ```javascript readonly
@@ -30,9 +32,9 @@ class Human extends Mammal {
30
32
  const myMammal = Neo.create(Human, {
31
33
  name: 'Herbert'
32
34
  });
33
- myMammal.speak(); // Logs "Hello! My name is Herbert. I am not married."
35
+ myMammal.speak(); // Logs "Hello! My name is Herbert. I am not married."
34
36
 
35
- Neo.setupClass(Mammal);
37
+ export default Neo.setupClass(Human);
36
38
  ```
37
39
 
38
40
  Any class in the hierarchy is free to add new properties and methods. Let's add
@@ -51,6 +53,7 @@ class Mammal extends Base {
51
53
  console.log(`(${this.name} is grunting)`);
52
54
  }
53
55
  }
56
+ export default Neo.setupClass(Mammal);
54
57
  ```
55
58
 
56
59
  ```javascript readonly
@@ -70,8 +73,9 @@ class Human extends Mammal {
70
73
  const myPerson = Neo.create(Human, {
71
74
  name: 'Herbert'
72
75
  });
73
- myPerson.speak(); // Logs "Hello! My name is Herbert. I am not married."
74
- myPerson.yodel(); // Logs "Yodelay hee hoo!"
75
76
 
76
- Neo.setupClass(Human);
77
+ myPerson.speak(); // Logs "Hello! My name is Herbert. I am not married."
78
+ myPerson.yodel(); // Logs "Yodelay hee hoo!"
79
+
80
+ export default Neo.setupClass(Human);
77
81
  ```