@saolabs/client 1.0.0 → 1.0.2

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 (378) hide show
  1. package/README.md +52 -195
  2. package/dist/index.d.ts +20 -5
  3. package/dist/index.d.ts.map +1 -1
  4. package/dist/index.js +14 -3
  5. package/dist/index.js.map +1 -1
  6. package/dist/plugins.d.ts +2 -2
  7. package/dist/plugins.js +2 -2
  8. package/dist/src/core/app/Application.d.ts +17 -15
  9. package/dist/src/core/app/Application.d.ts.map +1 -1
  10. package/dist/src/core/app/Application.js +41 -18
  11. package/dist/src/core/app/Application.js.map +1 -1
  12. package/dist/src/core/bootstrap/app.d.ts +1 -1
  13. package/dist/src/core/bootstrap/app.d.ts.map +1 -1
  14. package/dist/src/core/bootstrap/app.js +74 -4
  15. package/dist/src/core/bootstrap/app.js.map +1 -1
  16. package/dist/src/core/bootstrap/bundle.d.ts +41 -0
  17. package/dist/src/core/bootstrap/bundle.d.ts.map +1 -0
  18. package/dist/src/core/bootstrap/bundle.js +98 -0
  19. package/dist/src/core/bootstrap/bundle.js.map +1 -0
  20. package/dist/src/core/bootstrap/providers/ApiServiceProvider.d.ts +1 -1
  21. package/dist/src/core/bootstrap/providers/ApiServiceProvider.d.ts.map +1 -1
  22. package/dist/src/core/bootstrap/providers/ApiServiceProvider.js +3 -3
  23. package/dist/src/core/bootstrap/providers/ApiServiceProvider.js.map +1 -1
  24. package/dist/src/core/bootstrap/providers/CoreServiceProvider.d.ts +1 -1
  25. package/dist/src/core/bootstrap/providers/CoreServiceProvider.d.ts.map +1 -1
  26. package/dist/src/core/bootstrap/providers/CoreServiceProvider.js +11 -8
  27. package/dist/src/core/bootstrap/providers/CoreServiceProvider.js.map +1 -1
  28. package/dist/src/core/bootstrap/providers/HelperServiceProvider.d.ts +3 -1
  29. package/dist/src/core/bootstrap/providers/HelperServiceProvider.d.ts.map +1 -1
  30. package/dist/src/core/bootstrap/providers/HelperServiceProvider.js +8 -3
  31. package/dist/src/core/bootstrap/providers/HelperServiceProvider.js.map +1 -1
  32. package/dist/src/core/bootstrap/providers/RouteServiceProvider.d.ts +2 -1
  33. package/dist/src/core/bootstrap/providers/RouteServiceProvider.d.ts.map +1 -1
  34. package/dist/src/core/bootstrap/providers/RouteServiceProvider.js +14 -4
  35. package/dist/src/core/bootstrap/providers/RouteServiceProvider.js.map +1 -1
  36. package/dist/src/core/bootstrap/providers/ServiceProvider.d.ts +4 -4
  37. package/dist/src/core/bootstrap/providers/ServiceProvider.d.ts.map +1 -1
  38. package/dist/src/core/bootstrap/providers/ServiceProvider.js +5 -5
  39. package/dist/src/core/bootstrap/providers/ServiceProvider.js.map +1 -1
  40. package/dist/src/core/bootstrap/providers/ViewServiceProvider.d.ts +1 -1
  41. package/dist/src/core/bootstrap/providers/ViewServiceProvider.d.ts.map +1 -1
  42. package/dist/src/core/bootstrap/providers/ViewServiceProvider.js +3 -3
  43. package/dist/src/core/bootstrap/providers/ViewServiceProvider.js.map +1 -1
  44. package/dist/src/core/bootstrap/providers/default-providers.d.ts +1 -1
  45. package/dist/src/core/bootstrap/providers/default-providers.d.ts.map +1 -1
  46. package/dist/src/core/bootstrap/providers/default-providers.js +44 -11
  47. package/dist/src/core/bootstrap/providers/default-providers.js.map +1 -1
  48. package/dist/src/core/bootstrap/providers/index.d.ts +9 -9
  49. package/dist/src/core/bootstrap/providers/index.d.ts.map +1 -1
  50. package/dist/src/core/bootstrap/providers/index.js +8 -8
  51. package/dist/src/core/bootstrap/providers/index.js.map +1 -1
  52. package/dist/src/core/bootstrap/providers/provider-order.d.ts +1 -1
  53. package/dist/src/core/bootstrap/providers/provider-order.d.ts.map +1 -1
  54. package/dist/src/core/bootstrap/ssr.d.ts +47 -0
  55. package/dist/src/core/bootstrap/ssr.d.ts.map +1 -0
  56. package/dist/src/core/bootstrap/ssr.js +125 -0
  57. package/dist/src/core/bootstrap/ssr.js.map +1 -0
  58. package/dist/src/core/cache/ViewCache.d.ts +1 -1
  59. package/dist/src/core/cache/ViewCache.d.ts.map +1 -1
  60. package/dist/src/core/cache/index.d.ts +1 -1
  61. package/dist/src/core/cache/index.d.ts.map +1 -1
  62. package/dist/src/core/cache/index.js +1 -1
  63. package/dist/src/core/cache/index.js.map +1 -1
  64. package/dist/src/core/contracts/ApplicationInterface.d.ts +13 -11
  65. package/dist/src/core/contracts/ApplicationInterface.d.ts.map +1 -1
  66. package/dist/src/core/contracts/BlockInterface.d.ts +10 -10
  67. package/dist/src/core/contracts/BlockInterface.d.ts.map +1 -1
  68. package/dist/src/core/contracts/BundleInterface.d.ts +38 -0
  69. package/dist/src/core/contracts/BundleInterface.d.ts.map +1 -0
  70. package/dist/src/core/contracts/BundleInterface.js +2 -0
  71. package/dist/src/core/contracts/BundleInterface.js.map +1 -0
  72. package/dist/src/core/contracts/ComponentInterface.d.ts +7 -6
  73. package/dist/src/core/contracts/ComponentInterface.d.ts.map +1 -1
  74. package/dist/src/core/contracts/ElementInterface.d.ts +91 -27
  75. package/dist/src/core/contracts/ElementInterface.d.ts.map +1 -1
  76. package/dist/src/core/contracts/HeadServiceInterface.d.ts +37 -0
  77. package/dist/src/core/contracts/HeadServiceInterface.d.ts.map +1 -0
  78. package/dist/src/core/contracts/HeadServiceInterface.js +3 -0
  79. package/dist/src/core/contracts/HeadServiceInterface.js.map +1 -0
  80. package/dist/src/core/contracts/HelperInterface.d.ts +9 -1
  81. package/dist/src/core/contracts/HelperInterface.d.ts.map +1 -1
  82. package/dist/src/core/contracts/HttpServiceInterface.d.ts +3 -0
  83. package/dist/src/core/contracts/HttpServiceInterface.d.ts.map +1 -1
  84. package/dist/src/core/contracts/MarkerInterface.d.ts +29 -44
  85. package/dist/src/core/contracts/MarkerInterface.d.ts.map +1 -1
  86. package/dist/src/core/contracts/ReactiveInterface.d.ts +9 -9
  87. package/dist/src/core/contracts/ReactiveInterface.d.ts.map +1 -1
  88. package/dist/src/core/contracts/RouterInterface.d.ts +5 -2
  89. package/dist/src/core/contracts/RouterInterface.d.ts.map +1 -1
  90. package/dist/src/core/contracts/SectionInterface.d.ts +48 -0
  91. package/dist/src/core/contracts/SectionInterface.d.ts.map +1 -0
  92. package/dist/src/core/contracts/SectionInterface.js +2 -0
  93. package/dist/src/core/contracts/SectionInterface.js.map +1 -0
  94. package/dist/src/core/contracts/ServiceProviderInterface.d.ts +3 -3
  95. package/dist/src/core/contracts/ServiceProviderInterface.d.ts.map +1 -1
  96. package/dist/src/core/contracts/ViewControllerInterface.d.ts +116 -15
  97. package/dist/src/core/contracts/ViewControllerInterface.d.ts.map +1 -1
  98. package/dist/src/core/contracts/ViewInterface.d.ts +31 -5
  99. package/dist/src/core/contracts/ViewInterface.d.ts.map +1 -1
  100. package/dist/src/core/contracts/ViewManagerInterface.d.ts +47 -5
  101. package/dist/src/core/contracts/ViewManagerInterface.d.ts.map +1 -1
  102. package/dist/src/core/contracts/ViewStateInterface.d.ts +39 -2
  103. package/dist/src/core/contracts/ViewStateInterface.d.ts.map +1 -1
  104. package/dist/src/core/contracts/common.d.ts +3 -3
  105. package/dist/src/core/contracts/common.js +3 -3
  106. package/dist/src/core/contracts/utils.d.ts +19 -19
  107. package/dist/src/core/contracts/utils.d.ts.map +1 -1
  108. package/dist/src/core/contracts/views.d.ts +1 -22
  109. package/dist/src/core/contracts/views.d.ts.map +1 -1
  110. package/dist/src/core/devtools/hook.d.ts +66 -0
  111. package/dist/src/core/devtools/hook.d.ts.map +1 -0
  112. package/dist/src/core/devtools/hook.js +114 -0
  113. package/dist/src/core/devtools/hook.js.map +1 -0
  114. package/dist/src/core/devtools/index.d.ts +34 -0
  115. package/dist/src/core/devtools/index.d.ts.map +1 -0
  116. package/dist/src/core/devtools/index.js +33 -0
  117. package/dist/src/core/devtools/index.js.map +1 -0
  118. package/dist/src/core/devtools/inspector.d.ts +31 -0
  119. package/dist/src/core/devtools/inspector.d.ts.map +1 -0
  120. package/dist/src/core/devtools/inspector.js +249 -0
  121. package/dist/src/core/devtools/inspector.js.map +1 -0
  122. package/dist/src/core/elements/Block.d.ts +9 -7
  123. package/dist/src/core/elements/Block.d.ts.map +1 -1
  124. package/dist/src/core/elements/Block.js +33 -9
  125. package/dist/src/core/elements/Block.js.map +1 -1
  126. package/dist/src/core/elements/BlockOutlet.d.ts +19 -8
  127. package/dist/src/core/elements/BlockOutlet.d.ts.map +1 -1
  128. package/dist/src/core/elements/BlockOutlet.js +57 -13
  129. package/dist/src/core/elements/BlockOutlet.js.map +1 -1
  130. package/dist/src/core/elements/Component.d.ts +83 -11
  131. package/dist/src/core/elements/Component.d.ts.map +1 -1
  132. package/dist/src/core/elements/Component.js +334 -13
  133. package/dist/src/core/elements/Component.js.map +1 -1
  134. package/dist/src/core/elements/ForeachSlotCache.d.ts +95 -0
  135. package/dist/src/core/elements/ForeachSlotCache.d.ts.map +1 -0
  136. package/dist/src/core/elements/ForeachSlotCache.js +149 -0
  137. package/dist/src/core/elements/ForeachSlotCache.js.map +1 -0
  138. package/dist/src/core/elements/Fragment.d.ts +19 -13
  139. package/dist/src/core/elements/Fragment.d.ts.map +1 -1
  140. package/dist/src/core/elements/Fragment.js +43 -20
  141. package/dist/src/core/elements/Fragment.js.map +1 -1
  142. package/dist/src/core/elements/Html.d.ts +89 -12
  143. package/dist/src/core/elements/Html.d.ts.map +1 -1
  144. package/dist/src/core/elements/Html.js +707 -106
  145. package/dist/src/core/elements/Html.js.map +1 -1
  146. package/dist/src/core/elements/Output.d.ts +34 -10
  147. package/dist/src/core/elements/Output.d.ts.map +1 -1
  148. package/dist/src/core/elements/Output.js +141 -26
  149. package/dist/src/core/elements/Output.js.map +1 -1
  150. package/dist/src/core/elements/Reactive.d.ts +85 -14
  151. package/dist/src/core/elements/Reactive.d.ts.map +1 -1
  152. package/dist/src/core/elements/Reactive.js +315 -41
  153. package/dist/src/core/elements/Reactive.js.map +1 -1
  154. package/dist/src/core/elements/TextElement.d.ts +11 -7
  155. package/dist/src/core/elements/TextElement.d.ts.map +1 -1
  156. package/dist/src/core/elements/TextElement.js +18 -11
  157. package/dist/src/core/elements/TextElement.js.map +1 -1
  158. package/dist/src/core/elements/Wrapper.d.ts +24 -13
  159. package/dist/src/core/elements/Wrapper.d.ts.map +1 -1
  160. package/dist/src/core/elements/Wrapper.js +65 -8
  161. package/dist/src/core/elements/Wrapper.js.map +1 -1
  162. package/dist/src/core/elements/Yield.d.ts +10 -9
  163. package/dist/src/core/elements/Yield.d.ts.map +1 -1
  164. package/dist/src/core/elements/Yield.js +31 -19
  165. package/dist/src/core/elements/Yield.js.map +1 -1
  166. package/dist/src/core/elements/helpers.d.ts +7 -7
  167. package/dist/src/core/elements/helpers.d.ts.map +1 -1
  168. package/dist/src/core/elements/helpers.js +4 -4
  169. package/dist/src/core/elements/index.d.ts +12 -11
  170. package/dist/src/core/elements/index.d.ts.map +1 -1
  171. package/dist/src/core/elements/index.js +12 -11
  172. package/dist/src/core/elements/index.js.map +1 -1
  173. package/dist/src/core/elements/reconcileChildren.d.ts +7 -0
  174. package/dist/src/core/elements/reconcileChildren.d.ts.map +1 -0
  175. package/dist/src/core/elements/reconcileChildren.js +74 -0
  176. package/dist/src/core/elements/reconcileChildren.js.map +1 -0
  177. package/dist/src/core/hellpers/utils.d.ts +2 -2
  178. package/dist/src/core/hellpers/utils.js +4 -4
  179. package/dist/src/core/helpers/ApiClient.d.ts +58 -0
  180. package/dist/src/core/helpers/ApiClient.d.ts.map +1 -0
  181. package/dist/src/core/helpers/ApiClient.js +131 -0
  182. package/dist/src/core/helpers/ApiClient.js.map +1 -0
  183. package/dist/src/core/helpers/app.d.ts +3 -0
  184. package/dist/src/core/helpers/app.d.ts.map +1 -0
  185. package/dist/src/core/helpers/app.js +63 -0
  186. package/dist/src/core/helpers/app.js.map +1 -0
  187. package/dist/src/core/helpers/transition.d.ts +34 -0
  188. package/dist/src/core/helpers/transition.d.ts.map +1 -0
  189. package/dist/src/core/helpers/transition.js +118 -0
  190. package/dist/src/core/helpers/transition.js.map +1 -0
  191. package/dist/src/core/helpers/utils.d.ts +26 -0
  192. package/dist/src/core/helpers/utils.d.ts.map +1 -0
  193. package/dist/src/core/helpers/utils.js +96 -0
  194. package/dist/src/core/helpers/utils.js.map +1 -0
  195. package/dist/src/core/helpers/view.d.ts +39 -0
  196. package/dist/src/core/helpers/view.d.ts.map +1 -0
  197. package/dist/src/core/helpers/view.js +286 -0
  198. package/dist/src/core/helpers/view.js.map +1 -0
  199. package/dist/src/core/routers/Router.d.ts +108 -7
  200. package/dist/src/core/routers/Router.d.ts.map +1 -1
  201. package/dist/src/core/routers/Router.js +444 -68
  202. package/dist/src/core/routers/Router.js.map +1 -1
  203. package/dist/src/core/routers/index.d.ts +2 -2
  204. package/dist/src/core/routers/index.d.ts.map +1 -1
  205. package/dist/src/core/routers/index.js +1 -1
  206. package/dist/src/core/routers/index.js.map +1 -1
  207. package/dist/src/core/services/AssetManager.d.ts +112 -0
  208. package/dist/src/core/services/AssetManager.d.ts.map +1 -0
  209. package/dist/src/core/services/AssetManager.js +361 -0
  210. package/dist/src/core/services/AssetManager.js.map +1 -0
  211. package/dist/src/core/services/BlockManager.d.ts +73 -2
  212. package/dist/src/core/services/BlockManager.d.ts.map +1 -1
  213. package/dist/src/core/services/BlockManager.js +270 -48
  214. package/dist/src/core/services/BlockManager.js.map +1 -1
  215. package/dist/src/core/services/DomService.js +3 -3
  216. package/dist/src/core/services/DomService.js.map +1 -1
  217. package/dist/src/core/services/HeadService.d.ts +24 -0
  218. package/dist/src/core/services/HeadService.d.ts.map +1 -0
  219. package/dist/src/core/services/HeadService.js +120 -0
  220. package/dist/src/core/services/HeadService.js.map +1 -0
  221. package/dist/src/core/services/HelperService.d.ts +14 -3
  222. package/dist/src/core/services/HelperService.d.ts.map +1 -1
  223. package/dist/src/core/services/HelperService.js +32 -2
  224. package/dist/src/core/services/HelperService.js.map +1 -1
  225. package/dist/src/core/services/HttpService.d.ts +8 -0
  226. package/dist/src/core/services/HttpService.d.ts.map +1 -1
  227. package/dist/src/core/services/HttpService.js +121 -47
  228. package/dist/src/core/services/HttpService.js.map +1 -1
  229. package/dist/src/core/services/MarkerRegistry.d.ts +51 -8
  230. package/dist/src/core/services/MarkerRegistry.d.ts.map +1 -1
  231. package/dist/src/core/services/MarkerRegistry.js +135 -14
  232. package/dist/src/core/services/MarkerRegistry.js.map +1 -1
  233. package/dist/src/core/services/PageCache.d.ts +101 -0
  234. package/dist/src/core/services/PageCache.d.ts.map +1 -0
  235. package/dist/src/core/services/PageCache.js +184 -0
  236. package/dist/src/core/services/PageCache.js.map +1 -0
  237. package/dist/src/core/services/SectionManager.d.ts +100 -0
  238. package/dist/src/core/services/SectionManager.d.ts.map +1 -0
  239. package/dist/src/core/services/SectionManager.js +408 -0
  240. package/dist/src/core/services/SectionManager.js.map +1 -0
  241. package/dist/src/core/services/StorageService.js +1 -1
  242. package/dist/src/core/services/TranslationService.d.ts +21 -0
  243. package/dist/src/core/services/TranslationService.d.ts.map +1 -0
  244. package/dist/src/core/services/TranslationService.js +95 -0
  245. package/dist/src/core/services/TranslationService.js.map +1 -0
  246. package/dist/src/core/services/index.d.ts +11 -8
  247. package/dist/src/core/services/index.d.ts.map +1 -1
  248. package/dist/src/core/services/index.js +11 -8
  249. package/dist/src/core/services/index.js.map +1 -1
  250. package/dist/src/core/types/utils.d.ts +8 -8
  251. package/dist/src/core/types/utils.d.ts.map +1 -1
  252. package/dist/src/core/view/LoopContext.d.ts +21 -1
  253. package/dist/src/core/view/LoopContext.d.ts.map +1 -1
  254. package/dist/src/core/view/LoopContext.js +36 -0
  255. package/dist/src/core/view/LoopContext.js.map +1 -1
  256. package/dist/src/core/view/ResourceScope.d.ts +38 -0
  257. package/dist/src/core/view/ResourceScope.d.ts.map +1 -0
  258. package/dist/src/core/view/ResourceScope.js +167 -0
  259. package/dist/src/core/view/ResourceScope.js.map +1 -0
  260. package/dist/src/core/view/Section.d.ts +17 -32
  261. package/dist/src/core/view/Section.d.ts.map +1 -1
  262. package/dist/src/core/view/Section.js +14 -55
  263. package/dist/src/core/view/Section.js.map +1 -1
  264. package/dist/src/core/view/View.d.ts +43 -7
  265. package/dist/src/core/view/View.d.ts.map +1 -1
  266. package/dist/src/core/view/View.js +22 -4
  267. package/dist/src/core/view/View.js.map +1 -1
  268. package/dist/src/core/view/ViewController.d.ts +313 -40
  269. package/dist/src/core/view/ViewController.d.ts.map +1 -1
  270. package/dist/src/core/view/ViewController.js +1002 -147
  271. package/dist/src/core/view/ViewController.js.map +1 -1
  272. package/dist/src/core/view/ViewManager.d.ts +318 -27
  273. package/dist/src/core/view/ViewManager.d.ts.map +1 -1
  274. package/dist/src/core/view/ViewManager.js +1199 -258
  275. package/dist/src/core/view/ViewManager.js.map +1 -1
  276. package/dist/src/core/view/ViewState.d.ts +185 -6
  277. package/dist/src/core/view/ViewState.d.ts.map +1 -1
  278. package/dist/src/core/view/ViewState.js +851 -123
  279. package/dist/src/core/view/ViewState.js.map +1 -1
  280. package/dist/src/core/view/index.d.ts +5 -5
  281. package/dist/src/core/view/index.d.ts.map +1 -1
  282. package/dist/src/core/view/index.js +5 -5
  283. package/dist/src/core/view/index.js.map +1 -1
  284. package/dist/src/testing/index.d.ts +69 -0
  285. package/dist/src/testing/index.d.ts.map +1 -0
  286. package/dist/src/testing/index.js +140 -0
  287. package/dist/src/testing/index.js.map +1 -0
  288. package/index.ts +29 -5
  289. package/package.json +30 -21
  290. package/plugins.ts +2 -2
  291. package/src/core/app/Application.ts +58 -31
  292. package/src/core/bootstrap/app.ts +80 -6
  293. package/src/core/bootstrap/bundle.ts +101 -0
  294. package/src/core/bootstrap/providers/ApiServiceProvider.ts +4 -4
  295. package/src/core/bootstrap/providers/CoreServiceProvider.ts +14 -8
  296. package/src/core/bootstrap/providers/HelperServiceProvider.ts +8 -3
  297. package/src/core/bootstrap/providers/RouteServiceProvider.ts +15 -4
  298. package/src/core/bootstrap/providers/ServiceProvider.ts +8 -8
  299. package/src/core/bootstrap/providers/ViewServiceProvider.ts +3 -3
  300. package/src/core/bootstrap/providers/default-providers.ts +51 -16
  301. package/src/core/bootstrap/providers/index.ts +9 -9
  302. package/src/core/bootstrap/providers/provider-order.test.ts +16 -27
  303. package/src/core/bootstrap/providers/provider-order.ts +1 -1
  304. package/src/core/bootstrap/ssr.ts +136 -0
  305. package/src/core/cache/ViewCache.ts +1 -1
  306. package/src/core/cache/index.ts +1 -1
  307. package/src/core/contracts/ApplicationInterface.ts +13 -11
  308. package/src/core/contracts/BlockInterface.ts +18 -18
  309. package/src/core/contracts/BundleInterface.ts +40 -0
  310. package/src/core/contracts/ComponentInterface.ts +7 -6
  311. package/src/core/contracts/ElementInterface.ts +95 -27
  312. package/src/core/contracts/HeadServiceInterface.ts +41 -0
  313. package/src/core/contracts/HelperInterface.ts +9 -1
  314. package/src/core/contracts/HttpServiceInterface.ts +3 -0
  315. package/src/core/contracts/MarkerInterface.ts +22 -49
  316. package/src/core/contracts/ReactiveInterface.ts +9 -9
  317. package/src/core/contracts/RouterInterface.ts +5 -2
  318. package/src/core/contracts/SectionInterface.ts +49 -0
  319. package/src/core/contracts/ServiceProviderInterface.ts +3 -3
  320. package/src/core/contracts/ViewControllerInterface.ts +124 -16
  321. package/src/core/contracts/ViewInterface.ts +34 -5
  322. package/src/core/contracts/ViewManagerInterface.ts +40 -5
  323. package/src/core/contracts/ViewStateInterface.ts +39 -2
  324. package/src/core/contracts/common.ts +3 -3
  325. package/src/core/contracts/utils.ts +19 -19
  326. package/src/core/contracts/views.ts +2 -22
  327. package/src/core/devtools/hook.ts +142 -0
  328. package/src/core/devtools/index.ts +38 -0
  329. package/src/core/devtools/inspector.ts +270 -0
  330. package/src/core/elements/Block.ts +43 -21
  331. package/src/core/elements/BlockOutlet.ts +61 -21
  332. package/src/core/elements/Component.ts +352 -18
  333. package/src/core/elements/ElementManager.ts +9 -9
  334. package/src/core/elements/ForeachSlotCache.ts +170 -0
  335. package/src/core/elements/Fragment.ts +50 -32
  336. package/src/core/elements/Html.ts +696 -117
  337. package/src/core/elements/Output.ts +147 -30
  338. package/src/core/elements/Reactive.ts +329 -52
  339. package/src/core/elements/TextElement.ts +25 -16
  340. package/src/core/elements/Wrapper.ts +84 -18
  341. package/src/core/elements/Yield.ts +35 -24
  342. package/src/core/elements/helpers.ts +12 -12
  343. package/src/core/elements/index.ts +25 -24
  344. package/src/core/elements/reconcileChildren.ts +70 -0
  345. package/src/core/{hellpers → helpers}/ApiClient.ts +8 -1
  346. package/src/core/{hellpers → helpers}/app.ts +13 -2
  347. package/src/core/helpers/transition.ts +127 -0
  348. package/src/core/{hellpers → helpers}/utils.ts +4 -4
  349. package/src/core/helpers/view.ts +283 -0
  350. package/src/core/routers/Router.ts +458 -64
  351. package/src/core/routers/index.ts +2 -2
  352. package/src/core/services/AssetManager.ts +387 -0
  353. package/src/core/services/BlockManager.ts +272 -50
  354. package/src/core/services/DomService.ts +3 -3
  355. package/src/core/services/HeadService.ts +124 -0
  356. package/src/core/services/HelperService.ts +34 -4
  357. package/src/core/services/HttpService.ts +116 -55
  358. package/src/core/services/MarkerRegistry.ts +142 -16
  359. package/src/core/services/PageCache.ts +239 -0
  360. package/src/core/services/SectionManager.ts +387 -0
  361. package/src/core/services/StorageService.ts +1 -1
  362. package/src/core/services/TranslationService.ts +91 -0
  363. package/src/core/services/index.ts +11 -8
  364. package/src/core/types/utils.ts +8 -8
  365. package/src/core/view/LoopContext.ts +38 -1
  366. package/src/core/view/ResourceScope.ts +174 -0
  367. package/src/core/view/Section.ts +21 -68
  368. package/src/core/view/View.ts +57 -8
  369. package/src/core/view/ViewController.ts +1070 -186
  370. package/src/core/view/ViewManager.ts +1346 -272
  371. package/src/core/view/ViewState.ts +834 -116
  372. package/src/core/view/index.ts +5 -5
  373. package/src/testing/index.ts +184 -0
  374. package/dist/src/core/services/MarkerService.d.ts +0 -299
  375. package/dist/src/core/services/MarkerService.d.ts.map +0 -1
  376. package/dist/src/core/services/MarkerService.js +0 -723
  377. package/dist/src/core/services/MarkerService.js.map +0 -1
  378. package/src/core/services/MarkerService.ts +0 -923
