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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (485) hide show
  1. package/.github/RELEASE_NOTES/v10.0.0-beta.4.md +2 -2
  2. package/.github/RELEASE_NOTES/v10.0.0-beta.5.md +70 -0
  3. package/.github/RELEASE_NOTES/v10.0.0-beta.6.md +48 -0
  4. package/.github/epic-functional-components.md +498 -0
  5. package/.github/ticket-asymmetric-vdom-updates.md +122 -0
  6. package/README.md +0 -3
  7. package/ServiceWorker.mjs +2 -2
  8. package/apps/colors/store/Colors.mjs +1 -0
  9. package/apps/colors/view/GridContainer.mjs +3 -0
  10. package/apps/colors/view/HeaderToolbar.mjs +2 -0
  11. package/apps/colors/view/Viewport.mjs +3 -0
  12. package/apps/covid/view/FooterContainer.mjs +3 -0
  13. package/apps/covid/view/GalleryContainer.mjs +2 -0
  14. package/apps/covid/view/GalleryContainerController.mjs +1 -0
  15. package/apps/covid/view/HeaderContainer.mjs +2 -0
  16. package/apps/covid/view/HelixContainer.mjs +2 -0
  17. package/apps/covid/view/HelixContainerController.mjs +1 -0
  18. package/apps/covid/view/MainContainer.mjs +3 -0
  19. package/apps/covid/view/TableContainer.mjs +3 -0
  20. package/apps/covid/view/TableContainerController.mjs +1 -0
  21. package/apps/covid/view/WorldMapContainer.mjs +2 -0
  22. package/apps/covid/view/country/Gallery.mjs +3 -0
  23. package/apps/covid/view/country/Helix.mjs +8 -0
  24. package/apps/covid/view/country/HistoricalDataTable.mjs +1 -0
  25. package/apps/covid/view/country/Table.mjs +2 -0
  26. package/apps/covid/view/mapboxGl/Component.mjs +1 -0
  27. package/apps/covid/view/mapboxGl/Container.mjs +2 -0
  28. package/apps/email/EPIC_PLAN.md +58 -0
  29. package/apps/email/neo-config.json +2 -2
  30. package/apps/email/store/Emails.mjs +11 -1
  31. package/apps/email/view/ComposeView.mjs +44 -0
  32. package/apps/email/view/MainView.mjs +89 -0
  33. package/apps/email/view/Viewport.mjs +4 -33
  34. package/apps/email/view/ViewportStateProvider.mjs +3 -3
  35. package/apps/form/store/SideNav.mjs +1 -0
  36. package/apps/form/view/FormContainer.mjs +1 -0
  37. package/apps/form/view/FormPageContainer.mjs +2 -0
  38. package/apps/form/view/SideNavList.mjs +1 -0
  39. package/apps/form/view/Viewport.mjs +3 -0
  40. package/apps/portal/childapps/preview/MainContainer.mjs +1 -0
  41. package/apps/portal/index.html +1 -1
  42. package/apps/portal/store/BlogPosts.mjs +2 -0
  43. package/apps/portal/store/Content.mjs +1 -0
  44. package/apps/portal/store/ContentSections.mjs +1 -0
  45. package/apps/portal/store/Examples.mjs +1 -0
  46. package/apps/portal/view/HeaderToolbar.mjs +1 -0
  47. package/apps/portal/view/Viewport.mjs +5 -0
  48. package/apps/portal/view/ViewportController.mjs +8 -2
  49. package/apps/portal/view/about/Container.mjs +2 -0
  50. package/apps/portal/view/about/MemberContainer.mjs +7 -0
  51. package/apps/portal/view/blog/Container.mjs +2 -0
  52. package/apps/portal/view/blog/List.mjs +2 -0
  53. package/apps/portal/view/examples/List.mjs +1 -0
  54. package/apps/portal/view/examples/TabContainer.mjs +4 -0
  55. package/apps/portal/view/home/ContentBox.mjs +3 -0
  56. package/apps/portal/view/home/FeatureSection.mjs +8 -0
  57. package/apps/portal/view/home/FooterContainer.mjs +4 -1
  58. package/apps/portal/view/home/MainContainer.mjs +2 -0
  59. package/apps/portal/view/home/parts/AfterMath.mjs +2 -0
  60. package/apps/portal/view/home/parts/BaseContainer.mjs +1 -0
  61. package/apps/portal/view/home/parts/Colors.mjs +4 -0
  62. package/apps/portal/view/home/parts/Features.mjs +2 -0
  63. package/apps/portal/view/home/parts/Helix.mjs +5 -0
  64. package/apps/portal/view/home/parts/How.mjs +4 -0
  65. package/apps/portal/view/home/parts/MainNeo.mjs +1 -0
  66. package/apps/portal/view/home/parts/References.mjs +2 -0
  67. package/apps/portal/view/learn/ContentComponent.mjs +11 -5
  68. package/apps/portal/view/learn/ContentTreeList.mjs +2 -0
  69. package/apps/portal/view/learn/CubeLayoutButton.mjs +1 -0
  70. package/apps/portal/view/learn/MainContainer.mjs +4 -0
  71. package/apps/portal/view/learn/PageContainer.mjs +2 -0
  72. package/apps/portal/view/learn/PageSectionsContainer.mjs +3 -0
  73. package/apps/portal/view/learn/PageSectionsList.mjs +1 -0
  74. package/apps/portal/view/services/Component.mjs +1 -0
  75. package/apps/realworld/api/Base.mjs +1 -0
  76. package/apps/realworld/view/HeaderComponent.mjs +4 -0
  77. package/apps/realworld/view/HomeComponent.mjs +7 -0
  78. package/apps/realworld/view/MainContainer.mjs +2 -0
  79. package/apps/realworld/view/MainContainerController.mjs +2 -0
  80. package/apps/realworld/view/article/CommentComponent.mjs +3 -0
  81. package/apps/realworld/view/article/Component.mjs +17 -10
  82. package/apps/realworld/view/article/CreateCommentComponent.mjs +2 -0
  83. package/apps/realworld/view/article/CreateComponent.mjs +5 -0
  84. package/apps/realworld/view/article/PreviewComponent.mjs +9 -0
  85. package/apps/realworld/view/article/TagListComponent.mjs +2 -0
  86. package/apps/realworld/view/user/ProfileComponent.mjs +7 -0
  87. package/apps/realworld/view/user/SettingsComponent.mjs +5 -0
  88. package/apps/realworld/view/user/SignUpComponent.mjs +3 -0
  89. package/apps/realworld2/api/Base.mjs +1 -0
  90. package/apps/realworld2/view/FooterComponent.mjs +1 -0
  91. package/apps/realworld2/view/HeaderToolbar.mjs +3 -0
  92. package/apps/realworld2/view/HomeContainer.mjs +1 -0
  93. package/apps/realworld2/view/MainContainer.mjs +2 -0
  94. package/apps/realworld2/view/MainContainerController.mjs +1 -0
  95. package/apps/realworld2/view/article/Helix.mjs +1 -0
  96. package/apps/realworld2/view/article/PreviewComponent.mjs +9 -0
  97. package/apps/realworld2/view/article/PreviewList.mjs +1 -0
  98. package/apps/realworld2/view/article/TagListComponent.mjs +2 -0
  99. package/apps/route/view/CenterContainer.mjs +1 -0
  100. package/apps/route/view/MainView.mjs +1 -0
  101. package/apps/sharedcovid/childapps/sharedcovidchart/MainContainer.mjs +1 -0
  102. package/apps/sharedcovid/childapps/sharedcovidgallery/MainContainer.mjs +1 -0
  103. package/apps/sharedcovid/childapps/sharedcovidhelix/MainContainer.mjs +1 -0
  104. package/apps/sharedcovid/childapps/sharedcovidmap/MainContainer.mjs +1 -0
  105. package/apps/sharedcovid/view/FooterContainer.mjs +3 -0
  106. package/apps/sharedcovid/view/GalleryContainer.mjs +2 -0
  107. package/apps/sharedcovid/view/GalleryContainerController.mjs +1 -0
  108. package/apps/sharedcovid/view/HeaderContainer.mjs +2 -0
  109. package/apps/sharedcovid/view/HelixContainer.mjs +2 -0
  110. package/apps/sharedcovid/view/HelixContainerController.mjs +1 -0
  111. package/apps/sharedcovid/view/MainContainer.mjs +3 -0
  112. package/apps/sharedcovid/view/TableContainer.mjs +3 -0
  113. package/apps/sharedcovid/view/TableContainerController.mjs +1 -0
  114. package/apps/sharedcovid/view/WorldMapContainer.mjs +2 -0
  115. package/apps/sharedcovid/view/country/Gallery.mjs +3 -0
  116. package/apps/sharedcovid/view/country/Helix.mjs +8 -0
  117. package/apps/sharedcovid/view/country/HistoricalDataTable.mjs +1 -0
  118. package/apps/sharedcovid/view/country/Table.mjs +2 -0
  119. package/apps/sharedcovid/view/mapboxGl/Component.mjs +1 -0
  120. package/apps/sharedcovid/view/mapboxGl/Container.mjs +2 -0
  121. package/apps/shareddialog/childapps/shareddialog2/view/MainContainer.mjs +2 -0
  122. package/apps/shareddialog/view/DemoDialog.mjs +2 -0
  123. package/apps/shareddialog/view/MainContainer.mjs +2 -0
  124. package/apps/shareddialog/view/MainContainerController.mjs +1 -0
  125. package/buildScripts/addReactiveTags.mjs +191 -0
  126. package/buildScripts/checkReactiveTags.mjs +160 -0
  127. package/docs/app/store/Api.mjs +1 -0
  128. package/docs/app/store/Examples.mjs +1 -0
  129. package/docs/app/view/ApiTreeList.mjs +1 -0
  130. package/docs/app/view/ContentTabContainer.mjs +2 -0
  131. package/docs/app/view/ExamplesTreeList.mjs +2 -0
  132. package/docs/app/view/HeaderContainer.mjs +3 -0
  133. package/docs/app/view/MainContainer.mjs +5 -0
  134. package/docs/app/view/classdetails/HeaderComponent.mjs +1 -0
  135. package/docs/app/view/classdetails/MainContainer.mjs +3 -0
  136. package/docs/app/view/classdetails/MembersList.mjs +5 -0
  137. package/docs/app/view/classdetails/SourceViewComponent.mjs +2 -0
  138. package/examples/ConfigurationViewport.mjs +14 -8
  139. package/examples/button/effect/MainContainer.mjs +207 -0
  140. package/examples/button/effect/app.mjs +6 -0
  141. package/examples/button/effect/index.html +11 -0
  142. package/examples/button/effect/neo-config.json +6 -0
  143. package/examples/calendar/weekview/MainContainer.mjs +4 -0
  144. package/examples/component/coronaGallery/CountryGallery.mjs +2 -0
  145. package/examples/component/coronaGallery/CountryStore.mjs +1 -0
  146. package/examples/component/coronaGallery/Viewport.mjs +3 -0
  147. package/examples/component/coronaGallery/ViewportController.mjs +1 -0
  148. package/examples/component/coronaHelix/CountryHelix.mjs +7 -0
  149. package/examples/component/coronaHelix/MainContainer.mjs +1 -0
  150. package/examples/component/gallery/ImageStore.mjs +1 -0
  151. package/examples/component/helix/ImageStore.mjs +1 -0
  152. package/examples/component/helix/Viewport.mjs +3 -0
  153. package/examples/component/helix/ViewportController.mjs +1 -0
  154. package/examples/component/multiWindowCoronaGallery/childapp/Viewport.mjs +1 -0
  155. package/examples/component/multiWindowHelix/childapp/Viewport.mjs +1 -0
  156. package/examples/component/wrapper/googleMaps/MapComponent.mjs +2 -0
  157. package/examples/core/config/MainContainer.mjs +2 -0
  158. package/examples/dialog/DemoDialog.mjs +2 -0
  159. package/examples/dialog/MainContainer.mjs +1 -0
  160. package/examples/form/field/color/MainStore.mjs +1 -0
  161. package/examples/functional/defineComponent/Component.mjs +18 -0
  162. package/examples/functional/defineComponent/MainContainer.mjs +41 -0
  163. package/examples/functional/defineComponent/app.mjs +6 -0
  164. package/examples/functional/defineComponent/index.html +11 -0
  165. package/examples/functional/defineComponent/neo-config.json +6 -0
  166. package/examples/functional/hostComponent/Component.mjs +32 -0
  167. package/examples/functional/hostComponent/MainContainer.mjs +48 -0
  168. package/examples/functional/hostComponent/app.mjs +6 -0
  169. package/examples/functional/hostComponent/index.html +11 -0
  170. package/examples/functional/hostComponent/neo-config.json +6 -0
  171. package/examples/grid/animatedRowSorting/Viewport.mjs +1 -1
  172. package/examples/grid/bigData/ControlsContainer.mjs +3 -0
  173. package/examples/grid/bigData/GridContainer.mjs +4 -2
  174. package/examples/grid/bigData/MainContainer.mjs +2 -0
  175. package/examples/grid/bigData/MainModel.mjs +1 -0
  176. package/examples/grid/bigData/MainStore.mjs +3 -0
  177. package/examples/grid/cellEditing/MainContainer.mjs +1 -1
  178. package/examples/grid/container/MainContainer.mjs +1 -1
  179. package/examples/grid/covid/GridContainer.mjs +3 -0
  180. package/examples/grid/covid/MainContainer.mjs +2 -0
  181. package/examples/grid/covid/Store.mjs +1 -0
  182. package/examples/grid/nestedRecordFields/EditUserDialog.mjs +3 -0
  183. package/examples/grid/nestedRecordFields/Viewport.mjs +3 -1
  184. package/examples/list/animate/List.mjs +4 -0
  185. package/examples/list/animate/MainContainer.mjs +2 -0
  186. package/examples/list/circle/MainStore.mjs +1 -0
  187. package/examples/list/color/MainStore.mjs +1 -0
  188. package/examples/preloadingAssets/view/MainContainer.mjs +2 -0
  189. package/examples/stateProvider/advanced/MainContainer.mjs +1 -0
  190. package/examples/stateProvider/dialog/EditUserDialog.mjs +2 -0
  191. package/examples/stateProvider/dialog/MainContainer.mjs +1 -0
  192. package/examples/stateProvider/extendedClass/MainContainer.mjs +2 -0
  193. package/examples/stateProvider/inline/MainContainer.mjs +1 -0
  194. package/examples/stateProvider/inlineNoStateProvider/MainContainer.mjs +1 -0
  195. package/examples/stateProvider/inlineNoStateProvider/MainContainerController.mjs +2 -0
  196. package/examples/stateProvider/multiWindow/EditUserDialog.mjs +3 -0
  197. package/examples/stateProvider/multiWindow/MainContainer.mjs +1 -0
  198. package/examples/stateProvider/multiWindow/Viewport.mjs +1 -0
  199. package/examples/stateProvider/nestedData/MainContainer.mjs +1 -0
  200. package/examples/stateProvider/table/MainContainer.mjs +1 -0
  201. package/examples/table/covid/MainContainer.mjs +2 -0
  202. package/examples/table/covid/Store.mjs +1 -0
  203. package/examples/table/covid/TableContainer.mjs +3 -0
  204. package/examples/table/nestedRecordFields/EditUserDialog.mjs +3 -0
  205. package/examples/table/nestedRecordFields/Viewport.mjs +1 -0
  206. package/examples/todoList/version1/MainComponent.mjs +1 -1
  207. package/examples/toolbar/breadcrumb/view/MainContainer.mjs +2 -0
  208. package/examples/toolbar/paging/store/Users.mjs +1 -0
  209. package/examples/toolbar/paging/view/AddUserDialog.mjs +3 -0
  210. package/examples/toolbar/paging/view/MainContainer.mjs +3 -0
  211. package/examples/treeAccordion/MainContainer.mjs +2 -2
  212. package/examples/worker/task/MainContainer.mjs +1 -0
  213. package/learn/Glossary.md +1 -0
  214. package/learn/UsingTheseTopics.md +1 -0
  215. package/learn/benefits/ConfigSystem.md +2 -0
  216. package/learn/benefits/Effort.md +1 -0
  217. package/learn/benefits/Features.md +1 -0
  218. package/learn/benefits/FormsEngine.md +1 -0
  219. package/learn/benefits/FourEnvironments.md +2 -0
  220. package/learn/benefits/Introduction.md +2 -0
  221. package/learn/benefits/MultiWindow.md +3 -1
  222. package/learn/benefits/OffTheMainThread.md +2 -0
  223. package/learn/benefits/Quick.md +2 -0
  224. package/learn/benefits/RPCLayer.md +2 -0
  225. package/learn/benefits/Speed.md +2 -0
  226. package/learn/comparisons/NeoVsAngular.md +90 -0
  227. package/learn/comparisons/NeoVsExtJs.md +178 -0
  228. package/learn/comparisons/NeoVsNextJs.md +124 -0
  229. package/learn/comparisons/NeoVsReact.md +95 -0
  230. package/learn/comparisons/NeoVsSolid.md +78 -0
  231. package/learn/comparisons/NeoVsVue.md +92 -0
  232. package/learn/comparisons/Overview.md +46 -0
  233. package/learn/gettingstarted/ComponentModels.md +2 -0
  234. package/learn/gettingstarted/Config.md +2 -0
  235. package/learn/gettingstarted/DescribingTheUI.md +2 -0
  236. package/learn/gettingstarted/Events.md +2 -0
  237. package/learn/gettingstarted/Extending.md +2 -0
  238. package/learn/gettingstarted/References.md +2 -0
  239. package/learn/gettingstarted/Setup.md +3 -2
  240. package/learn/gettingstarted/Workspaces.md +2 -0
  241. package/learn/guides/datahandling/Collections.md +1 -0
  242. package/learn/guides/datahandling/Records.md +1 -0
  243. package/learn/guides/datahandling/StateProviders.md +131 -16
  244. package/learn/guides/datahandling/Tables.md +1 -1
  245. package/learn/guides/fundamentals/ConfigSystemDeepDive.md +1 -0
  246. package/learn/guides/fundamentals/DeclarativeComponentTreesVsImperativeVdom.md +2 -0
  247. package/learn/guides/fundamentals/DeclarativeVDOMWithEffects.md +168 -0
  248. package/learn/guides/fundamentals/ExtendingNeoClasses.md +1 -0
  249. package/learn/guides/fundamentals/InstanceLifecycle.md +3 -1
  250. package/learn/guides/fundamentals/MainThreadAddons.md +2 -0
  251. package/learn/guides/specificfeatures/Mixins.md +3 -1
  252. package/learn/guides/specificfeatures/MultiWindow.md +3 -1
  253. package/learn/guides/specificfeatures/PortalApp.md +2 -0
  254. package/learn/guides/uibuildingblocks/ComponentsAndContainers.md +2 -0
  255. package/learn/guides/uibuildingblocks/CustomComponents.md +2 -0
  256. package/learn/guides/uibuildingblocks/Layouts.md +2 -0
  257. package/learn/guides/uibuildingblocks/WorkingWithVDom.md +2 -0
  258. package/learn/guides/userinteraction/Forms.md +2 -0
  259. package/learn/guides/userinteraction/events/CustomEvents.md +2 -1
  260. package/learn/guides/userinteraction/events/DomEvents.md +2 -0
  261. package/learn/javascript/ClassFeatures.md +4 -3
  262. package/learn/javascript/Classes.md +10 -13
  263. package/learn/javascript/Overrides.md +10 -6
  264. package/learn/javascript/Super.md +12 -8
  265. package/learn/tree.json +71 -63
  266. package/learn/tutorials/Earthquakes.md +2 -0
  267. package/learn/tutorials/RSP.md +3 -1
  268. package/learn/tutorials/TodoList.md +103 -7
  269. package/package.json +6 -4
  270. package/resources/scss/src/apps/email/ComposeView.scss +16 -0
  271. package/resources/scss/src/apps/email/MainView.scss +5 -0
  272. package/resources/scss/src/apps/portal/learn/ContentComponent.scss +5 -4
  273. package/src/DefaultConfig.mjs +12 -2
  274. package/src/Main.mjs +1 -0
  275. package/src/Neo.mjs +377 -178
  276. package/src/Xhr.mjs +1 -0
  277. package/src/button/Base.mjs +13 -0
  278. package/src/button/Effect.mjs +449 -0
  279. package/src/button/Split.mjs +2 -0
  280. package/src/calendar/store/Calendars.mjs +1 -0
  281. package/src/calendar/store/Colors.mjs +1 -0
  282. package/src/calendar/store/Events.mjs +1 -0
  283. package/src/calendar/view/DayComponent.mjs +2 -0
  284. package/src/calendar/view/EditEventContainer.mjs +4 -1
  285. package/src/calendar/view/MainContainer.mjs +13 -0
  286. package/src/calendar/view/MainContainerStateProvider.mjs +14 -28
  287. package/src/calendar/view/SettingsContainer.mjs +1 -0
  288. package/src/calendar/view/YearComponent.mjs +16 -0
  289. package/src/calendar/view/calendars/ColorsList.mjs +2 -0
  290. package/src/calendar/view/calendars/Container.mjs +2 -0
  291. package/src/calendar/view/calendars/EditContainer.mjs +1 -0
  292. package/src/calendar/view/month/Component.mjs +11 -0
  293. package/src/calendar/view/settings/GeneralContainer.mjs +1 -0
  294. package/src/calendar/view/settings/MonthContainer.mjs +1 -0
  295. package/src/calendar/view/settings/WeekContainer.mjs +1 -0
  296. package/src/calendar/view/settings/YearContainer.mjs +1 -0
  297. package/src/calendar/view/week/Component.mjs +15 -1
  298. package/src/calendar/view/week/TimeAxisComponent.mjs +4 -0
  299. package/src/code/LivePreview.mjs +51 -23
  300. package/src/collection/Base.mjs +14 -12
  301. package/src/collection/Filter.mjs +6 -0
  302. package/src/collection/Sorter.mjs +3 -0
  303. package/src/component/Base.mjs +156 -802
  304. package/src/component/Canvas.mjs +1 -0
  305. package/src/component/Chip.mjs +4 -0
  306. package/src/component/Circle.mjs +14 -0
  307. package/src/component/Clock.mjs +4 -0
  308. package/src/component/DateSelector.mjs +12 -0
  309. package/src/component/Gallery.mjs +11 -0
  310. package/src/component/Helix.mjs +24 -0
  311. package/src/component/Label.mjs +1 -0
  312. package/src/component/Legend.mjs +3 -0
  313. package/src/component/MagicMoveText.mjs +4 -0
  314. package/src/component/Progress.mjs +3 -0
  315. package/src/component/Splitter.mjs +3 -0
  316. package/src/component/StatusBadge.mjs +6 -0
  317. package/src/component/Timer.mjs +4 -0
  318. package/src/component/Toast.mjs +6 -0
  319. package/src/component/Video.mjs +1 -0
  320. package/src/component/mwc/Button.mjs +7 -0
  321. package/src/component/mwc/TextField.mjs +9 -0
  322. package/src/component/wrapper/AmChart.mjs +2 -0
  323. package/src/component/wrapper/GoogleMaps.mjs +3 -0
  324. package/src/component/wrapper/MapboxGL.mjs +5 -0
  325. package/src/component/wrapper/MonacoEditor.mjs +12 -0
  326. package/src/container/Accordion.mjs +2 -0
  327. package/src/container/Base.mjs +34 -26
  328. package/src/container/Panel.mjs +1 -0
  329. package/src/container/Viewport.mjs +1 -0
  330. package/src/controller/Application.mjs +1 -0
  331. package/src/controller/Base.mjs +1 -0
  332. package/src/controller/Component.mjs +1 -0
  333. package/src/core/Base.mjs +193 -22
  334. package/src/core/Compare.mjs +4 -7
  335. package/src/core/Config.mjs +137 -33
  336. package/src/core/Effect.mjs +193 -0
  337. package/src/core/EffectBatchManager.mjs +67 -0
  338. package/src/core/EffectManager.mjs +60 -0
  339. package/src/core/IdGenerator.mjs +13 -44
  340. package/src/data/Model.mjs +2 -0
  341. package/src/data/Store.mjs +7 -0
  342. package/src/data/connection/WebSocket.mjs +2 -0
  343. package/src/date/DayViewComponent.mjs +2 -0
  344. package/src/date/SelectorContainer.mjs +14 -0
  345. package/src/dialog/Base.mjs +8 -0
  346. package/src/draggable/DragZone.mjs +5 -0
  347. package/src/draggable/tree/DragZone.mjs +1 -0
  348. package/src/filter/BooleanContainer.mjs +2 -0
  349. package/src/filter/NumberContainer.mjs +3 -0
  350. package/src/filter/ToggleOperatorsButton.mjs +2 -0
  351. package/src/form/Fieldset.mjs +6 -0
  352. package/src/form/field/Base.mjs +7 -0
  353. package/src/form/field/CheckBox.mjs +18 -0
  354. package/src/form/field/Chip.mjs +1 -0
  355. package/src/form/field/ComboBox.mjs +8 -0
  356. package/src/form/field/Country.mjs +1 -0
  357. package/src/form/field/Currency.mjs +2 -0
  358. package/src/form/field/Date.mjs +4 -0
  359. package/src/form/field/Display.mjs +1 -0
  360. package/src/form/field/Email.mjs +1 -0
  361. package/src/form/field/FileUpload.mjs +7 -0
  362. package/src/form/field/Hidden.mjs +1 -0
  363. package/src/form/field/Number.mjs +7 -0
  364. package/src/form/field/Password.mjs +1 -0
  365. package/src/form/field/Phone.mjs +3 -0
  366. package/src/form/field/Picker.mjs +2 -0
  367. package/src/form/field/Radio.mjs +1 -0
  368. package/src/form/field/Range.mjs +3 -0
  369. package/src/form/field/Search.mjs +2 -0
  370. package/src/form/field/Text.mjs +32 -0
  371. package/src/form/field/TextArea.mjs +7 -0
  372. package/src/form/field/Time.mjs +6 -0
  373. package/src/form/field/Url.mjs +3 -0
  374. package/src/form/field/ZipCode.mjs +2 -0
  375. package/src/form/field/trigger/Base.mjs +3 -0
  376. package/src/form/field/trigger/Clear.mjs +2 -0
  377. package/src/form/field/trigger/CopyToClipboard.mjs +2 -0
  378. package/src/form/field/trigger/Date.mjs +1 -0
  379. package/src/form/field/trigger/Picker.mjs +1 -0
  380. package/src/form/field/trigger/Search.mjs +1 -0
  381. package/src/form/field/trigger/SpinDown.mjs +2 -0
  382. package/src/form/field/trigger/SpinUp.mjs +1 -0
  383. package/src/form/field/trigger/Time.mjs +2 -0
  384. package/src/functional/_export.mjs +6 -0
  385. package/src/functional/component/Base.mjs +499 -0
  386. package/src/functional/defineComponent.mjs +102 -0
  387. package/src/functional/useConfig.mjs +52 -0
  388. package/src/functional/useEvent.mjs +43 -0
  389. package/src/grid/Body.mjs +20 -1
  390. package/src/grid/Container.mjs +57 -63
  391. package/src/grid/ScrollManager.mjs +2 -0
  392. package/src/grid/VerticalScrollbar.mjs +2 -0
  393. package/src/grid/column/Base.mjs +2 -0
  394. package/src/grid/column/Component.mjs +1 -1
  395. package/src/grid/header/Button.mjs +7 -0
  396. package/src/grid/header/Toolbar.mjs +6 -0
  397. package/src/grid/plugin/AnimateRows.mjs +2 -0
  398. package/src/layout/Base.mjs +3 -0
  399. package/src/layout/Card.mjs +1 -0
  400. package/src/layout/Cube.mjs +11 -1
  401. package/src/layout/Fit.mjs +1 -0
  402. package/src/layout/Flexbox.mjs +7 -0
  403. package/src/layout/Form.mjs +2 -0
  404. package/src/layout/Grid.mjs +1 -0
  405. package/src/layout/HBox.mjs +1 -0
  406. package/src/layout/VBox.mjs +1 -0
  407. package/src/list/Base.mjs +13 -0
  408. package/src/list/Chip.mjs +1 -0
  409. package/src/list/Circle.mjs +2 -0
  410. package/src/list/Color.mjs +1 -0
  411. package/src/list/plugin/Animate.mjs +2 -0
  412. package/src/main/DeltaUpdates.mjs +1 -0
  413. package/src/main/DomEvents.mjs +2 -0
  414. package/src/main/addon/CloneNode.mjs +1 -0
  415. package/src/main/addon/Cookie.mjs +1 -0
  416. package/src/main/addon/GoogleMaps.mjs +1 -0
  417. package/src/main/addon/LocalStorage.mjs +1 -0
  418. package/src/main/addon/MapboxGL.mjs +1 -0
  419. package/src/main/addon/Markdown.mjs +1 -0
  420. package/src/main/addon/Navigator.mjs +1 -0
  421. package/src/main/addon/Popover.mjs +1 -0
  422. package/src/main/addon/Stylesheet.mjs +1 -0
  423. package/src/main/addon/WindowPosition.mjs +1 -0
  424. package/src/manager/Component.mjs +0 -71
  425. package/src/manager/VDomUpdate.mjs +235 -0
  426. package/src/menu/List.mjs +6 -0
  427. package/src/menu/Model.mjs +1 -0
  428. package/src/menu/Panel.mjs +3 -0
  429. package/src/menu/Store.mjs +1 -0
  430. package/src/mixin/DomEvents.mjs +130 -0
  431. package/src/mixin/VdomLifecycle.mjs +667 -0
  432. package/src/plugin/Base.mjs +1 -0
  433. package/src/plugin/Resizable.mjs +2 -0
  434. package/src/selection/Model.mjs +15 -18
  435. package/src/selection/grid/BaseModel.mjs +1 -0
  436. package/src/sitemap/Component.mjs +1 -0
  437. package/src/state/Provider.mjs +376 -457
  438. package/src/state/createHierarchicalDataProxy.mjs +138 -0
  439. package/src/tab/Container.mjs +6 -0
  440. package/src/tab/Strip.mjs +1 -0
  441. package/src/tab/header/Button.mjs +2 -0
  442. package/src/tab/header/EffectButton.mjs +77 -0
  443. package/src/tab/header/Toolbar.mjs +1 -0
  444. package/src/table/Body.mjs +3 -0
  445. package/src/table/Container.mjs +10 -0
  446. package/src/table/header/Button.mjs +8 -0
  447. package/src/table/header/Toolbar.mjs +5 -0
  448. package/src/table/plugin/CellEditing.mjs +1 -0
  449. package/src/toolbar/Base.mjs +4 -0
  450. package/src/toolbar/Breadcrumb.mjs +3 -0
  451. package/src/toolbar/Paging.mjs +5 -0
  452. package/src/tooltip/Base.mjs +2 -0
  453. package/src/tree/List.mjs +3 -0
  454. package/src/util/HashHistory.mjs +1 -0
  455. package/src/util/KeyNavigation.mjs +2 -0
  456. package/src/util/Matrix.mjs +1 -0
  457. package/src/util/VDom.mjs +7 -1
  458. package/src/util/VNode.mjs +7 -1
  459. package/src/util/vdom/TreeBuilder.mjs +129 -0
  460. package/src/vdom/Helper.mjs +44 -33
  461. package/src/vdom/VNode.mjs +5 -7
  462. package/src/worker/App.mjs +1 -5
  463. package/src/worker/Base.mjs +2 -0
  464. package/src/worker/Manager.mjs +2 -0
  465. package/src/worker/ServiceBase.mjs +6 -1
  466. package/test/siesta/siesta.js +36 -1
  467. package/test/siesta/tests/CollectionBase.mjs +10 -10
  468. package/test/siesta/tests/VdomCalendar.mjs +13 -9
  469. package/test/siesta/tests/VdomHelper.mjs +22 -59
  470. package/test/siesta/tests/config/AfterSetConfig.mjs +100 -0
  471. package/test/siesta/tests/{ReactiveConfigs.mjs → config/Basic.mjs} +58 -21
  472. package/test/siesta/tests/config/CircularDependencies.mjs +166 -0
  473. package/test/siesta/tests/config/CustomFunctions.mjs +69 -0
  474. package/test/siesta/tests/config/Hierarchy.mjs +94 -0
  475. package/test/siesta/tests/config/MemoryLeak.mjs +92 -0
  476. package/test/siesta/tests/config/MultiLevelHierarchy.mjs +85 -0
  477. package/test/siesta/tests/core/Effect.mjs +127 -0
  478. package/test/siesta/tests/core/EffectBatching.mjs +310 -0
  479. package/test/siesta/tests/neo/MixinStaticConfig.mjs +138 -0
  480. package/test/siesta/tests/state/Provider.mjs +537 -0
  481. package/test/siesta/tests/state/ProviderNestedDataConfigs.mjs +255 -0
  482. package/test/siesta/tests/state/createHierarchicalDataProxy.mjs +204 -0
  483. package/test/siesta/tests/vdom/VdomAsymmetricUpdates.mjs +366 -0
  484. package/test/siesta/tests/vdom/VdomRealWorldUpdates.mjs +249 -0
  485. package/learn/javascript/NewNode.md +0 -31
