@deijose/nix-ionic 0.1.6 → 0.1.8
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/dist/lib/index.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
export { IonPage, createPageLifecycle, useIonViewWillEnter, useIonViewDidEnter, useIonViewWillLeave, useIonViewDidLeave, type PageLifecycle, } from "./lifecycle";
|
|
2
|
+
export { setupNixIonic } from "./setup";
|
|
2
3
|
export { IonRouterOutlet, IonBackButton, useRouter, type RouteDefinition, type PageContext, } from "./IonRouterOutlet";
|
package/dist/lib/nix-ionic.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let e=require("@deijose/nix-js");function
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});let e=require("@deijose/nix-js"),t=require("@ionic/core/components"),n=require("@ionic/core/components/ion-router.js"),r=require("@ionic/core/components/ion-route.js"),i=require("@ionic/core/components/ion-router-outlet.js"),a=require("@ionic/core/components/ion-back-button.js");function o(){return{willEnter:(0,e.signal)(0),didEnter:(0,e.signal)(0),willLeave:(0,e.signal)(0),didLeave:(0,e.signal)(0)}}var s=class extends e.NixComponent{__lc;constructor(e){super(),this.__lc=e}onInit(){let t=this.__lc;this.ionViewWillEnter&&(0,e.watch)(t.willEnter,this.ionViewWillEnter.bind(this)),this.ionViewDidEnter&&(0,e.watch)(t.didEnter,this.ionViewDidEnter.bind(this)),this.ionViewWillLeave&&(0,e.watch)(t.willLeave,this.ionViewWillLeave.bind(this)),this.ionViewDidLeave&&(0,e.watch)(t.didLeave,this.ionViewDidLeave.bind(this))}};function c(t,n){(0,e.watch)(t.willEnter,n)}function l(t,n){(0,e.watch)(t.didEnter,n)}function u(t,n){(0,e.watch)(t.willLeave,n)}function d(t,n){(0,e.watch)(t.didLeave,n)}var f=!1;function p(e={}){f||=((0,t.initialize)(e),(0,n.defineCustomElement)(),(0,r.defineCustomElement)(),(0,i.defineCustomElement)(),(0,a.defineCustomElement)(),!0)}function m(){let e=document.querySelector("ion-router");return{navigate:t=>{e?.push(t,"forward")},replace:t=>{e?.push(t,"root")},back:()=>{e?.back()}}}function h(e){return{__isNixTemplate:!0,mount(e){let t="string"==typeof e?document.querySelector(e):e;return{unmount:this._render(t,null)}},_render(t,n){let i=document.createElement("ion-back-button");return e&&i.setAttribute("default-href",e),t.insertBefore(i,n),()=>i.remove()}}}var g=class extends e.NixComponent{routes;constructor(e){super(),this.routes=e,this._registerCustomElements()}_extractParams(e,t){let n={},i=e.split("/"),r=t.split("/");for(let e=0;e<i.length;e++)i[e]?.startsWith(":")&&(n[i[e].slice(1)]=r[e]??"");return n}_pathToTag(e){return e&&"/"!==e?`nix-page-${e.replace(/\/:?[^/]+/g,e=>"-"+e.replace(/\//g,"").replace(/:/g,"")).replace(/^\//,"").replace(/\//g,"-")}`:"nix-page-home"}_registerCustomElements(){let e=this;for(let t of this.routes){if("*"===t.path)continue;let n=this._pathToTag(t.path);customElements.get(n)||customElements.define(n,class extends HTMLElement{_handle=null;connectedCallback(){if(this._handle)return;this.classList.add("ion-page");let n=o();this.addEventListener("ionViewWillEnter",()=>n.willEnter.update(e=>e+1)),this.addEventListener("ionViewDidEnter",()=>n.didEnter.update(e=>e+1)),this.addEventListener("ionViewWillLeave",()=>n.willLeave.update(e=>e+1)),this.addEventListener("ionViewDidLeave",()=>n.didLeave.update(e=>e+1));let i=e._extractParams(t.path,location.pathname),r=t.component({lc:n,params:i});if("render"in r&&"function"==typeof r.render){let e=r;e.onInit?.();let t=e.render()._render(this,null),n=e.onMount?.();this._handle={unmount:()=>{e.onUnmount?.(),"function"==typeof n&&n(),t()}}}else this._handle={unmount:r._render(this,null)}}disconnectedCallback(){this._handle?.unmount(),this._handle=null}})}}render(){let e=this;return{__isNixTemplate:!0,mount(e){let t="string"==typeof e?document.querySelector(e):e;return{unmount:this._render(t,null)}},_render(t,n){let i=document.createElement("ion-router");i.setAttribute("use-hash","false"),i.innerHTML=e.routes.filter(e=>"*"!==e.path).map(t=>`<ion-route url="${t.path}" component="${e._pathToTag(t.path)}"></ion-route>`).join("");let r=document.createElement("ion-router-outlet");return t.insertBefore(i,n),t.insertBefore(r,n),()=>{i.remove(),r.remove()}}}}};exports.IonBackButton=h,exports.IonPage=s,exports.IonRouterOutlet=g,exports.createPageLifecycle=o,exports.setupNixIonic=p,exports.useIonViewDidEnter=l,exports.useIonViewDidLeave=d,exports.useIonViewWillEnter=c,exports.useIonViewWillLeave=u,exports.useRouter=m;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nix-ionic.cjs","names":[],"sources":["../../src/lifecycle.ts","../../src/IonRouterOutlet.ts"],"sourcesContent":["/**\n * ionic-nix/lifecycle.ts\n *\n * Sistema de ciclo de vida de navegación, análogo a los hooks de Ionic:\n * ionViewWillEnter / ionViewDidEnter / ionViewWillLeave / ionViewDidLeave\n *\n * Cómo funciona (sin provide/inject):\n * 1. IonRouterOutlet crea un `PageLifecycle` por cada ruta.\n * 2. Lo pasa directamente al factory de la ruta como argumento.\n * 3. El factory llama a `new MiPagina(lc)` o `MiPagina(lc)`.\n * 4. IonPage/composables registran watchers sobre las señales del lc.\n * 5. Cuando el router navega, incrementa las señales → watchers se disparan.\n */\n\nimport { signal, watch } from \"@deijose/nix-js\";\nimport type { Signal } from \"@deijose/nix-js\";\nimport { NixComponent } from \"@deijose/nix-js\";\n\n// --------------------------------------------------------------------------\n// Tipos públicos\n// --------------------------------------------------------------------------\n\nexport interface PageLifecycle {\n willEnter: Signal<number>;\n didEnter: Signal<number>;\n willLeave: Signal<number>;\n didLeave: Signal<number>;\n}\n\n/** Crea un nuevo PageLifecycle con señales en 0. */\nexport function createPageLifecycle(): PageLifecycle {\n return {\n willEnter: signal(0),\n didEnter: signal(0),\n willLeave: signal(0),\n didLeave: signal(0),\n };\n}\n\n// --------------------------------------------------------------------------\n// IonPage — clase base para páginas con hooks de navegación\n// --------------------------------------------------------------------------\n//\n// Uso:\n// class HomePage extends IonPage {\n// constructor(lc: PageLifecycle) { super(lc); }\n//\n// ionViewWillEnter() { /* fetch de datos frescos */ }\n// render() { return html`...`; }\n// }\n\nexport abstract class IonPage extends NixComponent {\n private __lc: PageLifecycle;\n\n constructor(lc: PageLifecycle) {\n super();\n this.__lc = lc;\n }\n\n override onInit(): void {\n const lc = this.__lc;\n // watch no corre en init (immediate: false), así que ionViewWillEnter\n // solo se llama cuando el outlet incrementa la señal, no al construir.\n if (this.ionViewWillEnter) watch(lc.willEnter, this.ionViewWillEnter.bind(this));\n if (this.ionViewDidEnter) watch(lc.didEnter, this.ionViewDidEnter.bind(this));\n if (this.ionViewWillLeave) watch(lc.willLeave, this.ionViewWillLeave.bind(this));\n if (this.ionViewDidLeave) watch(lc.didLeave, this.ionViewDidLeave.bind(this));\n }\n\n ionViewWillEnter?(): void;\n ionViewDidEnter?(): void;\n ionViewWillLeave?(): void;\n ionViewDidLeave?(): void;\n}\n\n// --------------------------------------------------------------------------\n// Composables para function components\n// --------------------------------------------------------------------------\n//\n// Uso:\n// function ProfilePage(lc: PageLifecycle): NixTemplate {\n// useIonViewWillEnter(lc, () => { /* fetch */ });\n// return html`...`;\n// }\n\nexport function useIonViewWillEnter(lc: PageLifecycle, fn: () => void): void {\n watch(lc.willEnter, fn);\n}\n\nexport function useIonViewDidEnter(lc: PageLifecycle, fn: () => void): void {\n watch(lc.didEnter, fn);\n}\n\nexport function useIonViewWillLeave(lc: PageLifecycle, fn: () => void): void {\n watch(lc.willLeave, fn);\n}\n\nexport function useIonViewDidLeave(lc: PageLifecycle, fn: () => void): void {\n watch(lc.didLeave, fn);\n}","/**\n * ionic-nix/IonRouterOutlet.ts\n *\n * Bridge 100% nativo. Genera exactamente el mismo DOM que Vanilla Ionic.\n * Delegamos el view-caching y los ciclos de vida a los Eventos del DOM de ion-router-outlet.\n */\n\nimport { NixComponent } from \"@deijose/nix-js\";\nimport type { NixTemplate } from \"@deijose/nix-js\";\nimport { createPageLifecycle, type PageLifecycle } from \"./lifecycle\";\nimport { Components } from \"@ionic/core\";\n\n// --------------------------------------------------------------------------\n// Router store singleton\n// --------------------------------------------------------------------------\n\nexport function useRouter() {\n const router = <Components.IonRouter>document.querySelector(\"ion-router\");\n return {\n navigate: (path: string) => {\n router?.push(path, \"forward\");\n },\n replace: (path: string) => {\n router?.push(path, \"root\");\n },\n back: () => {\n router?.back();\n }\n };\n}\n\n// --------------------------------------------------------------------------\n// IonBackButton (Sin listeners, 100% nativo)\n// --------------------------------------------------------------------------\n\nexport function IonBackButton(defaultHref?: string): NixTemplate {\n return {\n __isNixTemplate: true as const,\n mount(container) {\n const el = typeof container === \"string\" ? document.querySelector(container)! : container;\n const cleanup = this._render(el, null);\n return { unmount: cleanup };\n },\n _render(parent: Node, before: Node | null): () => void {\n const btn = document.createElement(\"ion-back-button\") as HTMLElement;\n if (defaultHref) btn.setAttribute(\"default-href\", defaultHref);\n parent.insertBefore(btn, before);\n return () => btn.remove();\n },\n };\n}\n\n// --------------------------------------------------------------------------\n// Tipos públicos\n// --------------------------------------------------------------------------\n\nexport interface PageContext {\n lc: PageLifecycle;\n params: Record<string, string>;\n}\n\nexport interface RouteDefinition {\n path: string;\n component: (ctx: PageContext) => NixComponent | NixTemplate;\n}\n\n// --------------------------------------------------------------------------\n// IonRouterOutlet (El Bridge Maestro)\n// --------------------------------------------------------------------------\n\nexport class IonRouterOutlet extends NixComponent {\n private routes: RouteDefinition[];\n\n constructor(routes: RouteDefinition[]) {\n super();\n this.routes = routes;\n this._registerCustomElements();\n }\n\n // -------------------------------------------------------------------------\n // Helpers\n // -------------------------------------------------------------------------\n\n private _extractParams(routePath: string, realPath: string): Record<string, string> {\n const params: Record<string, string> = {};\n const rP = routePath.split(\"/\");\n const uP = realPath.split(\"/\");\n for (let i = 0; i < rP.length; i++) {\n if (rP[i]?.startsWith(\":\")) params[rP[i].slice(1)] = uP[i] ?? \"\";\n }\n return params;\n }\n\n private _pathToTag(path: string): string {\n if (!path || path === \"/\") return \"nix-page-home\";\n const clean = path\n .replace(/\\/:?[^/]+/g, (m) => \"-\" + m.replace(/\\//g, \"\").replace(/:/g, \"\"))\n .replace(/^\\//, \"\")\n .replace(/\\//g, \"-\");\n return `nix-page-${clean}`;\n }\n\n // -------------------------------------------------------------------------\n // Registro de Custom Elements estilo Vanilla JS\n // -------------------------------------------------------------------------\n\n private _registerCustomElements(): void {\n const self = this;\n for (const route of this.routes) {\n if (route.path === \"*\") continue;\n\n const tag = this._pathToTag(route.path);\n if (customElements.get(tag)) continue;\n\n customElements.define(tag, class extends HTMLElement {\n private _handle: { unmount(): void } | null = null;\n\n connectedCallback(): void {\n // Prevenir doble montaje si Ionic reconecta el nodo\n if (this._handle) return; \n\n this.classList.add(\"ion-page\");\n\n // 1. Escuchar los eventos NATIVOS del DOM que dispara ion-router-outlet\n const lc = createPageLifecycle();\n this.addEventListener(\"ionViewWillEnter\", () => lc.willEnter.update((n) => n + 1));\n this.addEventListener(\"ionViewDidEnter\", () => lc.didEnter.update((n) => n + 1));\n this.addEventListener(\"ionViewWillLeave\", () => lc.willLeave.update((n) => n + 1));\n this.addEventListener(\"ionViewDidLeave\", () => lc.didLeave.update((n) => n + 1));\n\n // 2. Extraer parámetros\n const params = self._extractParams(route.path, location.pathname);\n\n // 3. Montar componente Nix\n const pageNode = route.component({ lc, params });\n\n if (\"render\" in pageNode && typeof (pageNode as NixComponent).render === \"function\") {\n const comp = pageNode as NixComponent;\n comp.onInit?.();\n const renderCleanup = comp.render()._render(this, null);\n const mountRet = comp.onMount?.();\n\n this._handle = {\n unmount: () => {\n comp.onUnmount?.();\n if (typeof mountRet === \"function\") mountRet();\n renderCleanup();\n }\n };\n } else {\n const renderCleanup = (pageNode as NixTemplate)._render(this, null);\n this._handle = { unmount: renderCleanup };\n }\n }\n\n disconnectedCallback(): void {\n // ion-router-outlet SOLO desconecta el elemento cuando lo saca \n // definitivamente de la caché (ej. al hacer click en el back-button)\n this._handle?.unmount();\n this._handle = null;\n }\n });\n }\n }\n\n // -------------------------------------------------------------------------\n // Render exacto al HTML que te funcionaba\n // -------------------------------------------------------------------------\n\n override render(): NixTemplate {\n const self = this;\n return {\n __isNixTemplate: true as const,\n mount(container: Element | string) {\n const el = typeof container === \"string\" ? document.querySelector(container)! : container;\n const cleanup = this._render(el, null);\n return { unmount: cleanup };\n },\n _render(parent: Node, before: Node | null): () => void {\n \n // Creamos <ion-router>\n const routerEl = document.createElement(\"ion-router\");\n routerEl.setAttribute(\"use-hash\", \"false\");\n routerEl.innerHTML = self.routes\n .filter((r) => r.path !== \"*\")\n .map((r) => `<ion-route url=\"${r.path}\" component=\"${self._pathToTag(r.path)}\"></ion-route>`)\n .join(\"\");\n\n // Creamos <ion-router-outlet> real\n const outletEl = document.createElement(\"ion-router-outlet\");\n\n parent.insertBefore(routerEl, before);\n parent.insertBefore(outletEl, before);\n\n return () => {\n routerEl.remove();\n outletEl.remove();\n };\n },\n };\n }\n}"],"mappings":"oGA8BA,SAAgB,GAAqC,CACnD,MAAO,CACL,WAAA,EAAA,EAAA,QAAkB,EAAE,CACpB,UAAA,EAAA,EAAA,QAAkB,EAAE,CACpB,WAAA,EAAA,EAAA,QAAkB,EAAE,CACpB,UAAA,EAAA,EAAA,QAAkB,EAAE,CACrB,CAeH,IAAsB,EAAtB,cAAsC,EAAA,YAAa,CACjD,KAEA,YAAY,EAAmB,CAC7B,OAAO,CACP,KAAK,KAAO,EAGd,QAAwB,CACtB,IAAM,EAAK,KAAK,KAGZ,KAAK,mBAAkB,EAAA,EAAA,OAAM,EAAG,UAAW,KAAK,iBAAiB,KAAK,KAAK,CAAC,CAC5E,KAAK,kBAAkB,EAAA,EAAA,OAAM,EAAG,SAAW,KAAK,gBAAgB,KAAK,KAAK,CAAC,CAC3E,KAAK,mBAAkB,EAAA,EAAA,OAAM,EAAG,UAAW,KAAK,iBAAiB,KAAK,KAAK,CAAC,CAC5E,KAAK,kBAAkB,EAAA,EAAA,OAAM,EAAG,SAAW,KAAK,gBAAgB,KAAK,KAAK,CAAC,GAmBnF,SAAgB,EAAoB,EAAmB,EAAsB,EAC3E,EAAA,EAAA,OAAM,EAAG,UAAW,EAAG,CAGzB,SAAgB,EAAmB,EAAmB,EAAsB,EAC1E,EAAA,EAAA,OAAM,EAAG,SAAU,EAAG,CAGxB,SAAgB,EAAoB,EAAmB,EAAsB,EAC3E,EAAA,EAAA,OAAM,EAAG,UAAW,EAAG,CAGzB,SAAgB,EAAmB,EAAmB,EAAsB,EAC1E,EAAA,EAAA,OAAM,EAAG,SAAU,EAAG,CClFxB,SAAgB,GAAY,CAC1B,IAAM,EAA+B,SAAS,cAAc,aAAa,CACzE,MAAO,CACL,SAAW,GAAiB,CAC1B,GAAQ,KAAK,EAAM,UAAU,EAE/B,QAAU,GAAiB,CACzB,GAAQ,KAAK,EAAM,OAAO,EAE5B,SAAY,CACV,GAAQ,MAAM,EAEjB,CAOH,SAAgB,EAAc,EAAmC,CAC/D,MAAO,CACL,gBAAiB,GACjB,MAAM,EAAW,CACf,IAAM,EAAK,OAAO,GAAc,SAAW,SAAS,cAAc,EAAU,CAAI,EAEhF,MAAO,CAAE,QADO,KAAK,QAAQ,EAAI,KAAK,CACX,EAE7B,QAAQ,EAAc,EAAiC,CACrD,IAAM,EAAM,SAAS,cAAc,kBAAkB,CAGrD,OAFI,GAAa,EAAI,aAAa,eAAgB,EAAY,CAC9D,EAAO,aAAa,EAAK,EAAO,KACnB,EAAI,QAAQ,EAE5B,CAqBH,IAAa,EAAb,cAAqC,EAAA,YAAa,CAChD,OAEA,YAAY,EAA2B,CACrC,OAAO,CACP,KAAK,OAAS,EACd,KAAK,yBAAyB,CAOhC,eAAuB,EAAmB,EAA0C,CAClF,IAAM,EAAiC,EAAE,CACnC,EAAK,EAAU,MAAM,IAAI,CACzB,EAAK,EAAS,MAAM,IAAI,CAC9B,IAAK,IAAI,EAAI,EAAG,EAAI,EAAG,OAAQ,IACzB,EAAG,IAAI,WAAW,IAAI,GAAE,EAAO,EAAG,GAAG,MAAM,EAAE,EAAI,EAAG,IAAM,IAEhE,OAAO,EAGT,WAAmB,EAAsB,CAMvC,MALI,CAAC,GAAQ,IAAS,IAAY,gBAK3B,YAJO,EACX,QAAQ,aAAe,GAAM,IAAM,EAAE,QAAQ,MAAO,GAAG,CAAC,QAAQ,KAAM,GAAG,CAAC,CAC1E,QAAQ,MAAO,GAAG,CAClB,QAAQ,MAAO,IAAI,GAQxB,yBAAwC,CACtC,IAAM,EAAO,KACb,IAAK,IAAM,KAAS,KAAK,OAAQ,CAC/B,GAAI,EAAM,OAAS,IAAK,SAExB,IAAM,EAAM,KAAK,WAAW,EAAM,KAAK,CACnC,eAAe,IAAI,EAAI,EAE3B,eAAe,OAAO,EAAK,cAAc,WAAY,CACnD,QAA8C,KAE9C,mBAA0B,CAExB,GAAI,KAAK,QAAS,OAElB,KAAK,UAAU,IAAI,WAAW,CAG9B,IAAM,EAAK,GAAqB,CAChC,KAAK,iBAAiB,uBAA0B,EAAG,UAAU,OAAQ,GAAM,EAAI,EAAE,CAAC,CAClF,KAAK,iBAAiB,sBAA0B,EAAG,SAAS,OAAQ,GAAM,EAAI,EAAE,CAAC,CACjF,KAAK,iBAAiB,uBAA0B,EAAG,UAAU,OAAQ,GAAM,EAAI,EAAE,CAAC,CAClF,KAAK,iBAAiB,sBAA0B,EAAG,SAAS,OAAQ,GAAM,EAAI,EAAE,CAAC,CAGjF,IAAM,EAAS,EAAK,eAAe,EAAM,KAAM,SAAS,SAAS,CAG3D,EAAW,EAAM,UAAU,CAAE,KAAI,SAAQ,CAAC,CAEhD,GAAI,WAAY,GAAY,OAAQ,EAA0B,QAAW,WAAY,CACnF,IAAM,EAAO,EACb,EAAK,UAAU,CACf,IAAM,EAAgB,EAAK,QAAQ,CAAC,QAAQ,KAAM,KAAK,CACjD,EAAW,EAAK,WAAW,CAEjC,KAAK,QAAU,CACb,YAAe,CACb,EAAK,aAAa,CACd,OAAO,GAAa,YAAY,GAAU,CAC9C,GAAe,EAElB,MAGD,KAAK,QAAU,CAAE,QADM,EAAyB,QAAQ,KAAM,KAAK,CAC1B,CAI7C,sBAA6B,CAG3B,KAAK,SAAS,SAAS,CACvB,KAAK,QAAU,OAEjB,EAQN,QAA+B,CAC7B,IAAM,EAAO,KACb,MAAO,CACL,gBAAiB,GACjB,MAAM,EAA6B,CACjC,IAAM,EAAK,OAAO,GAAc,SAAW,SAAS,cAAc,EAAU,CAAI,EAEhF,MAAO,CAAE,QADO,KAAK,QAAQ,EAAI,KAAK,CACX,EAE7B,QAAQ,EAAc,EAAiC,CAGrD,IAAM,EAAW,SAAS,cAAc,aAAa,CACrD,EAAS,aAAa,WAAY,QAAQ,CAC1C,EAAS,UAAY,EAAK,OACvB,OAAQ,GAAM,EAAE,OAAS,IAAI,CAC7B,IAAK,GAAM,mBAAmB,EAAE,KAAK,eAAe,EAAK,WAAW,EAAE,KAAK,CAAC,gBAAgB,CAC5F,KAAK,GAAG,CAGX,IAAM,EAAW,SAAS,cAAc,oBAAoB,CAK5D,OAHA,EAAO,aAAa,EAAU,EAAO,CACrC,EAAO,aAAa,EAAU,EAAO,KAExB,CACX,EAAS,QAAQ,CACjB,EAAS,QAAQ,GAGtB"}
|
|
1
|
+
{"version":3,"file":"nix-ionic.cjs","names":[],"sources":["../../src/lifecycle.ts","../../src/setup.ts","../../src/IonRouterOutlet.ts"],"sourcesContent":["/**\n * ionic-nix/lifecycle.ts\n *\n * Sistema de ciclo de vida de navegación, análogo a los hooks de Ionic:\n * ionViewWillEnter / ionViewDidEnter / ionViewWillLeave / ionViewDidLeave\n *\n * Cómo funciona (sin provide/inject):\n * 1. IonRouterOutlet crea un `PageLifecycle` por cada ruta.\n * 2. Lo pasa directamente al factory de la ruta como argumento.\n * 3. El factory llama a `new MiPagina(lc)` o `MiPagina(lc)`.\n * 4. IonPage/composables registran watchers sobre las señales del lc.\n * 5. Cuando el router navega, incrementa las señales → watchers se disparan.\n */\n\nimport { signal, watch } from \"@deijose/nix-js\";\nimport type { Signal } from \"@deijose/nix-js\";\nimport { NixComponent } from \"@deijose/nix-js\";\n\n// --------------------------------------------------------------------------\n// Tipos públicos\n// --------------------------------------------------------------------------\n\nexport interface PageLifecycle {\n willEnter: Signal<number>;\n didEnter: Signal<number>;\n willLeave: Signal<number>;\n didLeave: Signal<number>;\n}\n\n/** Crea un nuevo PageLifecycle con señales en 0. */\nexport function createPageLifecycle(): PageLifecycle {\n return {\n willEnter: signal(0),\n didEnter: signal(0),\n willLeave: signal(0),\n didLeave: signal(0),\n };\n}\n\n// --------------------------------------------------------------------------\n// IonPage — clase base para páginas con hooks de navegación\n// --------------------------------------------------------------------------\n//\n// Uso:\n// class HomePage extends IonPage {\n// constructor(lc: PageLifecycle) { super(lc); }\n//\n// ionViewWillEnter() { /* fetch de datos frescos */ }\n// render() { return html`...`; }\n// }\n\nexport abstract class IonPage extends NixComponent {\n private __lc: PageLifecycle;\n\n constructor(lc: PageLifecycle) {\n super();\n this.__lc = lc;\n }\n\n override onInit(): void {\n const lc = this.__lc;\n // watch no corre en init (immediate: false), así que ionViewWillEnter\n // solo se llama cuando el outlet incrementa la señal, no al construir.\n if (this.ionViewWillEnter) watch(lc.willEnter, this.ionViewWillEnter.bind(this));\n if (this.ionViewDidEnter) watch(lc.didEnter, this.ionViewDidEnter.bind(this));\n if (this.ionViewWillLeave) watch(lc.willLeave, this.ionViewWillLeave.bind(this));\n if (this.ionViewDidLeave) watch(lc.didLeave, this.ionViewDidLeave.bind(this));\n }\n\n ionViewWillEnter?(): void;\n ionViewDidEnter?(): void;\n ionViewWillLeave?(): void;\n ionViewDidLeave?(): void;\n}\n\n// --------------------------------------------------------------------------\n// Composables para function components\n// --------------------------------------------------------------------------\n//\n// Uso:\n// function ProfilePage(lc: PageLifecycle): NixTemplate {\n// useIonViewWillEnter(lc, () => { /* fetch */ });\n// return html`...`;\n// }\n\nexport function useIonViewWillEnter(lc: PageLifecycle, fn: () => void): void {\n watch(lc.willEnter, fn);\n}\n\nexport function useIonViewDidEnter(lc: PageLifecycle, fn: () => void): void {\n watch(lc.didEnter, fn);\n}\n\nexport function useIonViewWillLeave(lc: PageLifecycle, fn: () => void): void {\n watch(lc.willLeave, fn);\n}\n\nexport function useIonViewDidLeave(lc: PageLifecycle, fn: () => void): void {\n watch(lc.didLeave, fn);\n}","import { initialize } from \"@ionic/core/components\";\nimport { defineCustomElement as defineIonRouter } from \"@ionic/core/components/ion-router.js\";\nimport { defineCustomElement as defineIonRoute } from \"@ionic/core/components/ion-route.js\";\nimport { defineCustomElement as defineIonRouterOutlet } from \"@ionic/core/components/ion-router-outlet.js\";\nimport { defineCustomElement as defineIonBackButton } from \"@ionic/core/components/ion-back-button.js\";\n\nlet isInitialized = false;\n\nexport function setupNixIonic(config: any = {}) {\n if (isInitialized) return;\n \n // 1. Inicializa el core de Ionic de forma segura\n initialize(config);\n \n // 2. Registra los Web Components vitales para el enrutamiento\n defineIonRouter();\n defineIonRoute();\n defineIonRouterOutlet();\n defineIonBackButton();\n \n isInitialized = true;\n}","/**\n * ionic-nix/IonRouterOutlet.ts\n *\n * Bridge 100% nativo. Genera exactamente el mismo DOM que Vanilla Ionic.\n * Delegamos el view-caching y los ciclos de vida a los Eventos del DOM de ion-router-outlet.\n */\n\nimport { NixComponent } from \"@deijose/nix-js\";\nimport type { NixTemplate } from \"@deijose/nix-js\";\nimport { createPageLifecycle, type PageLifecycle } from \"./lifecycle\";\nimport { Components } from \"@ionic/core\";\n\n// --------------------------------------------------------------------------\n// Router store singleton\n// --------------------------------------------------------------------------\n\nexport function useRouter() {\n const router = <Components.IonRouter>document.querySelector(\"ion-router\");\n return {\n navigate: (path: string) => {\n router?.push(path, \"forward\");\n },\n replace: (path: string) => {\n router?.push(path, \"root\");\n },\n back: () => {\n router?.back();\n }\n };\n}\n\n// --------------------------------------------------------------------------\n// IonBackButton (Sin listeners, 100% nativo)\n// --------------------------------------------------------------------------\n\nexport function IonBackButton(defaultHref?: string): NixTemplate {\n return {\n __isNixTemplate: true as const,\n mount(container) {\n const el = typeof container === \"string\" ? document.querySelector(container)! : container;\n const cleanup = this._render(el, null);\n return { unmount: cleanup };\n },\n _render(parent: Node, before: Node | null): () => void {\n const btn = document.createElement(\"ion-back-button\") as HTMLElement;\n if (defaultHref) btn.setAttribute(\"default-href\", defaultHref);\n parent.insertBefore(btn, before);\n return () => btn.remove();\n },\n };\n}\n\n// --------------------------------------------------------------------------\n// Tipos públicos\n// --------------------------------------------------------------------------\n\nexport interface PageContext {\n lc: PageLifecycle;\n params: Record<string, string>;\n}\n\nexport interface RouteDefinition {\n path: string;\n component: (ctx: PageContext) => NixComponent | NixTemplate;\n}\n\n// --------------------------------------------------------------------------\n// IonRouterOutlet (El Bridge Maestro)\n// --------------------------------------------------------------------------\n\nexport class IonRouterOutlet extends NixComponent {\n private routes: RouteDefinition[];\n\n constructor(routes: RouteDefinition[]) {\n super();\n this.routes = routes;\n this._registerCustomElements();\n }\n\n // -------------------------------------------------------------------------\n // Helpers\n // -------------------------------------------------------------------------\n\n private _extractParams(routePath: string, realPath: string): Record<string, string> {\n const params: Record<string, string> = {};\n const rP = routePath.split(\"/\");\n const uP = realPath.split(\"/\");\n for (let i = 0; i < rP.length; i++) {\n if (rP[i]?.startsWith(\":\")) params[rP[i].slice(1)] = uP[i] ?? \"\";\n }\n return params;\n }\n\n private _pathToTag(path: string): string {\n if (!path || path === \"/\") return \"nix-page-home\";\n const clean = path\n .replace(/\\/:?[^/]+/g, (m) => \"-\" + m.replace(/\\//g, \"\").replace(/:/g, \"\"))\n .replace(/^\\//, \"\")\n .replace(/\\//g, \"-\");\n return `nix-page-${clean}`;\n }\n\n // -------------------------------------------------------------------------\n // Registro de Custom Elements estilo Vanilla JS\n // -------------------------------------------------------------------------\n\n private _registerCustomElements(): void {\n const self = this;\n for (const route of this.routes) {\n if (route.path === \"*\") continue;\n\n const tag = this._pathToTag(route.path);\n if (customElements.get(tag)) continue;\n\n customElements.define(tag, class extends HTMLElement {\n private _handle: { unmount(): void } | null = null;\n\n connectedCallback(): void {\n // Prevenir doble montaje si Ionic reconecta el nodo\n if (this._handle) return; \n\n this.classList.add(\"ion-page\");\n\n // 1. Escuchar los eventos NATIVOS del DOM que dispara ion-router-outlet\n const lc = createPageLifecycle();\n this.addEventListener(\"ionViewWillEnter\", () => lc.willEnter.update((n) => n + 1));\n this.addEventListener(\"ionViewDidEnter\", () => lc.didEnter.update((n) => n + 1));\n this.addEventListener(\"ionViewWillLeave\", () => lc.willLeave.update((n) => n + 1));\n this.addEventListener(\"ionViewDidLeave\", () => lc.didLeave.update((n) => n + 1));\n\n // 2. Extraer parámetros\n const params = self._extractParams(route.path, location.pathname);\n\n // 3. Montar componente Nix\n const pageNode = route.component({ lc, params });\n\n if (\"render\" in pageNode && typeof (pageNode as NixComponent).render === \"function\") {\n const comp = pageNode as NixComponent;\n comp.onInit?.();\n const renderCleanup = comp.render()._render(this, null);\n const mountRet = comp.onMount?.();\n\n this._handle = {\n unmount: () => {\n comp.onUnmount?.();\n if (typeof mountRet === \"function\") mountRet();\n renderCleanup();\n }\n };\n } else {\n const renderCleanup = (pageNode as NixTemplate)._render(this, null);\n this._handle = { unmount: renderCleanup };\n }\n }\n\n disconnectedCallback(): void {\n // ion-router-outlet SOLO desconecta el elemento cuando lo saca \n // definitivamente de la caché (ej. al hacer click en el back-button)\n this._handle?.unmount();\n this._handle = null;\n }\n });\n }\n }\n\n // -------------------------------------------------------------------------\n // Render exacto al HTML que te funcionaba\n // -------------------------------------------------------------------------\n\n override render(): NixTemplate {\n const self = this;\n return {\n __isNixTemplate: true as const,\n mount(container: Element | string) {\n const el = typeof container === \"string\" ? document.querySelector(container)! : container;\n const cleanup = this._render(el, null);\n return { unmount: cleanup };\n },\n _render(parent: Node, before: Node | null): () => void {\n \n // Creamos <ion-router>\n const routerEl = document.createElement(\"ion-router\");\n routerEl.setAttribute(\"use-hash\", \"false\");\n routerEl.innerHTML = self.routes\n .filter((r) => r.path !== \"*\")\n .map((r) => `<ion-route url=\"${r.path}\" component=\"${self._pathToTag(r.path)}\"></ion-route>`)\n .join(\"\");\n\n // Creamos <ion-router-outlet> real\n const outletEl = document.createElement(\"ion-router-outlet\");\n\n parent.insertBefore(routerEl, before);\n parent.insertBefore(outletEl, before);\n\n return () => {\n routerEl.remove();\n outletEl.remove();\n };\n },\n };\n }\n}"],"mappings":"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"}
|
package/dist/lib/nix-ionic.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{NixComponent as e,signal as t,watch as n}from"@deijose/nix-js";function
|
|
1
|
+
import{NixComponent as e,signal as t,watch as n}from"@deijose/nix-js";import{initialize as r}from"@ionic/core/components";import{defineCustomElement as i}from"@ionic/core/components/ion-router.js";import{defineCustomElement as a}from"@ionic/core/components/ion-route.js";import{defineCustomElement as o}from"@ionic/core/components/ion-router-outlet.js";import{defineCustomElement as s}from"@ionic/core/components/ion-back-button.js";function c(){return{willEnter:t(0),didEnter:t(0),willLeave:t(0),didLeave:t(0)}}var l=class extends e{__lc;constructor(e){super(),this.__lc=e}onInit(){let e=this.__lc;this.ionViewWillEnter&&n(e.willEnter,this.ionViewWillEnter.bind(this)),this.ionViewDidEnter&&n(e.didEnter,this.ionViewDidEnter.bind(this)),this.ionViewWillLeave&&n(e.willLeave,this.ionViewWillLeave.bind(this)),this.ionViewDidLeave&&n(e.didLeave,this.ionViewDidLeave.bind(this))}};function u(e,t){n(e.willEnter,t)}function d(e,t){n(e.didEnter,t)}function f(e,t){n(e.willLeave,t)}function p(e,t){n(e.didLeave,t)}var m=!1;function h(e={}){m||=(r(e),i(),a(),o(),s(),!0)}function g(){let e=document.querySelector("ion-router");return{navigate:t=>{e?.push(t,"forward")},replace:t=>{e?.push(t,"root")},back:()=>{e?.back()}}}function _(e){return{__isNixTemplate:!0,mount(e){let t="string"==typeof e?document.querySelector(e):e;return{unmount:this._render(t,null)}},_render(t,n){let i=document.createElement("ion-back-button");return e&&i.setAttribute("default-href",e),t.insertBefore(i,n),()=>i.remove()}}}var v=class extends e{routes;constructor(e){super(),this.routes=e,this._registerCustomElements()}_extractParams(e,t){let n={},i=e.split("/"),o=t.split("/");for(let e=0;e<i.length;e++)i[e]?.startsWith(":")&&(n[i[e].slice(1)]=o[e]??"");return n}_pathToTag(e){return e&&"/"!==e?`nix-page-${e.replace(/\/:?[^/]+/g,e=>"-"+e.replace(/\//g,"").replace(/:/g,"")).replace(/^\//,"").replace(/\//g,"-")}`:"nix-page-home"}_registerCustomElements(){let e=this;for(let t of this.routes){if("*"===t.path)continue;let n=this._pathToTag(t.path);customElements.get(n)||customElements.define(n,class extends HTMLElement{_handle=null;connectedCallback(){if(this._handle)return;this.classList.add("ion-page");let n=c();this.addEventListener("ionViewWillEnter",()=>n.willEnter.update(e=>e+1)),this.addEventListener("ionViewDidEnter",()=>n.didEnter.update(e=>e+1)),this.addEventListener("ionViewWillLeave",()=>n.willLeave.update(e=>e+1)),this.addEventListener("ionViewDidLeave",()=>n.didLeave.update(e=>e+1));let i=e._extractParams(t.path,location.pathname),o=t.component({lc:n,params:i});if("render"in o&&"function"==typeof o.render){let e=o;e.onInit?.();let t=e.render()._render(this,null),n=e.onMount?.();this._handle={unmount:()=>{e.onUnmount?.(),"function"==typeof n&&n(),t()}}}else this._handle={unmount:o._render(this,null)}}disconnectedCallback(){this._handle?.unmount(),this._handle=null}})}}render(){let e=this;return{__isNixTemplate:!0,mount(e){let t="string"==typeof e?document.querySelector(e):e;return{unmount:this._render(t,null)}},_render(t,n){let i=document.createElement("ion-router");i.setAttribute("use-hash","false"),i.innerHTML=e.routes.filter(e=>"*"!==e.path).map(t=>`<ion-route url="${t.path}" component="${e._pathToTag(t.path)}"></ion-route>`).join("");let o=document.createElement("ion-router-outlet");return t.insertBefore(i,n),t.insertBefore(o,n),()=>{i.remove(),o.remove()}}}}};export{_ as IonBackButton,l as IonPage,v as IonRouterOutlet,c as createPageLifecycle,h as setupNixIonic,d as useIonViewDidEnter,p as useIonViewDidLeave,u as useIonViewWillEnter,f as useIonViewWillLeave,g as useRouter};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nix-ionic.js","names":[],"sources":["../../src/lifecycle.ts","../../src/IonRouterOutlet.ts"],"sourcesContent":["/**\n * ionic-nix/lifecycle.ts\n *\n * Sistema de ciclo de vida de navegación, análogo a los hooks de Ionic:\n * ionViewWillEnter / ionViewDidEnter / ionViewWillLeave / ionViewDidLeave\n *\n * Cómo funciona (sin provide/inject):\n * 1. IonRouterOutlet crea un `PageLifecycle` por cada ruta.\n * 2. Lo pasa directamente al factory de la ruta como argumento.\n * 3. El factory llama a `new MiPagina(lc)` o `MiPagina(lc)`.\n * 4. IonPage/composables registran watchers sobre las señales del lc.\n * 5. Cuando el router navega, incrementa las señales → watchers se disparan.\n */\n\nimport { signal, watch } from \"@deijose/nix-js\";\nimport type { Signal } from \"@deijose/nix-js\";\nimport { NixComponent } from \"@deijose/nix-js\";\n\n// --------------------------------------------------------------------------\n// Tipos públicos\n// --------------------------------------------------------------------------\n\nexport interface PageLifecycle {\n willEnter: Signal<number>;\n didEnter: Signal<number>;\n willLeave: Signal<number>;\n didLeave: Signal<number>;\n}\n\n/** Crea un nuevo PageLifecycle con señales en 0. */\nexport function createPageLifecycle(): PageLifecycle {\n return {\n willEnter: signal(0),\n didEnter: signal(0),\n willLeave: signal(0),\n didLeave: signal(0),\n };\n}\n\n// --------------------------------------------------------------------------\n// IonPage — clase base para páginas con hooks de navegación\n// --------------------------------------------------------------------------\n//\n// Uso:\n// class HomePage extends IonPage {\n// constructor(lc: PageLifecycle) { super(lc); }\n//\n// ionViewWillEnter() { /* fetch de datos frescos */ }\n// render() { return html`...`; }\n// }\n\nexport abstract class IonPage extends NixComponent {\n private __lc: PageLifecycle;\n\n constructor(lc: PageLifecycle) {\n super();\n this.__lc = lc;\n }\n\n override onInit(): void {\n const lc = this.__lc;\n // watch no corre en init (immediate: false), así que ionViewWillEnter\n // solo se llama cuando el outlet incrementa la señal, no al construir.\n if (this.ionViewWillEnter) watch(lc.willEnter, this.ionViewWillEnter.bind(this));\n if (this.ionViewDidEnter) watch(lc.didEnter, this.ionViewDidEnter.bind(this));\n if (this.ionViewWillLeave) watch(lc.willLeave, this.ionViewWillLeave.bind(this));\n if (this.ionViewDidLeave) watch(lc.didLeave, this.ionViewDidLeave.bind(this));\n }\n\n ionViewWillEnter?(): void;\n ionViewDidEnter?(): void;\n ionViewWillLeave?(): void;\n ionViewDidLeave?(): void;\n}\n\n// --------------------------------------------------------------------------\n// Composables para function components\n// --------------------------------------------------------------------------\n//\n// Uso:\n// function ProfilePage(lc: PageLifecycle): NixTemplate {\n// useIonViewWillEnter(lc, () => { /* fetch */ });\n// return html`...`;\n// }\n\nexport function useIonViewWillEnter(lc: PageLifecycle, fn: () => void): void {\n watch(lc.willEnter, fn);\n}\n\nexport function useIonViewDidEnter(lc: PageLifecycle, fn: () => void): void {\n watch(lc.didEnter, fn);\n}\n\nexport function useIonViewWillLeave(lc: PageLifecycle, fn: () => void): void {\n watch(lc.willLeave, fn);\n}\n\nexport function useIonViewDidLeave(lc: PageLifecycle, fn: () => void): void {\n watch(lc.didLeave, fn);\n}","/**\n * ionic-nix/IonRouterOutlet.ts\n *\n * Bridge 100% nativo. Genera exactamente el mismo DOM que Vanilla Ionic.\n * Delegamos el view-caching y los ciclos de vida a los Eventos del DOM de ion-router-outlet.\n */\n\nimport { NixComponent } from \"@deijose/nix-js\";\nimport type { NixTemplate } from \"@deijose/nix-js\";\nimport { createPageLifecycle, type PageLifecycle } from \"./lifecycle\";\nimport { Components } from \"@ionic/core\";\n\n// --------------------------------------------------------------------------\n// Router store singleton\n// --------------------------------------------------------------------------\n\nexport function useRouter() {\n const router = <Components.IonRouter>document.querySelector(\"ion-router\");\n return {\n navigate: (path: string) => {\n router?.push(path, \"forward\");\n },\n replace: (path: string) => {\n router?.push(path, \"root\");\n },\n back: () => {\n router?.back();\n }\n };\n}\n\n// --------------------------------------------------------------------------\n// IonBackButton (Sin listeners, 100% nativo)\n// --------------------------------------------------------------------------\n\nexport function IonBackButton(defaultHref?: string): NixTemplate {\n return {\n __isNixTemplate: true as const,\n mount(container) {\n const el = typeof container === \"string\" ? document.querySelector(container)! : container;\n const cleanup = this._render(el, null);\n return { unmount: cleanup };\n },\n _render(parent: Node, before: Node | null): () => void {\n const btn = document.createElement(\"ion-back-button\") as HTMLElement;\n if (defaultHref) btn.setAttribute(\"default-href\", defaultHref);\n parent.insertBefore(btn, before);\n return () => btn.remove();\n },\n };\n}\n\n// --------------------------------------------------------------------------\n// Tipos públicos\n// --------------------------------------------------------------------------\n\nexport interface PageContext {\n lc: PageLifecycle;\n params: Record<string, string>;\n}\n\nexport interface RouteDefinition {\n path: string;\n component: (ctx: PageContext) => NixComponent | NixTemplate;\n}\n\n// --------------------------------------------------------------------------\n// IonRouterOutlet (El Bridge Maestro)\n// --------------------------------------------------------------------------\n\nexport class IonRouterOutlet extends NixComponent {\n private routes: RouteDefinition[];\n\n constructor(routes: RouteDefinition[]) {\n super();\n this.routes = routes;\n this._registerCustomElements();\n }\n\n // -------------------------------------------------------------------------\n // Helpers\n // -------------------------------------------------------------------------\n\n private _extractParams(routePath: string, realPath: string): Record<string, string> {\n const params: Record<string, string> = {};\n const rP = routePath.split(\"/\");\n const uP = realPath.split(\"/\");\n for (let i = 0; i < rP.length; i++) {\n if (rP[i]?.startsWith(\":\")) params[rP[i].slice(1)] = uP[i] ?? \"\";\n }\n return params;\n }\n\n private _pathToTag(path: string): string {\n if (!path || path === \"/\") return \"nix-page-home\";\n const clean = path\n .replace(/\\/:?[^/]+/g, (m) => \"-\" + m.replace(/\\//g, \"\").replace(/:/g, \"\"))\n .replace(/^\\//, \"\")\n .replace(/\\//g, \"-\");\n return `nix-page-${clean}`;\n }\n\n // -------------------------------------------------------------------------\n // Registro de Custom Elements estilo Vanilla JS\n // -------------------------------------------------------------------------\n\n private _registerCustomElements(): void {\n const self = this;\n for (const route of this.routes) {\n if (route.path === \"*\") continue;\n\n const tag = this._pathToTag(route.path);\n if (customElements.get(tag)) continue;\n\n customElements.define(tag, class extends HTMLElement {\n private _handle: { unmount(): void } | null = null;\n\n connectedCallback(): void {\n // Prevenir doble montaje si Ionic reconecta el nodo\n if (this._handle) return; \n\n this.classList.add(\"ion-page\");\n\n // 1. Escuchar los eventos NATIVOS del DOM que dispara ion-router-outlet\n const lc = createPageLifecycle();\n this.addEventListener(\"ionViewWillEnter\", () => lc.willEnter.update((n) => n + 1));\n this.addEventListener(\"ionViewDidEnter\", () => lc.didEnter.update((n) => n + 1));\n this.addEventListener(\"ionViewWillLeave\", () => lc.willLeave.update((n) => n + 1));\n this.addEventListener(\"ionViewDidLeave\", () => lc.didLeave.update((n) => n + 1));\n\n // 2. Extraer parámetros\n const params = self._extractParams(route.path, location.pathname);\n\n // 3. Montar componente Nix\n const pageNode = route.component({ lc, params });\n\n if (\"render\" in pageNode && typeof (pageNode as NixComponent).render === \"function\") {\n const comp = pageNode as NixComponent;\n comp.onInit?.();\n const renderCleanup = comp.render()._render(this, null);\n const mountRet = comp.onMount?.();\n\n this._handle = {\n unmount: () => {\n comp.onUnmount?.();\n if (typeof mountRet === \"function\") mountRet();\n renderCleanup();\n }\n };\n } else {\n const renderCleanup = (pageNode as NixTemplate)._render(this, null);\n this._handle = { unmount: renderCleanup };\n }\n }\n\n disconnectedCallback(): void {\n // ion-router-outlet SOLO desconecta el elemento cuando lo saca \n // definitivamente de la caché (ej. al hacer click en el back-button)\n this._handle?.unmount();\n this._handle = null;\n }\n });\n }\n }\n\n // -------------------------------------------------------------------------\n // Render exacto al HTML que te funcionaba\n // -------------------------------------------------------------------------\n\n override render(): NixTemplate {\n const self = this;\n return {\n __isNixTemplate: true as const,\n mount(container: Element | string) {\n const el = typeof container === \"string\" ? document.querySelector(container)! : container;\n const cleanup = this._render(el, null);\n return { unmount: cleanup };\n },\n _render(parent: Node, before: Node | null): () => void {\n \n // Creamos <ion-router>\n const routerEl = document.createElement(\"ion-router\");\n routerEl.setAttribute(\"use-hash\", \"false\");\n routerEl.innerHTML = self.routes\n .filter((r) => r.path !== \"*\")\n .map((r) => `<ion-route url=\"${r.path}\" component=\"${self._pathToTag(r.path)}\"></ion-route>`)\n .join(\"\");\n\n // Creamos <ion-router-outlet> real\n const outletEl = document.createElement(\"ion-router-outlet\");\n\n parent.insertBefore(routerEl, before);\n parent.insertBefore(outletEl, before);\n\n return () => {\n routerEl.remove();\n outletEl.remove();\n };\n },\n };\n }\n}"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"nix-ionic.js","names":[],"sources":["../../src/lifecycle.ts","../../src/setup.ts","../../src/IonRouterOutlet.ts"],"sourcesContent":["/**\n * ionic-nix/lifecycle.ts\n *\n * Sistema de ciclo de vida de navegación, análogo a los hooks de Ionic:\n * ionViewWillEnter / ionViewDidEnter / ionViewWillLeave / ionViewDidLeave\n *\n * Cómo funciona (sin provide/inject):\n * 1. IonRouterOutlet crea un `PageLifecycle` por cada ruta.\n * 2. Lo pasa directamente al factory de la ruta como argumento.\n * 3. El factory llama a `new MiPagina(lc)` o `MiPagina(lc)`.\n * 4. IonPage/composables registran watchers sobre las señales del lc.\n * 5. Cuando el router navega, incrementa las señales → watchers se disparan.\n */\n\nimport { signal, watch } from \"@deijose/nix-js\";\nimport type { Signal } from \"@deijose/nix-js\";\nimport { NixComponent } from \"@deijose/nix-js\";\n\n// --------------------------------------------------------------------------\n// Tipos públicos\n// --------------------------------------------------------------------------\n\nexport interface PageLifecycle {\n willEnter: Signal<number>;\n didEnter: Signal<number>;\n willLeave: Signal<number>;\n didLeave: Signal<number>;\n}\n\n/** Crea un nuevo PageLifecycle con señales en 0. */\nexport function createPageLifecycle(): PageLifecycle {\n return {\n willEnter: signal(0),\n didEnter: signal(0),\n willLeave: signal(0),\n didLeave: signal(0),\n };\n}\n\n// --------------------------------------------------------------------------\n// IonPage — clase base para páginas con hooks de navegación\n// --------------------------------------------------------------------------\n//\n// Uso:\n// class HomePage extends IonPage {\n// constructor(lc: PageLifecycle) { super(lc); }\n//\n// ionViewWillEnter() { /* fetch de datos frescos */ }\n// render() { return html`...`; }\n// }\n\nexport abstract class IonPage extends NixComponent {\n private __lc: PageLifecycle;\n\n constructor(lc: PageLifecycle) {\n super();\n this.__lc = lc;\n }\n\n override onInit(): void {\n const lc = this.__lc;\n // watch no corre en init (immediate: false), así que ionViewWillEnter\n // solo se llama cuando el outlet incrementa la señal, no al construir.\n if (this.ionViewWillEnter) watch(lc.willEnter, this.ionViewWillEnter.bind(this));\n if (this.ionViewDidEnter) watch(lc.didEnter, this.ionViewDidEnter.bind(this));\n if (this.ionViewWillLeave) watch(lc.willLeave, this.ionViewWillLeave.bind(this));\n if (this.ionViewDidLeave) watch(lc.didLeave, this.ionViewDidLeave.bind(this));\n }\n\n ionViewWillEnter?(): void;\n ionViewDidEnter?(): void;\n ionViewWillLeave?(): void;\n ionViewDidLeave?(): void;\n}\n\n// --------------------------------------------------------------------------\n// Composables para function components\n// --------------------------------------------------------------------------\n//\n// Uso:\n// function ProfilePage(lc: PageLifecycle): NixTemplate {\n// useIonViewWillEnter(lc, () => { /* fetch */ });\n// return html`...`;\n// }\n\nexport function useIonViewWillEnter(lc: PageLifecycle, fn: () => void): void {\n watch(lc.willEnter, fn);\n}\n\nexport function useIonViewDidEnter(lc: PageLifecycle, fn: () => void): void {\n watch(lc.didEnter, fn);\n}\n\nexport function useIonViewWillLeave(lc: PageLifecycle, fn: () => void): void {\n watch(lc.willLeave, fn);\n}\n\nexport function useIonViewDidLeave(lc: PageLifecycle, fn: () => void): void {\n watch(lc.didLeave, fn);\n}","import { initialize } from \"@ionic/core/components\";\nimport { defineCustomElement as defineIonRouter } from \"@ionic/core/components/ion-router.js\";\nimport { defineCustomElement as defineIonRoute } from \"@ionic/core/components/ion-route.js\";\nimport { defineCustomElement as defineIonRouterOutlet } from \"@ionic/core/components/ion-router-outlet.js\";\nimport { defineCustomElement as defineIonBackButton } from \"@ionic/core/components/ion-back-button.js\";\n\nlet isInitialized = false;\n\nexport function setupNixIonic(config: any = {}) {\n if (isInitialized) return;\n \n // 1. Inicializa el core de Ionic de forma segura\n initialize(config);\n \n // 2. Registra los Web Components vitales para el enrutamiento\n defineIonRouter();\n defineIonRoute();\n defineIonRouterOutlet();\n defineIonBackButton();\n \n isInitialized = true;\n}","/**\n * ionic-nix/IonRouterOutlet.ts\n *\n * Bridge 100% nativo. Genera exactamente el mismo DOM que Vanilla Ionic.\n * Delegamos el view-caching y los ciclos de vida a los Eventos del DOM de ion-router-outlet.\n */\n\nimport { NixComponent } from \"@deijose/nix-js\";\nimport type { NixTemplate } from \"@deijose/nix-js\";\nimport { createPageLifecycle, type PageLifecycle } from \"./lifecycle\";\nimport { Components } from \"@ionic/core\";\n\n// --------------------------------------------------------------------------\n// Router store singleton\n// --------------------------------------------------------------------------\n\nexport function useRouter() {\n const router = <Components.IonRouter>document.querySelector(\"ion-router\");\n return {\n navigate: (path: string) => {\n router?.push(path, \"forward\");\n },\n replace: (path: string) => {\n router?.push(path, \"root\");\n },\n back: () => {\n router?.back();\n }\n };\n}\n\n// --------------------------------------------------------------------------\n// IonBackButton (Sin listeners, 100% nativo)\n// --------------------------------------------------------------------------\n\nexport function IonBackButton(defaultHref?: string): NixTemplate {\n return {\n __isNixTemplate: true as const,\n mount(container) {\n const el = typeof container === \"string\" ? document.querySelector(container)! : container;\n const cleanup = this._render(el, null);\n return { unmount: cleanup };\n },\n _render(parent: Node, before: Node | null): () => void {\n const btn = document.createElement(\"ion-back-button\") as HTMLElement;\n if (defaultHref) btn.setAttribute(\"default-href\", defaultHref);\n parent.insertBefore(btn, before);\n return () => btn.remove();\n },\n };\n}\n\n// --------------------------------------------------------------------------\n// Tipos públicos\n// --------------------------------------------------------------------------\n\nexport interface PageContext {\n lc: PageLifecycle;\n params: Record<string, string>;\n}\n\nexport interface RouteDefinition {\n path: string;\n component: (ctx: PageContext) => NixComponent | NixTemplate;\n}\n\n// --------------------------------------------------------------------------\n// IonRouterOutlet (El Bridge Maestro)\n// --------------------------------------------------------------------------\n\nexport class IonRouterOutlet extends NixComponent {\n private routes: RouteDefinition[];\n\n constructor(routes: RouteDefinition[]) {\n super();\n this.routes = routes;\n this._registerCustomElements();\n }\n\n // -------------------------------------------------------------------------\n // Helpers\n // -------------------------------------------------------------------------\n\n private _extractParams(routePath: string, realPath: string): Record<string, string> {\n const params: Record<string, string> = {};\n const rP = routePath.split(\"/\");\n const uP = realPath.split(\"/\");\n for (let i = 0; i < rP.length; i++) {\n if (rP[i]?.startsWith(\":\")) params[rP[i].slice(1)] = uP[i] ?? \"\";\n }\n return params;\n }\n\n private _pathToTag(path: string): string {\n if (!path || path === \"/\") return \"nix-page-home\";\n const clean = path\n .replace(/\\/:?[^/]+/g, (m) => \"-\" + m.replace(/\\//g, \"\").replace(/:/g, \"\"))\n .replace(/^\\//, \"\")\n .replace(/\\//g, \"-\");\n return `nix-page-${clean}`;\n }\n\n // -------------------------------------------------------------------------\n // Registro de Custom Elements estilo Vanilla JS\n // -------------------------------------------------------------------------\n\n private _registerCustomElements(): void {\n const self = this;\n for (const route of this.routes) {\n if (route.path === \"*\") continue;\n\n const tag = this._pathToTag(route.path);\n if (customElements.get(tag)) continue;\n\n customElements.define(tag, class extends HTMLElement {\n private _handle: { unmount(): void } | null = null;\n\n connectedCallback(): void {\n // Prevenir doble montaje si Ionic reconecta el nodo\n if (this._handle) return; \n\n this.classList.add(\"ion-page\");\n\n // 1. Escuchar los eventos NATIVOS del DOM que dispara ion-router-outlet\n const lc = createPageLifecycle();\n this.addEventListener(\"ionViewWillEnter\", () => lc.willEnter.update((n) => n + 1));\n this.addEventListener(\"ionViewDidEnter\", () => lc.didEnter.update((n) => n + 1));\n this.addEventListener(\"ionViewWillLeave\", () => lc.willLeave.update((n) => n + 1));\n this.addEventListener(\"ionViewDidLeave\", () => lc.didLeave.update((n) => n + 1));\n\n // 2. Extraer parámetros\n const params = self._extractParams(route.path, location.pathname);\n\n // 3. Montar componente Nix\n const pageNode = route.component({ lc, params });\n\n if (\"render\" in pageNode && typeof (pageNode as NixComponent).render === \"function\") {\n const comp = pageNode as NixComponent;\n comp.onInit?.();\n const renderCleanup = comp.render()._render(this, null);\n const mountRet = comp.onMount?.();\n\n this._handle = {\n unmount: () => {\n comp.onUnmount?.();\n if (typeof mountRet === \"function\") mountRet();\n renderCleanup();\n }\n };\n } else {\n const renderCleanup = (pageNode as NixTemplate)._render(this, null);\n this._handle = { unmount: renderCleanup };\n }\n }\n\n disconnectedCallback(): void {\n // ion-router-outlet SOLO desconecta el elemento cuando lo saca \n // definitivamente de la caché (ej. al hacer click en el back-button)\n this._handle?.unmount();\n this._handle = null;\n }\n });\n }\n }\n\n // -------------------------------------------------------------------------\n // Render exacto al HTML que te funcionaba\n // -------------------------------------------------------------------------\n\n override render(): NixTemplate {\n const self = this;\n return {\n __isNixTemplate: true as const,\n mount(container: Element | string) {\n const el = typeof container === \"string\" ? document.querySelector(container)! : container;\n const cleanup = this._render(el, null);\n return { unmount: cleanup };\n },\n _render(parent: Node, before: Node | null): () => void {\n \n // Creamos <ion-router>\n const routerEl = document.createElement(\"ion-router\");\n routerEl.setAttribute(\"use-hash\", \"false\");\n routerEl.innerHTML = self.routes\n .filter((r) => r.path !== \"*\")\n .map((r) => `<ion-route url=\"${r.path}\" component=\"${self._pathToTag(r.path)}\"></ion-route>`)\n .join(\"\");\n\n // Creamos <ion-router-outlet> real\n const outletEl = document.createElement(\"ion-router-outlet\");\n\n parent.insertBefore(routerEl, before);\n parent.insertBefore(outletEl, before);\n\n return () => {\n routerEl.remove();\n outletEl.remove();\n };\n },\n };\n }\n}"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function setupNixIonic(config?: any): void;
|