@@ -1,14 +1,11 @@
1
- import assert from "node:assert/strict";
2
- import { describe, it } from "node:test";
1
+ import { describe, it, expect } from "vitest";
3
2
  import { NamedServiceProvider, resolveProviderOrder, PROVIDER_NAMES } from "./provider-order";
4
3
 
5
4
  function provider(name: string, dependsOn: string[] = []): NamedServiceProvider {
6
5
  return {
7
6
  name,
8
7
  dependsOn,
9
- register() {
10
- // noop for ordering test
11
- }
8
+ register() {},
12
9
  };
13
10
  }
14
11
 
@@ -22,7 +19,7 @@ describe("resolveProviderOrder", () => {
22
19
  ]);
23
20
 
24
21
  const names = ordered.map((item) => item.name);
25
- assert.deepEqual(names, ["core", "view", "router", "api"]);
22
+ expect(names).toEqual(["core", "view", "router", "api"]);
26
23
  });
27
24
 
28
25
  it("works with PROVIDER_NAMES constants", () => {
@@ -33,35 +30,27 @@ describe("resolveProviderOrder", () => {
33
30
  ]);
34
31
 
35
32
  const names = ordered.map((p) => p.name);
36
- assert.equal(names.indexOf(PROVIDER_NAMES.CORE), 0);
37
- assert.ok(names.indexOf(PROVIDER_NAMES.VIEW) < names.indexOf(PROVIDER_NAMES.ROUTER));
33
+ expect(names.indexOf(PROVIDER_NAMES.CORE)).toBe(0);
34
+ expect(names.indexOf(PROVIDER_NAMES.VIEW)).toBeLessThan(names.indexOf(PROVIDER_NAMES.ROUTER));
38
35
  });
