@saolabs/client 1.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 (383) hide show
  1. package/README.md +221 -0
  2. package/dist/index.d.ts +46 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/dist/index.js +38 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/plugins.d.ts +38 -0
  7. package/dist/plugins.d.ts.map +1 -0
  8. package/dist/plugins.js +61 -0
  9. package/dist/plugins.js.map +1 -0
  10. package/dist/src/core/app/Application.d.ts +159 -0
  11. package/dist/src/core/app/Application.d.ts.map +1 -0
  12. package/dist/src/core/app/Application.js +338 -0
  13. package/dist/src/core/app/Application.js.map +1 -0
  14. package/dist/src/core/bootstrap/app.d.ts +4 -0
  15. package/dist/src/core/bootstrap/app.d.ts.map +1 -0
  16. package/dist/src/core/bootstrap/app.js +49 -0
  17. package/dist/src/core/bootstrap/app.js.map +1 -0
  18. package/dist/src/core/bootstrap/providers/ApiServiceProvider.d.ts +9 -0
  19. package/dist/src/core/bootstrap/providers/ApiServiceProvider.d.ts.map +1 -0
  20. package/dist/src/core/bootstrap/providers/ApiServiceProvider.js +18 -0
  21. package/dist/src/core/bootstrap/providers/ApiServiceProvider.js.map +1 -0
  22. package/dist/src/core/bootstrap/providers/CoreServiceProvider.d.ts +6 -0
  23. package/dist/src/core/bootstrap/providers/CoreServiceProvider.d.ts.map +1 -0
  24. package/dist/src/core/bootstrap/providers/CoreServiceProvider.js +21 -0
  25. package/dist/src/core/bootstrap/providers/CoreServiceProvider.js.map +1 -0
  26. package/dist/src/core/bootstrap/providers/HelperServiceProvider.d.ts +7 -0
  27. package/dist/src/core/bootstrap/providers/HelperServiceProvider.d.ts.map +1 -0
  28. package/dist/src/core/bootstrap/providers/HelperServiceProvider.js +14 -0
  29. package/dist/src/core/bootstrap/providers/HelperServiceProvider.js.map +1 -0
  30. package/dist/src/core/bootstrap/providers/RouteServiceProvider.d.ts +9 -0
  31. package/dist/src/core/bootstrap/providers/RouteServiceProvider.d.ts.map +1 -0
  32. package/dist/src/core/bootstrap/providers/RouteServiceProvider.js +18 -0
  33. package/dist/src/core/bootstrap/providers/RouteServiceProvider.js.map +1 -0
  34. package/dist/src/core/bootstrap/providers/ServiceProvider.d.ts +38 -0
  35. package/dist/src/core/bootstrap/providers/ServiceProvider.d.ts.map +1 -0
  36. package/dist/src/core/bootstrap/providers/ServiceProvider.js +41 -0
  37. package/dist/src/core/bootstrap/providers/ServiceProvider.js.map +1 -0
  38. package/dist/src/core/bootstrap/providers/ViewServiceProvider.d.ts +9 -0
  39. package/dist/src/core/bootstrap/providers/ViewServiceProvider.d.ts.map +1 -0
  40. package/dist/src/core/bootstrap/providers/ViewServiceProvider.js +18 -0
  41. package/dist/src/core/bootstrap/providers/ViewServiceProvider.js.map +1 -0
  42. package/dist/src/core/bootstrap/providers/default-providers.d.ts +14 -0
  43. package/dist/src/core/bootstrap/providers/default-providers.d.ts.map +1 -0
  44. package/dist/src/core/bootstrap/providers/default-providers.js +79 -0
  45. package/dist/src/core/bootstrap/providers/default-providers.js.map +1 -0
  46. package/dist/src/core/bootstrap/providers/index.d.ts +10 -0
  47. package/dist/src/core/bootstrap/providers/index.d.ts.map +1 -0
  48. package/dist/src/core/bootstrap/providers/index.js +9 -0
  49. package/dist/src/core/bootstrap/providers/index.js.map +1 -0
  50. package/dist/src/core/bootstrap/providers/provider-order.d.ts +19 -0
  51. package/dist/src/core/bootstrap/providers/provider-order.d.ts.map +1 -0
  52. package/dist/src/core/bootstrap/providers/provider-order.js +51 -0
  53. package/dist/src/core/bootstrap/providers/provider-order.js.map +1 -0
  54. package/dist/src/core/cache/ViewCache.d.ts +46 -0
  55. package/dist/src/core/cache/ViewCache.d.ts.map +1 -0
  56. package/dist/src/core/cache/ViewCache.js +85 -0
  57. package/dist/src/core/cache/ViewCache.js.map +1 -0
  58. package/dist/src/core/cache/index.d.ts +2 -0
  59. package/dist/src/core/cache/index.d.ts.map +1 -0
  60. package/dist/src/core/cache/index.js +2 -0
  61. package/dist/src/core/cache/index.js.map +1 -0
  62. package/dist/src/core/contracts/ApiInterface.d.ts +11 -0
  63. package/dist/src/core/contracts/ApiInterface.d.ts.map +1 -0
  64. package/dist/src/core/contracts/ApiInterface.js +2 -0
  65. package/dist/src/core/contracts/ApiInterface.js.map +1 -0
  66. package/dist/src/core/contracts/ApplicationInterface.d.ts +66 -0
  67. package/dist/src/core/contracts/ApplicationInterface.d.ts.map +1 -0
  68. package/dist/src/core/contracts/ApplicationInterface.js +3 -0
  69. package/dist/src/core/contracts/ApplicationInterface.js.map +1 -0
  70. package/dist/src/core/contracts/BlockInterface.d.ts +67 -0
  71. package/dist/src/core/contracts/BlockInterface.d.ts.map +1 -0
  72. package/dist/src/core/contracts/BlockInterface.js +2 -0
  73. package/dist/src/core/contracts/BlockInterface.js.map +1 -0
  74. package/dist/src/core/contracts/ComponentInterface.d.ts +24 -0
  75. package/dist/src/core/contracts/ComponentInterface.d.ts.map +1 -0
  76. package/dist/src/core/contracts/ComponentInterface.js +2 -0
  77. package/dist/src/core/contracts/ComponentInterface.js.map +1 -0
  78. package/dist/src/core/contracts/ElementInterface.d.ts +117 -0
  79. package/dist/src/core/contracts/ElementInterface.d.ts.map +1 -0
  80. package/dist/src/core/contracts/ElementInterface.js +2 -0
  81. package/dist/src/core/contracts/ElementInterface.js.map +1 -0
  82. package/dist/src/core/contracts/EventServiceInterface.d.ts +37 -0
  83. package/dist/src/core/contracts/EventServiceInterface.d.ts.map +1 -0
  84. package/dist/src/core/contracts/EventServiceInterface.js +3 -0
  85. package/dist/src/core/contracts/EventServiceInterface.js.map +1 -0
  86. package/dist/src/core/contracts/HelperInterface.d.ts +231 -0
  87. package/dist/src/core/contracts/HelperInterface.d.ts.map +1 -0
  88. package/dist/src/core/contracts/HelperInterface.js +3 -0
  89. package/dist/src/core/contracts/HelperInterface.js.map +1 -0
  90. package/dist/src/core/contracts/HttpServiceInterface.d.ts +38 -0
  91. package/dist/src/core/contracts/HttpServiceInterface.d.ts.map +1 -0
  92. package/dist/src/core/contracts/HttpServiceInterface.js +3 -0
  93. package/dist/src/core/contracts/HttpServiceInterface.js.map +1 -0
  94. package/dist/src/core/contracts/LoggerServiceInterface.d.ts +37 -0
  95. package/dist/src/core/contracts/LoggerServiceInterface.d.ts.map +1 -0
  96. package/dist/src/core/contracts/LoggerServiceInterface.js +3 -0
  97. package/dist/src/core/contracts/LoggerServiceInterface.js.map +1 -0
  98. package/dist/src/core/contracts/LoopContextInterface.d.ts +14 -0
  99. package/dist/src/core/contracts/LoopContextInterface.d.ts.map +1 -0
  100. package/dist/src/core/contracts/LoopContextInterface.js +3 -0
  101. package/dist/src/core/contracts/LoopContextInterface.js.map +1 -0
  102. package/dist/src/core/contracts/MarkerInterface.d.ts +55 -0
  103. package/dist/src/core/contracts/MarkerInterface.d.ts.map +1 -0
  104. package/dist/src/core/contracts/MarkerInterface.js +2 -0
  105. package/dist/src/core/contracts/MarkerInterface.js.map +1 -0
  106. package/dist/src/core/contracts/ReactiveInterface.d.ts +38 -0
  107. package/dist/src/core/contracts/ReactiveInterface.d.ts.map +1 -0
  108. package/dist/src/core/contracts/ReactiveInterface.js +2 -0
  109. package/dist/src/core/contracts/ReactiveInterface.js.map +1 -0
  110. package/dist/src/core/contracts/RouterInterface.d.ts +58 -0
  111. package/dist/src/core/contracts/RouterInterface.d.ts.map +1 -0
  112. package/dist/src/core/contracts/RouterInterface.js +2 -0
  113. package/dist/src/core/contracts/RouterInterface.js.map +1 -0
  114. package/dist/src/core/contracts/ServiceProviderInterface.d.ts +12 -0
  115. package/dist/src/core/contracts/ServiceProviderInterface.d.ts.map +1 -0
  116. package/dist/src/core/contracts/ServiceProviderInterface.js +2 -0
  117. package/dist/src/core/contracts/ServiceProviderInterface.js.map +1 -0
  118. package/dist/src/core/contracts/StorageServiceInterface.d.ts +43 -0
  119. package/dist/src/core/contracts/StorageServiceInterface.d.ts.map +1 -0
  120. package/dist/src/core/contracts/StorageServiceInterface.js +3 -0
  121. package/dist/src/core/contracts/StorageServiceInterface.js.map +1 -0
  122. package/dist/src/core/contracts/StoreServiceInterface.d.ts +45 -0
  123. package/dist/src/core/contracts/StoreServiceInterface.d.ts.map +1 -0
  124. package/dist/src/core/contracts/StoreServiceInterface.js +3 -0
  125. package/dist/src/core/contracts/StoreServiceInterface.js.map +1 -0
  126. package/dist/src/core/contracts/ViewCacheInterface.d.ts +13 -0
  127. package/dist/src/core/contracts/ViewCacheInterface.d.ts.map +1 -0
  128. package/dist/src/core/contracts/ViewCacheInterface.js +3 -0
  129. package/dist/src/core/contracts/ViewCacheInterface.js.map +1 -0
  130. package/dist/src/core/contracts/ViewControllerInterface.d.ts +115 -0
  131. package/dist/src/core/contracts/ViewControllerInterface.d.ts.map +1 -0
  132. package/dist/src/core/contracts/ViewControllerInterface.js +2 -0
  133. package/dist/src/core/contracts/ViewControllerInterface.js.map +1 -0
  134. package/dist/src/core/contracts/ViewInterface.d.ts +24 -0
  135. package/dist/src/core/contracts/ViewInterface.d.ts.map +1 -0
  136. package/dist/src/core/contracts/ViewInterface.js +2 -0
  137. package/dist/src/core/contracts/ViewInterface.js.map +1 -0
  138. package/dist/src/core/contracts/ViewManagerInterface.d.ts +44 -0
  139. package/dist/src/core/contracts/ViewManagerInterface.d.ts.map +1 -0
  140. package/dist/src/core/contracts/ViewManagerInterface.js +2 -0
  141. package/dist/src/core/contracts/ViewManagerInterface.js.map +1 -0
  142. package/dist/src/core/contracts/ViewStateInterface.d.ts +40 -0
  143. package/dist/src/core/contracts/ViewStateInterface.d.ts.map +1 -0
  144. package/dist/src/core/contracts/ViewStateInterface.js +3 -0
  145. package/dist/src/core/contracts/ViewStateInterface.js.map +1 -0
  146. package/dist/src/core/contracts/common.d.ts +28 -0
  147. package/dist/src/core/contracts/common.d.ts.map +1 -0
  148. package/dist/src/core/contracts/common.js +29 -0
  149. package/dist/src/core/contracts/common.js.map +1 -0
  150. package/dist/src/core/contracts/utils.d.ts +20 -0
  151. package/dist/src/core/contracts/utils.d.ts.map +1 -0
  152. package/dist/src/core/contracts/utils.js +4 -0
  153. package/dist/src/core/contracts/utils.js.map +1 -0
  154. package/dist/src/core/contracts/views.d.ts +23 -0
  155. package/dist/src/core/contracts/views.d.ts.map +1 -0
  156. package/dist/src/core/contracts/views.js +2 -0
  157. package/dist/src/core/contracts/views.js.map +1 -0
  158. package/dist/src/core/elements/Block.d.ts +58 -0
  159. package/dist/src/core/elements/Block.d.ts.map +1 -0
  160. package/dist/src/core/elements/Block.js +77 -0
  161. package/dist/src/core/elements/Block.js.map +1 -0
  162. package/dist/src/core/elements/BlockOutlet.d.ts +34 -0
  163. package/dist/src/core/elements/BlockOutlet.d.ts.map +1 -0
  164. package/dist/src/core/elements/BlockOutlet.js +59 -0
  165. package/dist/src/core/elements/BlockOutlet.js.map +1 -0
  166. package/dist/src/core/elements/Component.d.ts +62 -0
  167. package/dist/src/core/elements/Component.d.ts.map +1 -0
  168. package/dist/src/core/elements/Component.js +72 -0
  169. package/dist/src/core/elements/Component.js.map +1 -0
  170. package/dist/src/core/elements/ElementManager.d.ts +23 -0
  171. package/dist/src/core/elements/ElementManager.d.ts.map +1 -0
  172. package/dist/src/core/elements/ElementManager.js +33 -0
  173. package/dist/src/core/elements/ElementManager.js.map +1 -0
  174. package/dist/src/core/elements/Fragment.d.ts +51 -0
  175. package/dist/src/core/elements/Fragment.d.ts.map +1 -0
  176. package/dist/src/core/elements/Fragment.js +133 -0
  177. package/dist/src/core/elements/Fragment.js.map +1 -0
  178. package/dist/src/core/elements/Html.d.ts +52 -0
  179. package/dist/src/core/elements/Html.d.ts.map +1 -0
  180. package/dist/src/core/elements/Html.js +299 -0
  181. package/dist/src/core/elements/Html.js.map +1 -0
  182. package/dist/src/core/elements/Output.d.ts +69 -0
  183. package/dist/src/core/elements/Output.d.ts.map +1 -0
  184. package/dist/src/core/elements/Output.js +121 -0
  185. package/dist/src/core/elements/Output.js.map +1 -0
  186. package/dist/src/core/elements/Reactive.d.ts +77 -0
  187. package/dist/src/core/elements/Reactive.d.ts.map +1 -0
  188. package/dist/src/core/elements/Reactive.js +199 -0
  189. package/dist/src/core/elements/Reactive.js.map +1 -0
  190. package/dist/src/core/elements/TextElement.d.ts +46 -0
  191. package/dist/src/core/elements/TextElement.d.ts.map +1 -0
  192. package/dist/src/core/elements/TextElement.js +94 -0
  193. package/dist/src/core/elements/TextElement.js.map +1 -0
  194. package/dist/src/core/elements/Wrapper.d.ts +50 -0
  195. package/dist/src/core/elements/Wrapper.d.ts.map +1 -0
  196. package/dist/src/core/elements/Wrapper.js +96 -0
  197. package/dist/src/core/elements/Wrapper.js.map +1 -0
  198. package/dist/src/core/elements/Yield.d.ts +34 -0
  199. package/dist/src/core/elements/Yield.d.ts.map +1 -0
  200. package/dist/src/core/elements/Yield.js +56 -0
  201. package/dist/src/core/elements/Yield.js.map +1 -0
  202. package/dist/src/core/elements/helpers.d.ts +8 -0
  203. package/dist/src/core/elements/helpers.d.ts.map +1 -0
  204. package/dist/src/core/elements/helpers.js +40 -0
  205. package/dist/src/core/elements/helpers.js.map +1 -0
  206. package/dist/src/core/elements/index.d.ts +12 -0
  207. package/dist/src/core/elements/index.d.ts.map +1 -0
  208. package/dist/src/core/elements/index.js +12 -0
  209. package/dist/src/core/elements/index.js.map +1 -0
  210. package/dist/src/core/hellpers/ApiClient.d.ts +58 -0
  211. package/dist/src/core/hellpers/ApiClient.d.ts.map +1 -0
  212. package/dist/src/core/hellpers/ApiClient.js +122 -0
  213. package/dist/src/core/hellpers/ApiClient.js.map +1 -0
  214. package/dist/src/core/hellpers/app.d.ts +3 -0
  215. package/dist/src/core/hellpers/app.d.ts.map +1 -0
  216. package/dist/src/core/hellpers/app.js +53 -0
  217. package/dist/src/core/hellpers/app.js.map +1 -0
  218. package/dist/src/core/hellpers/utils.d.ts +26 -0
  219. package/dist/src/core/hellpers/utils.d.ts.map +1 -0
  220. package/dist/src/core/hellpers/utils.js +96 -0
  221. package/dist/src/core/hellpers/utils.js.map +1 -0
  222. package/dist/src/core/routers/Router.d.ts +212 -0
  223. package/dist/src/core/routers/Router.d.ts.map +1 -0
  224. package/dist/src/core/routers/Router.js +623 -0
  225. package/dist/src/core/routers/Router.js.map +1 -0
  226. package/dist/src/core/routers/index.d.ts +3 -0
  227. package/dist/src/core/routers/index.d.ts.map +1 -0
  228. package/dist/src/core/routers/index.js +2 -0
  229. package/dist/src/core/routers/index.js.map +1 -0
  230. package/dist/src/core/services/BlockManager.d.ts +63 -0
  231. package/dist/src/core/services/BlockManager.d.ts.map +1 -0
  232. package/dist/src/core/services/BlockManager.js +191 -0
  233. package/dist/src/core/services/BlockManager.js.map +1 -0
  234. package/dist/src/core/services/DomService.d.ts +9 -0
  235. package/dist/src/core/services/DomService.d.ts.map +1 -0
  236. package/dist/src/core/services/DomService.js +18 -0
  237. package/dist/src/core/services/DomService.js.map +1 -0
  238. package/dist/src/core/services/EventService.d.ts +58 -0
  239. package/dist/src/core/services/EventService.d.ts.map +1 -0
  240. package/dist/src/core/services/EventService.js +212 -0
  241. package/dist/src/core/services/EventService.js.map +1 -0
  242. package/dist/src/core/services/HelperService.d.ts +443 -0
  243. package/dist/src/core/services/HelperService.d.ts.map +1 -0
  244. package/dist/src/core/services/HelperService.js +1650 -0
  245. package/dist/src/core/services/HelperService.js.map +1 -0
  246. package/dist/src/core/services/HttpService.d.ts +63 -0
  247. package/dist/src/core/services/HttpService.d.ts.map +1 -0
  248. package/dist/src/core/services/HttpService.js +182 -0
  249. package/dist/src/core/services/HttpService.js.map +1 -0
  250. package/dist/src/core/services/LoggerService.d.ts +56 -0
  251. package/dist/src/core/services/LoggerService.d.ts.map +1 -0
  252. package/dist/src/core/services/LoggerService.js +94 -0
  253. package/dist/src/core/services/LoggerService.js.map +1 -0
  254. package/dist/src/core/services/MarkerRegistry.d.ts +94 -0
  255. package/dist/src/core/services/MarkerRegistry.d.ts.map +1 -0
  256. package/dist/src/core/services/MarkerRegistry.js +199 -0
  257. package/dist/src/core/services/MarkerRegistry.js.map +1 -0
  258. package/dist/src/core/services/MarkerService.d.ts +299 -0
  259. package/dist/src/core/services/MarkerService.d.ts.map +1 -0
  260. package/dist/src/core/services/MarkerService.js +723 -0
  261. package/dist/src/core/services/MarkerService.js.map +1 -0
  262. package/dist/src/core/services/StorageService.d.ts +69 -0
  263. package/dist/src/core/services/StorageService.d.ts.map +1 -0
  264. package/dist/src/core/services/StorageService.js +243 -0
  265. package/dist/src/core/services/StorageService.js.map +1 -0
  266. package/dist/src/core/services/StoreService.d.ts +80 -0
  267. package/dist/src/core/services/StoreService.d.ts.map +1 -0
  268. package/dist/src/core/services/StoreService.js +301 -0
  269. package/dist/src/core/services/StoreService.js.map +1 -0
  270. package/dist/src/core/services/index.d.ts +9 -0
  271. package/dist/src/core/services/index.d.ts.map +1 -0
  272. package/dist/src/core/services/index.js +9 -0
  273. package/dist/src/core/services/index.js.map +1 -0
  274. package/dist/src/core/types/utils.d.ts +29 -0
  275. package/dist/src/core/types/utils.d.ts.map +1 -0
  276. package/dist/src/core/types/utils.js +22 -0
  277. package/dist/src/core/types/utils.js.map +1 -0
  278. package/dist/src/core/view/LoopContext.d.ts +38 -0
  279. package/dist/src/core/view/LoopContext.d.ts.map +1 -0
  280. package/dist/src/core/view/LoopContext.js +100 -0
  281. package/dist/src/core/view/LoopContext.js.map +1 -0
  282. package/dist/src/core/view/Section.d.ts +41 -0
  283. package/dist/src/core/view/Section.d.ts.map +1 -0
  284. package/dist/src/core/view/Section.js +67 -0
  285. package/dist/src/core/view/Section.js.map +1 -0
  286. package/dist/src/core/view/View.d.ts +63 -0
  287. package/dist/src/core/view/View.d.ts.map +1 -0
  288. package/dist/src/core/view/View.js +85 -0
  289. package/dist/src/core/view/View.js.map +1 -0
  290. package/dist/src/core/view/ViewController.d.ts +277 -0
  291. package/dist/src/core/view/ViewController.d.ts.map +1 -0
  292. package/dist/src/core/view/ViewController.js +862 -0
  293. package/dist/src/core/view/ViewController.js.map +1 -0
  294. package/dist/src/core/view/ViewManager.d.ts +141 -0
  295. package/dist/src/core/view/ViewManager.d.ts.map +1 -0
  296. package/dist/src/core/view/ViewManager.js +565 -0
  297. package/dist/src/core/view/ViewManager.js.map +1 -0
  298. package/dist/src/core/view/ViewState.d.ts +117 -0
  299. package/dist/src/core/view/ViewState.d.ts.map +1 -0
  300. package/dist/src/core/view/ViewState.js +410 -0
  301. package/dist/src/core/view/ViewState.js.map +1 -0
  302. package/dist/src/core/view/index.d.ts +6 -0
  303. package/dist/src/core/view/index.d.ts.map +1 -0
  304. package/dist/src/core/view/index.js +6 -0
  305. package/dist/src/core/view/index.js.map +1 -0
  306. package/index.ts +62 -0
  307. package/package.json +70 -0
  308. package/plugins.ts +77 -0
  309. package/src/core/app/Application.ts +410 -0
  310. package/src/core/bootstrap/app.ts +58 -0
  311. package/src/core/bootstrap/providers/ApiServiceProvider.ts +18 -0
  312. package/src/core/bootstrap/providers/CoreServiceProvider.ts +19 -0
  313. package/src/core/bootstrap/providers/HelperServiceProvider.ts +12 -0
  314. package/src/core/bootstrap/providers/RouteServiceProvider.ts +17 -0
  315. package/src/core/bootstrap/providers/ServiceProvider.ts +51 -0
  316. package/src/core/bootstrap/providers/ViewServiceProvider.ts +17 -0
  317. package/src/core/bootstrap/providers/default-providers.ts +94 -0
  318. package/src/core/bootstrap/providers/index.ts +9 -0
  319. package/src/core/bootstrap/providers/provider-order.test.ts +67 -0
  320. package/src/core/bootstrap/providers/provider-order.ts +66 -0
  321. package/src/core/cache/ViewCache.ts +102 -0
  322. package/src/core/cache/index.ts +1 -0
  323. package/src/core/contracts/ApiInterface.ts +11 -0
  324. package/src/core/contracts/ApplicationInterface.ts +79 -0
  325. package/src/core/contracts/BlockInterface.ts +76 -0
  326. package/src/core/contracts/ComponentInterface.ts +26 -0
  327. package/src/core/contracts/ElementInterface.ts +140 -0
  328. package/src/core/contracts/EventServiceInterface.ts +47 -0
  329. package/src/core/contracts/HelperInterface.ts +256 -0
  330. package/src/core/contracts/HttpServiceInterface.ts +51 -0
  331. package/src/core/contracts/LoggerServiceInterface.ts +48 -0
  332. package/src/core/contracts/LoopContextInterface.ts +15 -0
  333. package/src/core/contracts/MarkerInterface.ts +77 -0
  334. package/src/core/contracts/ReactiveInterface.ts +45 -0
  335. package/src/core/contracts/RouterInterface.ts +65 -0
  336. package/src/core/contracts/ServiceProviderInterface.ts +12 -0
  337. package/src/core/contracts/StorageServiceInterface.ts +48 -0
  338. package/src/core/contracts/StoreServiceInterface.ts +50 -0
  339. package/src/core/contracts/ViewCacheInterface.ts +14 -0
  340. package/src/core/contracts/ViewControllerInterface.ts +135 -0
  341. package/src/core/contracts/ViewInterface.ts +31 -0
  342. package/src/core/contracts/ViewManagerInterface.ts +45 -0
  343. package/src/core/contracts/ViewStateInterface.ts +47 -0
  344. package/src/core/contracts/common.ts +27 -0
  345. package/src/core/contracts/utils.ts +23 -0
  346. package/src/core/contracts/views.ts +23 -0
  347. package/src/core/elements/Block.ts +113 -0
  348. package/src/core/elements/BlockOutlet.ts +83 -0
  349. package/src/core/elements/Component.ts +114 -0
  350. package/src/core/elements/ElementManager.ts +48 -0
  351. package/src/core/elements/Fragment.ts +168 -0
  352. package/src/core/elements/Html.ts +364 -0
  353. package/src/core/elements/Output.ts +167 -0
  354. package/src/core/elements/Reactive.ts +253 -0
  355. package/src/core/elements/TextElement.ts +110 -0
  356. package/src/core/elements/Wrapper.ts +131 -0
  357. package/src/core/elements/Yield.ts +70 -0
  358. package/src/core/elements/helpers.ts +56 -0
  359. package/src/core/elements/index.ts +26 -0
  360. package/src/core/hellpers/ApiClient.ts +145 -0
  361. package/src/core/hellpers/app.ts +57 -0
  362. package/src/core/hellpers/utils.ts +109 -0
  363. package/src/core/routers/Router.ts +765 -0
  364. package/src/core/routers/index.ts +2 -0
  365. package/src/core/services/BlockManager.ts +210 -0
  366. package/src/core/services/DomService.ts +26 -0
  367. package/src/core/services/EventService.ts +266 -0
  368. package/src/core/services/HelperService.ts +1653 -0
  369. package/src/core/services/HttpService.ts +235 -0
  370. package/src/core/services/LoggerService.ts +139 -0
  371. package/src/core/services/MarkerRegistry.ts +239 -0
  372. package/src/core/services/MarkerService.ts +923 -0
  373. package/src/core/services/StorageService.ts +268 -0
  374. package/src/core/services/StoreService.ts +338 -0
  375. package/src/core/services/index.ts +8 -0
  376. package/src/core/types/utils.ts +30 -0
  377. package/src/core/view/LoopContext.ts +109 -0
  378. package/src/core/view/Section.ts +86 -0
  379. package/src/core/view/View.ts +109 -0
  380. package/src/core/view/ViewController.ts +1002 -0
  381. package/src/core/view/ViewManager.ts +700 -0
  382. package/src/core/view/ViewState.ts +453 -0
  383. package/src/core/view/index.ts +5 -0