@@ -0,0 +1,310 @@
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';
5
+
6
+ class TestComponent extends core.Base {
7
+ static config = {
8
+ className: 'Neo.Test.EffectBatchingComponent',
9
+ configA_: 0,
10
+ configB_: 0,
11
+ configC_: 0
12
+ }
13
+ }
14
+ Neo.setupClass(TestComponent);
15
+
16
+ StartTest(t => {
17
+ t.it('Effects should be batched during core.Base#set() operations', t => {
18
+ const instance = Neo.create(TestComponent);
19
+ let effectRunCount = 0;
20
+ let sum = 0;
21
+
22
+ const effect = new Effect(() => {
23
+ effectRunCount++;
24
+ // Access all props to make them dependencies
25
+ sum = instance.configA + instance.configB + instance.configC;
26
+ t.pass(`Effect ran. Sum: ${sum}`);
27
+ });
28
+
29
+ t.is(effectRunCount, 1, 'Effect ran once on initial creation');
30
+ t.is(effect.dependencies.size, 3, 'Effect tracked 3 dependencies');
31
+ t.is(sum, 0, 'Initial sum should be 0');
32
+
33
+ // Reset run count for batching test
34
+ effectRunCount = 0;
35
+
36
+ // Change multiple properties in a single batch via instance.set()
37
+ instance.set({
38
+ configA: 1,
39
+ configB: 2,
40
+ configC: 3
41
+ });
42
+
43
+ t.is(effectRunCount, 1, 'Effect should run exactly once after a batched set() operation');
44
+ t.is(sum, 6, 'Sum should be 1 + 2 + 3 = 6 after batched set()');
45
+ t.is(instance.configA, 1, 'configA should be updated');
46
+ t.is(instance.configB, 2, 'configB should be updated');
47
+ t.is(instance.configC, 3, 'configC should be updated');
48
+
49
+ // Test individual property change outside a batch
50
+ effectRunCount = 0;
51
+ instance.configA = 10;
52
+ t.is(effectRunCount, 1, 'Effect should run immediately for individual property change outside a batch');
53
+ t.is(sum, 10 + 2 + 3, 'Sum should be 10 + 2 + 3 = 15 after individual configA change');
54
+
55
+ t.diag('Testing a no-OP batch');
56
+ effectRunCount = 0;
57
+
58
+ // Update all configs to their previous values (no change)
59
+ instance.set({
60
+ configA: 10,
61
+ configB: 2,
62
+ configC: 3
63
+ });
64
+
65
+ t.is(effectRunCount, 0, 'Effect should not run.');
66
+
67
+ effect.destroy();
68
+ instance.destroy();
69
+ });
70
+
71
+ t.it('EffectBatchManager should correctly manage batch state', t => {
72
+ t.is(EffectBatchManager.isBatchActive(), false, 'Batch should not be active initially');
73
+
74
+ EffectBatchManager.startBatch();
75
+ t.is(EffectBatchManager.isBatchActive(), true, 'Batch should be active after startBatch()');
76
+
77
+ EffectBatchManager.startBatch(); // Nested batch
78
+ t.is(EffectBatchManager.isBatchActive(), true, 'Batch should still be active for nested batch');
79
+
80
+ EffectBatchManager.endBatch();
81
+ t.is(EffectBatchManager.isBatchActive(), true, 'Batch should still be active after inner endBatch()');
82
+
83
+ EffectBatchManager.endBatch();
84
+ t.is(EffectBatchManager.isBatchActive(), false, 'Batch should not be active after all endBatch() calls');
85
+ });
86
+
87
+ t.it('Effect should run when a dependency is changed inside an afterSet hook', t => {
88
+ class IndirectDependencyComponent extends core.Base {
89
+ static config = {
90
+ className: 'Neo.Test.IndirectDependencyComponent',
91
+ configA_: 'initialA',
92
+ configB_: 'initialB'
93
+ }
94
+
95
+ afterSetConfigA(newValue, oldValue) {
96
+ // Only change configB if configA is being updated, not during initial construction
97
+ if (oldValue !== undefined) {
98
+ this.configB = `changed by A: ${newValue}`;
99
+ }
100
+ }
101
+ }
102
+ Neo.setupClass(IndirectDependencyComponent);
103
+
104
+ const instance = Neo.create(IndirectDependencyComponent);
105
+ let effectRunCount = 0;
106
+ let effectValue = '';
107
+
108
+ // Effect depends only on configB
109
+ const effect = new Effect(() => {
110
+ effectRunCount++;
111
+ effectValue = instance.configB;
112
+ t.pass(`Effect ran. configB: ${effectValue}`);
113
+ });
114
+
115
+ t.is(effectRunCount, 1, 'Effect ran once on initial creation');
116
+ t.is(effect.dependencies.size, 1, 'Effect tracked 1 dependency (configB)');
117
+ t.is(effectValue, 'initialB', 'Initial effect value is configB');
118
+
119
+ // Reset run count for test
120
+ effectRunCount = 0;
121
+
122
+ // Change configA, which should indirectly change configB via afterSetConfigA
123
+ instance.configA = 'newA';
124
+
125
+ t.is(effectRunCount, 1, 'Effect should run exactly once after indirect change to configB');
126
+ t.is(effectValue, 'changed by A: newA', 'Effect value should reflect indirect change');
127
+ t.is(instance.configA, 'newA', 'configA should be updated');
128
+ t.is(instance.configB, 'changed by A: newA', 'configB should be updated by afterSet hook');
129
+
130
+ effect.destroy();
131
+ instance.destroy();
132
+ });
133
+
134
+ t.it('Effect should run when a dependency is changed inside a beforeSet hook', t => {
135
+ class BeforeSetDependencyComponent extends core.Base {
136
+ static config = {
137
+ className: 'Neo.Test.BeforeSetDependencyComponent',
138
+ configA_: 'initialA',
139
+ configC_: 'initialC' // configC will be changed by beforeSetConfigA
140
+ }
141
+
142
+ beforeSetConfigA(newValue, oldValue) {
143
+ // Only change configC if configA is being updated, not during initial construction
144
+ if (oldValue !== undefined) {
145
+ this.configC = `changed by A (before): ${newValue}`;
146
+ }
147
+ return newValue; // Important: return newValue to allow configA to be set
148
+ }
149
+ }
150
+ Neo.setupClass(BeforeSetDependencyComponent);
151
+
152
+ const instance = Neo.create(BeforeSetDependencyComponent);
153
+ let effectRunCount = 0;
154
+ let effectValue = '';
155
+
156
+ // Effect depends only on configC
157
+ const effect = new Effect(() => {
158
+ effectRunCount++;
159
+ effectValue = instance.configC;
160
+ t.pass(`Effect ran. configC: ${effectValue}`);
161
+ });
162
+
163
+ t.is(effectRunCount, 1, 'Effect ran once on initial creation');
164
+ t.is(effect.dependencies.size, 1, 'Effect tracked 1 dependency (configC)');
165
+ t.is(effectValue, 'initialC', 'Initial effect value is configC');
166
+
167
+ // Reset run count for test
168
+ effectRunCount = 0;
169
+
170
+ // Change configA, which should indirectly change configC via beforeSetConfigA
171
+ instance.configA = 'newA';
172
+
173
+ t.is(effectRunCount, 1, 'Effect should run exactly once after indirect change to configC');
174
+ t.is(effectValue, 'changed by A (before): newA', 'Effect value should reflect indirect change from beforeSet');
175
+ t.is(instance.configA, 'newA', 'configA should be updated');
176
+ t.is(instance.configC, 'changed by A (before): newA', 'configC should be updated by beforeSet hook');
177
+
178
+ effect.destroy();
179
+ instance.destroy();
180
+ });
181
+
182
+ t.it('Effect should run for dependencies changed by both beforeSet and afterSet hooks', t => {
183
+ class CombinedDependencyComponent extends core.Base {
184
+ static config = {
185
+ className: 'Neo.Test.CombinedDependencyComponent',
186
+ configA_: 'initialA',
187
+ configB_: 'initialB', // Changed by afterSet
188
+ configC_: 'initialC' // Changed by beforeSet
189
+ }
190
+
191
+ beforeSetConfigA(newValue, oldValue) {
192
+ if (oldValue !== undefined) {
193
+ this.configC = `changed by A (before): ${newValue}`;
194
+ }
195
+ return newValue;
196
+ }
197
+
198
+ afterSetConfigA(newValue, oldValue) {
199
+ if (oldValue !== undefined) {
200
+ this.configB = `changed by A (after): ${newValue}`;
201
+ }
202
+ }
203
+ }
204
+ Neo.setupClass(CombinedDependencyComponent);
205
+
206
+ const instance = Neo.create(CombinedDependencyComponent);
207
+ let effectBRunCount = 0;
208
+ let effectCRunCount = 0;
209
+ let effectBValue = '';
210
+ let effectCValue = '';
211
+
212
+ // Effect for configB (changed by afterSet)
213
+ const effectB = new Effect(() => {
214
+ effectBRunCount++;
215
+ effectBValue = instance.configB;
216
+ t.pass(`EffectB ran. configB: ${effectBValue}`);
217
+ });
218
+
219
+ // Effect for configC (changed by beforeSet)
220
+ const effectC = new Effect(() => {
221
+ effectCRunCount++;
222
+ effectCValue = instance.configC;
223
+ t.pass(`EffectC ran. configC: ${effectCValue}`);
224
+ });
225
+
226
+ t.is(effectBRunCount, 1, 'EffectB ran once on initial creation');
227
+ t.is(effectB.dependencies.size, 1, 'EffectB tracked 1 dependency (configB)');
228
+ t.is(effectBValue, 'initialB', 'Initial EffectB value is configB');
229
+
230
+ t.is(effectCRunCount, 1, 'EffectC ran once on initial creation');
231
+ t.is(effectC.dependencies.size, 1, 'EffectC tracked 1 dependency (configC)');
232
+ t.is(effectCValue, 'initialC', 'Initial EffectC value is configC');
233
+
234
+ // Reset run counts for test
235
+ effectBRunCount = 0;
236
+ effectCRunCount = 0;
237
+
238
+ // Change configA, which should indirectly change configB and configC
239
+ instance.configA = 'newA';
240
+
241
+ t.is(effectBRunCount, 1, 'EffectB should run exactly once after indirect change to configB');
242
+ t.is(effectBValue, 'changed by A (after): newA', 'EffectB value should reflect indirect change from afterSet');
243
+ t.is(instance.configB, 'changed by A (after): newA', 'configB should be updated by afterSet hook');
244
+
245
+ t.is(effectCRunCount, 1, 'EffectC should run exactly once after indirect change to configC');
246
+ t.is(effectCValue, 'changed by A (before): newA', 'EffectC value should reflect indirect change from beforeSet');
247
+ t.is(instance.configC, 'changed by A (before): newA', 'configC should be updated by beforeSet hook');
248
+
249
+ t.is(instance.configA, 'newA', 'configA should be updated');
250
+
251
+ effectB.destroy();
252
+ effectC.destroy();
253
+ instance.destroy();
254
+ });
255
+
256
+ t.it('Single Effect should run once for dependencies changed by both beforeSet and afterSet hooks', t => {
257
+ class SingleEffectCombinedDependencyComponent extends core.Base {
258
+ static config = {
259
+ className: 'Neo.Test.SingleEffectCombinedDependencyComponent',
260
+ configA_: 'initialA',
261
+ configB_: 'initialB', // Changed by afterSet
262
+ configC_: 'initialC' // Changed by beforeSet
263
+ }
264
+
265
+ beforeSetConfigA(newValue, oldValue) {
266
+ if (oldValue !== undefined) {
267
+ this.configC = `changed by A (before): ${newValue}`;
268
+ }
269
+ return newValue;
270
+ }
271
+
272
+ afterSetConfigA(newValue, oldValue) {
273
+ if (oldValue !== undefined) {
274
+ this.configB = `changed by A (after): ${newValue}`;
275
+ }
276
+ }
277
+ }
278
+ Neo.setupClass(SingleEffectCombinedDependencyComponent);
279
+
280
+ const instance = Neo.create(SingleEffectCombinedDependencyComponent);
281
+ let effectRunCount = 0;
282
+ let effectValue = '';
283
+
284
+ // Single Effect depends on both configB and configC
285
+ const effect = new Effect(() => {
286
+ effectRunCount++;
287
+ effectValue = `${instance.configB} | ${instance.configC}`;
288
+ t.pass(`Effect ran. Combined: ${effectValue}`);
289
+ });
290
+
291
+ t.is(effectRunCount, 1, 'Effect ran once on initial creation');
292
+ t.is(effect.dependencies.size, 2, 'Effect tracked 2 dependencies (configB, configC)');
293
+ t.is(effectValue, 'initialB | initialC', 'Initial effect value is combined configB and configC');
294
+
295
+ // Reset run count for test
296
+ effectRunCount = 0;
297
+
298
+ // Change configA, which should indirectly change configB and configC
299
+ instance.configA = 'newA';
300
+
301
+ t.is(effectRunCount, 1, 'Effect should run exactly once after indirect changes to configB and configC');
302
+ t.is(effectValue, 'changed by A (after): newA | changed by A (before): newA', 'Effect value should reflect combined indirect changes');
303
+ t.is(instance.configA, 'newA', 'configA should be updated');
304
+ t.is(instance.configB, 'changed by A (after): newA', 'configB should be updated by afterSet hook');
305
+ t.is(instance.configC, 'changed by A (before): newA', 'configC should be updated by beforeSet hook');
306
+
307
+ effect.destroy();
308
+ instance.destroy();
309
+ });
310
+ });
@@ -0,0 +1,138 @@
1
+ import Neo from '../../../../src/Neo.mjs';
2
+ import * as core from '../../../../src/core/_export.mjs';
3
+
4
+ StartTest(t => {
5
+ t.it('should merge static configs from mixins', t => {
6
+ class TestMixin extends core.Base {
7
+ static config = {
8
+ className : 'Neo.test.mixin.TestMixin',
9
+ mixinConfig : 'mixinValue',
10
+ reactiveMixinConfig_: 'reactiveValue'
11
+ }
12
+ }
13
+
14
+ Neo.setupClass(TestMixin);
15
+
16
+ class TestClass extends core.Base {
17
+ static config = {
18
+ className : 'Neo.test.mixin.TestClass',
19
+ classConfig : 'classValue',
20
+ mixins : [TestMixin],
21
+ reactiveClassConfig_: 'reactiveValue'
22
+ }
23
+ }
24
+
25
+ Neo.setupClass(TestClass);
26
+
27
+ const instance = Neo.create(TestClass);
28
+ t.is(instance.mixinConfig, 'mixinValue', 'mixinConfig should be merged from the mixin');
29
+ t.is(instance.reactiveMixinConfig, 'reactiveValue', 'reactiveMixinConfig should be merged from the mixin and the underscore removed');
30
+ });
31
+
32
+ t.it('A class config should always win over a mixin config', t => {
33
+ class MixinWithConfigs extends core.Base {
34
+ static config = {
35
+ className : 'Neo.test.siesta.tests.neo.override.MixinWithConfigs',
36
+ nonReactiveConfig : 'mixinValue',
37
+ reactiveConfig_ : 'mixinValue'
38
+ }
39
+ }
40
+ Neo.setupClass(MixinWithConfigs);
41
+
42
+ class ClassWithConfigs extends core.Base {
43
+ static config = {
44
+ className : 'Neo.test.siesta.tests.neo.override.ClassWithConfigs',
45
+ mixins : [MixinWithConfigs],
46
+ nonReactiveConfig: 'classValue',
47
+ reactiveConfig_ : 'classValue'
48
+ }
49
+ }
50
+ Neo.setupClass(ClassWithConfigs);
51
+
52
+ const instance = Neo.create(ClassWithConfigs);
53
+
54
+ t.is(instance.nonReactiveConfig, 'classValue', 'Class non-reactive config should win over mixin');
55
+ t.is(instance.reactiveConfig, 'classValue', 'Class reactive config should win over mixin');
56
+ });
57
+
58
+ t.it('The first mixin in the array should win for conflicting configs', t => {
59
+ class MixinA extends core.Base {
60
+ static config = {
61
+ className : 'Neo.test.siesta.tests.neo.override.MixinA',
62
+ a_reactive_ : 'a',
63
+ common_reactive_ : 'a'
64
+ }
65
+ }
66
+ Neo.setupClass(MixinA);
67
+
68
+ class MixinB extends core.Base {
69
+ static config = {
70
+ className : 'Neo.test.siesta.tests.neo.override.MixinB',
71
+ b_reactive_ : 'b',
72
+ common_reactive_ : 'b'
73
+ }
74
+ }
75
+ Neo.setupClass(MixinB);
76
+
77
+ class ClassWithTwoMixins extends core.Base {
78
+ static config = {
79
+ className: 'Neo.test.siesta.tests.neo.override.ClassWithTwoMixins',
80
+ mixins : [MixinA, MixinB]
81
+ }
82
+ }
83
+ Neo.setupClass(ClassWithTwoMixins);
84
+
85
+ const instance = Neo.create(ClassWithTwoMixins);
86
+
87
+ t.is(instance.a_reactive, 'a', 'MixinA specific config should be applied');
88
+ t.is(instance.b_reactive, 'b', 'MixinB specific config should be applied');
89
+ t.is(instance.common_reactive, 'a', 'The first mixin (MixinA) should win for common_reactive_');
90
+ });
91
+
92
+ t.it('Mixin on base class should win over mixin on extended class', t => {
93
+ class MixinA extends core.Base {
94
+ static config = {
95
+ className : 'Neo.test.siesta.tests.neo.inheritance.MixinA',
96
+ mixin_a_reactive_ : 'A',
97
+ common_reactive_ : 'A'
98
+ }
99
+ methodA() { return 'A'; }
100
+ }
101
+ Neo.setupClass(MixinA);
102
+
103
+ class MixinB extends core.Base {
104
+ static config = {
105
+ className : 'Neo.test.siesta.tests.neo.inheritance.MixinB',
106
+ mixin_b_reactive_ : 'B',
107
+ common_reactive_ : 'B'
108
+ }
109
+ methodB() { return 'B'; }
110
+ }
111
+ Neo.setupClass(MixinB);
112
+
113
+ class BaseClassWithMixin extends core.Base {
114
+ static config = {
115
+ className: 'Neo.test.siesta.tests.neo.inheritance.BaseClassWithMixin',
116
+ mixins : [MixinA]
117
+ }
118
+ }
119
+ Neo.setupClass(BaseClassWithMixin);
120
+
121
+ class ExtendedClassWithMixin extends BaseClassWithMixin {
122
+ static config = {
123
+ className: 'Neo.test.siesta.tests.neo.inheritance.ExtendedClassWithMixin',
124
+ mixins : [MixinB]
125
+ }
126
+ }
127
+ Neo.setupClass(ExtendedClassWithMixin);
128
+
129
+ const instance = Neo.create(ExtendedClassWithMixin);
130
+
131
+ t.is(instance.mixin_a_reactive, 'A', 'MixinA specific config should be applied');
132
+ t.is(instance.mixin_b_reactive, 'B', 'MixinB specific config should be applied');
133
+ t.is(instance.common_reactive, 'A', 'The mixin on the base class (MixinA) should win for common_reactive_');
134
+
135
+ t.is(instance.methodA(), 'A', 'Method from MixinA should exist');
136
+ t.is(instance.methodB(), 'B', 'Method from MixinB should exist');
137
+ });
138
+ });