39
36
 
40
37
  it("throws for missing dependency", () => {
41
- assert.throws(
42
- () => resolveProviderOrder([provider("view", ["core"])]),
43
- /Missing provider dependency/
44
- );
38
+ expect(() => resolveProviderOrder([provider("view", ["core"])]))
39
+ .toThrow(/Missing provider dependency/);
45
40
  });
46
41
 
47
42
  it("throws for circular dependency", () => {
48
- assert.throws(
49
- () => resolveProviderOrder([
50
- provider("a", ["b"]),
51
- provider("b", ["c"]),
52
- provider("c", ["a"])
53
- ]),
54
- /Circular service provider dependency/
55
- );
43
+ expect(() => resolveProviderOrder([
44
+ provider("a", ["b"]),
45
+ provider("b", ["c"]),
46
+ provider("c", ["a"])
47
+ ])).toThrow(/Circular service provider dependency/);
56
48
  });
57
49
 
58
50
  it("throws for duplicate provider names", () => {
59
- assert.throws(
60
- () => resolveProviderOrder([
61
- provider("core"),
62
- provider("core")
63
- ]),
64
- /Duplicate provider name/
65
- );
51
+ expect(() => resolveProviderOrder([
52
+ provider("core"),
53
+ provider("core")
54
+ ])).toThrow(/Duplicate provider name/);
66
55
  });
