neo.mjs 10.0.0-beta.5 → 10.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (491) hide show
  1. package/.github/RELEASE_NOTES/v10.0.0-beta.1.md +20 -0
  2. package/.github/RELEASE_NOTES/v10.0.0-beta.2.md +73 -0
  3. package/.github/RELEASE_NOTES/v10.0.0-beta.3.md +39 -0
  4. package/.github/RELEASE_NOTES/v10.0.0-beta.5.md +70 -0
  5. package/.github/RELEASE_NOTES/v10.0.0-beta.6.md +48 -0
  6. package/.github/RELEASE_NOTES/v10.0.0.md +52 -0
  7. package/.github/epic-functional-components.md +498 -0
  8. package/.github/ticket-asymmetric-vdom-updates.md +122 -0
  9. package/README.md +0 -3
  10. package/ServiceWorker.mjs +2 -2
  11. package/apps/colors/store/Colors.mjs +1 -0
  12. package/apps/colors/view/GridContainer.mjs +3 -0
  13. package/apps/colors/view/HeaderToolbar.mjs +2 -0
  14. package/apps/colors/view/Viewport.mjs +3 -0
  15. package/apps/covid/view/FooterContainer.mjs +3 -0
  16. package/apps/covid/view/GalleryContainer.mjs +2 -0
  17. package/apps/covid/view/GalleryContainerController.mjs +1 -0
  18. package/apps/covid/view/HeaderContainer.mjs +2 -0
  19. package/apps/covid/view/HelixContainer.mjs +2 -0
  20. package/apps/covid/view/HelixContainerController.mjs +1 -0
  21. package/apps/covid/view/MainContainer.mjs +3 -0
  22. package/apps/covid/view/TableContainer.mjs +3 -0
  23. package/apps/covid/view/TableContainerController.mjs +1 -0
  24. package/apps/covid/view/WorldMapContainer.mjs +2 -0
  25. package/apps/covid/view/country/Gallery.mjs +3 -0
  26. package/apps/covid/view/country/Helix.mjs +8 -0
  27. package/apps/covid/view/country/HistoricalDataTable.mjs +1 -0
  28. package/apps/covid/view/country/Table.mjs +2 -0
  29. package/apps/covid/view/mapboxGl/Component.mjs +1 -0
  30. package/apps/covid/view/mapboxGl/Container.mjs +2 -0
  31. package/apps/email/EPIC_PLAN.md +58 -0
  32. package/apps/email/neo-config.json +2 -2
  33. package/apps/email/store/Emails.mjs +11 -1
  34. package/apps/email/view/ComposeView.mjs +44 -0
  35. package/apps/email/view/MainView.mjs +89 -0
  36. package/apps/email/view/Viewport.mjs +4 -33
  37. package/apps/email/view/ViewportStateProvider.mjs +3 -3
  38. package/apps/form/store/SideNav.mjs +1 -0
  39. package/apps/form/view/FormContainer.mjs +1 -0
  40. package/apps/form/view/FormPageContainer.mjs +2 -0
  41. package/apps/form/view/SideNavList.mjs +1 -0
  42. package/apps/form/view/Viewport.mjs +3 -0
  43. package/apps/portal/childapps/preview/MainContainer.mjs +1 -0
  44. package/apps/portal/index.html +1 -1
  45. package/apps/portal/store/BlogPosts.mjs +2 -0
  46. package/apps/portal/store/Content.mjs +1 -0
  47. package/apps/portal/store/ContentSections.mjs +1 -0
  48. package/apps/portal/store/Examples.mjs +1 -0
  49. package/apps/portal/view/HeaderToolbar.mjs +1 -0
  50. package/apps/portal/view/Viewport.mjs +5 -0
  51. package/apps/portal/view/ViewportController.mjs +11 -3
  52. package/apps/portal/view/about/Container.mjs +2 -0
  53. package/apps/portal/view/about/MemberContainer.mjs +7 -0
  54. package/apps/portal/view/blog/Container.mjs +2 -0
  55. package/apps/portal/view/blog/List.mjs +2 -0
  56. package/apps/portal/view/examples/List.mjs +29 -19
  57. package/apps/portal/view/examples/TabContainer.mjs +4 -0
  58. package/apps/portal/view/home/ContentBox.mjs +3 -0
  59. package/apps/portal/view/home/FeatureSection.mjs +8 -0
  60. package/apps/portal/view/home/FooterContainer.mjs +4 -1
  61. package/apps/portal/view/home/MainContainer.mjs +2 -0
  62. package/apps/portal/view/home/parts/AfterMath.mjs +2 -0
  63. package/apps/portal/view/home/parts/BaseContainer.mjs +1 -0
  64. package/apps/portal/view/home/parts/Colors.mjs +4 -0
  65. package/apps/portal/view/home/parts/Features.mjs +2 -0
  66. package/apps/portal/view/home/parts/Helix.mjs +5 -0
  67. package/apps/portal/view/home/parts/How.mjs +4 -0
  68. package/apps/portal/view/home/parts/MainNeo.mjs +1 -0
  69. package/apps/portal/view/home/parts/References.mjs +2 -0
  70. package/apps/portal/view/learn/ContentComponent.mjs +11 -5
  71. package/apps/portal/view/learn/ContentTreeList.mjs +2 -0
  72. package/apps/portal/view/learn/CubeLayoutButton.mjs +1 -0
  73. package/apps/portal/view/learn/MainContainer.mjs +4 -0
  74. package/apps/portal/view/learn/PageContainer.mjs +2 -0
  75. package/apps/portal/view/learn/PageSectionsContainer.mjs +3 -0
  76. package/apps/portal/view/learn/PageSectionsList.mjs +1 -0
  77. package/apps/portal/view/services/Component.mjs +1 -0
  78. package/apps/realworld/api/Base.mjs +1 -0
  79. package/apps/realworld/view/HeaderComponent.mjs +4 -0
  80. package/apps/realworld/view/HomeComponent.mjs +7 -0
  81. package/apps/realworld/view/MainContainer.mjs +2 -0
  82. package/apps/realworld/view/MainContainerController.mjs +2 -0
  83. package/apps/realworld/view/article/CommentComponent.mjs +3 -0
  84. package/apps/realworld/view/article/Component.mjs +17 -10
  85. package/apps/realworld/view/article/CreateCommentComponent.mjs +2 -0
  86. package/apps/realworld/view/article/CreateComponent.mjs +5 -0
  87. package/apps/realworld/view/article/PreviewComponent.mjs +9 -0
  88. package/apps/realworld/view/article/TagListComponent.mjs +2 -0
  89. package/apps/realworld/view/user/ProfileComponent.mjs +7 -0
  90. package/apps/realworld/view/user/SettingsComponent.mjs +5 -0
  91. package/apps/realworld/view/user/SignUpComponent.mjs +3 -0
  92. package/apps/realworld2/api/Base.mjs +1 -0
  93. package/apps/realworld2/view/FooterComponent.mjs +1 -0
  94. package/apps/realworld2/view/HeaderToolbar.mjs +3 -0
  95. package/apps/realworld2/view/HomeContainer.mjs +1 -0
  96. package/apps/realworld2/view/MainContainer.mjs +2 -0
  97. package/apps/realworld2/view/MainContainerController.mjs +1 -0
  98. package/apps/realworld2/view/article/Helix.mjs +1 -0
  99. package/apps/realworld2/view/article/PreviewComponent.mjs +9 -0
  100. package/apps/realworld2/view/article/PreviewList.mjs +1 -0
  101. package/apps/realworld2/view/article/TagListComponent.mjs +2 -0
  102. package/apps/route/view/CenterContainer.mjs +1 -0
  103. package/apps/route/view/MainView.mjs +1 -0
  104. package/apps/sharedcovid/childapps/sharedcovidchart/MainContainer.mjs +1 -0
  105. package/apps/sharedcovid/childapps/sharedcovidgallery/MainContainer.mjs +1 -0
  106. package/apps/sharedcovid/childapps/sharedcovidhelix/MainContainer.mjs +1 -0
  107. package/apps/sharedcovid/childapps/sharedcovidmap/MainContainer.mjs +1 -0
  108. package/apps/sharedcovid/view/FooterContainer.mjs +3 -0
  109. package/apps/sharedcovid/view/GalleryContainer.mjs +2 -0
  110. package/apps/sharedcovid/view/GalleryContainerController.mjs +1 -0
  111. package/apps/sharedcovid/view/HeaderContainer.mjs +2 -0
  112. package/apps/sharedcovid/view/HelixContainer.mjs +2 -0
  113. package/apps/sharedcovid/view/HelixContainerController.mjs +1 -0
  114. package/apps/sharedcovid/view/MainContainer.mjs +3 -0
  115. package/apps/sharedcovid/view/TableContainer.mjs +3 -0
  116. package/apps/sharedcovid/view/TableContainerController.mjs +1 -0
  117. package/apps/sharedcovid/view/WorldMapContainer.mjs +2 -0
  118. package/apps/sharedcovid/view/country/Gallery.mjs +3 -0
  119. package/apps/sharedcovid/view/country/Helix.mjs +8 -0
  120. package/apps/sharedcovid/view/country/HistoricalDataTable.mjs +1 -0
  121. package/apps/sharedcovid/view/country/Table.mjs +2 -0
  122. package/apps/sharedcovid/view/mapboxGl/Component.mjs +1 -0
  123. package/apps/sharedcovid/view/mapboxGl/Container.mjs +2 -0
  124. package/apps/shareddialog/childapps/shareddialog2/view/MainContainer.mjs +2 -0
  125. package/apps/shareddialog/view/DemoDialog.mjs +2 -0
  126. package/apps/shareddialog/view/MainContainer.mjs +2 -0
  127. package/apps/shareddialog/view/MainContainerController.mjs +1 -0
  128. package/buildScripts/addReactiveTags.mjs +191 -0
  129. package/buildScripts/checkReactiveTags.mjs +160 -0
  130. package/docs/app/store/Api.mjs +1 -0
  131. package/docs/app/store/Examples.mjs +1 -0
  132. package/docs/app/view/ApiTreeList.mjs +1 -0
  133. package/docs/app/view/ContentTabContainer.mjs +2 -0
  134. package/docs/app/view/ExamplesTreeList.mjs +2 -0
  135. package/docs/app/view/HeaderContainer.mjs +3 -0
  136. package/docs/app/view/MainContainer.mjs +5 -0
  137. package/docs/app/view/classdetails/HeaderComponent.mjs +1 -0
  138. package/docs/app/view/classdetails/MainContainer.mjs +3 -0
  139. package/docs/app/view/classdetails/MembersList.mjs +5 -0
  140. package/docs/app/view/classdetails/SourceViewComponent.mjs +2 -0
  141. package/examples/ConfigurationViewport.mjs +14 -8
  142. package/examples/calendar/weekview/MainContainer.mjs +4 -0
  143. package/examples/component/coronaGallery/CountryGallery.mjs +2 -0
  144. package/examples/component/coronaGallery/CountryStore.mjs +1 -0
  145. package/examples/component/coronaGallery/Viewport.mjs +3 -0
  146. package/examples/component/coronaGallery/ViewportController.mjs +1 -0
  147. package/examples/component/coronaHelix/CountryHelix.mjs +7 -0
  148. package/examples/component/coronaHelix/MainContainer.mjs +1 -0
  149. package/examples/component/gallery/ImageStore.mjs +1 -0
  150. package/examples/component/helix/ImageStore.mjs +1 -0
  151. package/examples/component/helix/Viewport.mjs +3 -0
  152. package/examples/component/helix/ViewportController.mjs +1 -0
  153. package/examples/component/multiWindowCoronaGallery/childapp/Viewport.mjs +1 -0
  154. package/examples/component/multiWindowHelix/childapp/Viewport.mjs +1 -0
  155. package/examples/component/wrapper/googleMaps/MapComponent.mjs +2 -0
  156. package/examples/core/config/MainContainer.mjs +2 -0
  157. package/examples/dialog/DemoDialog.mjs +2 -0
  158. package/examples/dialog/MainContainer.mjs +1 -0
  159. package/examples/form/field/color/MainStore.mjs +1 -0
  160. package/examples/functional/button/base/MainContainer.mjs +207 -0
  161. package/examples/functional/button/base/app.mjs +6 -0
  162. package/examples/functional/button/base/index.html +11 -0
  163. package/examples/functional/button/base/neo-config.json +6 -0
  164. package/examples/functional/defineComponent/Component.mjs +18 -0
  165. package/examples/functional/defineComponent/MainContainer.mjs +41 -0
  166. package/examples/functional/defineComponent/app.mjs +6 -0
  167. package/examples/functional/defineComponent/index.html +11 -0
  168. package/examples/functional/defineComponent/neo-config.json +6 -0
  169. package/examples/functional/hostComponent/Component.mjs +32 -0
  170. package/examples/functional/hostComponent/MainContainer.mjs +48 -0
  171. package/examples/functional/hostComponent/app.mjs +6 -0
  172. package/examples/functional/hostComponent/index.html +11 -0
  173. package/examples/functional/hostComponent/neo-config.json +6 -0
  174. package/examples/grid/animatedRowSorting/Viewport.mjs +1 -1
  175. package/examples/grid/bigData/ControlsContainer.mjs +3 -0
  176. package/examples/grid/bigData/GridContainer.mjs +4 -2
  177. package/examples/grid/bigData/MainContainer.mjs +2 -0
  178. package/examples/grid/bigData/MainModel.mjs +1 -0
  179. package/examples/grid/bigData/MainStore.mjs +3 -0
  180. package/examples/grid/cellEditing/MainContainer.mjs +1 -1
  181. package/examples/grid/container/MainContainer.mjs +1 -1
  182. package/examples/grid/covid/GridContainer.mjs +3 -0
  183. package/examples/grid/covid/MainContainer.mjs +2 -0
  184. package/examples/grid/covid/Store.mjs +1 -0
  185. package/examples/grid/nestedRecordFields/EditUserDialog.mjs +3 -0
  186. package/examples/grid/nestedRecordFields/Viewport.mjs +3 -1
  187. package/examples/list/animate/List.mjs +4 -0
  188. package/examples/list/animate/MainContainer.mjs +2 -0
  189. package/examples/list/circle/MainStore.mjs +1 -0
  190. package/examples/list/color/MainStore.mjs +1 -0
  191. package/examples/preloadingAssets/view/MainContainer.mjs +2 -0
  192. package/examples/stateProvider/advanced/MainContainer.mjs +1 -0
  193. package/examples/stateProvider/dialog/EditUserDialog.mjs +2 -0
  194. package/examples/stateProvider/dialog/MainContainer.mjs +1 -0
  195. package/examples/stateProvider/extendedClass/MainContainer.mjs +2 -0
  196. package/examples/stateProvider/inline/MainContainer.mjs +1 -0
  197. package/examples/stateProvider/inlineNoStateProvider/MainContainer.mjs +1 -0
  198. package/examples/stateProvider/inlineNoStateProvider/MainContainerController.mjs +2 -0
  199. package/examples/stateProvider/multiWindow/EditUserDialog.mjs +3 -0
  200. package/examples/stateProvider/multiWindow/MainContainer.mjs +1 -0
  201. package/examples/stateProvider/multiWindow/Viewport.mjs +1 -0
  202. package/examples/stateProvider/nestedData/MainContainer.mjs +1 -0
  203. package/examples/stateProvider/table/MainContainer.mjs +1 -0
  204. package/examples/table/covid/MainContainer.mjs +2 -0
  205. package/examples/table/covid/Store.mjs +1 -0
  206. package/examples/table/covid/TableContainer.mjs +3 -0
  207. package/examples/table/nestedRecordFields/EditUserDialog.mjs +3 -0
  208. package/examples/table/nestedRecordFields/Viewport.mjs +1 -0
  209. package/examples/todoList/version1/MainComponent.mjs +1 -1
  210. package/examples/toolbar/breadcrumb/view/MainContainer.mjs +2 -0
  211. package/examples/toolbar/paging/store/Users.mjs +1 -0
  212. package/examples/toolbar/paging/view/AddUserDialog.mjs +3 -0
  213. package/examples/toolbar/paging/view/MainContainer.mjs +3 -0
  214. package/examples/treeAccordion/MainContainer.mjs +2 -2
  215. package/examples/worker/task/MainContainer.mjs +1 -0
  216. package/learn/Glossary.md +1 -0
  217. package/learn/UsingTheseTopics.md +1 -0
  218. package/learn/benefits/ConfigSystem.md +2 -0
  219. package/learn/benefits/Effort.md +1 -0
  220. package/learn/benefits/Features.md +1 -0
  221. package/learn/benefits/FormsEngine.md +1 -0
  222. package/learn/benefits/FourEnvironments.md +2 -0
  223. package/learn/benefits/Introduction.md +2 -0
  224. package/learn/benefits/MultiWindow.md +3 -1
  225. package/learn/benefits/OffTheMainThread.md +2 -0
  226. package/learn/benefits/Quick.md +2 -0
  227. package/learn/benefits/RPCLayer.md +2 -0
  228. package/learn/benefits/Speed.md +2 -0
  229. package/learn/blog/v10-deep-dive-functional-components.md +293 -0
  230. package/learn/blog/v10-deep-dive-reactivity.md +522 -0
  231. package/learn/blog/v10-deep-dive-state-provider.md +432 -0
  232. package/learn/blog/v10-deep-dive-vdom-revolution.md +194 -0
  233. package/learn/blog/v10-post1-love-story.md +383 -0
  234. package/learn/comparisons/NeoVsAngular.md +90 -0
  235. package/learn/comparisons/NeoVsExtJs.md +178 -0
  236. package/learn/comparisons/NeoVsNextJs.md +124 -0
  237. package/learn/comparisons/NeoVsReact.md +95 -0
  238. package/learn/comparisons/NeoVsSolid.md +78 -0
  239. package/learn/comparisons/NeoVsVue.md +92 -0
  240. package/learn/comparisons/Overview.md +46 -0
  241. package/learn/gettingstarted/ComponentModels.md +2 -0
  242. package/learn/gettingstarted/Config.md +2 -0
  243. package/learn/gettingstarted/DescribingTheUI.md +2 -0
  244. package/learn/gettingstarted/Events.md +2 -0
  245. package/learn/gettingstarted/Extending.md +2 -0
  246. package/learn/gettingstarted/References.md +2 -0
  247. package/learn/gettingstarted/Setup.md +3 -2
  248. package/learn/gettingstarted/Workspaces.md +2 -0
  249. package/learn/guides/datahandling/Collections.md +1 -0
  250. package/learn/guides/datahandling/Records.md +1 -0
  251. package/learn/guides/datahandling/StateProviders.md +130 -16
  252. package/learn/guides/datahandling/Tables.md +1 -1
  253. package/learn/guides/fundamentals/ConfigSystemDeepDive.md +1 -0
  254. package/learn/guides/fundamentals/DeclarativeComponentTreesVsImperativeVdom.md +2 -0
  255. package/learn/guides/fundamentals/DeclarativeVDOMWithEffects.md +10 -8
  256. package/learn/guides/fundamentals/ExtendingNeoClasses.md +1 -0
  257. package/learn/guides/fundamentals/InstanceLifecycle.md +3 -1
  258. package/learn/guides/fundamentals/MainThreadAddons.md +2 -0
  259. package/learn/guides/specificfeatures/Mixins.md +3 -1
  260. package/learn/guides/specificfeatures/MultiWindow.md +3 -1
  261. package/learn/guides/specificfeatures/PortalApp.md +2 -0
  262. package/learn/guides/uibuildingblocks/ComponentsAndContainers.md +2 -0
  263. package/learn/guides/uibuildingblocks/CustomComponents.md +2 -0
  264. package/learn/guides/uibuildingblocks/Layouts.md +2 -0
  265. package/learn/guides/uibuildingblocks/WorkingWithVDom.md +28 -2
  266. package/learn/guides/userinteraction/Forms.md +2 -0
  267. package/learn/guides/userinteraction/events/CustomEvents.md +2 -1
  268. package/learn/guides/userinteraction/events/DomEvents.md +2 -0
  269. package/learn/javascript/ClassFeatures.md +4 -3
  270. package/learn/javascript/Classes.md +10 -13
  271. package/learn/javascript/Overrides.md +10 -6
  272. package/learn/javascript/Super.md +12 -8
  273. package/learn/tree.json +71 -64
  274. package/learn/tutorials/Earthquakes.md +2 -0
  275. package/learn/tutorials/RSP.md +3 -1
  276. package/learn/tutorials/TodoList.md +103 -7
  277. package/package.json +8 -6
  278. package/resources/scss/src/apps/email/ComposeView.scss +16 -0
  279. package/resources/scss/src/apps/email/MainView.scss +5 -0
  280. package/resources/scss/src/apps/portal/learn/ContentComponent.scss +5 -4
  281. package/src/DefaultConfig.mjs +12 -2
  282. package/src/Main.mjs +1 -0
  283. package/src/Neo.mjs +219 -166
  284. package/src/Xhr.mjs +1 -0
  285. package/src/button/Base.mjs +13 -0
  286. package/src/button/Effect.mjs +16 -2
  287. package/src/button/Split.mjs +2 -0
  288. package/src/calendar/store/Calendars.mjs +1 -0
  289. package/src/calendar/store/Colors.mjs +1 -0
  290. package/src/calendar/store/Events.mjs +1 -0
  291. package/src/calendar/view/DayComponent.mjs +2 -0
  292. package/src/calendar/view/EditEventContainer.mjs +4 -1
  293. package/src/calendar/view/MainContainer.mjs +13 -0
  294. package/src/calendar/view/MainContainerStateProvider.mjs +14 -28
  295. package/src/calendar/view/SettingsContainer.mjs +1 -0
  296. package/src/calendar/view/YearComponent.mjs +16 -0
  297. package/src/calendar/view/calendars/ColorsList.mjs +2 -0
  298. package/src/calendar/view/calendars/Container.mjs +2 -0
  299. package/src/calendar/view/calendars/EditContainer.mjs +1 -0
  300. package/src/calendar/view/month/Component.mjs +11 -0
  301. package/src/calendar/view/settings/GeneralContainer.mjs +1 -0
  302. package/src/calendar/view/settings/MonthContainer.mjs +1 -0
  303. package/src/calendar/view/settings/WeekContainer.mjs +1 -0
  304. package/src/calendar/view/settings/YearContainer.mjs +1 -0
  305. package/src/calendar/view/week/Component.mjs +15 -1
  306. package/src/calendar/view/week/TimeAxisComponent.mjs +4 -0
  307. package/src/code/LivePreview.mjs +51 -23
  308. package/src/collection/Base.mjs +7 -10
  309. package/src/collection/Filter.mjs +6 -0
  310. package/src/collection/Sorter.mjs +3 -0
  311. package/src/component/Abstract.mjs +412 -0
  312. package/src/component/Base.mjs +48 -1077
  313. package/src/component/Canvas.mjs +1 -0
  314. package/src/component/Chip.mjs +4 -0
  315. package/src/component/Circle.mjs +14 -0
  316. package/src/component/Clock.mjs +4 -0
  317. package/src/component/DateSelector.mjs +12 -0
  318. package/src/component/Gallery.mjs +11 -0
  319. package/src/component/Helix.mjs +24 -0
  320. package/src/component/Label.mjs +1 -0
  321. package/src/component/Legend.mjs +3 -0
  322. package/src/component/MagicMoveText.mjs +4 -0
  323. package/src/component/Progress.mjs +3 -0
  324. package/src/component/Splitter.mjs +3 -0
  325. package/src/component/StatusBadge.mjs +6 -0
  326. package/src/component/Timer.mjs +4 -0
  327. package/src/component/Toast.mjs +6 -0
  328. package/src/component/Video.mjs +1 -0
  329. package/src/component/mwc/Button.mjs +7 -0
  330. package/src/component/mwc/TextField.mjs +9 -0
  331. package/src/component/wrapper/AmChart.mjs +2 -0
  332. package/src/component/wrapper/GoogleMaps.mjs +3 -0
  333. package/src/component/wrapper/MapboxGL.mjs +5 -0
  334. package/src/component/wrapper/MonacoEditor.mjs +12 -0
  335. package/src/container/Accordion.mjs +2 -0
  336. package/src/container/Base.mjs +7 -3
  337. package/src/container/Panel.mjs +1 -0
  338. package/src/container/Viewport.mjs +1 -0
  339. package/src/controller/Application.mjs +1 -0
  340. package/src/controller/Base.mjs +1 -0
  341. package/src/controller/Component.mjs +1 -0
  342. package/src/core/Base.mjs +86 -33
  343. package/src/core/Compare.mjs +4 -7
  344. package/src/core/Config.mjs +65 -52
  345. package/src/core/Effect.mjs +86 -24
  346. package/src/core/EffectManager.mjs +117 -8
  347. package/src/core/IdGenerator.mjs +13 -44
  348. package/src/core/Observable.mjs +69 -65
  349. package/src/data/Model.mjs +2 -0
  350. package/src/data/Store.mjs +7 -0
  351. package/src/data/connection/WebSocket.mjs +2 -0
  352. package/src/date/DayViewComponent.mjs +2 -0
  353. package/src/date/SelectorContainer.mjs +14 -0
  354. package/src/dialog/Base.mjs +8 -0
  355. package/src/draggable/DragZone.mjs +5 -0
  356. package/src/draggable/tree/DragZone.mjs +1 -0
  357. package/src/filter/BooleanContainer.mjs +2 -0
  358. package/src/filter/NumberContainer.mjs +3 -0
  359. package/src/filter/ToggleOperatorsButton.mjs +2 -0
  360. package/src/form/Fieldset.mjs +6 -0
  361. package/src/form/field/Base.mjs +7 -0
  362. package/src/form/field/CheckBox.mjs +18 -0
  363. package/src/form/field/Chip.mjs +1 -0
  364. package/src/form/field/ComboBox.mjs +8 -0
  365. package/src/form/field/Country.mjs +1 -0
  366. package/src/form/field/Currency.mjs +2 -0
  367. package/src/form/field/Date.mjs +4 -0
  368. package/src/form/field/Display.mjs +1 -0
  369. package/src/form/field/Email.mjs +1 -0
  370. package/src/form/field/FileUpload.mjs +7 -0
  371. package/src/form/field/Hidden.mjs +1 -0
  372. package/src/form/field/Number.mjs +7 -0
  373. package/src/form/field/Password.mjs +1 -0
  374. package/src/form/field/Phone.mjs +3 -0
  375. package/src/form/field/Picker.mjs +2 -0
  376. package/src/form/field/Radio.mjs +1 -0
  377. package/src/form/field/Range.mjs +3 -0
  378. package/src/form/field/Search.mjs +2 -0
  379. package/src/form/field/Text.mjs +43 -5
  380. package/src/form/field/TextArea.mjs +7 -0
  381. package/src/form/field/Time.mjs +6 -0
  382. package/src/form/field/Url.mjs +3 -0
  383. package/src/form/field/ZipCode.mjs +2 -0
  384. package/src/form/field/trigger/Base.mjs +3 -0
  385. package/src/form/field/trigger/Clear.mjs +2 -0
  386. package/src/form/field/trigger/CopyToClipboard.mjs +2 -0
  387. package/src/form/field/trigger/Date.mjs +1 -0
  388. package/src/form/field/trigger/Picker.mjs +1 -0
  389. package/src/form/field/trigger/Search.mjs +1 -0
  390. package/src/form/field/trigger/SpinDown.mjs +2 -0
  391. package/src/form/field/trigger/SpinUp.mjs +1 -0
  392. package/src/form/field/trigger/Time.mjs +2 -0
  393. package/src/functional/_export.mjs +6 -0
  394. package/src/functional/button/Base.mjs +384 -0
  395. package/src/functional/component/Base.mjs +405 -0
  396. package/src/functional/defineComponent.mjs +102 -0
  397. package/src/functional/useConfig.mjs +52 -0
  398. package/src/functional/useEvent.mjs +43 -0
  399. package/src/grid/Body.mjs +20 -1
  400. package/src/grid/Container.mjs +50 -60
  401. package/src/grid/ScrollManager.mjs +2 -0
  402. package/src/grid/VerticalScrollbar.mjs +2 -0
  403. package/src/grid/column/Base.mjs +2 -0
  404. package/src/grid/header/Button.mjs +7 -0
  405. package/src/grid/header/Toolbar.mjs +6 -0
  406. package/src/grid/plugin/AnimateRows.mjs +2 -0
  407. package/src/layout/Base.mjs +3 -0
  408. package/src/layout/Card.mjs +1 -0
  409. package/src/layout/Cube.mjs +18 -4
  410. package/src/layout/Fit.mjs +1 -0
  411. package/src/layout/Flexbox.mjs +7 -0
  412. package/src/layout/Form.mjs +2 -0
  413. package/src/layout/Grid.mjs +1 -0
  414. package/src/layout/HBox.mjs +1 -0
  415. package/src/layout/VBox.mjs +1 -0
  416. package/src/list/Base.mjs +13 -0
  417. package/src/list/Chip.mjs +1 -0
  418. package/src/list/Circle.mjs +2 -0
  419. package/src/list/Color.mjs +1 -0
  420. package/src/list/plugin/Animate.mjs +2 -0
  421. package/src/main/DeltaUpdates.mjs +1 -0
  422. package/src/main/DomEvents.mjs +2 -0
  423. package/src/main/addon/CloneNode.mjs +1 -0
  424. package/src/main/addon/Cookie.mjs +1 -0
  425. package/src/main/addon/GoogleMaps.mjs +1 -0
  426. package/src/main/addon/LocalStorage.mjs +1 -0
  427. package/src/main/addon/MapboxGL.mjs +1 -0
  428. package/src/main/addon/Markdown.mjs +1 -0
  429. package/src/main/addon/Navigator.mjs +1 -0
  430. package/src/main/addon/Popover.mjs +1 -0
  431. package/src/main/addon/Stylesheet.mjs +1 -0
  432. package/src/main/addon/WindowPosition.mjs +1 -0
  433. package/src/manager/Component.mjs +0 -71
  434. package/src/manager/VDomUpdate.mjs +320 -0
  435. package/src/menu/List.mjs +6 -0
  436. package/src/menu/Model.mjs +1 -0
  437. package/src/menu/Panel.mjs +3 -0
  438. package/src/menu/Store.mjs +1 -0
  439. package/src/mixin/DomEvents.mjs +130 -0
  440. package/src/mixin/VdomLifecycle.mjs +670 -0
  441. package/src/plugin/Base.mjs +1 -0
  442. package/src/plugin/Resizable.mjs +2 -0
  443. package/src/selection/Model.mjs +15 -18
  444. package/src/selection/grid/BaseModel.mjs +1 -0
  445. package/src/sitemap/Component.mjs +1 -0
  446. package/src/state/Provider.mjs +129 -87
  447. package/src/state/createHierarchicalDataProxy.mjs +39 -25
  448. package/src/tab/Container.mjs +6 -0
  449. package/src/tab/Strip.mjs +1 -0
  450. package/src/tab/header/Button.mjs +2 -0
  451. package/src/tab/header/EffectButton.mjs +2 -0
  452. package/src/tab/header/Toolbar.mjs +1 -0
  453. package/src/table/Body.mjs +3 -0
  454. package/src/table/Container.mjs +10 -0
  455. package/src/table/header/Button.mjs +8 -0
  456. package/src/table/header/Toolbar.mjs +5 -0
  457. package/src/table/plugin/CellEditing.mjs +1 -0
  458. package/src/toolbar/Base.mjs +4 -0
  459. package/src/toolbar/Breadcrumb.mjs +3 -0
  460. package/src/toolbar/Paging.mjs +5 -0
  461. package/src/tooltip/Base.mjs +2 -0
  462. package/src/tree/List.mjs +3 -0
  463. package/src/util/HashHistory.mjs +1 -0
  464. package/src/util/KeyNavigation.mjs +2 -0
  465. package/src/util/Matrix.mjs +1 -0
  466. package/src/util/VDom.mjs +18 -5
  467. package/src/util/VNode.mjs +7 -1
  468. package/src/util/vdom/TreeBuilder.mjs +105 -0
  469. package/src/vdom/Helper.mjs +35 -23
  470. package/src/vdom/VNode.mjs +4 -6
  471. package/src/worker/App.mjs +1 -0
  472. package/src/worker/Base.mjs +2 -0
  473. package/src/worker/Manager.mjs +2 -0
  474. package/src/worker/ServiceBase.mjs +6 -1
  475. package/src/worker/mixin/RemoteMethodAccess.mjs +1 -6
  476. package/test/siesta/siesta.js +17 -2
  477. package/test/siesta/tests/VdomCalendar.mjs +19 -15
  478. package/test/siesta/tests/VdomHelper.mjs +7 -7
  479. package/test/siesta/tests/classic/Button.mjs +113 -0
  480. package/test/siesta/tests/core/Effect.mjs +10 -14
  481. package/test/siesta/tests/core/EffectBatching.mjs +72 -79
  482. package/test/siesta/tests/functional/Button.mjs +113 -0
  483. package/test/siesta/tests/state/ProviderNestedDataConfigs.mjs +314 -0
  484. package/test/siesta/tests/state/createHierarchicalDataProxy.mjs +42 -55
  485. package/test/siesta/tests/vdom/Advanced.mjs +14 -8
  486. package/test/siesta/tests/vdom/VdomAsymmetricUpdates.mjs +366 -0
  487. package/test/siesta/tests/vdom/VdomRealWorldUpdates.mjs +249 -0
  488. package/test/siesta/tests/vdom/layout/Cube.mjs +11 -7
  489. package/test/siesta/tests/vdom/table/Container.mjs +9 -5
  490. package/learn/javascript/NewNode.md +0 -31
  491. package/src/core/EffectBatchManager.mjs +0 -68
