commit b7cd369c12b5c16c89f5cf7eff59b593c1e12b86 Author: Dave Mc Nicoll Date: Thu Nov 6 12:15:10 2025 -0500 - First push to add as a composer module diff --git a/asset/lean-live/app.js b/asset/lean-live/app.js new file mode 100644 index 0000000..b4e3b01 --- /dev/null +++ b/asset/lean-live/app.js @@ -0,0 +1,2 @@ +import { UiLive } from "./ui-live.mjs"; +window.customElements.define("ui-live", UiLive); \ No newline at end of file diff --git a/asset/lean-live/ui-live.mjs b/asset/lean-live/ui-live.mjs new file mode 100644 index 0000000..4182155 --- /dev/null +++ b/asset/lean-live/ui-live.mjs @@ -0,0 +1,69 @@ +import { Webcomponent } from "../../webcomponent/module/webcomponent.js"; +import { Hourglass } from "../../webcomponent/hourglass.js"; + +const config = { + url: window.location.href, + template: { + fetch : false + } +}; + +class UiLive extends Webcomponent { + + constructor() { + super(config); + + this.init(); + } + + init() { + if (this.pool) { + new Hourglass(this.fetchAndRender.bind(this), { + timer: this.pool * 1000, + start: true, + }); + } + } + + fetchAndRender() { + this.classList.add("live-loading"); + + fetch(this.config.url, { + method: "GET", + headers: { + 'X-Ui-Live': JSON.stringify([ { name: this.name } ]) + } + }).then( response => response.text() ) + .then(html => { + this.swapHtml(html); + }) + .catch((error) => { + console.error(error); + }); + } + + swapHtml(html) { + this.innerHTML = ( new DOMParser() ) + .parseFromString(html, "text/html") + .querySelector('ui-live[data-name="' + this.name + '"]') + .innerHTML; + + this.dispatchEvent(new CustomEvent("live:swap")); + } + + /** @return string */ + get name() { + return this.dataset["name"]; + } + + /** @return int | undefined */ + get pool() { + if (isNaN(this.dataset['pool'])) { + return undefined; + } + + return this.dataset["pool"]; + } +} + +export { UiLive }; \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..a5e06a1 --- /dev/null +++ b/composer.json @@ -0,0 +1,41 @@ +{ + "name": "mcnd/lean-live", + "description": "Seamless operations between PHP and your users browsers actions.", + "type": "library", + "license": "MIT", + "authors": [ + { + "name": "Dave Mc Nicoll", + "email": "info@mcnd.ca" + } + ], + "require": { + "php": "^8.4", + "php-di/php-di": "dev-master", + "ext-json": "*", + "mcnd/lean": "dev-master" + }, + "repositories": [ + { + "type": "vcs", + "url": "https://git.mcnd.ca/mcndave/lean.git" + } + ], + "autoload": { + "psr-4": { + "Lean\\Live\\": "src/" + } + }, + "extra" : { + "lean" : { + "autoload": { + "definitions" : [ + "meta/definitions/software.php" + ], + "config": [ + "meta/config.php" + ] + } + } + } +} \ No newline at end of file diff --git a/meta/config.php b/meta/config.php new file mode 100644 index 0000000..fe49f3e --- /dev/null +++ b/meta/config.php @@ -0,0 +1,11 @@ + [ + 'autoload' => [ + 'lean.live', + ] + ], +]; \ No newline at end of file diff --git a/meta/definitions/software.php b/meta/definitions/software.php new file mode 100644 index 0000000..8847256 --- /dev/null +++ b/meta/definitions/software.php @@ -0,0 +1,60 @@ + [ + 'picea' => [ + 'context' => Lean\Api\View::class, + + 'view' => [ + [ + 'path' => implode(DIRECTORY_SEPARATOR, [ $path , "view", '' ]), + 'order' => 99, + ], + ], + + 'asset' => [ + [ + 'path' => implode(DIRECTORY_SEPARATOR, [ $path, "asset", '' ]), + 'order' => 10 + ], + ], + ], + + 'ulmus' => [ + 'entities' => [ 'Lean\\Api\\Entity' => implode(DIRECTORY_SEPARATOR, [ $path, 'src', 'Entity', '' ]) ], + 'adapters' => [ + DI\get('lean.api:storage'), + ] + ], + + 'tell' => [ + 'json' => [ + [ + 'path' => implode(DIRECTORY_SEPARATOR, [ $path, "meta", "i18n", "" ]), + 'order' => 99, + ], + ] + ], + + 'routes' => [ + 'Lean\\Api\\Controller' => implode(DIRECTORY_SEPARATOR, [ $path, "src", "Controller", "" ]), + ], + ], + + 'lean.api:storage' => function($c) { + $adapter = new ConnectionAdapter('lean.api', $c->get('config')['ulmus'], false); + $adapter->resolveConfiguration(); + + return $adapter; + }, + + Lean\ApplicationStrategy\NotFoundDecoratorInterface::class => DI\autowire(Lean\Api\ApplicationStrategy\NotFoundDecorator::class), + Lean\ApplicationStrategy\MethodNotAllowedInterface::class => DI\autowire(Lean\Api\ApplicationStrategy\MethodNotAllowedDecorator::class), + Lean\Api\Factory\MessageFactoryInterface::class => DI\autowire(Lean\Api\Lib\Message::class), + Lean\Api\Factory\DebugFormFactoryInterface::class => DI\autowire(Lean\Api\Factory\DebugFormFactory::class), + # League\Route\Strategy\ApplicationStrategy::class => DI\autowire(Lean\Api\ApplicationStrategy::class), +]; \ No newline at end of file