67
56
  });
@@ -1,4 +1,4 @@
1
- import type { ServiceProviderInterface } from "../../contracts/ServiceProviderInterface";
1
+ import type { ServiceProviderInterface } from "../../contracts/ServiceProviderInterface.js";
2
2
 
3
3
  /**
4
4
  * Tên các provider mặc định — dùng constant thay vì magic string.
@@ -0,0 +1,136 @@
1
+ /**
2
+ * SSR boot detection — đọc thông tin server nhúng để hydrate route đầu tiên.
3
+ * Tham chiếu: RUNTIME_CONTRACT.md §6 (Hydration boot).
4
+ */
5
+
6
+ /** Thông tin boot server nhúng cho trang server-rendered. */
7
+ export interface SSRBootInfo {
8
+ /** Registry path của page entry (vd 'web.modules.home'). */
9
+ view: string;
10
+ /** viewId server đã dùng prefix markers/classes của page. */
11
+ viewId: string;
12
+ /** CSS selector container chứa SSR HTML (mặc định '#app-root'). */
13
+ container?: string;
14
+ }
15
+
16
+ /**
17
+ * Đọc SSR boot info từ DOM:
18
+ *
19
+ * <script type="application/json" data-ref="saola-ssr">
20
+ * { "container": "#app-root", "view": "web.modules.home", "viewId": "v_abc" }
21
+ * </script>
22
+ *
23
+ * viewId của layout chain được đọc từ APP_CONFIGS.view.ssrData khi server có
24
+ * cung cấp; DOM marker chỉ là fallback tương thích cho output cũ.
25
+ * Trả null nếu không phải trang server-rendered → CSR boot bình thường.
26
+ */
27
+ export function readSSRBoot(): SSRBootInfo | null {
28
+ if (typeof document === 'undefined') return null;
29
+ const el = document.querySelector('script[type="application/json"][data-ref="saola-ssr"]');
30
+ if (!el || !el.textContent) return null;
31
+ try {
32
+ const info = JSON.parse(el.textContent);
33
+ if (info && typeof info.view === 'string' && typeof info.viewId === 'string') {
34
+ return {
35
+ view: info.view,
36
+ viewId: info.viewId,
37
+ container: typeof info.container === 'string' ? info.container : undefined,
38
+ };
39
+ }
40
+ } catch (e) {
41
+ console.warn('[Bootstrap] SSR boot JSON không hợp lệ:', e);
42
+ }
43
+ return null;
44
+ }
45
+
46
+ /**
47
+ * Đọc boot config server nhúng qua `window.APP_CONFIGS` (contract server hiện tại)
48
+ * và map về shape config của client (`{ view, router, api }`).
49
+ *
50
+ * Server (`_system/page/end.blade.php`) đã emit:
51
+ * window.APP_CONFIGS = {
52
+ * container: '#app-root',
53
+ * router: { mode, base, allRoutes: [{name,path,params,component}], ... },
54
+ * ...
55
+ * }
56
+ * `allRoutes` đã đúng shape `Router.addRoutes` cần ({path, component}).
57
+ *
58
+ * Trả null nếu không có APP_CONFIGS (→ app tự truyền config cho App.start).
59
+ */
60
+ export function readBootConfig(): Record<string, any> | null {
61
+ if (typeof window === 'undefined') return null;
62
+ const cfg = (window as any).APP_CONFIGS;
63
+ if (!cfg || typeof cfg !== 'object') return null;
64
+
65
+ const out: Record<string, any> = {};
66
+ if (cfg.i18n && typeof cfg.i18n === "object") out.i18n = cfg.i18n;
67
+
68
+ // view.systemData (server: __layout__/__base__/__page__/...) PHẢI tới được
69
+ // ViewManager: compiled factory destructure `__layout__` từ systemData để
70
+ // resolve superView (`${__layout__+"base"}`). Thiếu → 'undefinedbase' →
71
+ // "View not found in registry" + page render() trả rỗng.
72
+ const view: Record<string, any> = {};
73
+ if (typeof cfg.container === 'string') {
74
+ view.container = cfg.container;
75
+ }
76
+ if (typeof cfg.view?.dataEndpoint === 'string') view.dataEndpoint = cfg.view.dataEndpoint;
77
+ if (cfg.view?.fetchOptions && typeof cfg.view.fetchOptions === 'object') view.fetchOptions = cfg.view.fetchOptions;
78
+ if (cfg.api && typeof cfg.api === 'object') out.api = cfg.api;
79
+
80
+ if (cfg.view?.systemData && typeof cfg.view.systemData === 'object') {
81
+ view.systemData = cfg.view.systemData;
82
+ }
83
+ if (typeof cfg.view?.revision === 'string') {
84
+ view.revision = cfg.view.revision;
85
+ }
86
+ if (typeof cfg.view?.contextViews === 'string') {
87
+ view.contextViews = cfg.view.contextViews;
88
+ }
89
+ if (cfg.view?.ssrData && typeof cfg.view.ssrData === 'object') {
90
+ view.ssrData = cfg.view.ssrData;
91
+ }
92
+ if (Object.keys(view).length > 0) {
93
+ out.view = view;
94
+ }
95
+
96
+ // Danh sách bundle nạp rời (theme…) — server là chỗ DUY NHẤT biết theme nào
97
+ // đang bật, nên client không đoán đường dẫn. Xem EXTENSION_ARCHITECTURE §8.
98
+ if (Array.isArray(cfg.bundles)) {
99
+ out.bundles = cfg.bundles.filter((u: unknown) => typeof u === 'string' && u !== '');
100
+ }
101
+
102
+ const routes = cfg.router?.allRoutes ?? cfg.router?.routes;
103
+ if (Array.isArray(routes)) {
104
+ out.router = {
105
+ mode: cfg.router?.mode ?? 'history',
106
+ base: cfg.router?.base,
107
+ defaultRoute: cfg.router?.defaultRoute,
108
+ routes,
109
+ };
110
+ }
111
+
112
+ return Object.keys(out).length > 0 ? out : null;
113
+ }
114
+
115
+ /**
116
+ * Merge nông 2 tầng config boot (base) với config app truyền (override).
117
+ * Per top-level key (view/router/api): nếu cả hai là object thì merge nông,
118
+ * ngược lại override thắng. Dùng để config app truyền có ưu tiên hơn boot.
119
+ */
120
+ export function mergeBootConfig(
121
+ base: Record<string, any>,
122
+ override: Record<string, any>
123
+ ): Record<string, any> {
124
+ const out: Record<string, any> = { ...base };
125
+ for (const key of Object.keys(override)) {
126
+ const b = out[key];
127
+ const o = override[key];
128
+ if (b && o && typeof b === 'object' && typeof o === 'object'
129
+ && !Array.isArray(b) && !Array.isArray(o)) {
130
+ out[key] = { ...b, ...o };
131
+ } else {
132
+ out[key] = o;
133
+ }
134
+ }
135
+ return out;
136
+ }
@@ -1,4 +1,4 @@
1
- import type { ViewCacheInterface } from "../contracts/ViewCacheInterface";
1
+ import type { ViewCacheInterface } from "../contracts/ViewCacheInterface.js";
2
2
 
