@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.
- package/README.md +52 -195
- package/dist/index.d.ts +20 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -3
- package/dist/index.js.map +1 -1
- package/dist/plugins.d.ts +2 -2
- package/dist/plugins.js +2 -2
- package/dist/src/core/app/Application.d.ts +17 -15
- package/dist/src/core/app/Application.d.ts.map +1 -1
- package/dist/src/core/app/Application.js +41 -18
- package/dist/src/core/app/Application.js.map +1 -1
- package/dist/src/core/bootstrap/app.d.ts +1 -1
- package/dist/src/core/bootstrap/app.d.ts.map +1 -1
- package/dist/src/core/bootstrap/app.js +74 -4
- package/dist/src/core/bootstrap/app.js.map +1 -1
- package/dist/src/core/bootstrap/bundle.d.ts +41 -0
- package/dist/src/core/bootstrap/bundle.d.ts.map +1 -0
- package/dist/src/core/bootstrap/bundle.js +98 -0
- package/dist/src/core/bootstrap/bundle.js.map +1 -0
- package/dist/src/core/bootstrap/providers/ApiServiceProvider.d.ts +1 -1
- package/dist/src/core/bootstrap/providers/ApiServiceProvider.d.ts.map +1 -1
- package/dist/src/core/bootstrap/providers/ApiServiceProvider.js +3 -3
- package/dist/src/core/bootstrap/providers/ApiServiceProvider.js.map +1 -1
- package/dist/src/core/bootstrap/providers/CoreServiceProvider.d.ts +1 -1
- package/dist/src/core/bootstrap/providers/CoreServiceProvider.d.ts.map +1 -1
- package/dist/src/core/bootstrap/providers/CoreServiceProvider.js +11 -8
- package/dist/src/core/bootstrap/providers/CoreServiceProvider.js.map +1 -1
- package/dist/src/core/bootstrap/providers/HelperServiceProvider.d.ts +3 -1
- package/dist/src/core/bootstrap/providers/HelperServiceProvider.d.ts.map +1 -1
- package/dist/src/core/bootstrap/providers/HelperServiceProvider.js +8 -3
- package/dist/src/core/bootstrap/providers/HelperServiceProvider.js.map +1 -1
- package/dist/src/core/bootstrap/providers/RouteServiceProvider.d.ts +2 -1
- package/dist/src/core/bootstrap/providers/RouteServiceProvider.d.ts.map +1 -1
- package/dist/src/core/bootstrap/providers/RouteServiceProvider.js +14 -4
- package/dist/src/core/bootstrap/providers/RouteServiceProvider.js.map +1 -1
- package/dist/src/core/bootstrap/providers/ServiceProvider.d.ts +4 -4
- package/dist/src/core/bootstrap/providers/ServiceProvider.d.ts.map +1 -1
- package/dist/src/core/bootstrap/providers/ServiceProvider.js +5 -5
- package/dist/src/core/bootstrap/providers/ServiceProvider.js.map +1 -1
- package/dist/src/core/bootstrap/providers/ViewServiceProvider.d.ts +1 -1
- package/dist/src/core/bootstrap/providers/ViewServiceProvider.d.ts.map +1 -1
- package/dist/src/core/bootstrap/providers/ViewServiceProvider.js +3 -3
- package/dist/src/core/bootstrap/providers/ViewServiceProvider.js.map +1 -1
- package/dist/src/core/bootstrap/providers/default-providers.d.ts +1 -1
- package/dist/src/core/bootstrap/providers/default-providers.d.ts.map +1 -1
- package/dist/src/core/bootstrap/providers/default-providers.js +44 -11
- package/dist/src/core/bootstrap/providers/default-providers.js.map +1 -1
- package/dist/src/core/bootstrap/providers/index.d.ts +9 -9
- package/dist/src/core/bootstrap/providers/index.d.ts.map +1 -1
- package/dist/src/core/bootstrap/providers/index.js +8 -8
- package/dist/src/core/bootstrap/providers/index.js.map +1 -1
- package/dist/src/core/bootstrap/providers/provider-order.d.ts +1 -1
- package/dist/src/core/bootstrap/providers/provider-order.d.ts.map +1 -1
- package/dist/src/core/bootstrap/ssr.d.ts +47 -0
- package/dist/src/core/bootstrap/ssr.d.ts.map +1 -0
- package/dist/src/core/bootstrap/ssr.js +125 -0
- package/dist/src/core/bootstrap/ssr.js.map +1 -0
- package/dist/src/core/cache/ViewCache.d.ts +1 -1
- package/dist/src/core/cache/ViewCache.d.ts.map +1 -1
- package/dist/src/core/cache/index.d.ts +1 -1
- package/dist/src/core/cache/index.d.ts.map +1 -1
- package/dist/src/core/cache/index.js +1 -1
- package/dist/src/core/cache/index.js.map +1 -1
- package/dist/src/core/contracts/ApplicationInterface.d.ts +13 -11
- package/dist/src/core/contracts/ApplicationInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/BlockInterface.d.ts +10 -10
- package/dist/src/core/contracts/BlockInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/BundleInterface.d.ts +38 -0
- package/dist/src/core/contracts/BundleInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/BundleInterface.js +2 -0
- package/dist/src/core/contracts/BundleInterface.js.map +1 -0
- package/dist/src/core/contracts/ComponentInterface.d.ts +7 -6
- package/dist/src/core/contracts/ComponentInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/ElementInterface.d.ts +91 -27
- package/dist/src/core/contracts/ElementInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/HeadServiceInterface.d.ts +37 -0
- package/dist/src/core/contracts/HeadServiceInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/HeadServiceInterface.js +3 -0
- package/dist/src/core/contracts/HeadServiceInterface.js.map +1 -0
- package/dist/src/core/contracts/HelperInterface.d.ts +9 -1
- package/dist/src/core/contracts/HelperInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/HttpServiceInterface.d.ts +3 -0
- package/dist/src/core/contracts/HttpServiceInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/MarkerInterface.d.ts +29 -44
- package/dist/src/core/contracts/MarkerInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/ReactiveInterface.d.ts +9 -9
- package/dist/src/core/contracts/ReactiveInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/RouterInterface.d.ts +5 -2
- package/dist/src/core/contracts/RouterInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/SectionInterface.d.ts +48 -0
- package/dist/src/core/contracts/SectionInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/SectionInterface.js +2 -0
- package/dist/src/core/contracts/SectionInterface.js.map +1 -0
- package/dist/src/core/contracts/ServiceProviderInterface.d.ts +3 -3
- package/dist/src/core/contracts/ServiceProviderInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/ViewControllerInterface.d.ts +116 -15
- package/dist/src/core/contracts/ViewControllerInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/ViewInterface.d.ts +31 -5
- package/dist/src/core/contracts/ViewInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/ViewManagerInterface.d.ts +47 -5
- package/dist/src/core/contracts/ViewManagerInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/ViewStateInterface.d.ts +39 -2
- package/dist/src/core/contracts/ViewStateInterface.d.ts.map +1 -1
- package/dist/src/core/contracts/common.d.ts +3 -3
- package/dist/src/core/contracts/common.js +3 -3
- package/dist/src/core/contracts/utils.d.ts +19 -19
- package/dist/src/core/contracts/utils.d.ts.map +1 -1
- package/dist/src/core/contracts/views.d.ts +1 -22
- package/dist/src/core/contracts/views.d.ts.map +1 -1
- package/dist/src/core/devtools/hook.d.ts +66 -0
- package/dist/src/core/devtools/hook.d.ts.map +1 -0
- package/dist/src/core/devtools/hook.js +114 -0
- package/dist/src/core/devtools/hook.js.map +1 -0
- package/dist/src/core/devtools/index.d.ts +34 -0
- package/dist/src/core/devtools/index.d.ts.map +1 -0
- package/dist/src/core/devtools/index.js +33 -0
- package/dist/src/core/devtools/index.js.map +1 -0
- package/dist/src/core/devtools/inspector.d.ts +31 -0
- package/dist/src/core/devtools/inspector.d.ts.map +1 -0
- package/dist/src/core/devtools/inspector.js +249 -0
- package/dist/src/core/devtools/inspector.js.map +1 -0
- package/dist/src/core/elements/Block.d.ts +9 -7
- package/dist/src/core/elements/Block.d.ts.map +1 -1
- package/dist/src/core/elements/Block.js +33 -9
- package/dist/src/core/elements/Block.js.map +1 -1
- package/dist/src/core/elements/BlockOutlet.d.ts +19 -8
- package/dist/src/core/elements/BlockOutlet.d.ts.map +1 -1
- package/dist/src/core/elements/BlockOutlet.js +57 -13
- package/dist/src/core/elements/BlockOutlet.js.map +1 -1
- package/dist/src/core/elements/Component.d.ts +83 -11
- package/dist/src/core/elements/Component.d.ts.map +1 -1
- package/dist/src/core/elements/Component.js +334 -13
- package/dist/src/core/elements/Component.js.map +1 -1
- package/dist/src/core/elements/ForeachSlotCache.d.ts +95 -0
- package/dist/src/core/elements/ForeachSlotCache.d.ts.map +1 -0
- package/dist/src/core/elements/ForeachSlotCache.js +149 -0
- package/dist/src/core/elements/ForeachSlotCache.js.map +1 -0
- package/dist/src/core/elements/Fragment.d.ts +19 -13
- package/dist/src/core/elements/Fragment.d.ts.map +1 -1
- package/dist/src/core/elements/Fragment.js +43 -20
- package/dist/src/core/elements/Fragment.js.map +1 -1
- package/dist/src/core/elements/Html.d.ts +89 -12
- package/dist/src/core/elements/Html.d.ts.map +1 -1
- package/dist/src/core/elements/Html.js +707 -106
- package/dist/src/core/elements/Html.js.map +1 -1
- package/dist/src/core/elements/Output.d.ts +34 -10
- package/dist/src/core/elements/Output.d.ts.map +1 -1
- package/dist/src/core/elements/Output.js +141 -26
- package/dist/src/core/elements/Output.js.map +1 -1
- package/dist/src/core/elements/Reactive.d.ts +85 -14
- package/dist/src/core/elements/Reactive.d.ts.map +1 -1
- package/dist/src/core/elements/Reactive.js +315 -41
- package/dist/src/core/elements/Reactive.js.map +1 -1
- package/dist/src/core/elements/TextElement.d.ts +11 -7
- package/dist/src/core/elements/TextElement.d.ts.map +1 -1
- package/dist/src/core/elements/TextElement.js +18 -11
- package/dist/src/core/elements/TextElement.js.map +1 -1
- package/dist/src/core/elements/Wrapper.d.ts +24 -13
- package/dist/src/core/elements/Wrapper.d.ts.map +1 -1
- package/dist/src/core/elements/Wrapper.js +65 -8
- package/dist/src/core/elements/Wrapper.js.map +1 -1
- package/dist/src/core/elements/Yield.d.ts +10 -9
- package/dist/src/core/elements/Yield.d.ts.map +1 -1
- package/dist/src/core/elements/Yield.js +31 -19
- package/dist/src/core/elements/Yield.js.map +1 -1
- package/dist/src/core/elements/helpers.d.ts +7 -7
- package/dist/src/core/elements/helpers.d.ts.map +1 -1
- package/dist/src/core/elements/helpers.js +4 -4
- package/dist/src/core/elements/index.d.ts +12 -11
- package/dist/src/core/elements/index.d.ts.map +1 -1
- package/dist/src/core/elements/index.js +12 -11
- package/dist/src/core/elements/index.js.map +1 -1
- package/dist/src/core/elements/reconcileChildren.d.ts +7 -0
- package/dist/src/core/elements/reconcileChildren.d.ts.map +1 -0
- package/dist/src/core/elements/reconcileChildren.js +74 -0
- package/dist/src/core/elements/reconcileChildren.js.map +1 -0
- package/dist/src/core/hellpers/utils.d.ts +2 -2
- package/dist/src/core/hellpers/utils.js +4 -4
- package/dist/src/core/helpers/ApiClient.d.ts +58 -0
- package/dist/src/core/helpers/ApiClient.d.ts.map +1 -0
- package/dist/src/core/helpers/ApiClient.js +131 -0
- package/dist/src/core/helpers/ApiClient.js.map +1 -0
- package/dist/src/core/helpers/app.d.ts +3 -0
- package/dist/src/core/helpers/app.d.ts.map +1 -0
- package/dist/src/core/helpers/app.js +63 -0
- package/dist/src/core/helpers/app.js.map +1 -0
- package/dist/src/core/helpers/transition.d.ts +34 -0
- package/dist/src/core/helpers/transition.d.ts.map +1 -0
- package/dist/src/core/helpers/transition.js +118 -0
- package/dist/src/core/helpers/transition.js.map +1 -0
- package/dist/src/core/helpers/utils.d.ts +26 -0
- package/dist/src/core/helpers/utils.d.ts.map +1 -0
- package/dist/src/core/helpers/utils.js +96 -0
- package/dist/src/core/helpers/utils.js.map +1 -0
- package/dist/src/core/helpers/view.d.ts +39 -0
- package/dist/src/core/helpers/view.d.ts.map +1 -0
- package/dist/src/core/helpers/view.js +286 -0
- package/dist/src/core/helpers/view.js.map +1 -0
- package/dist/src/core/routers/Router.d.ts +108 -7
- package/dist/src/core/routers/Router.d.ts.map +1 -1
- package/dist/src/core/routers/Router.js +444 -68
- package/dist/src/core/routers/Router.js.map +1 -1
- package/dist/src/core/routers/index.d.ts +2 -2
- package/dist/src/core/routers/index.d.ts.map +1 -1
- package/dist/src/core/routers/index.js +1 -1
- package/dist/src/core/routers/index.js.map +1 -1
- package/dist/src/core/services/AssetManager.d.ts +112 -0
- package/dist/src/core/services/AssetManager.d.ts.map +1 -0
- package/dist/src/core/services/AssetManager.js +361 -0
- package/dist/src/core/services/AssetManager.js.map +1 -0
- package/dist/src/core/services/BlockManager.d.ts +73 -2
- package/dist/src/core/services/BlockManager.d.ts.map +1 -1
- package/dist/src/core/services/BlockManager.js +270 -48
- package/dist/src/core/services/BlockManager.js.map +1 -1
- package/dist/src/core/services/DomService.js +3 -3
- package/dist/src/core/services/DomService.js.map +1 -1
- package/dist/src/core/services/HeadService.d.ts +24 -0
- package/dist/src/core/services/HeadService.d.ts.map +1 -0
- package/dist/src/core/services/HeadService.js +120 -0
- package/dist/src/core/services/HeadService.js.map +1 -0
- package/dist/src/core/services/HelperService.d.ts +14 -3
- package/dist/src/core/services/HelperService.d.ts.map +1 -1
- package/dist/src/core/services/HelperService.js +32 -2
- package/dist/src/core/services/HelperService.js.map +1 -1
- package/dist/src/core/services/HttpService.d.ts +8 -0
- package/dist/src/core/services/HttpService.d.ts.map +1 -1
- package/dist/src/core/services/HttpService.js +121 -47
- package/dist/src/core/services/HttpService.js.map +1 -1
- package/dist/src/core/services/MarkerRegistry.d.ts +51 -8
- package/dist/src/core/services/MarkerRegistry.d.ts.map +1 -1
- package/dist/src/core/services/MarkerRegistry.js +135 -14
- package/dist/src/core/services/MarkerRegistry.js.map +1 -1
- package/dist/src/core/services/PageCache.d.ts +101 -0
- package/dist/src/core/services/PageCache.d.ts.map +1 -0
- package/dist/src/core/services/PageCache.js +184 -0
- package/dist/src/core/services/PageCache.js.map +1 -0
- package/dist/src/core/services/SectionManager.d.ts +100 -0
- package/dist/src/core/services/SectionManager.d.ts.map +1 -0
- package/dist/src/core/services/SectionManager.js +408 -0
- package/dist/src/core/services/SectionManager.js.map +1 -0
- package/dist/src/core/services/StorageService.js +1 -1
- package/dist/src/core/services/TranslationService.d.ts +21 -0
- package/dist/src/core/services/TranslationService.d.ts.map +1 -0
- package/dist/src/core/services/TranslationService.js +95 -0
- package/dist/src/core/services/TranslationService.js.map +1 -0
- package/dist/src/core/services/index.d.ts +11 -8
- package/dist/src/core/services/index.d.ts.map +1 -1
- package/dist/src/core/services/index.js +11 -8
- package/dist/src/core/services/index.js.map +1 -1
- package/dist/src/core/types/utils.d.ts +8 -8
- package/dist/src/core/types/utils.d.ts.map +1 -1
- package/dist/src/core/view/LoopContext.d.ts +21 -1
- package/dist/src/core/view/LoopContext.d.ts.map +1 -1
- package/dist/src/core/view/LoopContext.js +36 -0
- package/dist/src/core/view/LoopContext.js.map +1 -1
- package/dist/src/core/view/ResourceScope.d.ts +38 -0
- package/dist/src/core/view/ResourceScope.d.ts.map +1 -0
- package/dist/src/core/view/ResourceScope.js +167 -0
- package/dist/src/core/view/ResourceScope.js.map +1 -0
- package/dist/src/core/view/Section.d.ts +17 -32
- package/dist/src/core/view/Section.d.ts.map +1 -1
- package/dist/src/core/view/Section.js +14 -55
- package/dist/src/core/view/Section.js.map +1 -1
- package/dist/src/core/view/View.d.ts +43 -7
- package/dist/src/core/view/View.d.ts.map +1 -1
- package/dist/src/core/view/View.js +22 -4
- package/dist/src/core/view/View.js.map +1 -1
- package/dist/src/core/view/ViewController.d.ts +313 -40
- package/dist/src/core/view/ViewController.d.ts.map +1 -1
- package/dist/src/core/view/ViewController.js +1002 -147
- package/dist/src/core/view/ViewController.js.map +1 -1
- package/dist/src/core/view/ViewManager.d.ts +318 -27
- package/dist/src/core/view/ViewManager.d.ts.map +1 -1
- package/dist/src/core/view/ViewManager.js +1199 -258
- package/dist/src/core/view/ViewManager.js.map +1 -1
- package/dist/src/core/view/ViewState.d.ts +185 -6
- package/dist/src/core/view/ViewState.d.ts.map +1 -1
- package/dist/src/core/view/ViewState.js +851 -123
- package/dist/src/core/view/ViewState.js.map +1 -1
- package/dist/src/core/view/index.d.ts +5 -5
- package/dist/src/core/view/index.d.ts.map +1 -1
- package/dist/src/core/view/index.js +5 -5
- package/dist/src/core/view/index.js.map +1 -1
- package/dist/src/testing/index.d.ts +69 -0
- package/dist/src/testing/index.d.ts.map +1 -0
- package/dist/src/testing/index.js +140 -0
- package/dist/src/testing/index.js.map +1 -0
- package/index.ts +29 -5
- package/package.json +30 -21
- package/plugins.ts +2 -2
- package/src/core/app/Application.ts +58 -31
- package/src/core/bootstrap/app.ts +80 -6
- package/src/core/bootstrap/bundle.ts +101 -0
- package/src/core/bootstrap/providers/ApiServiceProvider.ts +4 -4
- package/src/core/bootstrap/providers/CoreServiceProvider.ts +14 -8
- package/src/core/bootstrap/providers/HelperServiceProvider.ts +8 -3
- package/src/core/bootstrap/providers/RouteServiceProvider.ts +15 -4
- package/src/core/bootstrap/providers/ServiceProvider.ts +8 -8
- package/src/core/bootstrap/providers/ViewServiceProvider.ts +3 -3
- package/src/core/bootstrap/providers/default-providers.ts +51 -16
- package/src/core/bootstrap/providers/index.ts +9 -9
- package/src/core/bootstrap/providers/provider-order.test.ts +16 -27
- package/src/core/bootstrap/providers/provider-order.ts +1 -1
- package/src/core/bootstrap/ssr.ts +136 -0
- package/src/core/cache/ViewCache.ts +1 -1
- package/src/core/cache/index.ts +1 -1
- package/src/core/contracts/ApplicationInterface.ts +13 -11
- package/src/core/contracts/BlockInterface.ts +18 -18
- package/src/core/contracts/BundleInterface.ts +40 -0
- package/src/core/contracts/ComponentInterface.ts +7 -6
- package/src/core/contracts/ElementInterface.ts +95 -27
- package/src/core/contracts/HeadServiceInterface.ts +41 -0
- package/src/core/contracts/HelperInterface.ts +9 -1
- package/src/core/contracts/HttpServiceInterface.ts +3 -0
- package/src/core/contracts/MarkerInterface.ts +22 -49
- package/src/core/contracts/ReactiveInterface.ts +9 -9
- package/src/core/contracts/RouterInterface.ts +5 -2
- package/src/core/contracts/SectionInterface.ts +49 -0
- package/src/core/contracts/ServiceProviderInterface.ts +3 -3
- package/src/core/contracts/ViewControllerInterface.ts +124 -16
- package/src/core/contracts/ViewInterface.ts +34 -5
- package/src/core/contracts/ViewManagerInterface.ts +40 -5
- package/src/core/contracts/ViewStateInterface.ts +39 -2
- package/src/core/contracts/common.ts +3 -3
- package/src/core/contracts/utils.ts +19 -19
- package/src/core/contracts/views.ts +2 -22
- package/src/core/devtools/hook.ts +142 -0
- package/src/core/devtools/index.ts +38 -0
- package/src/core/devtools/inspector.ts +270 -0
- package/src/core/elements/Block.ts +43 -21
- package/src/core/elements/BlockOutlet.ts +61 -21
- package/src/core/elements/Component.ts +352 -18
- package/src/core/elements/ElementManager.ts +9 -9
- package/src/core/elements/ForeachSlotCache.ts +170 -0
- package/src/core/elements/Fragment.ts +50 -32
- package/src/core/elements/Html.ts +696 -117
- package/src/core/elements/Output.ts +147 -30
- package/src/core/elements/Reactive.ts +329 -52
- package/src/core/elements/TextElement.ts +25 -16
- package/src/core/elements/Wrapper.ts +84 -18
- package/src/core/elements/Yield.ts +35 -24
- package/src/core/elements/helpers.ts +12 -12
- package/src/core/elements/index.ts +25 -24
- package/src/core/elements/reconcileChildren.ts +70 -0
- package/src/core/{hellpers → helpers}/ApiClient.ts +8 -1
- package/src/core/{hellpers → helpers}/app.ts +13 -2
- package/src/core/helpers/transition.ts +127 -0
- package/src/core/{hellpers → helpers}/utils.ts +4 -4
- package/src/core/helpers/view.ts +283 -0
- package/src/core/routers/Router.ts +458 -64
- package/src/core/routers/index.ts +2 -2
- package/src/core/services/AssetManager.ts +387 -0
- package/src/core/services/BlockManager.ts +272 -50
- package/src/core/services/DomService.ts +3 -3
- package/src/core/services/HeadService.ts +124 -0
- package/src/core/services/HelperService.ts +34 -4
- package/src/core/services/HttpService.ts +116 -55
- package/src/core/services/MarkerRegistry.ts +142 -16
- package/src/core/services/PageCache.ts +239 -0
- package/src/core/services/SectionManager.ts +387 -0
- package/src/core/services/StorageService.ts +1 -1
- package/src/core/services/TranslationService.ts +91 -0
- package/src/core/services/index.ts +11 -8
- package/src/core/types/utils.ts +8 -8
- package/src/core/view/LoopContext.ts +38 -1
- package/src/core/view/ResourceScope.ts +174 -0
- package/src/core/view/Section.ts +21 -68
- package/src/core/view/View.ts +57 -8
- package/src/core/view/ViewController.ts +1070 -186
- package/src/core/view/ViewManager.ts +1346 -272
- package/src/core/view/ViewState.ts +834 -116
- package/src/core/view/index.ts +5 -5
- package/src/testing/index.ts +184 -0
- package/dist/src/core/services/MarkerService.d.ts +0 -299
- package/dist/src/core/services/MarkerService.d.ts.map +0 -1
- package/dist/src/core/services/MarkerService.js +0 -723
- package/dist/src/core/services/MarkerService.js.map +0 -1
- package/src/core/services/MarkerService.ts +0 -923
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import type { BlockRenderFactory } from "../contracts/BlockInterface";
|
|
2
|
-
import type { HtmlInterface,
|
|
3
|
-
import type { ReactiveRenderFn } from "../contracts/ReactiveInterface";
|
|
4
|
-
import type { ViewControllerInterface } from "../contracts/ViewControllerInterface";
|
|
5
|
-
import { Html } from "./Html";
|
|
6
|
-
import { TextElement } from "./TextElement";
|
|
7
|
-
import { Reactive } from "./Reactive";
|
|
8
|
-
import { Fragment } from "./Fragment";
|
|
9
|
-
import { Block } from "./Block";
|
|
1
|
+
import type { BlockRenderFactory } from "../contracts/BlockInterface.js";
|
|
2
|
+
import type { HtmlInterface, SaoElementConfig, SaoChildrenFactory } from "../contracts/ElementInterface.js";
|
|
3
|
+
import type { ReactiveRenderFn } from "../contracts/ReactiveInterface.js";
|
|
4
|
+
import type { ViewControllerInterface } from "../contracts/ViewControllerInterface.js";
|
|
5
|
+
import { Html } from "./Html.js";
|
|
6
|
+
import { TextElement } from "./TextElement.js";
|
|
7
|
+
import { Reactive } from "./Reactive.js";
|
|
8
|
+
import { Fragment } from "./Fragment.js";
|
|
9
|
+
import { Block } from "./Block.js";
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* OneElementManager — factory/registry for creating One elements.
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ForeachSlotCache — keyed slot manager cho @foreach reconciliation.
|
|
3
|
+
*
|
|
4
|
+
* # Cơ chế
|
|
5
|
+
* Mỗi item được identify bằng một cache key:
|
|
6
|
+
* - Có @key(expr) → key = giá trị expr (field keying, vd `item.id`)
|
|
7
|
+
* - Không có @key → key = object reference của item (identity keying)
|
|
8
|
+
* Duplicate keys (primitive lists `['a','b','a']`, refs lặp) được phân biệt
|
|
9
|
+
* bằng occurrence index trong pass — key thứ n trùng nhau map vào slot thứ n.
|
|
10
|
+
*
|
|
11
|
+
* # Reuse contract
|
|
12
|
+
* Slot chỉ được REUSE khi cache key khớp VÀ item ref không đổi
|
|
13
|
+
* (`slot.item === item`). Ref đổi → recreate, vì compiled output đóng gói
|
|
14
|
+
* `item` trực tiếp vào closure (`() => item.name`) — reuse với ref cũ sẽ
|
|
15
|
+
* hiển thị data cũ. Field key vì vậy chủ yếu mang lại: bookkeeping đúng cho
|
|
16
|
+
* duplicate/primitive items + ý định tường minh của developer.
|
|
17
|
+
*
|
|
18
|
+
* # Pass protocol (một chu kỳ render)
|
|
19
|
+
* 1. `beginPass()` — reset occurrence counters + tập slot touched
|
|
20
|
+
* 2. `claim(key, item)` mỗi item theo thứ tự list:
|
|
21
|
+
* hit (slot.item === item) → dùng lại, slot được mark touched
|
|
22
|
+
* miss → caller tạo elements rồi `store(key, occ, item, elements)`
|
|
23
|
+
* 3. `prunePass(onRemove)` — slot KHÔNG được touch trong pass = item đã rời
|
|
24
|
+
* list → callback destroy + gỡ khỏi cache. (Trước đây bước này là dead
|
|
25
|
+
* code — cache không bao giờ gỡ entry → element của item bị xoá leak.)
|
|
26
|
+
* Slot bị `store()` GHI ĐÈ (cùng key, ref mới) cũng đi qua đây: nó rơi khỏi
|
|
27
|
+
* `_map` ngay lúc ghi đè nên prunePass không còn thấy → phải giữ tạm trong
|
|
28
|
+
* `_evicted`. Thiếu bước này thì refresh list từ server (`@key` giữ nguyên,
|
|
29
|
+
* ref đổi) KHÔNG destroy elements cũ → view con của @include bị tái dùng
|
|
30
|
+
* trong DOM đã detach và biến mất khỏi trang.
|
|
31
|
+
*
|
|
32
|
+
* # Quan hệ với Reactive
|
|
33
|
+
* Reactive type 'foreach' giữ một instance; cửa sổ `_currentForeachCache`
|
|
34
|
+
* chỉ mở quanh CHÍNH childrenFactory call (không mở trong child.render() —
|
|
35
|
+
* tránh nested @foreach ghi nhầm vào cache của loop ngoài).
|
|
36
|
+
*
|
|
37
|
+
* @see Reactive.renderForeach()
|
|
38
|
+
* @see ViewController.__foreach()
|
|
39
|
+
*/
|
|
40
|
+
|
|
41
|
+
/** Một slot tương ứng với một item trong foreach list. */
|
|
42
|
+
export interface ForeachSlot {
|
|
43
|
+
/** Reference tới item gốc — điều kiện reuse là ref không đổi */
|
|
44
|
+
item: any;
|
|
45
|
+
/** Saola elements sinh ra bởi item factory — Html, Output, Reactive, ... */
|
|
46
|
+
elements: any[];
|
|
47
|
+
/** Compiler opt-in: closures are refreshed within this occurrence's scope. */
|
|
48
|
+
registry?: Map<string, any>;
|
|
49
|
+
identity?: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Kết quả claim: slot khi reuse được, occ để store khi phải tạo mới. */
|
|
53
|
+
export interface ForeachClaim {
|
|
54
|
+
slot: ForeachSlot | null;
|
|
55
|
+
occ: number;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export class ForeachSlotCache {
|
|
59
|
+
readonly refreshedElements = new Set<any>();
|
|
60
|
+
private nextIdentity = 0;
|
|
61
|
+
|
|
62
|
+
/** Initial SSR indexes, then monotonically allocated identities for new rows. */
|
|
63
|
+
allocateIdentity(index: number): number {
|
|
64
|
+
const identity = Math.max(index, this.nextIdentity);
|
|
65
|
+
this.nextIdentity = identity + 1;
|
|
66
|
+
return identity;
|
|
67
|
+
}
|
|
68
|
+
/** Map key → danh sách slot theo occurrence (duplicate keys) */
|
|
69
|
+
private _map: Map<any, ForeachSlot[]> = new Map();
|
|
70
|
+
/** Occurrence counter của pass hiện tại */
|
|
71
|
+
private _passOcc: Map<any, number> = new Map();
|
|
72
|
+
/** Slots được claim-hit hoặc store trong pass hiện tại */
|
|
73
|
+
private _touched: Set<ForeachSlot> = new Set();
|
|
74
|
+
/** Slots bị store() ghi đè trong pass hiện tại — prunePass destroy rồi clear */
|
|
75
|
+
private _evicted: ForeachSlot[] = [];
|
|
76
|
+
|
|
77
|
+
/** Tổng số slot đang cache (mọi occurrence). */
|
|
78
|
+
get size(): number {
|
|
79
|
+
let n = 0;
|
|
80
|
+
for (const slots of this._map.values()) n += slots.length;
|
|
81
|
+
return n;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Bắt đầu một chu kỳ render — reset counters + touched set. */
|
|
85
|
+
beginPass(): void {
|
|
86
|
+
this.refreshedElements.clear();
|
|
87
|
+
this._passOcc = new Map();
|
|
88
|
+
this._touched = new Set();
|
|
89
|
+
this._evicted = [];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Claim slot cho (key, item) theo thứ tự list.
|
|
94
|
+
* Trả slot khi reuse được (key khớp + ref không đổi); ngược lại slot=null
|
|
95
|
+
* và caller phải store(key, occ, ...) sau khi tạo elements.
|
|
96
|
+
*/
|
|
97
|
+
claim(key: any, item: any, reconcile = false): ForeachClaim {
|
|
98
|
+
const occ = this._passOcc.get(key) ?? 0;
|
|
99
|
+
this._passOcc.set(key, occ + 1);
|
|
100
|
+
|
|
101
|
+
const slot = this._map.get(key)?.[occ] ?? null;
|
|
102
|
+
if (slot && (slot.item === item || (reconcile && slot.registry))) {
|
|
103
|
+
this._touched.add(slot);
|
|
104
|
+
return { slot, occ };
|
|
105
|
+
}
|
|
106
|
+
return { slot: null, occ };
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Lưu slot mới tại (key, occ) — ghi đè slot cũ nếu ref đã đổi.
|
|
111
|
+
* Slot bị ghi đè KHÔNG còn nằm trong `_map` nên prunePass duyệt `_map` sẽ
|
|
112
|
+
* không thấy nó nữa → phải chuyển sang `_evicted` để vẫn được destroy.
|
|
113
|
+
*/
|
|
114
|
+
store(key: any, occ: number, item: any, elements: any[], registry?: Map<string, any>): ForeachSlot {
|
|
115
|
+
const slot: ForeachSlot = { item, elements, registry };
|
|
116
|
+
let slots = this._map.get(key);
|
|
117
|
+
if (!slots) {
|
|
118
|
+
slots = [];
|
|
119
|
+
this._map.set(key, slots);
|
|
120
|
+
}
|
|
121
|
+
const evicted = slots[occ];
|
|
122
|
+
if (evicted && !this._touched.has(evicted)) {
|
|
123
|
+
this._evicted.push(evicted);
|
|
124
|
+
}
|
|
125
|
+
slots[occ] = slot;
|
|
126
|
+
this._touched.add(slot);
|
|
127
|
+
return slot;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Kết thúc pass: mọi slot không được touch = item đã rời list (hoặc bị
|
|
132
|
+
* thay bằng ref mới) → gọi onRemove(slot) để destroy elements, gỡ khỏi cache.
|
|
133
|
+
*/
|
|
134
|
+
prunePass(onRemove: (slot: ForeachSlot) => void): void {
|
|
135
|
+
// Slot bị ghi đè: đã rời `_map` lúc store() nên chỉ cần destroy.
|
|
136
|
+
for (const slot of this._evicted) onRemove(slot);
|
|
137
|
+
this._evicted = [];
|
|
138
|
+
|
|
139
|
+
for (const [key, slots] of this._map) {
|
|
140
|
+
let hasRemoval = false;
|
|
141
|
+
for (const slot of slots) {
|
|
142
|
+
if (slot && !this._touched.has(slot)) {
|
|
143
|
+
onRemove(slot);
|
|
144
|
+
hasRemoval = true;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (hasRemoval) {
|
|
148
|
+
const kept = slots.filter(s => s && this._touched.has(s));
|
|
149
|
+
if (kept.length) {
|
|
150
|
+
this._map.set(key, kept);
|
|
151
|
+
} else {
|
|
152
|
+
this._map.delete(key);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Xoá toàn bộ cache — dùng khi Reactive bị destroy.
|
|
160
|
+
* KHÔNG tự gọi destroy() trên elements — caller phải làm trước.
|
|
161
|
+
*/
|
|
162
|
+
clear(): void {
|
|
163
|
+
this.nextIdentity = 0;
|
|
164
|
+
this.refreshedElements.clear();
|
|
165
|
+
this._map.clear();
|
|
166
|
+
this._passOcc = new Map();
|
|
167
|
+
this._touched = new Set();
|
|
168
|
+
this._evicted = [];
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { InitMode, InitModes } from "../contracts/common";
|
|
2
|
-
import type { FragmentInterface, HtmlInterface,
|
|
3
|
-
import type { ViewControllerInterface } from "../contracts/ViewControllerInterface";
|
|
4
|
-
import { generateUUID } from "../
|
|
5
|
-
import type {
|
|
1
|
+
import { InitMode, InitModes } from "../contracts/common.js";
|
|
2
|
+
import type { FragmentInterface, HtmlInterface, SaoChildrenFactory, SaoChildrenFactoryOutput, SaoElementChildren } from "../contracts/ElementInterface.js";
|
|
3
|
+
import type { ViewControllerInterface } from "../contracts/ViewControllerInterface.js";
|
|
4
|
+
import { generateUUID } from "../helpers/utils.js";
|
|
5
|
+
import type { SaoObjectType } from "../types/utils.js";
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* Fragment — renders multiple root nodes into a parent without a wrapping tag.
|
|
@@ -14,13 +14,13 @@ import type { OneObjectType } from "../types/utils";
|
|
|
14
14
|
* similar to Reactive but without the reactivity overhead.
|
|
15
15
|
*/
|
|
16
16
|
export class Fragment implements FragmentInterface {
|
|
17
|
-
|
|
17
|
+
saoType: SaoObjectType = 'Fragment';
|
|
18
18
|
public parent: HtmlInterface | null;
|
|
19
19
|
public nodes: Node[] = [];
|
|
20
20
|
/** Tracked child element wrappers (Html, Output, Reactive, TextElement, etc.) */
|
|
21
|
-
public children:
|
|
21
|
+
public children: SaoElementChildren = [];
|
|
22
22
|
private ctx: ViewControllerInterface;
|
|
23
|
-
private childrenFactory:
|
|
23
|
+
private childrenFactory: SaoChildrenFactory;
|
|
24
24
|
public openTag: Comment;
|
|
25
25
|
public closeTag: Comment;
|
|
26
26
|
public id: string; // Unique ID for debugging and marker registry
|
|
@@ -39,7 +39,7 @@ export class Fragment implements FragmentInterface {
|
|
|
39
39
|
id?: string | null,
|
|
40
40
|
initMode?: InitMode,
|
|
41
41
|
parentElement?: HtmlInterface | null,
|
|
42
|
-
childrenFactory:
|
|
42
|
+
childrenFactory: SaoChildrenFactory
|
|
43
43
|
}) {
|
|
44
44
|
this.ctx = ctx;
|
|
45
45
|
this.parent = parentElement;
|
|
@@ -52,48 +52,64 @@ export class Fragment implements FragmentInterface {
|
|
|
52
52
|
setParentElement(parent: HtmlInterface | null): void {
|
|
53
53
|
this.parent = parent;
|
|
54
54
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const parentEl = this.parent.element;
|
|
55
|
+
/** Registry guard — element đã destroy không được reuse */
|
|
56
|
+
public __destroyed__: boolean = false;
|
|
59
57
|
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Render — idempotent + position-aware (RUNTIME_CONTRACT.md §2),
|
|
60
|
+
* cùng pattern với Reactive.render().
|
|
61
|
+
*/
|
|
62
|
+
render(): void {
|
|
63
|
+
if (this.__destroyed__) return;
|
|
64
|
+
|
|
65
|
+
if (!this.openTag.parentNode) {
|
|
66
|
+
if (!this.parent || !this.parent.element) return;
|
|
67
|
+
const parentEl = this.parent.element;
|
|
68
|
+
parentEl.appendChild(this.openTag);
|
|
69
|
+
parentEl.appendChild(this.closeTag);
|
|
70
|
+
} else {
|
|
71
|
+
this.clear(false);
|
|
72
|
+
}
|
|
62
73
|
|
|
63
74
|
// Build children — compiled output uses (parentElement) => [...] signature
|
|
64
|
-
const output:
|
|
75
|
+
const output: SaoChildrenFactoryOutput = this.childrenFactory(this.parent);
|
|
76
|
+
const insertBeforeClose = (node: Node) => {
|
|
77
|
+
this.closeTag.parentNode?.insertBefore(node, this.closeTag);
|
|
78
|
+
};
|
|
65
79
|
|
|
66
80
|
for (const child of output) {
|
|
81
|
+
if (child === null || child === undefined) continue;
|
|
67
82
|
if (typeof child === 'string' || typeof child === 'number') {
|
|
68
83
|
const textNode = document.createTextNode(String(child));
|
|
69
|
-
|
|
84
|
+
insertBeforeClose(textNode);
|
|
70
85
|
this.nodes.push(textNode);
|
|
71
|
-
} else if (child
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
86
|
+
} else if (child instanceof Node) {
|
|
87
|
+
insertBeforeClose(child);
|
|
88
|
+
this.nodes.push(child);
|
|
89
|
+
} else if (typeof child === 'object') {
|
|
90
|
+
if ('element' in child && (child as any).element) {
|
|
91
|
+
insertBeforeClose((child as any).element);
|
|
92
|
+
this.nodes.push((child as any).element);
|
|
76
93
|
this.children.push(child);
|
|
77
94
|
child.render();
|
|
78
95
|
} else if ('openTag' in child) {
|
|
79
|
-
//
|
|
96
|
+
// Marker-based: đặt markers đúng vị trí trước, render sau
|
|
80
97
|
if ('parent' in child) {
|
|
81
98
|
(child as any).parent = this.parent;
|
|
82
99
|
}
|
|
83
100
|
if ('parentElement' in child) {
|
|
84
101
|
(child as any).parentElement = this.parent;
|
|
85
102
|
}
|
|
103
|
+
insertBeforeClose((child as any).openTag);
|
|
104
|
+
insertBeforeClose((child as any).closeTag);
|
|
86
105
|
this.children.push(child);
|
|
87
106
|
child.render();
|
|
88
107
|
}
|
|
89
108
|
}
|
|
90
109
|
}
|
|
91
|
-
|
|
92
|
-
// Place end marker
|
|
93
|
-
parentEl.appendChild(this.closeTag);
|
|
94
110
|
}
|
|
95
111
|
|
|
96
|
-
setChildrenFactory(factory:
|
|
112
|
+
setChildrenFactory(factory: SaoChildrenFactory): void {
|
|
97
113
|
this.childrenFactory = factory;
|
|
98
114
|
}
|
|
99
115
|
|
|
@@ -126,7 +142,7 @@ export class Fragment implements FragmentInterface {
|
|
|
126
142
|
}
|
|
127
143
|
|
|
128
144
|
/** Remove all nodes between markers from the DOM */
|
|
129
|
-
clear(): void {
|
|
145
|
+
clear(_destroyChildren: boolean = true): void {
|
|
130
146
|
// Destroy managed children first
|
|
131
147
|
for (const child of this.children) {
|
|
132
148
|
if ('destroy' in child && typeof child.destroy === 'function') {
|
|
@@ -146,23 +162,25 @@ export class Fragment implements FragmentInterface {
|
|
|
146
162
|
}
|
|
147
163
|
|
|
148
164
|
destroy(): void {
|
|
165
|
+
this.__destroyed__ = true;
|
|
166
|
+
this.ctx.releaseElement?.(this);
|
|
149
167
|
this.clear();
|
|
150
168
|
this.openTag.remove();
|
|
151
169
|
this.closeTag.remove();
|
|
152
170
|
this.parent = null;
|
|
153
171
|
}
|
|
154
172
|
|
|
155
|
-
get
|
|
173
|
+
get isSaoElement(): boolean {
|
|
156
174
|
return true;
|
|
157
175
|
}
|
|
158
|
-
set
|
|
176
|
+
set isSaoElement(value: boolean) {
|
|
159
177
|
// No-op setter to satisfy the Interface; this property is always true for Fragment elements
|
|
160
178
|
}
|
|
161
179
|
|
|
162
|
-
get
|
|
180
|
+
get isSaoFragment(): boolean {
|
|
163
181
|
return true;
|
|
164
182
|
}
|
|
165
|
-
set
|
|
183
|
+
set isSaoFragment(value: boolean) {
|
|
166
184
|
// No-op setter to satisfy the Interface; this property is always true for Fragment elements
|
|
167
185
|
}
|
|
168
186
|
}
|