@@ -9,6 +9,8 @@ import RemoteMethodAccess from './mixin/RemoteMethodAccess.mjs';
9
9
  * The abstract base class for e.g. the App, Data & VDom worker
10
10
  * @class Neo.worker.Base
11
11
  * @extends Neo.core.Base
12
+ * @mixes Neo.core.Observable
13
+ * @mixes Neo.worker.mixin.RemoteMethodAccess
12
14
  * @abstract
13
15
  */
14
16
  class Worker extends Base {
@@ -18,6 +18,8 @@ navigator.serviceWorker?.addEventListener('controllerchange', function() {
18
18
  * Also, responsible for sending messages from the main thread to the different workers.
19
19
  * @class Neo.worker.Manager
20
20
  * @extends Neo.core.Base
21
+ * @mixes Neo.core.Observable
22
+ * @mixes Neo.worker.mixin.RemoteMethodAccess
21
23
  * @singleton
22
24
  */
23
25
  class Manager extends Base {
@@ -16,6 +16,7 @@ class ServiceBase extends Base {
16
16
  className: 'Neo.worker.ServiceBase',
17
17
  /**
18
18
  * @member {String} cacheName_='neo-runtime'
19
+ * @reactive
19
20
  */
20
21
  cacheName_: 'neo-runtime',
21
22
  /**
@@ -26,6 +27,7 @@ class ServiceBase extends Base {
26
27
  * Remote method access for other workers
27
28
  * @member {Object} remote={app: [//...]}
28
29
  * @protected
30
+ * @reactive
29
31
  */
30
32
  remote: {
31
33
  app: [
@@ -175,6 +177,8 @@ class ServiceBase extends Base {
175
177
  * @param {ExtendableMessageEvent} event
176
178
  */
177
179
  async onActivate(event) {
180
+ await globalThis.clients.claim();
181
+
178
182
  console.log('onActivate', event);
179
183
 
180
184
  let me = this,
@@ -229,7 +233,8 @@ class ServiceBase extends Base {
229
233
  * @param {ExtendableMessageEvent} event
230
234
  */
231
235
  onInstall(event) {
232
- console.log('onInstall', event)
236
+ console.log('onInstall', event);
237
+ globalThis.skipWaiting();
233
238
  }
234
239
 
235
240
  /**
@@ -10,12 +10,7 @@ class RemoteMethodAccess extends Base {
10
10
  * @member {String} className='Neo.worker.mixin.RemoteMethodAccess'
11
11
  * @protected
12
12
  */
13
- className: 'Neo.worker.mixin.RemoteMethodAccess',
14
- /**
15
- * @member {Boolean} mixin=true
16
- * @protected
17
- */
18
- mixin: true
13
+ className: 'Neo.worker.mixin.RemoteMethodAccess'
19
14
  }
20
15
 
21
16
  /**
@@ -48,7 +48,8 @@ project.plan(
48
48
  group: 'state',
49
49
  items: [
50
50
  'tests/state/createHierarchicalDataProxy.mjs',
51
- 'tests/state/Provider.mjs'
51
+ 'tests/state/Provider.mjs',
52
+ 'tests/state/ProviderNestedDataConfigs.mjs'
52
53
  ]
53
54
  },
54
55
  'tests/CollectionBase.mjs',
@@ -69,7 +70,21 @@ project.plan(
69
70
  'tests/vdom/table/Container.mjs'
70
71
  ]
71
72
  },
72
- 'tests/vdom/Advanced.mjs']
73
+ 'tests/vdom/Advanced.mjs',
74
+ 'tests/vdom/VdomAsymmetricUpdates.mjs',
75
+ 'tests/vdom/VdomRealWorldUpdates.mjs']
76
+ },
77
+ {
78
+ group: 'functional',
79
+ items: [
80
+ 'tests/functional/Button.mjs'
81
+ ]
82
+ },
83
+ {
84
+ group: 'classic',
85
+ items: [
86
+ 'tests/classic/Button.mjs'
87
+ ]
73
88
  }
74
89
  );
75
90
 
@@ -1,12 +1,16 @@
1
- import Neo from '../../../src/Neo.mjs';
2
- import * as core from '../../../src/core/_export.mjs';
3
- import NeoArray from '../../../src/util/Array.mjs';
4
- import Style from '../../../src/util/Style.mjs';
5
- import VdomHelper from '../../../src/vdom/Helper.mjs';
6
- import VDomUtil from '../../../src/util/VDom.mjs';
1
+ import Neo from '../../../src/Neo.mjs';
2
+ import * as core from '../../../src/core/_export.mjs';
3
+ import NeoArray from '../../../src/util/Array.mjs';
4
+ import Style from '../../../src/util/Style.mjs';
5
+ import StringFromVnode from '../../../src/vdom/util/StringFromVnode.mjs';
6
+ import VdomHelper from '../../../src/vdom/Helper.mjs';
7
+ import VDomUtil from '../../../src/util/VDom.mjs';
7
8
 
8
9
  let deltas, output, vdom, vnode;
9
10
 
11
+ // tests are designed for this rendering mode
12
+ Neo.config.useDomApiRenderer = false;
13
+
10
14
  StartTest(t => {
11
15
  t.it('Week view: Infinite Scrolling', t => {
12
16
  vdom =
@@ -23,7 +27,7 @@ StartTest(t => {
23
27
  {id: 'col-15'}
24
28
  ]};
25
29
 
26
- vnode = VdomHelper.create(vdom);
30
+ let vnode = VdomHelper.create({vdom}).vnode;
27
31
 
28
32
  vdom =
29
33
  {id: 'neo-vnode-1', cn: [
@@ -105,7 +109,7 @@ StartTest(t => {
105
109
  ]}
106
110
  ]};
107
111
 
108
- vnode = VdomHelper.create(vdom);
112
+ let vnode = VdomHelper.create({vdom}).vnode;
109
113
 
110
114
  vdom =
111
115
  {id: 'neo-calendar-week', cn: [
@@ -165,7 +169,7 @@ StartTest(t => {
165
169
  ]}
166
170
  ]};
167
171
 
168
- vnode = VdomHelper.create(vdom);
172
+ let vnode = VdomHelper.create({vdom}).vnode;
169
173
 
170
174
  vdom =
171
175
  {id: 'neo-calendar-week', cn: [
@@ -216,7 +220,7 @@ StartTest(t => {
216
220
  ]}
217
221
  ]};
218
222
 
219
- vnode = VdomHelper.create(vdom);
223
+ let vnode = VdomHelper.create({vdom}).vnode;
220
224
 
221
225
  vdom =
222
226
  {id: 'neo-calendar-week', cn: [
@@ -268,7 +272,7 @@ StartTest(t => {
268
272
  {id: 'neo-column-3'}
269
273
  ]};
270
274
 
271
- vnode = VdomHelper.create(vdom);
275
+ let vnode = VdomHelper.create({vdom}).vnode;
272
276
 
273
277
  vdom =
274
278
  {id: 'neo-calendar-week', cn: [
@@ -333,7 +337,7 @@ StartTest(t => {
333
337
  vdom =
334
338
  {id: 'neo-1'};
335
339
 
336
- vnode = VdomHelper.create(vdom);
340
+ vnode = VdomHelper.create({vdom}).vnode;
337
341
 
338
342
  vdom =
339
343
  {id: 'neo-1', removeDom: true};
@@ -358,7 +362,7 @@ StartTest(t => {
358
362
  ]}
359
363
  ]};
360
364
 
361
- vnode = VdomHelper.create(vdom);
365
+ vnode = VdomHelper.create({vdom}).vnode;
362
366
 
363
367
  vdom =
364
368
  {id: 'neo-calendar-week', cn: [
@@ -403,7 +407,7 @@ StartTest(t => {
403
407
  ]}
404
408
  ]};
405
409
 
406
- vnode = VdomHelper.create(vdom);
410
+ vnode = VdomHelper.create({vdom}).vnode;
407
411
 
408
412
  vdom =
409
413
  {tag: 'ul', id: 'neo-calendar-calendars-list-1', cn: [
@@ -1696,7 +1700,7 @@ StartTest(t => {
1696
1700
  }], tag: 'div'
1697
1701
  }
1698
1702
 
1699
- vnode = VdomHelper.create(vdom);
1703
+ let vnode = VdomHelper.create({vdom}).vnode;
1700
1704
 
1701
1705
  vdom =
1702
1706
  {cls: ['neo-c-m-scrollcontainer', 'neo-scroll-shadows', 'neo-is-scrolling'], id: 'neo-vnode-150', cn: [
@@ -1,13 +1,13 @@
1
- import Neo from '../../../src/Neo.mjs';
2
- import * as core from '../../../src/core/_export.mjs';
3
- import NeoArray from '../../../src/util/Array.mjs';
4
- import Style from '../../../src/util/Style.mjs';
5
- import VdomHelper from '../../../src/vdom/Helper.mjs';
6
- import VDomUtil from '../../../src/util/VDom.mjs';
1
+ import Neo from '../../../src/Neo.mjs';
2
+ import * as core from '../../../src/core/_export.mjs';
3
+ import NeoArray from '../../../src/util/Array.mjs';
4
+ import Style from '../../../src/util/Style.mjs';
5
+ import StringFromVnode from '../../../src/vdom/util/StringFromVnode.mjs';
6
+ import VdomHelper from '../../../src/vdom/Helper.mjs';
7
+ import VDomUtil from '../../../src/util/VDom.mjs';
7
8
 
8
9
  // tests are designed for this rendering mode
9
10
  Neo.config.useDomApiRenderer = false;
10
- VdomHelper.onNeoConfigChange({useDomApiRenderer: false})
11
11
 
12
12
  let deltas, output, tmp, vdom, vnode;
13
13
 
@@ -0,0 +1,113 @@
1
+ import Neo from '../../../../src/Neo.mjs';
2
+ import * as core from '../../../../src/core/_export.mjs';
3
+ import Button from '../../../../src/button/Base.mjs';
4
+ import DomApiVnodeCreator from '../../../../src/vdom/util/DomApiVnodeCreator.mjs';
5
+ import VdomHelper from '../../../../src/vdom/Helper.mjs';
6
+
7
+ // IMPORTANT: This test file uses real components and expects them to render.
8
+ // We need to enable unitTestMode for isolation, but also allow VDOM updates.
9
+ Neo.config.unitTestMode = true;
10
+ Neo.config.allowVdomUpdatesInTests = true;
11
+ // This ensures that the VdomHelper uses the correct renderer for the assertions.
12
+ Neo.config.useDomApiRenderer = true;
13
+
14
+ // Create a mock application context, as the component lifecycle requires it for updates.
15
+ const appName = 'ClassicButtonTest';
16
+ Neo.apps = Neo.apps || {};
17
+ Neo.apps[appName] = {
18
+ name : appName,
19
+ fire : Neo.emptyFn,
20
+ isMounted: () => true,
21
+ rendering: false
22
+ };
23
+
24
+ StartTest(t => {
25
+ let button, vnode;
26
+ let testRun = 0;
27
+
28
+ t.beforeEach(async t => {
29
+ testRun++;
30
+
31
+ button = Neo.create(Button, {
32
+ appName,
33
+ id : 'my-button-' + testRun,
34
+ iconCls: 'fa fa-home',
35
+ text : 'Click me'
36
+ });
37
+
38
+ ({vnode} = await button.render());
39
+ button.mounted = true; // Manually mount to enable updates in the test env
40
+ });
41
+
42
+ t.afterEach(t => {
43
+ button?.destroy();
44
+ button = null;
45
+ vnode = null;
46
+ });
47
+
48
+ t.it('should create initial vnode correctly', async t => {
49
+ t.expect(vnode.nodeName).toBe('button');
50
+ t.expect(vnode.className).toEqual(['neo-button', 'icon-left']);
51
+ t.expect(vnode.childNodes.length).toBe(2); // icon & text. badge & ripple have removeDom:true
52
+
53
+ const iconNode = vnode.childNodes[0];
54
+ t.expect(iconNode.className).toEqual(['neo-button-glyph', 'fa', 'fa-home']);
55
+
56
+ const textNode = vnode.childNodes[1];
57
+ t.expect(textNode.className).toEqual(['neo-button-text']);
58
+ t.expect(textNode.textContent).toBe('Click me');
59
+ });
60
+
61
+ t.it('should update vnode and create delta for a single config change', async t => {
62
+ const textNodeId = vnode.childNodes[1].id;
63
+ const {deltas} = await button.set({text: 'New Text'});
64
+
65
+ t.is(deltas.length, 1, 'Should generate exactly one delta');
66
+ const delta = deltas[0];
67
+
68
+ t.is(delta.id, textNodeId, 'Delta should target the text node');
69
+ t.is(delta.textContent, 'New Text', 'Delta textContent is correct');
70
+ });
71
+
72
+ t.it('should update vnode and create delta for multiple config changes', async t => {
73
+ const iconNodeId = vnode.childNodes[0].id;
74
+ const textNodeId = vnode.childNodes[1].id;
75
+
76
+ const {deltas} = await button.set({
77
+ iconCls: 'fa fa-user',
78
+ text : 'Submit'
79
+ });
80
+
81
+ t.is(deltas.length, 2, 'Should generate exactly two deltas');
82
+
83
+ const iconDelta = deltas.find(d => d.id === iconNodeId);
84
+ const textDelta = deltas.find(d => d.id === textNodeId);
85
+
86
+ t.ok(iconDelta, 'Should have a delta for the icon node');
87
+ t.isDeeply(iconDelta.cls.remove, ['fa-home'], 'Icon delta should remove old class');
88
+ t.isDeeply(iconDelta.cls.add, ['fa-user'], 'Icon delta should add new class');
89
+
90
+ t.ok(textDelta, 'Should have a delta for the text node');
91
+ t.is(textDelta.textContent, 'Submit', 'Text delta is correct');
92
+ });
93
+
94
+ t.it('should handle pressed state change', async t => {
95
+ t.notOk(vnode.className.includes('pressed'), 'Initial vnode should not have "pressed" class');
96
+
97
+ let updateData = await button.set({pressed: true});
98
+
99
+ t.is(updateData.deltas.length, 1, 'Should generate one delta for pressed: true');
100
+ let delta = updateData.deltas[0];
101
+ t.is(delta.id, button.id, 'Delta should target the button component root');
102
+ t.isDeeply(delta.cls.add, ['pressed'], 'Delta should add "pressed" class');
103
+ t.ok(updateData.vnode.className.includes('pressed'), 'Vnode should have "pressed" class');
104
+
105
+ updateData = await button.set({pressed: false});
106
+
107
+ t.is(updateData.deltas.length, 1, 'Should generate one delta for pressed: false');
108
+ delta = updateData.deltas[0];
109
+ t.is(delta.id, button.id, 'Delta should target the button component root');
110
+ t.isDeeply(delta.cls.remove, ['pressed'], 'Delta should remove "pressed" class');
111
+ t.notOk(updateData.vnode.className.includes('pressed'), 'Vnode should not have "pressed" class');
112
+ });
113
+ });
@@ -6,8 +6,8 @@ import Config from '../../../../src/core/Config.mjs';
6
6
 
7
7
  StartTest(t => {
8
8
  t.it('EffectManager should manage active effects', t => {
9
- const effect1 = new Effect({fn: () => {}});
10
- const effect2 = new Effect({fn: () => {}});
9
+ const effect1 = new Effect(() => {});
10
+ const effect2 = new Effect(() => {});
11
11
 
12
12
  t.is(EffectManager.getActiveEffect(), null, 'No active effect initially');
13
13
 
@@ -38,13 +38,11 @@ StartTest(t => {
38
38
  t.is(configB, configB, 'configB is strictly equal to itself');
39
39
  t.isNot(configA, configB, 'configA is not strictly equal to configB');
40
40
 
41
- const effect = new Effect({
42
- fn: () => {
43
- runCount++;
44
- // Access configs to register them as dependencies
45
- sum = configA.get() + configB.get();
46
- t.pass(`Effect ran. Sum: ${sum}`);
47
- }
41
+ const effect = new Effect(() => {
42
+ runCount++;
43
+ // Access configs to register them as dependencies
44
+ sum = configA.get() + configB.get();
45
+ t.pass(`Effect ran. Sum: ${sum}`);
48
46
  });
49
47
 
50
48
  t.is(runCount, 1, 'Effect function ran once on creation');
@@ -82,11 +80,9 @@ StartTest(t => {
82
80
  const configY = new Config('Y');
83
81
 
84
82
  // Initial effect: depends on configX
85
- const effect = new Effect({
86
- fn: () => {
87
- runCount++;
88
- t.is(configX.get(), 'X', 'Effect ran (1st): configX value');
89
- }
83
+ const effect = new Effect(() => {
84
+ runCount++;
85
+ t.is(configX.get(), 'X', 'Effect ran (1st): configX value');
90
86
  });
91
87
 
92
88
  t.is(runCount, 1, 'Effect ran once initially');
@@ -1,31 +1,30 @@
1
- import Neo from '../../../../src/Neo.mjs';
2
- import * as core from '../../../../src/core/_export.mjs';
3
- import Effect from '../../../../src/core/Effect.mjs';
4
- import EffectBatchManager from '../../../../src/core/EffectBatchManager.mjs';
1
+ import Neo from '../../../../src/Neo.mjs';
2
+ import * as core from '../../../../src/core/_export.mjs';
3
+ import Effect from '../../../../src/core/Effect.mjs';
4
+ import EffectManager from '../../../../src/core/EffectManager.mjs';
5
5
 
6
6
  class TestComponent extends core.Base {
7
7
  static config = {
8
8
  className: 'Neo.Test.EffectBatchingComponent',
9
- configA_: 0,
10
- configB_: 0,
11
- configC_: 0
9
+ configA_ : 0,
10
+ configB_ : 0,
11
+ configC_ : 0
12
12
  }
13
13
  }
14
+
14
15
  Neo.setupClass(TestComponent);
15
16
 
16
17
  StartTest(t => {
17
18
  t.it('Effects should be batched during core.Base#set() operations', t => {
18
- const instance = Neo.create(TestComponent);
19
+ const instance = Neo.create(TestComponent);
19
20
  let effectRunCount = 0;
20
- let sum = 0;
21
-
22
- const effect = new Effect({
23
- fn: () => {
24
- effectRunCount++;
25
- // Access all props to make them dependencies
26
- sum = instance.configA + instance.configB + instance.configC;
27
- t.pass(`Effect ran. Sum: ${sum}`);
28
- }
21
+ let sum = 0;
22
+
23
+ const effect = new Effect(() => {
24
+ effectRunCount++;
25
+ // Access all props to make them dependencies
26
+ sum = instance.configA + instance.configB + instance.configC;
27
+ t.pass(`Effect ran. Sum: ${sum}`);
29
28
  });
30
29
 
31
30
  t.is(effectRunCount, 1, 'Effect ran once on initial creation');
@@ -49,7 +48,7 @@ StartTest(t => {
49
48
  t.is(instance.configC, 3, 'configC should be updated');
50
49
 
51
50
  // Test individual property change outside a batch
52
- effectRunCount = 0;
51
+ effectRunCount = 0;
53
52
  instance.configA = 10;
54
53
  t.is(effectRunCount, 1, 'Effect should run immediately for individual property change outside a batch');
55
54
  t.is(sum, 10 + 2 + 3, 'Sum should be 10 + 2 + 3 = 15 after individual configA change');
@@ -60,8 +59,8 @@ StartTest(t => {
60
59
  // Update all configs to their previous values (no change)
61
60
  instance.set({
62
61
  configA: 10,
63
- configB: 2,
64
- configC: 3
62
+ configB: 2,
63
+ configC: 3
65
64
  });
66
65
 
67
66
  t.is(effectRunCount, 0, 'Effect should not run.');
@@ -70,28 +69,28 @@ StartTest(t => {
70
69
  instance.destroy();
71
70
  });
72
71
 
73
- t.it('EffectBatchManager should correctly manage batch state', t => {
74
- t.is(EffectBatchManager.isBatchActive(), false, 'Batch should not be active initially');
72
+ t.it('EffectManager should correctly manage batch state via pause() and resume()', t => {
73
+ t.is(EffectManager.isPaused(), false, 'Batch should not be active initially');
75
74
 
76
- EffectBatchManager.startBatch();
77
- t.is(EffectBatchManager.isBatchActive(), true, 'Batch should be active after startBatch()');
75
+ EffectManager.pause();
76
+ t.is(EffectManager.isPaused(), true, 'Batch should be active after pause()');
78
77
 
79
- EffectBatchManager.startBatch(); // Nested batch
80
- t.is(EffectBatchManager.isBatchActive(), true, 'Batch should still be active for nested batch');
78
+ EffectManager.pause(); // Nested batch
79
+ t.is(EffectManager.isPaused(), true, 'Batch should still be active for nested pause()');
81
80
 
82
- EffectBatchManager.endBatch();
83
- t.is(EffectBatchManager.isBatchActive(), true, 'Batch should still be active after inner endBatch()');
81
+ EffectManager.resume();
82
+ t.is(EffectManager.isPaused(), true, 'Batch should still be active after inner resume()');
84
83
 
85
- EffectBatchManager.endBatch();
86
- t.is(EffectBatchManager.isBatchActive(), false, 'Batch should not be active after all endBatch() calls');
84
+ EffectManager.resume();
85
+ t.is(EffectManager.isPaused(), false, 'Batch should not be active after all resume() calls');
87
86
  });
88
87
 
89
88
  t.it('Effect should run when a dependency is changed inside an afterSet hook', t => {
90
89
  class IndirectDependencyComponent extends core.Base {
91
90
  static config = {
92
91
  className: 'Neo.Test.IndirectDependencyComponent',
93
- configA_: 'initialA',
94
- configB_: 'initialB'
92
+ configA_ : 'initialA',
93
+ configB_ : 'initialB'
95
94
  }
96
95
 
97
96
  afterSetConfigA(newValue, oldValue) {
@@ -101,19 +100,18 @@ StartTest(t => {
101
100
  }
102
101
  }
103
102
  }
103
+
104
104
  Neo.setupClass(IndirectDependencyComponent);
105
105
 
106
- const instance = Neo.create(IndirectDependencyComponent);
106
+ const instance = Neo.create(IndirectDependencyComponent);
107
107
  let effectRunCount = 0;
108
- let effectValue = '';
108
+ let effectValue = '';
109
109
 
110
110
  // Effect depends only on configB
111
- const effect = new Effect({
112
- fn: () => {
113
- effectRunCount++;
114
- effectValue = instance.configB;
115
- t.pass(`Effect ran. configB: ${effectValue}`);
116
- }
111
+ const effect = new Effect(() => {
112
+ effectRunCount++;
113
+ effectValue = instance.configB;
114
+ t.pass(`Effect ran. configB: ${effectValue}`);
117
115
  });
118
116
 
119
117
  t.is(effectRunCount, 1, 'Effect ran once on initial creation');
@@ -139,8 +137,8 @@ StartTest(t => {
139
137
  class BeforeSetDependencyComponent extends core.Base {
140
138
  static config = {
141
139
  className: 'Neo.Test.BeforeSetDependencyComponent',
142
- configA_: 'initialA',
143
- configC_: 'initialC' // configC will be changed by beforeSetConfigA
140
+ configA_ : 'initialA',
141
+ configC_ : 'initialC' // configC will be changed by beforeSetConfigA
144
142
  }
145
143
 
146
144
  beforeSetConfigA(newValue, oldValue) {
@@ -151,19 +149,18 @@ StartTest(t => {
151
149
  return newValue; // Important: return newValue to allow configA to be set
152
150
  }
153
151
  }
152
+
154
153
  Neo.setupClass(BeforeSetDependencyComponent);
155
154
 
156
- const instance = Neo.create(BeforeSetDependencyComponent);
155
+ const instance = Neo.create(BeforeSetDependencyComponent);
157
156
  let effectRunCount = 0;
158
- let effectValue = '';
157
+ let effectValue = '';
159
158
 
160
159
  // Effect depends only on configC
161
- const effect = new Effect({
162
- fn: () => {
163
- effectRunCount++;
164
- effectValue = instance.configC;
165
- t.pass(`Effect ran. configC: ${effectValue}`);
166
- }
160
+ const effect = new Effect(() => {
161
+ effectRunCount++;
162
+ effectValue = instance.configC;
163
+ t.pass(`Effect ran. configC: ${effectValue}`);
167
164
  });
168
165
 
169
166
  t.is(effectRunCount, 1, 'Effect ran once on initial creation');
@@ -189,9 +186,9 @@ StartTest(t => {
189
186
  class CombinedDependencyComponent extends core.Base {
190
187
  static config = {
191
188
  className: 'Neo.Test.CombinedDependencyComponent',
192
- configA_: 'initialA',
193
- configB_: 'initialB', // Changed by afterSet
194
- configC_: 'initialC' // Changed by beforeSet
189
+ configA_ : 'initialA',
190
+ configB_ : 'initialB', // Changed by afterSet
191
+ configC_ : 'initialC' // Changed by beforeSet
195
192
  }
196
193
 
197
194
  beforeSetConfigA(newValue, oldValue) {
@@ -207,30 +204,27 @@ StartTest(t => {
207
204
  }
208
205
  }
209
206
  }
207
+
210
208
  Neo.setupClass(CombinedDependencyComponent);
211
209
 
212
- const instance = Neo.create(CombinedDependencyComponent);
210
+ const instance = Neo.create(CombinedDependencyComponent);
213
211
  let effectBRunCount = 0;
214
212
  let effectCRunCount = 0;
215
- let effectBValue = '';
216
- let effectCValue = '';
213
+ let effectBValue = '';
214
+ let effectCValue = '';
217
215
 
218
216
  // Effect for configB (changed by afterSet)
219
- const effectB = new Effect({
220
- fn: () => {
221
- effectBRunCount++;
222
- effectBValue = instance.configB;
223
- t.pass(`EffectB ran. configB: ${effectBValue}`);
224
- }
217
+ const effectB = new Effect(() => {
218
+ effectBRunCount++;
219
+ effectBValue = instance.configB;
220
+ t.pass(`EffectB ran. configB: ${effectBValue}`);
225
221
  });
226
222
 
227
223
  // Effect for configC (changed by beforeSet)
228
- const effectC = new Effect({
229
- fn: () => {
230
- effectCRunCount++;
231
- effectCValue = instance.configC;
232
- t.pass(`EffectC ran. configC: ${effectCValue}`);
233
- }
224
+ const effectC = new Effect(() => {
225
+ effectCRunCount++;
226
+ effectCValue = instance.configC;
227
+ t.pass(`EffectC ran. configC: ${effectCValue}`);
234
228
  });
235
229
 
236
230
  t.is(effectBRunCount, 1, 'EffectB ran once on initial creation');
@@ -267,9 +261,9 @@ StartTest(t => {
267
261
  class SingleEffectCombinedDependencyComponent extends core.Base {
268
262
  static config = {
269
263
  className: 'Neo.Test.SingleEffectCombinedDependencyComponent',
270
- configA_: 'initialA',
271
- configB_: 'initialB', // Changed by afterSet
272
- configC_: 'initialC' // Changed by beforeSet
264
+ configA_ : 'initialA',
265
+ configB_ : 'initialB', // Changed by afterSet
266
+ configC_ : 'initialC' // Changed by beforeSet
273
267
  }
274
268
 
275
269
  beforeSetConfigA(newValue, oldValue) {
@@ -285,19 +279,18 @@ StartTest(t => {
285
279
  }
286
280
  }
287
281
  }
282
+
288
283
  Neo.setupClass(SingleEffectCombinedDependencyComponent);
289
284
 
290
- const instance = Neo.create(SingleEffectCombinedDependencyComponent);
285
+ const instance = Neo.create(SingleEffectCombinedDependencyComponent);
291
286
  let effectRunCount = 0;
292
- let effectValue = '';
287
+ let effectValue = '';
293
288
 
294
289
  // Single Effect depends on both configB and configC
295
- const effect = new Effect({
296
- fn: () => {
297
- effectRunCount++;
298
- effectValue = `${instance.configB} | ${instance.configC}`;
299
- t.pass(`Effect ran. Combined: ${effectValue}`);
300
- }
290
+ const effect = new Effect(() => {
291
+ effectRunCount++;
292
+ effectValue = `${instance.configB} | ${instance.configC}`;
293
+ t.pass(`Effect ran. Combined: ${effectValue}`);
301
294
  });
302
295
 
303
296
  t.is(effectRunCount, 1, 'Effect ran once on initial creation');