3
3
  /**
4
4
  * ViewCache — stores rendered view DOM for instant restore on navigation.
@@ -1 +1 @@
1
- export { ViewCache } from './ViewCache';
1
+ export { ViewCache } from './ViewCache.js';
@@ -1,15 +1,16 @@
1
1
  // ─── Application Interface ───────────────────────────────────────
2
2
 
3
- import { RouterInterface, ViewManagerInterface } from "./utils";
4
- import type { HelperInterface } from "./HelperInterface";
5
- import type { EventServiceInterface } from "./EventServiceInterface";
6
- import type { HttpServiceInterface } from "./HttpServiceInterface";
7
- import type { StoreServiceInterface } from "./StoreServiceInterface";
8
- import type { StorageServiceInterface } from "./StorageServiceInterface";
9
- import type { LoggerServiceInterface } from "./LoggerServiceInterface";
10
- import { APIClientInterface } from "./ApiInterface";
11
- import type { ServiceProviderInterface } from "./ServiceProviderInterface";
12
- import { OneObjectType } from "../types/utils";
3
+ import { RouterInterface, ViewManagerInterface } from "./utils.js";
4
+ import type { HelperInterface } from "./HelperInterface.js";
5
+ import type { EventServiceInterface } from "./EventServiceInterface.js";
6
+ import type { HttpServiceInterface } from "./HttpServiceInterface.js";
7
+ import type { StoreServiceInterface } from "./StoreServiceInterface.js";
8
+ import type { StorageServiceInterface } from "./StorageServiceInterface.js";
9
+ import type { LoggerServiceInterface } from "./LoggerServiceInterface.js";
10
+ import type { HeadServiceInterface } from "./HeadServiceInterface.js";
11
+ import { APIClientInterface } from "./ApiInterface.js";
12
+ import type { ServiceProviderInterface } from "./ServiceProviderInterface.js";
13
+ import { SaoObjectType } from "../types/utils.js";
13
14
 
14
15
  export interface ApplicationInterface {
15
16
  [key: string]: any;
@@ -30,7 +31,7 @@ export interface ApplicationInterface {
30
31
  setMethod(name: string, method: Function, isOne?: boolean): void;
31
32
  get<T = any>(name: string): T;
32
33
 
33
- oneType?: OneObjectType;
34
+ saoType?: SaoObjectType;
34
35
 
35
36
  // Service properties — set during bootstrap via App.set()
36
37
  isInitialized: boolean;
@@ -44,6 +45,7 @@ export interface ApplicationInterface {
44
45
  Store: StoreServiceInterface;
45
46
  Storage: StorageServiceInterface;
46
47
  Logger: LoggerServiceInterface;
48
+ Head: HeadServiceInterface;
47
49
  }
48
50
 
49
51
  // ─── App Factory (helper function type) ─────────────────────────
@@ -1,7 +1,7 @@
1
- import type { OneObjectType } from "../types/utils";
2
- import type { ViewControllerInterface } from "./ViewControllerInterface";
3
- import type { HtmlInterface, FragmentInterface, OneChildrenFactoryOutput, OneNodeInterface } from "./ElementInterface";
4
- import { InitMode } from "./common";
1
+ import type { SaoObjectType } from "../types/utils.js";
2
+ import type { ViewControllerInterface } from "./ViewControllerInterface.js";
3
+ import type { HtmlInterface, FragmentInterface, SaoChildrenFactoryOutput, SaoNodeInterface } from "./ElementInterface.js";
4
+ import { InitMode } from "./common.js";
5
5
 
6
6
  // ─── Block / Layout Interfaces ───────────────────────────────────
7
7
  export type BlockConstructorParams = {
@@ -13,7 +13,7 @@ export type BlockConstructorParams = {
13
13
  initMode?: InitMode;
14
14
  };
15
15
  export interface BlockInterface {
16
- oneType: OneObjectType;
16
+ saoType: SaoObjectType;
17
17
  /** Unique block slot name (e.g. 'content', 'sidebar') */
