wu-framework 1.1.16 → 1.1.18
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 -20
- package/package.json +48 -3
- package/src/adapters/alpine/index.d.ts +60 -0
- package/src/adapters/alpine/index.js +231 -0
- package/src/adapters/alpine.d.ts +3 -0
- package/src/adapters/alpine.js +3 -0
- package/src/adapters/htmx/index.d.ts +60 -0
- package/src/adapters/htmx/index.js +242 -0
- package/src/adapters/htmx.d.ts +3 -0
- package/src/adapters/htmx.js +3 -0
- package/src/adapters/index.js +60 -3
- package/src/adapters/qwik/index.d.ts +52 -0
- package/src/adapters/qwik/index.js +214 -0
- package/src/adapters/qwik.d.ts +3 -0
- package/src/adapters/qwik.js +3 -0
- package/src/adapters/react/ai.js +135 -135
- package/src/adapters/react/index.d.ts +246 -246
- package/src/adapters/react/index.js +695 -695
- package/src/adapters/stencil/index.d.ts +54 -0
- package/src/adapters/stencil/index.js +228 -0
- package/src/adapters/stencil.d.ts +3 -0
- package/src/adapters/stencil.js +3 -0
- package/src/adapters/stimulus/index.d.ts +60 -0
- package/src/adapters/stimulus/index.js +255 -0
- package/src/adapters/stimulus.d.ts +3 -0
- package/src/adapters/stimulus.js +3 -0
- package/src/adapters/svelte/index.js +1 -1
- package/src/adapters/vanilla/index.js +1 -1
- package/src/adapters/vue/index.js +8 -0
- package/src/core/wu-cache.js +24 -3
- package/src/core/wu-core.js +15 -1
- package/src/core/wu-error-boundary.js +17 -3
- package/src/core/wu-event-bus.js +43 -1
- package/src/core/wu-html-parser.js +13 -4
- package/src/core/wu-loader.js +162 -50
- package/src/core/wu-logger.js +21 -13
- package/src/core/wu-manifest.js +23 -0
- package/src/core/wu-plugin.js +57 -4
- package/src/core/wu-proxy-sandbox.js +2 -1
- package/src/core/wu-script-executor.js +48 -0
- package/src/core/wu-store.js +13 -3
- package/src/index.d.ts +317 -0
- package/src/index.js +11 -1
- package/dist/wu-framework.cjs.js +0 -3
- package/dist/wu-framework.cjs.js.map +0 -1
- package/dist/wu-framework.dev.js +0 -15302
- package/dist/wu-framework.dev.js.map +0 -1
- package/dist/wu-framework.esm.js +0 -3
- package/dist/wu-framework.esm.js.map +0 -1
- package/dist/wu-framework.umd.js +0 -3
- package/dist/wu-framework.umd.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="https://wu-framework
|
|
2
|
+
<img src="https://raw.githubusercontent.com/LuisPadre25/wu-framework/main/wu-logo.png" width="80" alt="Wu Framework" />
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
<h1 align="center">Wu Framework</h1>
|
|
@@ -10,16 +10,16 @@
|
|
|
10
10
|
|
|
11
11
|
<p align="center">
|
|
12
12
|
<a href="https://www.npmjs.com/package/wu-framework"><img src="https://img.shields.io/npm/v/wu-framework.svg?color=8b5cf6&label=npm" alt="npm version" /></a>
|
|
13
|
-
<a href="https://github.com/
|
|
13
|
+
<a href="https://github.com/LuisPadre25/wu-framework/actions"><img src="https://img.shields.io/github/actions/workflow/status/LuisPadre25/wu-framework/ci.yml?label=tests&color=10b981" alt="tests" /></a>
|
|
14
14
|
<img src="https://img.shields.io/badge/tests-650%20passed-10b981" alt="650 tests" />
|
|
15
15
|
<img src="https://img.shields.io/badge/dependencies-0-8b5cf6" alt="zero deps" />
|
|
16
16
|
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="MIT License" /></a>
|
|
17
17
|
</p>
|
|
18
18
|
|
|
19
19
|
<p align="center">
|
|
20
|
-
<a href="https://wu-framework.
|
|
21
|
-
<a href="https://wu-framework.
|
|
22
|
-
<a href="https://wu-framework.
|
|
20
|
+
<a href="https://www.wu-framework.com">Documentation</a> ·
|
|
21
|
+
<a href="https://www.wu-framework.com/docs/quick-start">Quick Start</a> ·
|
|
22
|
+
<a href="https://www.wu-framework.com/docs/ai/overview">AI Integration</a> ·
|
|
23
23
|
<a href="#wucommerce--real-world-example">Live Example</a>
|
|
24
24
|
</p>
|
|
25
25
|
|
|
@@ -345,7 +345,7 @@ npm run test:coverage # Coverage report
|
|
|
345
345
|
| `wu-framework.esm.js` | ES Module | Bundler imports |
|
|
346
346
|
| `wu-framework.cjs.js` | CommonJS | Node.js require |
|
|
347
347
|
| `wu-framework.umd.js` | UMD | CDN / script tag |
|
|
348
|
-
| `wu-framework.
|
|
348
|
+
| `www.wu-framework.com.js` | ES Module | Development |
|
|
349
349
|
|
|
350
350
|
---
|
|
351
351
|
|
|
@@ -376,20 +376,20 @@ npm run test:coverage # Coverage report
|
|
|
376
376
|
|
|
377
377
|
## Documentation
|
|
378
378
|
|
|
379
|
-
Full documentation at **[wu-framework.
|
|
380
|
-
|
|
381
|
-
- [Quick Start](https://wu-framework.
|
|
382
|
-
- [Getting Started](https://wu-framework.
|
|
383
|
-
- [API Reference](https://wu-framework.
|
|
384
|
-
- [Event Bus](https://wu-framework.
|
|
385
|
-
- [Shared Store](https://wu-framework.
|
|
386
|
-
- [Sandbox](https://wu-framework.
|
|
387
|
-
- [AI Overview](https://wu-framework.
|
|
388
|
-
- [AI Actions](https://wu-framework.
|
|
389
|
-
- [Browser Actions](https://wu-framework.
|
|
390
|
-
- [MCP Server](https://wu-framework.
|
|
391
|
-
- [CSS Isolation](https://wu-framework.
|
|
392
|
-
- [Deployment](https://wu-framework.
|
|
379
|
+
Full documentation at **[www.wu-framework.com](https://www.wu-framework.com)**
|
|
380
|
+
|
|
381
|
+
- [Quick Start](https://www.wu-framework.com/docs/quick-start) — Get running in 5 minutes
|
|
382
|
+
- [Getting Started](https://www.wu-framework.com/docs/getting-started) — Deeper tutorial with cross-app communication
|
|
383
|
+
- [API Reference](https://www.wu-framework.com/docs/core/api) — Full API docs
|
|
384
|
+
- [Event Bus](https://www.wu-framework.com/docs/core/event-bus) — Inter-app communication
|
|
385
|
+
- [Shared Store](https://www.wu-framework.com/docs/core/store) — Cross-app reactive state
|
|
386
|
+
- [Sandbox](https://www.wu-framework.com/docs/core/sandbox) — JS isolation strategies
|
|
387
|
+
- [AI Overview](https://www.wu-framework.com/docs/ai/overview) — 4 AI paradigms
|
|
388
|
+
- [AI Actions](https://www.wu-framework.com/docs/ai/actions) — Register tools for the LLM
|
|
389
|
+
- [Browser Actions](https://www.wu-framework.com/docs/ai/browser-actions) — 10 built-in browser tools
|
|
390
|
+
- [MCP Server](https://www.wu-framework.com/docs/ai/mcp-server) — Connect AI agents to live apps
|
|
391
|
+
- [CSS Isolation](https://www.wu-framework.com/docs/guides/css-isolation) — Shadow DOM style modes
|
|
392
|
+
- [Deployment](https://www.wu-framework.com/docs/guides/deployment) — Production deployment guide
|
|
393
393
|
|
|
394
394
|
---
|
|
395
395
|
|
|
@@ -397,6 +397,38 @@ Full documentation at **[wu-framework.dev](https://wu-framework.dev)**
|
|
|
397
397
|
|
|
398
398
|
Chrome 80+, Firefox 78+, Safari 14+, Edge 80+. Shadow DOM v1 required.
|
|
399
399
|
|
|
400
|
+
---
|
|
401
|
+
|
|
402
|
+
<div align="center">
|
|
403
|
+
|
|
404
|
+
### What if Wu Framework could think without thinking?
|
|
405
|
+
|
|
406
|
+
</div>
|
|
407
|
+
|
|
408
|
+
```
|
|
409
|
+
User: "add to cart"
|
|
410
|
+
|
|
411
|
+
Before After
|
|
412
|
+
────── ─────
|
|
413
|
+
wu.ai.send() → LLM wu.ai.send() → ???
|
|
414
|
+
~2,000 ms ~0.73 ms
|
|
415
|
+
$0.003 per call $0.000
|
|
416
|
+
```
|
|
417
|
+
|
|
418
|
+
Something is coming. It learned from every LLM call you ever made. It doesn't need the cloud anymore.
|
|
419
|
+
|
|
420
|
+
**99.79% accuracy. 0.73 milliseconds. 800 KB. Zero GPU. Zero internet.**
|
|
421
|
+
|
|
422
|
+
274x faster than neural networks. And it dreams.
|
|
423
|
+
|
|
424
|
+
<div align="center">
|
|
425
|
+
|
|
426
|
+
**COMING SOON**
|
|
427
|
+
|
|
428
|
+
</div>
|
|
429
|
+
|
|
430
|
+
---
|
|
431
|
+
|
|
400
432
|
## Contributing
|
|
401
433
|
|
|
402
434
|
Contributions welcome. Please open an issue first to discuss what you'd like to change.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wu-framework",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.18",
|
|
4
4
|
"description": "Universal Microfrontends Framework - 8 frameworks, zero config, Shadow DOM isolation",
|
|
5
5
|
"main": "dist/wu-framework.cjs.js",
|
|
6
6
|
"module": "src/index.js",
|
|
@@ -22,6 +22,11 @@
|
|
|
22
22
|
"./adapters/solid": "./src/adapters/solid/index.js",
|
|
23
23
|
"./adapters/lit": "./src/adapters/lit/index.js",
|
|
24
24
|
"./adapters/vanilla": "./src/adapters/vanilla/index.js",
|
|
25
|
+
"./adapters/alpine": "./src/adapters/alpine/index.js",
|
|
26
|
+
"./adapters/qwik": "./src/adapters/qwik/index.js",
|
|
27
|
+
"./adapters/stencil": "./src/adapters/stencil/index.js",
|
|
28
|
+
"./adapters/htmx": "./src/adapters/htmx/index.js",
|
|
29
|
+
"./adapters/stimulus": "./src/adapters/stimulus/index.js",
|
|
25
30
|
"./integrations/astro": "./integrations/astro/index.js",
|
|
26
31
|
"./integrations/astro/WuApp.astro": "./integrations/astro/WuApp.astro",
|
|
27
32
|
"./integrations/astro/WuShell.astro": "./integrations/astro/WuShell.astro"
|
|
@@ -35,7 +40,10 @@
|
|
|
35
40
|
"clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
|
|
36
41
|
"test": "vitest run",
|
|
37
42
|
"test:watch": "vitest",
|
|
38
|
-
"test:coverage": "vitest run --coverage"
|
|
43
|
+
"test:coverage": "vitest run --coverage",
|
|
44
|
+
"lint": "eslint src/",
|
|
45
|
+
"format": "prettier --write src/",
|
|
46
|
+
"format:check": "prettier --check src/"
|
|
39
47
|
},
|
|
40
48
|
"keywords": [
|
|
41
49
|
"microfrontends",
|
|
@@ -109,6 +117,21 @@
|
|
|
109
117
|
],
|
|
110
118
|
"adapters/vanilla": [
|
|
111
119
|
"src/adapters/vanilla/index.d.ts"
|
|
120
|
+
],
|
|
121
|
+
"adapters/alpine": [
|
|
122
|
+
"src/adapters/alpine/index.d.ts"
|
|
123
|
+
],
|
|
124
|
+
"adapters/qwik": [
|
|
125
|
+
"src/adapters/qwik/index.d.ts"
|
|
126
|
+
],
|
|
127
|
+
"adapters/stencil": [
|
|
128
|
+
"src/adapters/stencil/index.d.ts"
|
|
129
|
+
],
|
|
130
|
+
"adapters/htmx": [
|
|
131
|
+
"src/adapters/htmx/index.d.ts"
|
|
132
|
+
],
|
|
133
|
+
"adapters/stimulus": [
|
|
134
|
+
"src/adapters/stimulus/index.d.ts"
|
|
112
135
|
]
|
|
113
136
|
}
|
|
114
137
|
},
|
|
@@ -118,7 +141,9 @@
|
|
|
118
141
|
"@rollup/plugin-replace": "^5.0.5",
|
|
119
142
|
"@rollup/plugin-terser": "^0.4.4",
|
|
120
143
|
"@vitest/coverage-v8": "^4.0.18",
|
|
144
|
+
"eslint": "^10.0.2",
|
|
121
145
|
"jsdom": "^28.0.0",
|
|
146
|
+
"prettier": "^3.8.1",
|
|
122
147
|
"rollup": "^4.9.0",
|
|
123
148
|
"vitest": "^4.0.18"
|
|
124
149
|
},
|
|
@@ -130,7 +155,12 @@
|
|
|
130
155
|
"react-dom": ">=16.8.0",
|
|
131
156
|
"solid-js": ">=1.0.0",
|
|
132
157
|
"svelte": ">=3.0.0",
|
|
133
|
-
"vue": ">=3.0.0"
|
|
158
|
+
"vue": ">=3.0.0",
|
|
159
|
+
"alpinejs": ">=3.0.0",
|
|
160
|
+
"@builder.io/qwik": ">=1.0.0",
|
|
161
|
+
"@stencil/core": ">=4.0.0",
|
|
162
|
+
"htmx.org": ">=2.0.0",
|
|
163
|
+
"@hotwired/stimulus": ">=3.0.0"
|
|
134
164
|
},
|
|
135
165
|
"peerDependenciesMeta": {
|
|
136
166
|
"react": {
|
|
@@ -156,6 +186,21 @@
|
|
|
156
186
|
},
|
|
157
187
|
"lit": {
|
|
158
188
|
"optional": true
|
|
189
|
+
},
|
|
190
|
+
"alpinejs": {
|
|
191
|
+
"optional": true
|
|
192
|
+
},
|
|
193
|
+
"@builder.io/qwik": {
|
|
194
|
+
"optional": true
|
|
195
|
+
},
|
|
196
|
+
"@stencil/core": {
|
|
197
|
+
"optional": true
|
|
198
|
+
},
|
|
199
|
+
"htmx.org": {
|
|
200
|
+
"optional": true
|
|
201
|
+
},
|
|
202
|
+
"@hotwired/stimulus": {
|
|
203
|
+
"optional": true
|
|
159
204
|
}
|
|
160
205
|
}
|
|
161
206
|
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WU-FRAMEWORK ALPINE.JS ADAPTER - TypeScript Declarations
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { WuCore } from '../../core/wu-core';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Alpine.js app configuration
|
|
9
|
+
*/
|
|
10
|
+
export interface AlpineAppConfig {
|
|
11
|
+
/** HTML template string containing Alpine directives (x-data, x-bind, etc.) */
|
|
12
|
+
template: string;
|
|
13
|
+
/** Function that returns the Alpine data object */
|
|
14
|
+
data?: () => Record<string, any>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Alpine.js adapter registration options
|
|
19
|
+
*/
|
|
20
|
+
export interface AlpineRegisterOptions {
|
|
21
|
+
/** Callback after mounting */
|
|
22
|
+
onMount?: (container: HTMLElement) => void;
|
|
23
|
+
/** Callback before unmounting */
|
|
24
|
+
onUnmount?: (container: HTMLElement) => void;
|
|
25
|
+
/** Allow standalone execution when Wu Framework is not available */
|
|
26
|
+
standalone?: boolean;
|
|
27
|
+
/** CSS selector for standalone mode container */
|
|
28
|
+
standaloneContainer?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Register an Alpine.js app as a Wu microfrontend
|
|
33
|
+
*/
|
|
34
|
+
export function register(
|
|
35
|
+
appName: string,
|
|
36
|
+
appConfig: AlpineAppConfig,
|
|
37
|
+
options?: AlpineRegisterOptions
|
|
38
|
+
): Promise<boolean>;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Get the current Wu Framework instance
|
|
42
|
+
*/
|
|
43
|
+
export function getWuInstance(): WuCore | null;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Wait for Wu Framework to become available
|
|
47
|
+
*/
|
|
48
|
+
export function waitForWu(timeout?: number): Promise<WuCore>;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Alpine.js adapter interface
|
|
52
|
+
*/
|
|
53
|
+
export interface WuAlpineAdapter {
|
|
54
|
+
register: typeof register;
|
|
55
|
+
getWuInstance: typeof getWuInstance;
|
|
56
|
+
waitForWu: typeof waitForWu;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const wuAlpine: WuAlpineAdapter;
|
|
60
|
+
export default wuAlpine;
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WU-FRAMEWORK ALPINE.JS ADAPTER
|
|
3
|
+
*
|
|
4
|
+
* Bridges Alpine.js reactive components into Wu Framework's
|
|
5
|
+
* microfrontend orchestration layer. Alpine's declarative
|
|
6
|
+
* x-data / x-bind paradigm maps naturally to a template + data
|
|
7
|
+
* registration model.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* import { wuAlpine } from 'wu-framework/adapters/alpine';
|
|
11
|
+
*
|
|
12
|
+
* wuAlpine.register('my-app', {
|
|
13
|
+
* template: '<div x-data="app"><span x-text="message"></span></div>',
|
|
14
|
+
* data: () => ({ message: 'Hello from Alpine' })
|
|
15
|
+
* });
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* // With lifecycle hooks
|
|
19
|
+
* wuAlpine.register('counter', {
|
|
20
|
+
* template: `
|
|
21
|
+
* <div x-data="app">
|
|
22
|
+
* <span x-text="count"></span>
|
|
23
|
+
* <button @click="count++">+</button>
|
|
24
|
+
* </div>
|
|
25
|
+
* `,
|
|
26
|
+
* data: () => ({ count: 0 })
|
|
27
|
+
* }, {
|
|
28
|
+
* onMount: (container) => console.log('Mounted'),
|
|
29
|
+
* onUnmount: (container) => console.log('Unmounted')
|
|
30
|
+
* });
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
// Adapter-scoped state
|
|
34
|
+
const adapterState = {
|
|
35
|
+
apps: new Map()
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Obtiene la instancia de Wu Framework
|
|
40
|
+
*/
|
|
41
|
+
function getWuInstance() {
|
|
42
|
+
if (typeof window === 'undefined') return null;
|
|
43
|
+
|
|
44
|
+
return window.wu
|
|
45
|
+
|| window.parent?.wu
|
|
46
|
+
|| window.top?.wu
|
|
47
|
+
|| null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Espera a que Wu Framework este disponible
|
|
52
|
+
*/
|
|
53
|
+
function waitForWu(timeout = 5000) {
|
|
54
|
+
return new Promise((resolve, reject) => {
|
|
55
|
+
const wu = getWuInstance();
|
|
56
|
+
if (wu) {
|
|
57
|
+
resolve(wu);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const startTime = Date.now();
|
|
62
|
+
|
|
63
|
+
const handleWuReady = () => {
|
|
64
|
+
cleanup();
|
|
65
|
+
resolve(getWuInstance());
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
window.addEventListener('wu:ready', handleWuReady);
|
|
69
|
+
window.addEventListener('wu:app:ready', handleWuReady);
|
|
70
|
+
|
|
71
|
+
const checkInterval = setInterval(() => {
|
|
72
|
+
const wu = getWuInstance();
|
|
73
|
+
if (wu) {
|
|
74
|
+
cleanup();
|
|
75
|
+
resolve(wu);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (Date.now() - startTime > timeout) {
|
|
80
|
+
cleanup();
|
|
81
|
+
reject(new Error(`Wu Framework not found after ${timeout}ms`));
|
|
82
|
+
}
|
|
83
|
+
}, 200);
|
|
84
|
+
|
|
85
|
+
function cleanup() {
|
|
86
|
+
clearInterval(checkInterval);
|
|
87
|
+
window.removeEventListener('wu:ready', handleWuReady);
|
|
88
|
+
window.removeEventListener('wu:app:ready', handleWuReady);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Registra una app Alpine.js como microfrontend
|
|
95
|
+
*
|
|
96
|
+
* @param {string} appName - Nombre unico del microfrontend
|
|
97
|
+
* @param {Object} appConfig - Configuracion de la app Alpine
|
|
98
|
+
* @param {string} appConfig.template - HTML string con directivas Alpine (x-data, x-bind, etc.)
|
|
99
|
+
* @param {Function} appConfig.data - Funcion que retorna el objeto de datos Alpine
|
|
100
|
+
* @param {Object} [options] - Opciones adicionales
|
|
101
|
+
* @param {Function} [options.onMount] - Callback despues de montar
|
|
102
|
+
* @param {Function} [options.onUnmount] - Callback antes de desmontar
|
|
103
|
+
* @param {boolean} [options.standalone=true] - Permitir ejecucion standalone
|
|
104
|
+
* @param {string} [options.standaloneContainer='#app'] - Selector para modo standalone
|
|
105
|
+
* @returns {Promise<boolean>} true si el registro fue exitoso
|
|
106
|
+
*/
|
|
107
|
+
async function register(appName, appConfig, options = {}) {
|
|
108
|
+
const { template, data } = appConfig;
|
|
109
|
+
|
|
110
|
+
const {
|
|
111
|
+
onMount = null,
|
|
112
|
+
onUnmount = null,
|
|
113
|
+
standalone = true,
|
|
114
|
+
standaloneContainer = '#app'
|
|
115
|
+
} = options;
|
|
116
|
+
|
|
117
|
+
if (!template || typeof template !== 'string') {
|
|
118
|
+
throw new Error(`[WuAlpine] template (HTML string) is required for ${appName}`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Mount function
|
|
122
|
+
const mountApp = (container) => {
|
|
123
|
+
if (!container) {
|
|
124
|
+
console.error(`[WuAlpine] Mount failed for ${appName}: container is null`);
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Prevent double-mount
|
|
129
|
+
if (adapterState.apps.has(appName)) {
|
|
130
|
+
console.warn(`[WuAlpine] ${appName} already mounted, unmounting first`);
|
|
131
|
+
unmountApp();
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
try {
|
|
135
|
+
container.innerHTML = '';
|
|
136
|
+
|
|
137
|
+
// Inject template HTML
|
|
138
|
+
container.innerHTML = template;
|
|
139
|
+
|
|
140
|
+
// Initialize Alpine on this subtree
|
|
141
|
+
const Alpine = window.Alpine;
|
|
142
|
+
if (Alpine) {
|
|
143
|
+
if (data && typeof data === 'function') {
|
|
144
|
+
Alpine.data('app', data);
|
|
145
|
+
}
|
|
146
|
+
Alpine.initTree(container);
|
|
147
|
+
} else {
|
|
148
|
+
console.warn(`[WuAlpine] window.Alpine not found - template inserted but not initialized`);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
adapterState.apps.set(appName, { container, config: appConfig });
|
|
152
|
+
|
|
153
|
+
console.log(`[WuAlpine] ${appName} mounted successfully`);
|
|
154
|
+
|
|
155
|
+
if (onMount) {
|
|
156
|
+
onMount(container);
|
|
157
|
+
}
|
|
158
|
+
} catch (error) {
|
|
159
|
+
console.error(`[WuAlpine] Mount error for ${appName}:`, error);
|
|
160
|
+
throw error;
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
// Unmount function
|
|
165
|
+
const unmountApp = (container) => {
|
|
166
|
+
const appData = adapterState.apps.get(appName);
|
|
167
|
+
|
|
168
|
+
if (appData) {
|
|
169
|
+
try {
|
|
170
|
+
if (onUnmount) {
|
|
171
|
+
onUnmount(appData.container);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Tear down Alpine reactivity on this subtree
|
|
175
|
+
const Alpine = window.Alpine;
|
|
176
|
+
if (Alpine && typeof Alpine.destroyTree === 'function') {
|
|
177
|
+
Alpine.destroyTree(appData.container);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
appData.container.innerHTML = '';
|
|
181
|
+
adapterState.apps.delete(appName);
|
|
182
|
+
|
|
183
|
+
console.log(`[WuAlpine] ${appName} unmounted successfully`);
|
|
184
|
+
} catch (error) {
|
|
185
|
+
console.error(`[WuAlpine] Unmount error for ${appName}:`, error);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (container) {
|
|
190
|
+
container.innerHTML = '';
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
// Register with Wu Framework or fall back to standalone
|
|
195
|
+
try {
|
|
196
|
+
const wu = await waitForWu(3000);
|
|
197
|
+
|
|
198
|
+
wu.define(appName, {
|
|
199
|
+
mount: mountApp,
|
|
200
|
+
unmount: unmountApp
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
console.log(`[WuAlpine] ${appName} registered with Wu Framework`);
|
|
204
|
+
return true;
|
|
205
|
+
|
|
206
|
+
} catch (error) {
|
|
207
|
+
console.warn(`[WuAlpine] Wu Framework not available for ${appName}`);
|
|
208
|
+
|
|
209
|
+
if (standalone) {
|
|
210
|
+
const containerElement = document.querySelector(standaloneContainer);
|
|
211
|
+
|
|
212
|
+
if (containerElement) {
|
|
213
|
+
console.log(`[WuAlpine] Running ${appName} in standalone mode`);
|
|
214
|
+
mountApp(containerElement);
|
|
215
|
+
return true;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Public API
|
|
224
|
+
export const wuAlpine = {
|
|
225
|
+
register,
|
|
226
|
+
getWuInstance,
|
|
227
|
+
waitForWu
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
export { register, getWuInstance, waitForWu };
|
|
231
|
+
export default wuAlpine;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WU-FRAMEWORK HTMX ADAPTER - TypeScript Declarations
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { WuCore } from '../../core/wu-core';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* HTMX app configuration
|
|
9
|
+
*/
|
|
10
|
+
export interface HtmxAppConfig {
|
|
11
|
+
/** HTML template string containing hx-* attributes */
|
|
12
|
+
template: string;
|
|
13
|
+
/** Base URL for HTMX endpoints (rewrites relative paths in hx-get, hx-post, etc.) */
|
|
14
|
+
baseUrl?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* HTMX adapter registration options
|
|
19
|
+
*/
|
|
20
|
+
export interface HtmxRegisterOptions {
|
|
21
|
+
/** Callback after mounting */
|
|
22
|
+
onMount?: (container: HTMLElement) => void;
|
|
23
|
+
/** Callback before unmounting */
|
|
24
|
+
onUnmount?: (container: HTMLElement) => void;
|
|
25
|
+
/** Allow standalone execution when Wu Framework is not available */
|
|
26
|
+
standalone?: boolean;
|
|
27
|
+
/** CSS selector for standalone mode container */
|
|
28
|
+
standaloneContainer?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Register an HTMX app as a Wu microfrontend
|
|
33
|
+
*/
|
|
34
|
+
export function register(
|
|
35
|
+
appName: string,
|
|
36
|
+
config: HtmxAppConfig,
|
|
37
|
+
options?: HtmxRegisterOptions
|
|
38
|
+
): Promise<boolean>;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Get the current Wu Framework instance
|
|
42
|
+
*/
|
|
43
|
+
export function getWuInstance(): WuCore | null;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Wait for Wu Framework to become available
|
|
47
|
+
*/
|
|
48
|
+
export function waitForWu(timeout?: number): Promise<WuCore>;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* HTMX adapter interface
|
|
52
|
+
*/
|
|
53
|
+
export interface WuHtmxAdapter {
|
|
54
|
+
register: typeof register;
|
|
55
|
+
getWuInstance: typeof getWuInstance;
|
|
56
|
+
waitForWu: typeof waitForWu;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export const wuHtmx: WuHtmxAdapter;
|
|
60
|
+
export default wuHtmx;
|