@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.
- package/README.md +221 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins.d.ts +38 -0
- package/dist/plugins.d.ts.map +1 -0
- package/dist/plugins.js +61 -0
- package/dist/plugins.js.map +1 -0
- package/dist/src/core/app/Application.d.ts +159 -0
- package/dist/src/core/app/Application.d.ts.map +1 -0
- package/dist/src/core/app/Application.js +338 -0
- package/dist/src/core/app/Application.js.map +1 -0
- package/dist/src/core/bootstrap/app.d.ts +4 -0
- package/dist/src/core/bootstrap/app.d.ts.map +1 -0
- package/dist/src/core/bootstrap/app.js +49 -0
- package/dist/src/core/bootstrap/app.js.map +1 -0
- package/dist/src/core/bootstrap/providers/ApiServiceProvider.d.ts +9 -0
- package/dist/src/core/bootstrap/providers/ApiServiceProvider.d.ts.map +1 -0
- package/dist/src/core/bootstrap/providers/ApiServiceProvider.js +18 -0
- package/dist/src/core/bootstrap/providers/ApiServiceProvider.js.map +1 -0
- package/dist/src/core/bootstrap/providers/CoreServiceProvider.d.ts +6 -0
- package/dist/src/core/bootstrap/providers/CoreServiceProvider.d.ts.map +1 -0
- package/dist/src/core/bootstrap/providers/CoreServiceProvider.js +21 -0
- package/dist/src/core/bootstrap/providers/CoreServiceProvider.js.map +1 -0
- package/dist/src/core/bootstrap/providers/HelperServiceProvider.d.ts +7 -0
- package/dist/src/core/bootstrap/providers/HelperServiceProvider.d.ts.map +1 -0
- package/dist/src/core/bootstrap/providers/HelperServiceProvider.js +14 -0
- package/dist/src/core/bootstrap/providers/HelperServiceProvider.js.map +1 -0
- package/dist/src/core/bootstrap/providers/RouteServiceProvider.d.ts +9 -0
- package/dist/src/core/bootstrap/providers/RouteServiceProvider.d.ts.map +1 -0
- package/dist/src/core/bootstrap/providers/RouteServiceProvider.js +18 -0
- package/dist/src/core/bootstrap/providers/RouteServiceProvider.js.map +1 -0
- package/dist/src/core/bootstrap/providers/ServiceProvider.d.ts +38 -0
- package/dist/src/core/bootstrap/providers/ServiceProvider.d.ts.map +1 -0
- package/dist/src/core/bootstrap/providers/ServiceProvider.js +41 -0
- package/dist/src/core/bootstrap/providers/ServiceProvider.js.map +1 -0
- package/dist/src/core/bootstrap/providers/ViewServiceProvider.d.ts +9 -0
- package/dist/src/core/bootstrap/providers/ViewServiceProvider.d.ts.map +1 -0
- package/dist/src/core/bootstrap/providers/ViewServiceProvider.js +18 -0
- package/dist/src/core/bootstrap/providers/ViewServiceProvider.js.map +1 -0
- package/dist/src/core/bootstrap/providers/default-providers.d.ts +14 -0
- package/dist/src/core/bootstrap/providers/default-providers.d.ts.map +1 -0
- package/dist/src/core/bootstrap/providers/default-providers.js +79 -0
- package/dist/src/core/bootstrap/providers/default-providers.js.map +1 -0
- package/dist/src/core/bootstrap/providers/index.d.ts +10 -0
- package/dist/src/core/bootstrap/providers/index.d.ts.map +1 -0
- package/dist/src/core/bootstrap/providers/index.js +9 -0
- package/dist/src/core/bootstrap/providers/index.js.map +1 -0
- package/dist/src/core/bootstrap/providers/provider-order.d.ts +19 -0
- package/dist/src/core/bootstrap/providers/provider-order.d.ts.map +1 -0
- package/dist/src/core/bootstrap/providers/provider-order.js +51 -0
- package/dist/src/core/bootstrap/providers/provider-order.js.map +1 -0
- package/dist/src/core/cache/ViewCache.d.ts +46 -0
- package/dist/src/core/cache/ViewCache.d.ts.map +1 -0
- package/dist/src/core/cache/ViewCache.js +85 -0
- package/dist/src/core/cache/ViewCache.js.map +1 -0
- package/dist/src/core/cache/index.d.ts +2 -0
- package/dist/src/core/cache/index.d.ts.map +1 -0
- package/dist/src/core/cache/index.js +2 -0
- package/dist/src/core/cache/index.js.map +1 -0
- package/dist/src/core/contracts/ApiInterface.d.ts +11 -0
- package/dist/src/core/contracts/ApiInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/ApiInterface.js +2 -0
- package/dist/src/core/contracts/ApiInterface.js.map +1 -0
- package/dist/src/core/contracts/ApplicationInterface.d.ts +66 -0
- package/dist/src/core/contracts/ApplicationInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/ApplicationInterface.js +3 -0
- package/dist/src/core/contracts/ApplicationInterface.js.map +1 -0
- package/dist/src/core/contracts/BlockInterface.d.ts +67 -0
- package/dist/src/core/contracts/BlockInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/BlockInterface.js +2 -0
- package/dist/src/core/contracts/BlockInterface.js.map +1 -0
- package/dist/src/core/contracts/ComponentInterface.d.ts +24 -0
- package/dist/src/core/contracts/ComponentInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/ComponentInterface.js +2 -0
- package/dist/src/core/contracts/ComponentInterface.js.map +1 -0
- package/dist/src/core/contracts/ElementInterface.d.ts +117 -0
- package/dist/src/core/contracts/ElementInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/ElementInterface.js +2 -0
- package/dist/src/core/contracts/ElementInterface.js.map +1 -0
- package/dist/src/core/contracts/EventServiceInterface.d.ts +37 -0
- package/dist/src/core/contracts/EventServiceInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/EventServiceInterface.js +3 -0
- package/dist/src/core/contracts/EventServiceInterface.js.map +1 -0
- package/dist/src/core/contracts/HelperInterface.d.ts +231 -0
- package/dist/src/core/contracts/HelperInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/HelperInterface.js +3 -0
- package/dist/src/core/contracts/HelperInterface.js.map +1 -0
- package/dist/src/core/contracts/HttpServiceInterface.d.ts +38 -0
- package/dist/src/core/contracts/HttpServiceInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/HttpServiceInterface.js +3 -0
- package/dist/src/core/contracts/HttpServiceInterface.js.map +1 -0
- package/dist/src/core/contracts/LoggerServiceInterface.d.ts +37 -0
- package/dist/src/core/contracts/LoggerServiceInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/LoggerServiceInterface.js +3 -0
- package/dist/src/core/contracts/LoggerServiceInterface.js.map +1 -0
- package/dist/src/core/contracts/LoopContextInterface.d.ts +14 -0
- package/dist/src/core/contracts/LoopContextInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/LoopContextInterface.js +3 -0
- package/dist/src/core/contracts/LoopContextInterface.js.map +1 -0
- package/dist/src/core/contracts/MarkerInterface.d.ts +55 -0
- package/dist/src/core/contracts/MarkerInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/MarkerInterface.js +2 -0
- package/dist/src/core/contracts/MarkerInterface.js.map +1 -0
- package/dist/src/core/contracts/ReactiveInterface.d.ts +38 -0
- package/dist/src/core/contracts/ReactiveInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/ReactiveInterface.js +2 -0
- package/dist/src/core/contracts/ReactiveInterface.js.map +1 -0
- package/dist/src/core/contracts/RouterInterface.d.ts +58 -0
- package/dist/src/core/contracts/RouterInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/RouterInterface.js +2 -0
- package/dist/src/core/contracts/RouterInterface.js.map +1 -0
- package/dist/src/core/contracts/ServiceProviderInterface.d.ts +12 -0
- package/dist/src/core/contracts/ServiceProviderInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/ServiceProviderInterface.js +2 -0
- package/dist/src/core/contracts/ServiceProviderInterface.js.map +1 -0
- package/dist/src/core/contracts/StorageServiceInterface.d.ts +43 -0
- package/dist/src/core/contracts/StorageServiceInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/StorageServiceInterface.js +3 -0
- package/dist/src/core/contracts/StorageServiceInterface.js.map +1 -0
- package/dist/src/core/contracts/StoreServiceInterface.d.ts +45 -0
- package/dist/src/core/contracts/StoreServiceInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/StoreServiceInterface.js +3 -0
- package/dist/src/core/contracts/StoreServiceInterface.js.map +1 -0
- package/dist/src/core/contracts/ViewCacheInterface.d.ts +13 -0
- package/dist/src/core/contracts/ViewCacheInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/ViewCacheInterface.js +3 -0
- package/dist/src/core/contracts/ViewCacheInterface.js.map +1 -0
- package/dist/src/core/contracts/ViewControllerInterface.d.ts +115 -0
- package/dist/src/core/contracts/ViewControllerInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/ViewControllerInterface.js +2 -0
- package/dist/src/core/contracts/ViewControllerInterface.js.map +1 -0
- package/dist/src/core/contracts/ViewInterface.d.ts +24 -0
- package/dist/src/core/contracts/ViewInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/ViewInterface.js +2 -0
- package/dist/src/core/contracts/ViewInterface.js.map +1 -0
- package/dist/src/core/contracts/ViewManagerInterface.d.ts +44 -0
- package/dist/src/core/contracts/ViewManagerInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/ViewManagerInterface.js +2 -0
- package/dist/src/core/contracts/ViewManagerInterface.js.map +1 -0
- package/dist/src/core/contracts/ViewStateInterface.d.ts +40 -0
- package/dist/src/core/contracts/ViewStateInterface.d.ts.map +1 -0
- package/dist/src/core/contracts/ViewStateInterface.js +3 -0
- package/dist/src/core/contracts/ViewStateInterface.js.map +1 -0
- package/dist/src/core/contracts/common.d.ts +28 -0
- package/dist/src/core/contracts/common.d.ts.map +1 -0
- package/dist/src/core/contracts/common.js +29 -0
- package/dist/src/core/contracts/common.js.map +1 -0
- package/dist/src/core/contracts/utils.d.ts +20 -0
- package/dist/src/core/contracts/utils.d.ts.map +1 -0
- package/dist/src/core/contracts/utils.js +4 -0
- package/dist/src/core/contracts/utils.js.map +1 -0
- package/dist/src/core/contracts/views.d.ts +23 -0
- package/dist/src/core/contracts/views.d.ts.map +1 -0
- package/dist/src/core/contracts/views.js +2 -0
- package/dist/src/core/contracts/views.js.map +1 -0
- package/dist/src/core/elements/Block.d.ts +58 -0
- package/dist/src/core/elements/Block.d.ts.map +1 -0
- package/dist/src/core/elements/Block.js +77 -0
- package/dist/src/core/elements/Block.js.map +1 -0
- package/dist/src/core/elements/BlockOutlet.d.ts +34 -0
- package/dist/src/core/elements/BlockOutlet.d.ts.map +1 -0
- package/dist/src/core/elements/BlockOutlet.js +59 -0
- package/dist/src/core/elements/BlockOutlet.js.map +1 -0
- package/dist/src/core/elements/Component.d.ts +62 -0
- package/dist/src/core/elements/Component.d.ts.map +1 -0
- package/dist/src/core/elements/Component.js +72 -0
- package/dist/src/core/elements/Component.js.map +1 -0
- package/dist/src/core/elements/ElementManager.d.ts +23 -0
- package/dist/src/core/elements/ElementManager.d.ts.map +1 -0
- package/dist/src/core/elements/ElementManager.js +33 -0
- package/dist/src/core/elements/ElementManager.js.map +1 -0
- package/dist/src/core/elements/Fragment.d.ts +51 -0
- package/dist/src/core/elements/Fragment.d.ts.map +1 -0
- package/dist/src/core/elements/Fragment.js +133 -0
- package/dist/src/core/elements/Fragment.js.map +1 -0
- package/dist/src/core/elements/Html.d.ts +52 -0
- package/dist/src/core/elements/Html.d.ts.map +1 -0
- package/dist/src/core/elements/Html.js +299 -0
- package/dist/src/core/elements/Html.js.map +1 -0
- package/dist/src/core/elements/Output.d.ts +69 -0
- package/dist/src/core/elements/Output.d.ts.map +1 -0
- package/dist/src/core/elements/Output.js +121 -0
- package/dist/src/core/elements/Output.js.map +1 -0
- package/dist/src/core/elements/Reactive.d.ts +77 -0
- package/dist/src/core/elements/Reactive.d.ts.map +1 -0
- package/dist/src/core/elements/Reactive.js +199 -0
- package/dist/src/core/elements/Reactive.js.map +1 -0
- package/dist/src/core/elements/TextElement.d.ts +46 -0
- package/dist/src/core/elements/TextElement.d.ts.map +1 -0
- package/dist/src/core/elements/TextElement.js +94 -0
- package/dist/src/core/elements/TextElement.js.map +1 -0
- package/dist/src/core/elements/Wrapper.d.ts +50 -0
- package/dist/src/core/elements/Wrapper.d.ts.map +1 -0
- package/dist/src/core/elements/Wrapper.js +96 -0
- package/dist/src/core/elements/Wrapper.js.map +1 -0
- package/dist/src/core/elements/Yield.d.ts +34 -0
- package/dist/src/core/elements/Yield.d.ts.map +1 -0
- package/dist/src/core/elements/Yield.js +56 -0
- package/dist/src/core/elements/Yield.js.map +1 -0
- package/dist/src/core/elements/helpers.d.ts +8 -0
- package/dist/src/core/elements/helpers.d.ts.map +1 -0
- package/dist/src/core/elements/helpers.js +40 -0
- package/dist/src/core/elements/helpers.js.map +1 -0
- package/dist/src/core/elements/index.d.ts +12 -0
- package/dist/src/core/elements/index.d.ts.map +1 -0
- package/dist/src/core/elements/index.js +12 -0
- package/dist/src/core/elements/index.js.map +1 -0
- package/dist/src/core/hellpers/ApiClient.d.ts +58 -0
- package/dist/src/core/hellpers/ApiClient.d.ts.map +1 -0
- package/dist/src/core/hellpers/ApiClient.js +122 -0
- package/dist/src/core/hellpers/ApiClient.js.map +1 -0
- package/dist/src/core/hellpers/app.d.ts +3 -0
- package/dist/src/core/hellpers/app.d.ts.map +1 -0
- package/dist/src/core/hellpers/app.js +53 -0
- package/dist/src/core/hellpers/app.js.map +1 -0
- package/dist/src/core/hellpers/utils.d.ts +26 -0
- package/dist/src/core/hellpers/utils.d.ts.map +1 -0
- package/dist/src/core/hellpers/utils.js +96 -0
- package/dist/src/core/hellpers/utils.js.map +1 -0
- package/dist/src/core/routers/Router.d.ts +212 -0
- package/dist/src/core/routers/Router.d.ts.map +1 -0
- package/dist/src/core/routers/Router.js +623 -0
- package/dist/src/core/routers/Router.js.map +1 -0
- package/dist/src/core/routers/index.d.ts +3 -0
- package/dist/src/core/routers/index.d.ts.map +1 -0
- package/dist/src/core/routers/index.js +2 -0
- package/dist/src/core/routers/index.js.map +1 -0
- package/dist/src/core/services/BlockManager.d.ts +63 -0
- package/dist/src/core/services/BlockManager.d.ts.map +1 -0
- package/dist/src/core/services/BlockManager.js +191 -0
- package/dist/src/core/services/BlockManager.js.map +1 -0
- package/dist/src/core/services/DomService.d.ts +9 -0
- package/dist/src/core/services/DomService.d.ts.map +1 -0
- package/dist/src/core/services/DomService.js +18 -0
- package/dist/src/core/services/DomService.js.map +1 -0
- package/dist/src/core/services/EventService.d.ts +58 -0
- package/dist/src/core/services/EventService.d.ts.map +1 -0
- package/dist/src/core/services/EventService.js +212 -0
- package/dist/src/core/services/EventService.js.map +1 -0
- package/dist/src/core/services/HelperService.d.ts +443 -0
- package/dist/src/core/services/HelperService.d.ts.map +1 -0
- package/dist/src/core/services/HelperService.js +1650 -0
- package/dist/src/core/services/HelperService.js.map +1 -0
- package/dist/src/core/services/HttpService.d.ts +63 -0
- package/dist/src/core/services/HttpService.d.ts.map +1 -0
- package/dist/src/core/services/HttpService.js +182 -0
- package/dist/src/core/services/HttpService.js.map +1 -0
- package/dist/src/core/services/LoggerService.d.ts +56 -0
- package/dist/src/core/services/LoggerService.d.ts.map +1 -0
- package/dist/src/core/services/LoggerService.js +94 -0
- package/dist/src/core/services/LoggerService.js.map +1 -0
- package/dist/src/core/services/MarkerRegistry.d.ts +94 -0
- package/dist/src/core/services/MarkerRegistry.d.ts.map +1 -0
- package/dist/src/core/services/MarkerRegistry.js +199 -0
- package/dist/src/core/services/MarkerRegistry.js.map +1 -0
- package/dist/src/core/services/MarkerService.d.ts +299 -0
- package/dist/src/core/services/MarkerService.d.ts.map +1 -0
- package/dist/src/core/services/MarkerService.js +723 -0
- package/dist/src/core/services/MarkerService.js.map +1 -0
- package/dist/src/core/services/StorageService.d.ts +69 -0
- package/dist/src/core/services/StorageService.d.ts.map +1 -0
- package/dist/src/core/services/StorageService.js +243 -0
- package/dist/src/core/services/StorageService.js.map +1 -0
- package/dist/src/core/services/StoreService.d.ts +80 -0
- package/dist/src/core/services/StoreService.d.ts.map +1 -0
- package/dist/src/core/services/StoreService.js +301 -0
- package/dist/src/core/services/StoreService.js.map +1 -0
- package/dist/src/core/services/index.d.ts +9 -0
- package/dist/src/core/services/index.d.ts.map +1 -0
- package/dist/src/core/services/index.js +9 -0
- package/dist/src/core/services/index.js.map +1 -0
- package/dist/src/core/types/utils.d.ts +29 -0
- package/dist/src/core/types/utils.d.ts.map +1 -0
- package/dist/src/core/types/utils.js +22 -0
- package/dist/src/core/types/utils.js.map +1 -0
- package/dist/src/core/view/LoopContext.d.ts +38 -0
- package/dist/src/core/view/LoopContext.d.ts.map +1 -0
- package/dist/src/core/view/LoopContext.js +100 -0
- package/dist/src/core/view/LoopContext.js.map +1 -0
- package/dist/src/core/view/Section.d.ts +41 -0
- package/dist/src/core/view/Section.d.ts.map +1 -0
- package/dist/src/core/view/Section.js +67 -0
- package/dist/src/core/view/Section.js.map +1 -0
- package/dist/src/core/view/View.d.ts +63 -0
- package/dist/src/core/view/View.d.ts.map +1 -0
- package/dist/src/core/view/View.js +85 -0
- package/dist/src/core/view/View.js.map +1 -0
- package/dist/src/core/view/ViewController.d.ts +277 -0
- package/dist/src/core/view/ViewController.d.ts.map +1 -0
- package/dist/src/core/view/ViewController.js +862 -0
- package/dist/src/core/view/ViewController.js.map +1 -0
- package/dist/src/core/view/ViewManager.d.ts +141 -0
- package/dist/src/core/view/ViewManager.d.ts.map +1 -0
- package/dist/src/core/view/ViewManager.js +565 -0
- package/dist/src/core/view/ViewManager.js.map +1 -0
- package/dist/src/core/view/ViewState.d.ts +117 -0
- package/dist/src/core/view/ViewState.d.ts.map +1 -0
- package/dist/src/core/view/ViewState.js +410 -0
- package/dist/src/core/view/ViewState.js.map +1 -0
- package/dist/src/core/view/index.d.ts +6 -0
- package/dist/src/core/view/index.d.ts.map +1 -0
- package/dist/src/core/view/index.js +6 -0
- package/dist/src/core/view/index.js.map +1 -0
- package/index.ts +62 -0
- package/package.json +70 -0
- package/plugins.ts +77 -0
- package/src/core/app/Application.ts +410 -0
- package/src/core/bootstrap/app.ts +58 -0
- package/src/core/bootstrap/providers/ApiServiceProvider.ts +18 -0
- package/src/core/bootstrap/providers/CoreServiceProvider.ts +19 -0
- package/src/core/bootstrap/providers/HelperServiceProvider.ts +12 -0
- package/src/core/bootstrap/providers/RouteServiceProvider.ts +17 -0
- package/src/core/bootstrap/providers/ServiceProvider.ts +51 -0
- package/src/core/bootstrap/providers/ViewServiceProvider.ts +17 -0
- package/src/core/bootstrap/providers/default-providers.ts +94 -0
- package/src/core/bootstrap/providers/index.ts +9 -0
- package/src/core/bootstrap/providers/provider-order.test.ts +67 -0
- package/src/core/bootstrap/providers/provider-order.ts +66 -0
- package/src/core/cache/ViewCache.ts +102 -0
- package/src/core/cache/index.ts +1 -0
- package/src/core/contracts/ApiInterface.ts +11 -0
- package/src/core/contracts/ApplicationInterface.ts +79 -0
- package/src/core/contracts/BlockInterface.ts +76 -0
- package/src/core/contracts/ComponentInterface.ts +26 -0
- package/src/core/contracts/ElementInterface.ts +140 -0
- package/src/core/contracts/EventServiceInterface.ts +47 -0
- package/src/core/contracts/HelperInterface.ts +256 -0
- package/src/core/contracts/HttpServiceInterface.ts +51 -0
- package/src/core/contracts/LoggerServiceInterface.ts +48 -0
- package/src/core/contracts/LoopContextInterface.ts +15 -0
- package/src/core/contracts/MarkerInterface.ts +77 -0
- package/src/core/contracts/ReactiveInterface.ts +45 -0
- package/src/core/contracts/RouterInterface.ts +65 -0
- package/src/core/contracts/ServiceProviderInterface.ts +12 -0
- package/src/core/contracts/StorageServiceInterface.ts +48 -0
- package/src/core/contracts/StoreServiceInterface.ts +50 -0
- package/src/core/contracts/ViewCacheInterface.ts +14 -0
- package/src/core/contracts/ViewControllerInterface.ts +135 -0
- package/src/core/contracts/ViewInterface.ts +31 -0
- package/src/core/contracts/ViewManagerInterface.ts +45 -0
- package/src/core/contracts/ViewStateInterface.ts +47 -0
- package/src/core/contracts/common.ts +27 -0
- package/src/core/contracts/utils.ts +23 -0
- package/src/core/contracts/views.ts +23 -0
- package/src/core/elements/Block.ts +113 -0
- package/src/core/elements/BlockOutlet.ts +83 -0
- package/src/core/elements/Component.ts +114 -0
- package/src/core/elements/ElementManager.ts +48 -0
- package/src/core/elements/Fragment.ts +168 -0
- package/src/core/elements/Html.ts +364 -0
- package/src/core/elements/Output.ts +167 -0
- package/src/core/elements/Reactive.ts +253 -0
- package/src/core/elements/TextElement.ts +110 -0
- package/src/core/elements/Wrapper.ts +131 -0
- package/src/core/elements/Yield.ts +70 -0
- package/src/core/elements/helpers.ts +56 -0
- package/src/core/elements/index.ts +26 -0
- package/src/core/hellpers/ApiClient.ts +145 -0
- package/src/core/hellpers/app.ts +57 -0
- package/src/core/hellpers/utils.ts +109 -0
- package/src/core/routers/Router.ts +765 -0
- package/src/core/routers/index.ts +2 -0
- package/src/core/services/BlockManager.ts +210 -0
- package/src/core/services/DomService.ts +26 -0
- package/src/core/services/EventService.ts +266 -0
- package/src/core/services/HelperService.ts +1653 -0
- package/src/core/services/HttpService.ts +235 -0
- package/src/core/services/LoggerService.ts +139 -0
- package/src/core/services/MarkerRegistry.ts +239 -0
- package/src/core/services/MarkerService.ts +923 -0
- package/src/core/services/StorageService.ts +268 -0
- package/src/core/services/StoreService.ts +338 -0
- package/src/core/services/index.ts +8 -0
- package/src/core/types/utils.ts +30 -0
- package/src/core/view/LoopContext.ts +109 -0
- package/src/core/view/Section.ts +86 -0
- package/src/core/view/View.ts +109 -0
- package/src/core/view/ViewController.ts +1002 -0
- package/src/core/view/ViewManager.ts +700 -0
- package/src/core/view/ViewState.ts +453 -0
- 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
|