18
18
  name: string;
19
19
  id: string;
@@ -24,30 +24,30 @@ export interface BlockInterface {
24
24
  fragment: FragmentInterface | null;
25
25
  parentElement: HtmlInterface | null;
26
26
  domChildren: Node[];
27
- isOneElement: boolean;
27
+ isSaoElement: boolean;
28
28
  isOneBlock: boolean;
29
29
  initMode?: InitMode;
30
- /** Initialize the block (e.g. during hydration) */
30
+ /** Initialize the block (e.g. during hydration) */
31
31
  init(): void;
32
- /** Render the block's content into the parent element */
32
+ /** Render the block's content into the parent element */
33
33
  render(): void;
34
- /** Mount the block's content into the DOM, finding matching outlets */
34
+ /** Mount the block's content into the DOM, finding matching outlets */
35
35
  mount(mountCtx: ViewControllerInterface, parentElement: HtmlInterface): any;
36
- /** Unmount the block's content from the DOM */
36
+ /** Unmount the block's content from the DOM */
37
37
  unmount(): void;
38
- /** Destroy the block and clean up resources */
38
+ /** Destroy the block and clean up resources */
39
39
  destroy(): void;
40
- /** Update the block's content (e.g. on state change) */
40
+ /** Update the block's content (e.g. on state change) */
41
41
  update(): void;
42
- /** Set the block's parent element (used for mounting) */
42
+ /** Set the block's parent element (used for mounting) */
43
43
  setParentElement(parentElement: HtmlInterface | null): void;
44
44
 
45
45
  contentRenderFactory: BlockRenderFactory | null;
46
46
  // new(params: BlockConstructorParams, ...args: any[]): BlockInterface;
47
47
  }
48
48
 