@@ -0,0 +1,862 @@
1
+ import { ViewState } from "./ViewState";
2
+ import { LoopContext } from "./LoopContext";
3
+ import { Reactive } from "../elements/Reactive";
4
+ import BlockManager from "../services/BlockManager";
5
+ import { Component } from "../elements/Component";
6
+ import { generateUUID } from "../hellpers/utils";
7
+ import { Output } from "../elements/Output";
8
+ import { Section } from "./Section";
9
+ import { Block, BlockOutlet, Fragment, Html } from "../elements";
10
+ import { Wrapper } from "../elements/Wrapper";
11
+ import { YieldElement } from "../elements/Yield";
12
+ import { app } from "../hellpers/app";
13
+ /**
14
+ * ViewController — the brain behind a View.
15
+ *
16
+ * Manages:
17
+ * - Reactive state (ViewState) — useState, subscribe, batch flush
18
+ * - DOM element tree — via Html, Reactive, TextElement, Fragment
19
+ * - Event delegation — addEventListener with centralized cleanup
20
+ * - Loop contexts — @foreach, @for, @while with LoopContext stack
21
+ * - Block management — for layout views with @useBlock
22
+ * - Lifecycle — setup, render, destroy
23
+ * - Reactive scheduling — batched DOM updates via requestAnimationFrame
24
+ *
25
+ * KEY DIFFERENCE from core/ViewController:
26
+ * OLD: render() returns HTML string → innerHTML → scan DOM for bindings
27
+ * NEW: render() builds element tree directly → Reactive regions update in-place
28
+ *
29
+ * Compiled .one output calls methods like:
30
+ * this.__ctrl__.addEventListener(el, 'click', handlers)
31
+ * this.__ctrl__.states.__.useState(0, 'count')
32
+ * this.__ctrl__.__foreach(items, (item, key, index, loop) => [...])
33
+ */
34
+ export class ViewController {
35
+ // ─── Constructor ────────────────────────────────────────────
36
+ constructor(view, path = '', viewType = 'view', viewId = null) {
37
+ // ─── Identity ───────────────────────────────────────────────
38
+ this.oneType = 'ViewController';
39
+ // ─── View Hierarchy ─────────────────────────────────────────
40
+ /** Parent view controller (for nested views) */
41
+ this.parent = null;
42
+ /** Child view controllers (for nested views) */
43
+ this.children = [];
44
+ /** Layout (super) view's controller */
45
+ this.superView = null;
46
+ /** Path to layout (super) view — e.g. 'layouts.main' */
47
+ this.superViewPath = null;
48
+ /** Whether this controller IS a layout */
49
+ this.isSuperView = false;
50
+ /** For layouts: the original page view's controller (for block mounting) */
51
+ this.originView = null;
52
+ // ─── Data & Config ──────────────────────────────────────────
53
+ /** Raw input data from route/parent */
54
+ this.data = {};
55
+ /** User-defined config from setup() */
56
+ this.config = {};
57
+ /** Typed runtime config from compiled $__setup__ */
58
+ this.runtimeConfig = {};
59
+ /** Track own properties to avoid conflicts when setting user config */
60
+ this.ownProperties = new Set(['__ctrl__']);
61
+ // ─── DOM & Rendering ────────────────────────────────────────
62
+ /** Root Html element — the container this view renders into */
63
+ this.rootElement = null;
64
+ this.parentElement = null; // For non-root views, track the parent element for correct mounting
65
+ /** Root element tree returned by renderFactory (Fragment, Html, etc.) */
66
+ this._rootTree = null;
67
+ /** Compiled render factory — produces the element tree */
68
+ this.renderFactory = null;
69
+ /** Compiled prerender factory — produces the prerender element tree */
70
+ this.prerenderFactory = null;
71
+ this.childrenFactory = null;
72
+ /** Stored render output for lifecycle management */
73
+ this.renderOutput = null;
74
+ /** Stored prerender output for hydration or caching */
75
+ this.prerenderOutput = null;
76
+ /** DOM children — for compatibility with HtmlInterface */
77
+ this.domChildren = [];
78
+ /** Flag: currently in a virtual render (for hydration or caching) */
79
+ this.isVirtualRendering = false;
80
+ this.initMode = 'create';
81
+ // ─── Reactive System ────────────────────────────────────────
82
+ /** Pending reactive updates — deduped, flushed in one RAF */
83
+ this.pendingReactiveUpdates = new Set();
84
+ this.hasScheduledUpdate = false;
85
+ /** Centralized AbortController for all event listeners */
86
+ this.eventAbortController = new AbortController();
87
+ // ─── Loop ───────────────────────────────────────────────────
88
+ /** Current loop context stack (@foreach, @for, @while) */
89
+ this.loopContext = null;
90
+ // ─── Layout (Sections & Blocks) ─────────────────────────────
91
+ /** Section management across views */
92
+ this.sections = new Map();
93
+ /** Block slots in layout views */
94
+ this.blocks = new Map();
95
+ this.elements = new Map();
96
+ this.preloadElement = null; // For pre-rendering elements before the main render
97
+ this.mainElement = null; // The main rendered element tree
98
+ // ─── Lifecycle Flags ────────────────────────────────────────
99
+ /** Whether this view is currently active (mounted in DOM) */
100
+ this.isActive = false;
101
+ /** Whether initial data has been committed */
102
+ this._isDataCommitted = false;
103
+ /** Whether the view has been mounted */
104
+ this._isMounted = false;
105
+ /** Whether the view has been fully destroyed */
106
+ this._isDestroyed = false;
107
+ /** For future use: scanning DOM for bindings */
108
+ this.isScanMode = false;
109
+ // --- Route params for reference in blocks and sections (set by ViewManager on navigate) ---
110
+ this.urlPath = null;
111
+ this.callingMethod = null; // For debugging: track which method is currently executing
112
+ this.__App = app();
113
+ this.view = view;
114
+ this.path = path;
115
+ this.viewType = viewType;
116
+ this.viewId = viewId ?? this.generateViewId();
117
+ this.states = new ViewState(this);
118
+ }
119
+ // ─── Lifecycle ──────────────────────────────────────────────
120
+ /**
121
+ * Setup — called by compiled $__setup__ with full config.
122
+ *
123
+ * Lưu config, extract metadata, lưu render factory.
124
+ * CHƯA gọi commitConstructorData — đợi ViewManager gọi commitData().
125
+ */
126
+ setup(config) {
127
+ this.runtimeConfig = config;
128
+ // Extract metadata
129
+ if (config.viewId)
130
+ this.viewId = config.viewId;
131
+ if (config.path)
132
+ this.path = config.path;
133
+ this.data = config.data || {};
134
+ this.superViewPath = config.superView || null;
135
+ // Store render factory
136
+ if (typeof config.render === 'function') {
137
+ this.setRenderFactory(config.render.bind(this));
138
+ }
139
+ if (typeof config.prerender === 'function') {
140
+ this.prerenderFactory = config.prerender.bind(this);
141
+ }
142
+ }
143
+ getConfig(key, defaultValue) {
144
+ if (key) {
145
+ return this.runtimeConfig?.[key] ?? (this.config[key] ?? defaultValue);
146
+ }
147
+ return { ...this.runtimeConfig, ...this.config };
148
+ }
149
+ /** Set static view config shared by all instances of a compiled view class. */
150
+ setStaticConfig(config) {
151
+ this.config = config || {};
152
+ }
153
+ /** Set user-defined properties/methods on the View instance */
154
+ setUserDefinedConfig(userConfig) {
155
+ for (const [key, value] of Object.entries(userConfig)) {
156
+ if (!this.ownProperties.has(key)) {
157
+ this.view[key] = typeof value === 'function' && value.bind
158
+ ? value.bind(this.view)
159
+ : value;
160
+ }
161
+ }
162
+ }
163
+ /** Set the compiled render factory */
164
+ setRenderFactory(factory) {
165
+ this.renderFactory = factory;
166
+ }
167
+ /** Set root element — the container this view renders into */
168
+ setRootElement(rootElement) {
169
+ this.rootElement = rootElement;
170
+ }
171
+ setParentElement(parent) {
172
+ this.parentElement = parent;
173
+ }
174
+ /** Render the view's element tree into rootElement.
175
+ *
176
+ * The compiled render factory (bound to this ViewController) returns
177
+ * the root element tree (typically a Fragment). We set its parent
178
+ * to rootElement, call render() to build DOM, and store the reference
179
+ * for start/stop lifecycle management.
180
+ */
181
+ render() {
182
+ const oldCallingMethod = this.callingMethod;
183
+ this.callingMethod = 'render';
184
+ let output = this.renderFactory ? this.renderFactory() : null;
185
+ if (this.isVirtualRendering) {
186
+ return output;
187
+ }
188
+ this.renderOutput = output;
189
+ this.callingMethod = oldCallingMethod;
190
+ return output;
191
+ }
192
+ prerender() {
193
+ const oldCallingMethod = this.callingMethod;
194
+ this.callingMethod = 'prerender';
195
+ let output = this.prerenderFactory ? this.prerenderFactory() : null;
196
+ if (this.isVirtualRendering) {
197
+ return output;
198
+ }
199
+ this.prerenderOutput = output;
200
+ this.callingMethod = oldCallingMethod;
201
+ return output;
202
+ }
203
+ hydrate() {
204
+ this.initMode = 'hydrate';
205
+ }
206
+ hydrateRender() {
207
+ this.initMode = 'hydrate';
208
+ let output = this.render();
209
+ this.initMode = 'create';
210
+ return output;
211
+ }
212
+ hydratePrerender() {
213
+ this.initMode = 'hydrate';
214
+ let output = this.prerender();
215
+ this.initMode = 'create';
216
+ return output;
217
+ }
218
+ mount(root) {
219
+ }
220
+ unmount() {
221
+ }
222
+ /**
223
+ * Start — activate reactive subscriptions throughout the element tree.
224
+ * Called AFTER render() and commitData().
225
+ *
226
+ * Flow: render() → commitData() → start()
227
+ * This ensures initial state values are set before subscriptions fire.
228
+ */
229
+ start() {
230
+ if (this._isDestroyed || !this._rootTree)
231
+ return;
232
+ // Recursively start all children (Output, TextElement, Html, Reactive, Fragment)
233
+ if ('start' in this._rootTree && typeof this._rootTree.start === 'function') {
234
+ this._rootTree.start();
235
+ }
236
+ // Fire onMounted hook
237
+ if (typeof this.view.onMounted === 'function') {
238
+ try {
239
+ this.view.onMounted();
240
+ }
241
+ catch (e) {
242
+ console.error(`[ViewController] onMounted error in "${this.path}":`, e);
243
+ }
244
+ }
245
+ }
246
+ /**
247
+ * Stop — deactivate reactive subscriptions (for caching/deactivation).
248
+ * DOM stays intact but reactive updates are paused.
249
+ */
250
+ stop() {
251
+ if (this._isDestroyed || !this._rootTree)
252
+ return;
253
+ // Recursively stop all children
254
+ if ('stop' in this._rootTree && typeof this._rootTree.stop === 'function') {
255
+ this._rootTree.stop();
256
+ }
257
+ // Fire onDeactivated hook
258
+ if (typeof this.view.onDeactivated === 'function') {
259
+ try {
260
+ this.view.onDeactivated();
261
+ }
262
+ catch (e) {
263
+ console.error(`[ViewController] onDeactivated error in "${this.path}":`, e);
264
+ }
265
+ }
266
+ }
267
+ /** Full destroy — cleanup everything */
268
+ destroy() {
269
+ if (this._isDestroyed)
270
+ return;
271
+ this._isDestroyed = true;
272
+ // Stop reactive subscriptions first
273
+ this.stop();
274
+ // Cancel pending updates
275
+ this.pendingReactiveUpdates.clear();
276
+ this.hasScheduledUpdate = false;
277
+ // Abort all event listeners
278
+ this.eventAbortController.abort();
279
+ // Destroy root tree
280
+ if (this._rootTree && 'destroy' in this._rootTree && typeof this._rootTree.destroy === 'function') {
281
+ this._rootTree.destroy();
282
+ }
283
+ this._rootTree = null;
284
+ // Destroy state
285
+ this.states.__.destroy();
286
+ // Cleanup loop context stack
287
+ this.loopContext = null;
288
+ // Fire onDestroy hook
289
+ if (typeof this.view.onDestroy === 'function') {
290
+ try {
291
+ this.view.onDestroy();
292
+ }
293
+ catch (e) {
294
+ console.error(`[ViewController] onDestroy error in "${this.path}":`, e);
295
+ }
296
+ }
297
+ // Nullify references
298
+ this.rootElement = null;
299
+ this.renderFactory = null;
300
+ this.prerenderFactory = null;
301
+ this._isMounted = false;
302
+ }
303
+ // ─── Data Lifecycle ─────────────────────────────────────────
304
+ /**
305
+ * Commit initial data — set initial state values.
306
+ * Called by ViewManager AFTER render + block mounting.
307
+ *
308
+ * Flow: commitConstructorData() → update$xxx(initial) → lockUpdateRealState()
309
+ */
310
+ commitData() {
311
+ }
312
+ /**
313
+ * Update data from external source (navigate same view, different params).
314
+ * Flow: unlock → updateVariableData(newData) → re-set states → lock
315
+ */
316
+ updateData(newData) {
317
+ this.runtimeConfig?.updateVariableData?.(newData);
318
+ }
319
+ /**
320
+ * Update single data item.
321
+ */
322
+ updateDataItem(key, value) {
323
+ }
324
+ // ─── Event Management ───────────────────────────────────────
325
+ /**
326
+ * Register event listeners on an element.
327
+ * All listeners are tracked via AbortController for centralized cleanup.
328
+ *
329
+ * Handlers can be:
330
+ * - Direct function: (event) => { ... }
331
+ * - Object with handler + params: { handler: fn, params: [...] }
332
+ * - Object with string handler (method name on view): { handler: 'handleClick' }
333
+ */
334
+ addEventListener(element, event, handlers) {
335
+ for (const h of handlers) {
336
+ let fn;
337
+ if (typeof h === 'function') {
338
+ fn = h;
339
+ }
340
+ else if (typeof h === 'object' && h !== null) {
341
+ const handlerDef = h;
342
+ if (typeof handlerDef.handler === 'string') {
343
+ // Method name on view
344
+ const methodName = handlerDef.handler;
345
+ const view = this.view;
346
+ fn = ((event) => {
347
+ if (typeof view[methodName] === 'function') {
348
+ const params = handlerDef.params
349
+ ? handlerDef.params.map(p => {
350
+ if (typeof p === 'function')
351
+ return p(event);
352
+ return p === '@EVENT' ? event : p;
353
+ })
354
+ : [event];
355
+ view[methodName](...params);
356
+ }
357
+ });
358
+ }
359
+ else if (typeof handlerDef.handler === 'function') {
360
+ const originalHandler = handlerDef.handler;
361
+ if (handlerDef.params) {
362
+ fn = ((event) => {
363
+ const params = handlerDef.params.map((p) => {
364
+ if (typeof p === 'function')
365
+ return p(event);
366
+ return p === '@EVENT' ? event : p;
367
+ });
368
+ originalHandler.apply(this.view, params);
369
+ });
370
+ }
371
+ else {
372
+ fn = originalHandler;
373
+ }
374
+ }
375
+ else {
376
+ continue;
377
+ }
378
+ }
379
+ else {
380
+ continue;
381
+ }
382
+ element.addEventListener(event, fn, { signal: this.eventAbortController.signal });
383
+ }
384
+ }
385
+ // ─── Reactive Scheduling ────────────────────────────────────
386
+ /**
387
+ * Schedule a reactive region for re-render.
388
+ * Multiple calls in the same frame are batched into a single RAF.
389
+ */
390
+ scheduleUpdate(reactive) {
391
+ if (this._isDestroyed)
392
+ return;
393
+ this.pendingReactiveUpdates.add(reactive);
394
+ if (!this.hasScheduledUpdate) {
395
+ this.hasScheduledUpdate = true;
396
+ requestAnimationFrame(() => this.flushReactiveUpdates());
397
+ }
398
+ }
399
+ flushReactiveUpdates() {
400
+ if (this._isDestroyed)
401
+ return;
402
+ this.hasScheduledUpdate = false;
403
+ const updates = Array.from(this.pendingReactiveUpdates);
404
+ this.pendingReactiveUpdates.clear();
405
+ for (const reactive of updates) {
406
+ try {
407
+ reactive.render();
408
+ }
409
+ catch (e) {
410
+ console.error(`[ViewController] Reactive update error in "${this.path}":`, e);
411
+ }
412
+ }
413
+ }
414
+ section(name, config, contentRenderFactory) {
415
+ if (this.sections.has(name)) {
416
+ const section = this.sections.get(name);
417
+ if (section) {
418
+ return section;
419
+ }
420
+ }
421
+ config.ctx = this;
422
+ config.name = name;
423
+ config.renderFactory = contentRenderFactory;
424
+ const section = new Section(config);
425
+ this.sections.set(name, section);
426
+ return section;
427
+ }
428
+ // template methods called by compiled output — these build the element tree directly
429
+ block(id, name, contentRenderFactory) {
430
+ if (!id) {
431
+ id = `b-${name}`;
432
+ }
433
+ const existing = this.blocks.get(id);
434
+ const initMode = this.initMode;
435
+ if (existing) {
436
+ existing.contentRenderFactory = contentRenderFactory;
437
+ BlockManager.active(name, this.viewId);
438
+ existing.initMode = initMode;
439
+ return existing;
440
+ }
441
+ const block = new Block({ ctx: this, name, id, initMode, contentRenderFactory });
442
+ this.blocks.set(id, block);
443
+ BlockManager.add(block);
444
+ return block;
445
+ }
446
+ blockOutlet(id = null, name, parentElement) {
447
+ const initMode = this.initMode;
448
+ if (!id) {
449
+ id = `ob-${name}`;
450
+ }
451
+ const existing = this.elements.get(id);
452
+ if (existing instanceof BlockOutlet) {
453
+ existing.setParentElement(parentElement);
454
+ existing.initMode = initMode;
455
+ return existing;
456
+ }
457
+ const outlet = new BlockOutlet({ ctx: this, name, id, parentElement, initMode });
458
+ this.elements.set(id, outlet);
459
+ // do something if needed
460
+ return outlet;
461
+ }
462
+ mountBlock(id = null, name, parent) {
463
+ return this.blockOutlet(id, name, parent);
464
+ }
465
+ /**
466
+ * @useBlock(name) — register a block slot in the layout.
467
+ * Creates a Reactive region between markers that will hold the block content.
468
+ * BlockManager.mountAll() later inserts the page view's block content here.
469
+ */
470
+ useBlock(id = null, name, parent) {
471
+ return this.blockOutlet(id, name, parent);
472
+ }
473
+ yield(id, name, defaultValue = null, parentElement = null) {
474
+ const existing = this.elements.get(id);
475
+ if (existing instanceof YieldElement) {
476
+ existing.setParentElement(parentElement);
477
+ existing.defaultValue = defaultValue;
478
+ return existing;
479
+ }
480
+ const yieldEl = new YieldElement({ ctx: this, name, initMode: this.initMode, id, defaultValue });
481
+ yieldEl.setParentElement(parentElement);
482
+ this.elements.set(id, yieldEl);
483
+ return yieldEl;
484
+ }
485
+ yieldContent(name, defaultValue = null) {
486
+ return this.App.View?.yieldContent?.(name, defaultValue) ?? defaultValue;
487
+ }
488
+ wrapper(factory) {
489
+ const callingMethod = this.callingMethod;
490
+ let key = callingMethod === 'prerender' ? 'preloadElement' : 'mainElement';
491
+ let wrapper = this[key];
492
+ if (!wrapper) {
493
+ wrapper = new Wrapper({ ctx: this, initMode: this.initMode, parentElement: this.parentElement, childrenFactory: factory });
494
+ this[key] = wrapper;
495
+ }
496
+ else {
497
+ wrapper.setChildrenFactory(factory);
498
+ }
499
+ return wrapper;
500
+ }
501
+ fragment(id = null, parentElement, childrenFactory) {
502
+ if (!id) {
503
+ id = `fr-${generateUUID(5)}`;
504
+ }
505
+ const existing = this.elements.get(id);
506
+ if (existing instanceof Fragment) {
507
+ if (childrenFactory) {
508
+ existing.setChildrenFactory(childrenFactory);
509
+ }
510
+ return existing;
511
+ }
512
+ const initMode = this.initMode;
513
+ const fragment = new Fragment({ ctx: this, id, initMode, parentElement, childrenFactory });
514
+ this.elements.set(id, fragment);
515
+ return fragment;
516
+ }
517
+ /**
518
+ * Template and Directive Helpers
519
+ * These methods are called by the compiled output for loops, conditionals, and other directives.
520
+ */
521
+ html(id = null, tagName, parentElement, config, childrenFactory) {
522
+ if (!id) {
523
+ id = `el-${tagName}-${generateUUID(5)}`;
524
+ }
525
+ const existing = this.elements.get(id);
526
+ if (existing instanceof Html) {
527
+ existing.updateConfig(config);
528
+ if (childrenFactory) {
529
+ existing.setChildrenFactory(childrenFactory);
530
+ }
531
+ return existing;
532
+ }
533
+ const element = new Html({ ctx: this, tagName, id, parentElement, initMode: this.initMode, config, childrenFactory });
534
+ this.elements.set(id, element);
535
+ return element;
536
+ }
537
+ reactive(id, type, parentReactive, parentElement, stateKeys, childrenFactory) {
538
+ // check
539
+ if (!id) {
540
+ id = `r-${type}-${generateUUID(5)}`;
541
+ }
542
+ const existing = this.elements.get(id);
543
+ if (existing instanceof Reactive) {
544
+ existing.setChildrenFactory(childrenFactory);
545
+ existing.setStateKeys(stateKeys);
546
+ return existing;
547
+ }
548
+ const reactive = new Reactive({
549
+ type,
550
+ id,
551
+ ctx: this,
552
+ parentReactive,
553
+ parentElement,
554
+ stateKeys,
555
+ childrenFactory
556
+ });
557
+ this.elements.set(id, reactive);
558
+ return reactive;
559
+ }
560
+ output(id, parent, isEscapeHTML = true, stateKeys = [], contentFactory = () => '') {
561
+ if (!id) {
562
+ id = `o-${generateUUID(5)}`;
563
+ }
564
+ const existing = this.elements.get(id);
565
+ if (existing instanceof Output) {
566
+ existing.setStateKeys(stateKeys);
567
+ existing.contentFactory = contentFactory;
568
+ return existing;
569
+ }
570
+ const output = new Output({
571
+ ctx: this,
572
+ id,
573
+ parent,
574
+ stateKeys,
575
+ isEscapeHTML,
576
+ contentFactory,
577
+ });
578
+ this.elements.set(id, output);
579
+ return output;
580
+ }
581
+ text(text) {
582
+ return document.createTextNode(text);
583
+ }
584
+ include(id = null, path = '', parentElement, stateKeys, dataFactory) {
585
+ if (!id) {
586
+ id = `cpn-${generateUUID(5)}`;
587
+ }
588
+ const existing = this.elements.get(id);
589
+ if (existing instanceof Component) {
590
+ existing.setDataFactory(dataFactory);
591
+ if (stateKeys) {
592
+ existing.setStateKeys(stateKeys);
593
+ }
594
+ return existing;
595
+ }
596
+ let component = new Component({
597
+ ctx: this,
598
+ id: id ?? generateUUID(10),
599
+ stateKeys,
600
+ parent: parentElement,
601
+ dataFactory,
602
+ path,
603
+ type: 'default',
604
+ });
605
+ this.elements.set(id, component);
606
+ return component;
607
+ }
608
+ includeIf(id = null, path, parentElement, stateKeys, dataFactory) {
609
+ if (!id) {
610
+ id = `c-${generateUUID(5)}`;
611
+ }
612
+ const existing = this.elements.get(id);
613
+ if (existing instanceof Component) {
614
+ existing.setDataFactory(dataFactory);
615
+ if (stateKeys) {
616
+ existing.setStateKeys(stateKeys);
617
+ }
618
+ return existing;
619
+ }
620
+ let component = new Component({
621
+ ctx: this,
622
+ id: id ?? generateUUID(10),
623
+ stateKeys,
624
+ parent: parentElement,
625
+ dataFactory,
626
+ path,
627
+ type: 'if',
628
+ });
629
+ this.elements.set(id, component);
630
+ return component;
631
+ }
632
+ includeWhen(id, condition, path, parentElement, stateKeys, dataFactory) {
633
+ if (!id) {
634
+ id = `cpn-${generateUUID(5)}`;
635
+ }
636
+ const existing = this.elements.get(id);
637
+ if (existing instanceof Component) {
638
+ existing.setDataFactory(dataFactory);
639
+ existing.setCondition(condition);
640
+ if (stateKeys) {
641
+ existing.setStateKeys(stateKeys);
642
+ }
643
+ return existing;
644
+ }
645
+ let component = new Component({
646
+ ctx: this,
647
+ id: id ?? generateUUID(10),
648
+ stateKeys,
649
+ parent: parentElement,
650
+ dataFactory,
651
+ path,
652
+ type: 'when',
653
+ condition,
654
+ });
655
+ this.elements.set(id, component);
656
+ return component;
657
+ }
658
+ extendView(path, data = {}) {
659
+ this.superViewPath = path;
660
+ const superView = this.App.View?.view(path, data, true);
661
+ if (superView) {
662
+ this.setSuperView(superView?.__ctrl__);
663
+ return superView;
664
+ }
665
+ // If super view not found, log error and return null
666
+ return superView;
667
+ }
668
+ // ─── Loop Directives ────────────────────────────────────────
669
+ /** Create and push a new LoopContext onto the stack */
670
+ __setLoopContext(length) {
671
+ const parent = this.loopContext;
672
+ this.loopContext = new LoopContext(parent);
673
+ this.loopContext.setCount(length);
674
+ return this.loopContext;
675
+ }
676
+ /** Pop the current LoopContext, restore parent */
677
+ __resetLoopContext() {
678
+ if (this.loopContext?.parent) {
679
+ const parent = this.loopContext.parent;
680
+ this.loopContext.parent = null;
681
+ Object.freeze(this.loopContext);
682
+ this.loopContext = parent;
683
+ }
684
+ else if (this.loopContext) {
685
+ Object.freeze(this.loopContext);
686
+ this.loopContext = null;
687
+ }
688
+ return this.loopContext;
689
+ }
690
+ /**
691
+ * @foreach directive — iterate over array or object.
692
+ * Returns array of children (not HTML string like the old system).
693
+ *
694
+ * @example Compiled output:
695
+ * ctrl.__foreach(items, (item, key, index, loop) => [
696
+ * em.h(ctrl, parent, 'div', {}, () => [em.t(`Item: ${item}`)])
697
+ * ])
698
+ */
699
+ __foreach(list, callback) {
700
+ if (!list || typeof list !== 'object')
701
+ return [];
702
+ const result = [];
703
+ try {
704
+ if (Array.isArray(list)) {
705
+ const loopCtx = this.__setLoopContext(list.length);
706
+ loopCtx.setType('increment');
707
+ list.forEach((item, index) => {
708
+ loopCtx.setCurrentTimes(index);
709
+ const output = callback(item, String(index), index, loopCtx);
710
+ if (output !== undefined && output !== null) {
711
+ if (Array.isArray(output))
712
+ result.push(...output);
713
+ else
714
+ result.push(output);
715
+ }
716
+ });
717
+ }
718
+ else {
719
+ const keys = Object.keys(list);
720
+ const loopCtx = this.__setLoopContext(keys.length);
721
+ loopCtx.setType('increment');
722
+ keys.forEach((key, index) => {
723
+ loopCtx.setCurrentTimes(index);
724
+ const output = callback(list[key], key, index, loopCtx);
725
+ if (output !== undefined && output !== null) {
726
+ if (Array.isArray(output))
727
+ result.push(...output);
728
+ else
729
+ result.push(output);
730
+ }
731
+ });
732
+ }
733
+ }
734
+ catch (e) {
735
+ console.error(`[ViewController] @foreach error in "${this.path}":`, e);
736
+ }
737
+ finally {
738
+ this.__resetLoopContext();
739
+ }
740
+ return result;
741
+ }
742
+ __forelse(list, callback, emptyCallback = () => []) {
743
+ if (this.App.Helper.count(list) === 0) {
744
+ return emptyCallback();
745
+ }
746
+ return this.__foreach(list, callback);
747
+ }
748
+ __each(list, callback) {
749
+ return this.__foreach(list, callback);
750
+ }
751
+ /**
752
+ * @for directive
753
+ */
754
+ __for(loopType = 'increment', start = 0, end = 0, execute = () => []) {
755
+ const loopCtx = this.__setLoopContext(end);
756
+ loopCtx.setType(loopType);
757
+ let result;
758
+ try {
759
+ result = typeof execute === 'function' ? execute(loopCtx) : [];
760
+ }
761
+ catch (e) {
762
+ console.error(`[ViewController] @for error in "${this.path}":`, e);
763
+ result = [];
764
+ }
765
+ finally {
766
+ this.__resetLoopContext();
767
+ }
768
+ return result;
769
+ }
770
+ /**
771
+ * @while directive
772
+ */
773
+ __while(execute, maxIterations = 10000) {
774
+ const loopCtx = this.__setLoopContext(-1);
775
+ loopCtx.setType('increment');
776
+ let result;
777
+ try {
778
+ result = typeof execute === 'function' ? execute(loopCtx) : [];
779
+ }
780
+ catch (e) {
781
+ console.error(`[ViewController] @while error in "${this.path}":`, e);
782
+ result = [];
783
+ }
784
+ finally {
785
+ if (loopCtx.count === -1) {
786
+ loopCtx.count = loopCtx.iteration;
787
+ }
788
+ this.__resetLoopContext();
789
+ }
790
+ return result;
791
+ }
792
+ // mounting
793
+ // ─── Config & App Access ────────────────────────────────────
794
+ setApp(app) {
795
+ this.__App = app;
796
+ }
797
+ getParentView() {
798
+ return this.parent ? this.parent.view : null;
799
+ }
800
+ getChildrenViews() {
801
+ return this.children.map(child => child.view);
802
+ }
803
+ getSuperView() {
804
+ return this.superView ? this.superView.view : null;
805
+ }
806
+ getOriginView() {
807
+ return this.originView?.view || null;
808
+ }
809
+ setOriginView(origin) {
810
+ this.originView = origin;
811
+ }
812
+ setSuperView(superView) {
813
+ this.superView = superView;
814
+ }
815
+ setIsSuperView(isSuper) {
816
+ this.isSuperView = isSuper;
817
+ }
818
+ setParent(parent) {
819
+ this.parent = parent;
820
+ }
821
+ addChild(child) {
822
+ this.children.push(child);
823
+ }
824
+ /**
825
+ * For nested views: set the chain of super views up to the root, so each view has a reference to its layout parents.
826
+ * Called by ViewManager after creating the view and its super view(s).
827
+ */
828
+ setChainFromOrigin() {
829
+ if (this.superView) {
830
+ this.superView.setOriginView(this);
831
+ this.superView.setChainFromOrigin();
832
+ }
833
+ }
834
+ /**
835
+ * When a view is destroyed, it should eject itself from the origin chain to prevent memory leaks.
836
+ */
837
+ ejectOriginChain() {
838
+ if (this.originView) {
839
+ const origin = this.originView;
840
+ this.originView = null;
841
+ origin.ejectOriginChain();
842
+ }
843
+ }
844
+ get App() {
845
+ return this.__App;
846
+ }
847
+ get isMounted() {
848
+ return this._isMounted;
849
+ }
850
+ get isDestroyed() {
851
+ return this._isDestroyed;
852
+ }
853
+ /** Whether this view has a super view (layout) */
854
+ get hasSuperView() {
855
+ return this.superViewPath !== null && this.superViewPath !== '';
856
+ }
857
+ // ─── Private ────────────────────────────────────────────────
858
+ generateViewId() {
859
+ return `v_${Date.now().toString(36)}_${Math.random().toString(36).substring(2, 8)}`;
860
+ }
861
+ }
862
+ //# sourceMappingURL=ViewController.js.map