49
- export interface BlockOutletInterface extends OneNodeInterface {
50
- oneType: OneObjectType;
49
+ export interface BlockOutletInterface extends SaoNodeInterface {
50
+ saoType: SaoObjectType;
51
51
  id: string;
52
52
  name: string;
53
53
  parent: HtmlInterface | null;
@@ -56,9 +56,9 @@ export interface BlockOutletInterface extends OneNodeInterface {
56
56
  parentElement: HtmlInterface | null;
57
57
  ctx: ViewControllerInterface;
58
58
  initMode: InitMode;
59
- isOneElement: boolean;
59
+ isSaoElement: boolean;
60
60
  isOneBlockOutlet: boolean;
61
- /** Render the outlet's markers into the parent element */
61
+ /** Render the outlet's markers into the parent element */
62
62
  render(): any;
63
63
  hydrate(): any;
64
64
  destroy(): any;
@@ -73,4 +73,4 @@ export interface BlockManagerInterface {
73
73
 
74
74
  // ─── Block Types ────────────────────────────────────────────────
75
75
 
76
- export type BlockRenderFactory = (parentElement: HtmlInterface) => OneChildrenFactoryOutput;
76
+ export type BlockRenderFactory = (parentElement: HtmlInterface) => SaoChildrenFactoryOutput;
@@ -0,0 +1,40 @@
1
+ import type { ApplicationInterface } from "./ApplicationInterface.js";
2
+ import type { ServiceProviderInterface } from "./ServiceProviderInterface.js";
3
+
4
+ /** Factory view mà registry nhận: đồng bộ, hoặc lazy trả Promise<module>. */
5
+ export type ViewFactory = ((...args: any[]) => any) | (() => Promise<any>);
6
+
7
+ /**
8
+ * Manifest của một bundle nạp rời (theme, gói mở rộng).
9
+ *
10
+ * Cùng MỘT hình dạng cho mọi loại bundle: file chỉ có view thì điền `views`,
11
+ * file chỉ có code thì điền `providers`/`services`. Hai shape khác nhau = hai
12
+ * nhánh loader = hai chỗ để lệch.
13
+ */
14
+ export interface SaolaBundle {
15
+ /** Định danh, dùng để báo lỗi và bắt trùng tên. */
16
+ name?: string;
17
+ /** Provider của bundle — class hoặc instance, đưa thẳng vào resolveProviderOrder. */
18
+ providers?: any[];
19
+ /** { Tên: Class | instance | object } → App.set(tên, …). */
20
+ services?: Record<string, any>;
21
+ /** { tên: fn } → gộp vào App.Helper. */
22
+ helpers?: Record<string, any>;
23
+ /** { 'dot.path': factory } → View.setViewRegistry(). Nạp sau ĐÈ nạp trước. */
24
+ views?: Record<string, ViewFactory>;
25
+ /** Chạy sau khi mọi bundle đã merge và App đã init. */
26
+ boot?(app: ApplicationInterface): void;
27
+ }
28
+
29
+ /** Kết quả gộp nhiều bundle, theo đúng thứ tự mảng URL. */
30
+ export interface MergedBundles {
31
+ providers: (ServiceProviderInterface | any)[];
32
+ services: Record<string, any>;
33
+ helpers: Record<string, any>;
34
+ views: Record<string, ViewFactory>;
35
+ boots: Array<(app: ApplicationInterface) => void>;
36
+ /** Tên (hoặc URL) của bundle đã nạp được. */
37
+ loaded: string[];
38
+ /** [url, thông điệp lỗi] — nạp hỏng thì bỏ qua, KHÔNG làm sập boot. */
39
+ failed: Array<[string, string]>;
40
+ }
@@ -1,12 +1,12 @@
1
- import type { OneObjectType } from "../types/utils";
2
- import type { ViewControllerInterface } from "./ViewControllerInterface";
3
- import type { ViewInterface } from "./ViewInterface";
4
- import type { HtmlInterface } from "./ElementInterface";
1
+ import type { SaoObjectType } from "../types/utils.js";
2
+ import type { ViewControllerInterface } from "./ViewControllerInterface.js";
3
+ import type { ViewInterface } from "./ViewInterface.js";
4
+ import type { HtmlInterface } from "./ElementInterface.js";
5
5
 
6
6
  // ─── Component Interface ─────────────────────────────────────────
7
7
 
8
8
  export interface ComponentInterface {
9
- oneType: OneObjectType;
9
+ saoType: SaoObjectType;
10
10
  id: string;
11
11
  ctx: ViewControllerInterface;
12
12
  viewRef: ViewInterface | null;
@@ -15,12 +15,13 @@ export interface ComponentInterface {
15
15
  openTag: Comment;
16
16
  closeTag: Comment;
17
17
  stateKeys: string[];
18
+ listeners: Record<string, (...args: any[]) => any>;
18
19
  subscribeFn: () => void;
19
20
  unsubscribeFn: () => void;
20
21
  render(): void;
21
22
  destroy(): void;
22
23
  setParent(parent: HtmlInterface | null): void;
23
- isOneElement: boolean;
24
+ isSaoElement: boolean;
24
25
  isOneComponent: boolean;
25
26
  [key: string]: any;
26
27
  }
@@ -1,39 +1,45 @@
1
- import type { OneObjectType } from "../types/utils";
2
- import type { ViewControllerInterface } from "./ViewControllerInterface";
3
- import type { ReactiveInterface } from "./ReactiveInterface";
1
+ import type { SaoObjectType } from "../types/utils.js";
2
+ import type { ViewControllerInterface } from "./ViewControllerInterface.js";
3
+ import type { ReactiveInterface } from "./ReactiveInterface.js";
4
4
 
5
5
  // ─── Element Interfaces ──────────────────────────────────────────
6
6
 
7
7
  /** Base for any renderable node in the tree */
8
- export interface OneNodeInterface {
9
- oneType: OneObjectType;
8
+ export interface SaoNodeInterface {
9
+ saoType: SaoObjectType;
10
10
  parent: HtmlInterface | null;
11
11
  render(): void;
12
12
  destroy(): void;
13
- isOneElement: boolean;
13
+ isSaoElement: boolean;
14
14
  setParentElement(parent: HtmlInterface | null): void;
15
15
  [key: string]: any;
16
16
 
17
17
  }
18
18
 
19
19
  /** Native HTML element wrapper */
20
- export interface HtmlInterface extends OneNodeInterface {
20
+ export interface HtmlInterface extends SaoNodeInterface {
21
21
  element: HTMLElement;
22
22
  domChildren: Node[];
23
23
  [key: string]: any;
24
+ clearHTML(): void;
25
+ appendElement(element: HTMLElement | Comment | Text): void;
26
+ getElement(): HTMLElement;
27
+ renderChildren(): SaoElementChildren;
28
+ render(): HTMLElement;
24
29
  }
25
30
 
26
31
  /** Text node wrapper */
27
- export interface TextInterface extends OneNodeInterface {
32
+ export interface TextInterface extends SaoNodeInterface {
28
33
  element: Text;
29
34
  text: string;
30
35
 
31
36
 
32
37
  domChildren: Node[];
33
38
  update(newText: string): void;
39
+ render(): HTMLElement | Text | Comment;
34
40
  }
35
41
 
36
- export interface OutputInterface extends OneNodeInterface {
42
+ export interface OutputInterface extends SaoNodeInterface {
37
43
  ctx: ViewControllerInterface;
38
44
  parent: HtmlInterface | null;
39
45
  stateKeys: string[];
@@ -43,12 +49,11 @@ export interface OutputInterface extends OneNodeInterface {
43
49
  [key: string]: any;
44
50
  }
45
51
 
46
- export interface YieldInterface extends OneNodeInterface {
52
+ export interface YieldInterface extends SaoNodeInterface {
47
53
  ctx: ViewControllerInterface;
48
54
  parent: HtmlInterface | null;
49
55
  name: string;
50
- contentFactory: () => OneChildrenFactoryOutput;
51
- setContentFactory(factory: () => OneChildrenFactoryOutput): void;
56
+ defaultValue: string;
52
57
  openTag: Comment;
53
58
  closeTag: Comment;
54
59
  domChildren: Node[];
@@ -56,40 +61,84 @@ export interface YieldInterface extends OneNodeInterface {
56
61
  }
57
62
 
58
63
  /** Fragment — renders multiple root nodes into a parent without a wrapping tag */
59
- export interface FragmentInterface extends OneNodeInterface {
64
+ export interface FragmentInterface extends SaoNodeInterface {
60
65
  nodes: Node[];
61
66
  domChildren: Node[];
62
67
  [key: string]: any;
63
68
 
64
69
  }
65
70
  /** Wrapper — renders multiple root nodes into a parent without a wrapping tag */
66
- export interface WrapperInterface extends OneNodeInterface {
71
+ export interface WrapperInterface extends SaoNodeInterface {
67
72
  nodes: Node[];
68
73
  domChildren: Node[];
69
74
  [key: string]: any;
75
+ /** Render — chạy childrenFactory, trả về danh sách children đã tạo. */
76
+ render(): SaoElementChildren;
77
+ appendTo(parent: HtmlInterface): void;
78
+ mountTo(parent: HtmlInterface): void;
79
+ clear(): void;
80
+ setChildrenFactory(factory: SaoChildrenFactory): void;
81
+ children: SaoElementChildren;
82
+ openTag: Comment;
83
+ closeTag: Comment;
84
+
70
85
  }
71
86
 
72
87
  // ─── Element Config Types ────────────────────────────────────────
73
88
 
74
- export type OneElementConfig = {
89
+ /**
90
+ * Contract chuẩn (RUNTIME_CONTRACT.md §1.1): type = 'static' | 'binding'.
91
+ * 'value' giữ làm legacy alias của 'static' đến v0.2.
92
+ */
93
+ export type BindingConfigType = 'static' | 'binding' | 'value';
94
+
95
+ export type SaoElementConfig = {
96
+ /** Marker-free content for HTML RCDATA elements (textarea/title). */
97
+ content?: {
98
+ factory: () => any;
99
+ stateKeys?: string[];
100
+ },
75
101
  attrs?: {
76
102
  [key: string]: {
77
- type: 'value' | 'binding';
103
+ type: BindingConfigType;
78
104
  value?: any;
79
105
  stateKeys?: string[];
80
106
  factory?: () => any;
107
+ /** `@yield(name, ...)` used as the whole attribute value — no static stateKeys
108
+ * (the section it resolves to is only known at runtime), so Html subscribes to
109
+ * SectionManager by name instead. */
110
+ yieldName?: string;
81
111
  }
82
112
  },
83
113
  props?: {
84
114
  [key: string]: {
85
- type: 'value' | 'binding';
115
+ type: BindingConfigType;
86
116
  value?: any;
87
117
  stateKeys?: string[];
88
118
  factory?: () => any;
89
119
  }
90
120
  },
91
121
  events?: {
92
- [key: string]: OneElementEventHandler;
122
+ [key: string]: SaoElementEventHandler;
123
+ },
124
+ /**
125
+ * `@click.prevent.stop(...)` — bucket RIÊNG cạnh `events` để shape
126
+ * `events: {click: [...]}` (contract sẵn có) không đổi; view compile trước
127
+ * khi có modifier không có key này và chạy y nguyên.
128
+ */
129
+ eventModifiers?: {
130
+ [key: string]: EventModifier[];
131
+ },
132
+ /** `@bind(key)`/`@val(key)` — two-way binding, own bucket (sibling of attrs/props/events). */
133
+ bind?: {
134
+ key: string;
135
+ },
136
+ /**
137
+ * `@transition('fade')` — tiền tố class enter/leave (`fade-enter-from`, ...).
138
+ * Bucket riêng như `bind`/`eventModifiers`; vắng mặt = hành vi cũ y nguyên.
139
+ */
140
+ transition?: {
141
+ name: string;
93
142
  },
94
143
  classes?: {
95
144
  [className: string]: {
@@ -99,14 +148,15 @@ export type OneElementConfig = {
99
148
  factory?: () => boolean;
100
149
  }
101
150
  } | Array<{
102
- type: 'static' | 'binding';
151
+ /** 'dynamic' = factory trả về TÊN class (`class="language-{{ lang }}"`), không có `value`. */
152
+ type: 'static' | 'binding' | 'dynamic';
103
153
  value?: string;
104
154
  stateKeys?: string[];
105
- factory?: () => boolean;
155
+ factory?: () => boolean | string;
106
156
  }>,
107
157
  styles?: {
108
158
  [prop: string]: {
109
- type: 'value' | 'binding';
159
+ type: BindingConfigType;
110
160
  value?: string;
111
161
  stateKeys?: string[];
112
162
  factory?: () => string;
@@ -115,7 +165,7 @@ export type OneElementConfig = {
115
165
  [key: string]: any;
116
166
  }
117
167
 
118
- export type HtmlElementConfig = OneElementConfig & {
168
+ export type HtmlElementConfig = SaoElementConfig & {
119
169
  ctx: ViewControllerInterface;
120
170
  parentElement?: HtmlInterface | null;
121
171
  parent?: HtmlInterface | null;
@@ -123,18 +173,36 @@ export type HtmlElementConfig = OneElementConfig & {
123
173
 
124
174
  // ─── Event Handler ──────────────────────────────────────────────
125
175
 
126
- export type OneElementEventHandler = Array<{
176
+ /**
177
+ * Modifier của `@click.prevent.stop(...)`. Phải khớp `EVENT_MODIFIERS` trong
178
+ * `compiler/src/sao2js/template_ast.py` — compiler chỉ emit tên trong tập đó.
179
+ */
180
+ export type EventModifier = 'prevent' | 'stop' | 'self' | 'once';
181
+
182
+ export type SaoElementEventHandler = Array<{
127
183
  handler: string | ((event: Event) => any);
128
184
  params?: (any | ((event: Event) => any[]))[];
129
185
  } | ((event: Event) => any)>;
130
186
 
187
+ export type SaoElement = WrapperInterface | HtmlInterface | ReactiveInterface | TextInterface | FragmentInterface;
188
+ export type DOMElement = HTMLElement | SVGElement | DocumentFragment | Text | Comment;
131
189
  // ─── Children Types ─────────────────────────────────────────────
132
190
 
133
191
  /** All possible rendered child node types */
134
- export type OneElementChildren = Array<HtmlInterface | ReactiveInterface | TextInterface | FragmentInterface | HTMLElement | SVGElement | DocumentFragment | Text | Comment>;
192
+ export type SaoElementChildren = Array<SaoElement | SaoNodeInterface | DOMElement>;
135
193
 
136
- /** What a children factory can return (before mounting) */
137
- export type OneChildrenFactoryOutput = Array<HtmlInterface | ReactiveInterface | TextInterface | FragmentInterface | string | number | HTMLElement | SVGElement | DocumentFragment | Text | Comment>;
194
+ /** What a children factory can return (before mounting).
195
+ * SaoNodeInterface bao phủ các marker-based element (Output, Component, Block...)
196
+ * mà compiled output vẫn trả về trong children factories. */
197
+ export type SaoChildrenFactoryOutput = Array<SaoElement | SaoNodeInterface | DOMElement | string | number | null | undefined>;
138
198
 
139
199
  /** Factory function that produces children given parent element */
140
- export type OneChildrenFactory = (parentElement: HtmlInterface | null) => OneChildrenFactoryOutput;
200
+ export type SaoChildrenFactory = (parentElement: HtmlInterface | null) => SaoChildrenFactoryOutput;
201
+
202
+ /**
203
+ * Lazy payload passed from a parent component to one ChildrenNode placeholder.
204
+ * A factory is deliberately not executed while component data is resolved; the
205
+ * child view invokes it only when its render traversal reaches the placeholder.
206
+ */
207
+ export type SaoChildrenSlotFactory = SaoChildrenFactory;
208
+ export type SaoChildrenSlotContent = SaoChildrenSlotFactory | string | number | null | undefined;