@deijose/nix-js 0.1.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 +1024 -0
- package/dist/lib/index.d.ts +2 -0
- package/dist/lib/nix/async.d.ts +69 -0
- package/dist/lib/nix/component.d.ts +13 -0
- package/dist/lib/nix/context.d.ts +61 -0
- package/dist/lib/nix/index.d.ts +14 -0
- package/dist/lib/nix/lifecycle.d.ts +70 -0
- package/dist/lib/nix/reactivity.d.ts +116 -0
- package/dist/lib/nix/router.d.ts +115 -0
- package/dist/lib/nix/store.d.ts +40 -0
- package/dist/lib/nix/template.d.ts +62 -0
- package/dist/lib/nix-js.cjs +22 -0
- package/dist/lib/nix-js.js +764 -0
- package/package.json +62 -0
- package/src/index.ts +61 -0
- package/src/nix/async.ts +164 -0
- package/src/nix/component.ts +76 -0
- package/src/nix/context.ts +142 -0
- package/src/nix/index.ts +14 -0
- package/src/nix/lifecycle.ts +112 -0
- package/src/nix/reactivity.ts +308 -0
- package/src/nix/router.ts +393 -0
- package/src/nix/store.ts +117 -0
- package/src/nix/template.ts +793 -0
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { Signal, signal, effect, computed, batch, watch, untrack, nextTick, html, repeat, ref, mount, NixComponent, createStore, createRouter, RouterView, Link, useRouter, suspend, lazy, provide, inject, createInjectionKey, } from "./nix";
|
|
2
|
+
export type { WatchOptions, NixTemplate, NixMountHandle, KeyedList, NixRef, Store, StoreSignals, Router, RouteRecord, SuspenseOptions, InjectionKey, } from "./nix";
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { NixComponent } from "./lifecycle";
|
|
2
|
+
import type { NixTemplate } from "./template";
|
|
3
|
+
export interface SuspenseOptions {
|
|
4
|
+
/**
|
|
5
|
+
* Template a mostrar mientras la promesa está pendiente.
|
|
6
|
+
* Por defecto: spinner de puntos animados.
|
|
7
|
+
*/
|
|
8
|
+
fallback?: NixTemplate;
|
|
9
|
+
/**
|
|
10
|
+
* Factory que recibe el error y devuelve el template de error.
|
|
11
|
+
* Por defecto: mensaje de error en rojo.
|
|
12
|
+
*/
|
|
13
|
+
errorFallback?: (err: unknown) => NixTemplate;
|
|
14
|
+
/**
|
|
15
|
+
* Si `true`, mantiene el fallback visible mientras `asyncFn` vuelve a
|
|
16
|
+
* ejecutarse tras un cambio reactivo. Si `false` (por defecto), durante
|
|
17
|
+
* las recargas se sigue mostrando el contenido anterior hasta que la nueva
|
|
18
|
+
* promesa se resuelva.
|
|
19
|
+
*/
|
|
20
|
+
resetOnRefresh?: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Ejecuta una función async y renderiza según su estado (pending / resolved /
|
|
24
|
+
* error). Equivale al patrón <Suspense> de otros frameworks.
|
|
25
|
+
*
|
|
26
|
+
* @param asyncFn Función que devuelve una promesa con los datos.
|
|
27
|
+
* @param renderFn Recibe los datos resueltos y devuelve el template/componente.
|
|
28
|
+
* @param options `fallback`, `errorFallback`, `resetOnRefresh`.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* // Uso simple con fallback por defecto
|
|
32
|
+
* const userView = suspend(
|
|
33
|
+
* () => fetchUser(userId.value),
|
|
34
|
+
* user => html`<div>${user.name}</div>`
|
|
35
|
+
* );
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* // Con fallback personalizado y manejo de error
|
|
39
|
+
* suspend(
|
|
40
|
+
* () => api.getItems(),
|
|
41
|
+
* items => html`<ul>${items.map(i => html`<li>${i}</li>`)}</ul>`,
|
|
42
|
+
* {
|
|
43
|
+
* fallback: html`<span>Cargando items…</span>`,
|
|
44
|
+
* errorFallback: err => html`<p style="color:red">Error: ${String(err)}</p>`,
|
|
45
|
+
* }
|
|
46
|
+
* )
|
|
47
|
+
*/
|
|
48
|
+
export declare function suspend<T>(asyncFn: () => Promise<T>, renderFn: (data: T) => NixTemplate | NixComponent, options?: SuspenseOptions): NixComponent;
|
|
49
|
+
/**
|
|
50
|
+
* Envuelve un import dinámico para lazy loading de componentes de ruta.
|
|
51
|
+
* El módulo se carga una sola vez (cacheado) y mientras tanto muestra el
|
|
52
|
+
* fallback. Compatible directamente con el campo `component` de `RouteRecord`.
|
|
53
|
+
*
|
|
54
|
+
* El módulo importado debe exportar el componente como **export default**.
|
|
55
|
+
*
|
|
56
|
+
* @param importFn Función que hace el import dinámico.
|
|
57
|
+
* @param fallback Template opcional mientras se descarga el chunk.
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* createRouter([
|
|
61
|
+
* { path: "/", component: lazy(() => import("./pages/Home")) },
|
|
62
|
+
* { path: "/about", component: lazy(() => import("./pages/About")) },
|
|
63
|
+
* { path: "/admin", component: lazy(() => import("./pages/Admin"),
|
|
64
|
+
* html`<p>Cargando panel…</p>`) },
|
|
65
|
+
* ])
|
|
66
|
+
*/
|
|
67
|
+
export declare function lazy(importFn: () => Promise<{
|
|
68
|
+
default: new () => NixComponent;
|
|
69
|
+
}>, fallback?: NixTemplate): () => NixComponent;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { NixTemplate, NixMountHandle } from "./template";
|
|
2
|
+
import { type NixComponent } from "./lifecycle";
|
|
3
|
+
/**
|
|
4
|
+
* Monta un NixTemplate o NixComponent en el DOM.
|
|
5
|
+
*
|
|
6
|
+
* mount(App(), "#app"); // NixTemplate (función componente)
|
|
7
|
+
* mount(new Timer(), "#app"); // NixComponent (clase con lifecycle)
|
|
8
|
+
*
|
|
9
|
+
* @param component NixTemplate (resultado de html``) o instancia de NixComponent.
|
|
10
|
+
* @param container Selector CSS o HTMLElement donde se insertará.
|
|
11
|
+
* @returns { unmount() } para limpiar effects y remover el DOM.
|
|
12
|
+
*/
|
|
13
|
+
export declare function mount(component: NixTemplate | NixComponent, container: Element | string): NixMountHandle;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clave tipada para provide/inject.
|
|
3
|
+
* El parámetro genérico T garantiza coherencia entre proveedor y consumidor.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* const THEME_KEY = createInjectionKey<Signal<string>>("theme");
|
|
7
|
+
*/
|
|
8
|
+
export type InjectionKey<T> = symbol & {
|
|
9
|
+
readonly __nixType?: T;
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* Crea una InjectionKey única y tipada.
|
|
13
|
+
* Cada llamada produce un símbolo distinto, evitando colisiones.
|
|
14
|
+
*
|
|
15
|
+
* @param description Nombre descriptivo (aparece en Symbol.toString())
|
|
16
|
+
*/
|
|
17
|
+
export declare function createInjectionKey<T>(description?: string): InjectionKey<T>;
|
|
18
|
+
/** @internal — devuelve copia del stack (para capturar en closures de efectos). */
|
|
19
|
+
export declare function _captureContextSnapshot(): Map<unknown, unknown>[];
|
|
20
|
+
/** @internal — push de un contexto vacío para un nuevo componente (render estático). */
|
|
21
|
+
export declare function _pushComponentContext(): void;
|
|
22
|
+
/** @internal — pop del contexto del componente actual (render estático). */
|
|
23
|
+
export declare function _popComponentContext(): void;
|
|
24
|
+
/**
|
|
25
|
+
* @internal — ejecuta `fn` con `parentSnapshot` como ancestros y un nuevo
|
|
26
|
+
* contexto vacío en el tope, luego restaura el stack previo.
|
|
27
|
+
*
|
|
28
|
+
* Usado por efectos reactivos que pueden re-ejecutarse fuera del árbol de
|
|
29
|
+
* rendering original (p.ej. NixComponents dentro de `() => new MyComp()`).
|
|
30
|
+
*/
|
|
31
|
+
export declare function _withComponentContext<T>(parentSnapshot: Map<unknown, unknown>[], fn: () => T): T;
|
|
32
|
+
/**
|
|
33
|
+
* Registra un valor para que los componentes descendientes puedan obtenerlo
|
|
34
|
+
* con `inject()`.
|
|
35
|
+
*
|
|
36
|
+
* Debe llamarse en `onInit()` o en el constructor de un `NixComponent`.
|
|
37
|
+
* Si se llama fuera del contexto de render de un componente, lanza un error.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* class ThemeProvider extends NixComponent {
|
|
41
|
+
* theme = signal("dark");
|
|
42
|
+
* onInit() { provide(THEME_KEY, this.theme); } // ← aquí
|
|
43
|
+
* render() { return html`${new ThemedButton()}`; }
|
|
44
|
+
* }
|
|
45
|
+
*/
|
|
46
|
+
export declare function provide<T>(key: InjectionKey<T> | string | symbol, value: T): void;
|
|
47
|
+
/**
|
|
48
|
+
* Obtiene un valor provisto por un componente ancestro.
|
|
49
|
+
* Busca de hijo a padre; retorna `undefined` si la clave no fue provista.
|
|
50
|
+
*
|
|
51
|
+
* Úsalo como propiedad de clase o dentro de `onInit()`.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* class ThemedButton extends NixComponent {
|
|
55
|
+
* theme = inject(THEME_KEY); // Signal<string> | undefined
|
|
56
|
+
* render() {
|
|
57
|
+
* return html`<button class=${() => this.theme?.value ?? "light"}>OK</button>`;
|
|
58
|
+
* }
|
|
59
|
+
* }
|
|
60
|
+
*/
|
|
61
|
+
export declare function inject<T>(key: InjectionKey<T> | string | symbol): T | undefined;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { Signal, signal, effect, computed, batch, watch, untrack, nextTick } from "./reactivity";
|
|
2
|
+
export type { WatchOptions } from "./reactivity";
|
|
3
|
+
export { html, repeat, ref } from "./template";
|
|
4
|
+
export type { NixTemplate, NixMountHandle, KeyedList, NixRef } from "./template";
|
|
5
|
+
export { mount } from "./component";
|
|
6
|
+
export { NixComponent } from "./lifecycle";
|
|
7
|
+
export { createStore } from "./store";
|
|
8
|
+
export type { Store, StoreSignals } from "./store";
|
|
9
|
+
export { createRouter, RouterView, Link, useRouter } from "./router";
|
|
10
|
+
export type { Router, RouteRecord } from "./router";
|
|
11
|
+
export { suspend, lazy } from "./async";
|
|
12
|
+
export type { SuspenseOptions } from "./async";
|
|
13
|
+
export { provide, inject, createInjectionKey } from "./context";
|
|
14
|
+
export type { InjectionKey } from "./context";
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { NixTemplate } from "./template";
|
|
2
|
+
/**
|
|
3
|
+
* Clase base para componentes con lifecycle.
|
|
4
|
+
*
|
|
5
|
+
* Implementa `render()` y haz override de los hooks que necesites.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* class Timer extends NixComponent {
|
|
9
|
+
* ticks = signal(0);
|
|
10
|
+
*
|
|
11
|
+
* onMount() {
|
|
12
|
+
* const id = setInterval(() => this.ticks.update(n => n + 1), 1000);
|
|
13
|
+
* return () => clearInterval(id); // cleanup automático al desmontar
|
|
14
|
+
* }
|
|
15
|
+
*
|
|
16
|
+
* render() {
|
|
17
|
+
* return html`<span>${() => this.ticks.value}s</span>`;
|
|
18
|
+
* }
|
|
19
|
+
* }
|
|
20
|
+
*
|
|
21
|
+
* mount(new Timer(), "#app");
|
|
22
|
+
*/
|
|
23
|
+
export declare abstract class NixComponent {
|
|
24
|
+
/** @internal – marca que identifica instancias NixComponent en el engine. */
|
|
25
|
+
readonly __isNixComponent: true;
|
|
26
|
+
/**
|
|
27
|
+
* Debe implementarse: retorna el template del componente.
|
|
28
|
+
* Se llama UNA sola vez al montar — las actualizaciones ocurren por signals.
|
|
29
|
+
*/
|
|
30
|
+
abstract render(): NixTemplate;
|
|
31
|
+
/**
|
|
32
|
+
* Llamado ANTES de `render()` — sin DOM todavía.
|
|
33
|
+
* Útil para inicializar estado complejo derivado de props u otras
|
|
34
|
+
* operaciones síncronas que render() necesita.
|
|
35
|
+
*
|
|
36
|
+
* Los errores aquí son capturados por `onError` si está implementado.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* onInit() {
|
|
40
|
+
* this.derived = computed(() => this.base.value * 2);
|
|
41
|
+
* }
|
|
42
|
+
*/
|
|
43
|
+
onInit?(): void;
|
|
44
|
+
/**
|
|
45
|
+
* Llamado DESPUÉS de que el componente se inserta en el DOM.
|
|
46
|
+
* Si retorna una función, se usa como cleanup automático al desmontar.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* onMount() {
|
|
50
|
+
* const id = setInterval(() => this.count.update(n => n + 1), 1000);
|
|
51
|
+
* return () => clearInterval(id);
|
|
52
|
+
* }
|
|
53
|
+
*/
|
|
54
|
+
onMount?(): (() => void) | void;
|
|
55
|
+
/**
|
|
56
|
+
* Llamado ANTES de remover el componente del DOM.
|
|
57
|
+
* Se ejecuta siempre al desmontar, incluso si no se definió onMount.
|
|
58
|
+
*/
|
|
59
|
+
onUnmount?(): void;
|
|
60
|
+
/**
|
|
61
|
+
* Captura errores lanzados dentro de `onMount`.
|
|
62
|
+
* Si se implementa, el error queda absorbido y el componente permanece montado.
|
|
63
|
+
* Si no se implementa, el error se re-lanza.
|
|
64
|
+
*/
|
|
65
|
+
onError?(err: unknown): void;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* @internal – Verifica si un valor es una instancia de NixComponent.
|
|
69
|
+
*/
|
|
70
|
+
export declare function isNixComponent(v: unknown): v is NixComponent;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
export declare class Signal<T> {
|
|
2
|
+
private _value;
|
|
3
|
+
private _subs;
|
|
4
|
+
constructor(initialValue: T);
|
|
5
|
+
/**
|
|
6
|
+
* Leer el valor.
|
|
7
|
+
* Si hay un effect activo, se suscribe automáticamente.
|
|
8
|
+
*/
|
|
9
|
+
get value(): T;
|
|
10
|
+
/**
|
|
11
|
+
* Escribir un nuevo valor.
|
|
12
|
+
* Si es diferente al actual, notifica a todos los effects suscritos.
|
|
13
|
+
*/
|
|
14
|
+
set value(newValue: T);
|
|
15
|
+
/**
|
|
16
|
+
* Modificar el valor con una función.
|
|
17
|
+
* count.update(n => n + 1)
|
|
18
|
+
*/
|
|
19
|
+
update(fn: (current: T) => T): void;
|
|
20
|
+
/**
|
|
21
|
+
* Leer SIN suscribirse.
|
|
22
|
+
* Útil cuando necesitas el valor pero no quieres
|
|
23
|
+
* que el effect se re-ejecute si cambia.
|
|
24
|
+
*/
|
|
25
|
+
peek(): T;
|
|
26
|
+
/** @internal */
|
|
27
|
+
_removeSub(sub: () => void): void;
|
|
28
|
+
private _notify;
|
|
29
|
+
dispose(): void;
|
|
30
|
+
}
|
|
31
|
+
export declare function signal<T>(initialValue: T): Signal<T>;
|
|
32
|
+
/**
|
|
33
|
+
* Ejecuta una función y la RE-EJECUTA cada vez que
|
|
34
|
+
* algún signal leído dentro de ella cambie.
|
|
35
|
+
*
|
|
36
|
+
* Retorna una función dispose() para destruir el effect.
|
|
37
|
+
*
|
|
38
|
+
* const dispose = effect(() => {
|
|
39
|
+
* console.log(count.value);
|
|
40
|
+
* return () => console.log("cleanup");
|
|
41
|
+
* });
|
|
42
|
+
*
|
|
43
|
+
* dispose();
|
|
44
|
+
*/
|
|
45
|
+
export declare function effect(fn: () => void | (() => void)): () => void;
|
|
46
|
+
/**
|
|
47
|
+
* Valor derivado que se recalcula automáticamente.
|
|
48
|
+
*
|
|
49
|
+
* const doubled = computed(() => count.value * 2);
|
|
50
|
+
*/
|
|
51
|
+
export declare function computed<T>(fn: () => T): Signal<T>;
|
|
52
|
+
/**
|
|
53
|
+
* Agrupa múltiples cambios para que los effects
|
|
54
|
+
* se ejecuten UNA sola vez al final.
|
|
55
|
+
*
|
|
56
|
+
* batch(() => {
|
|
57
|
+
* x.value = 1;
|
|
58
|
+
* y.value = 2;
|
|
59
|
+
* });
|
|
60
|
+
*/
|
|
61
|
+
export declare function batch(fn: () => void): void;
|
|
62
|
+
/**
|
|
63
|
+
* Ejecuta `fn` sin suscribirse a ninguna signal que lea dentro de ella.
|
|
64
|
+
* Útil para leer valores reactivos sin que esas lecturas re-disparen el
|
|
65
|
+
* efecto actual (p.ej. en callbacks de `watch`).
|
|
66
|
+
*
|
|
67
|
+
* const total = untrack(() => price.value * qty.value); // no se suscribe
|
|
68
|
+
*/
|
|
69
|
+
export declare function untrack<T>(fn: () => T): T;
|
|
70
|
+
export interface WatchOptions {
|
|
71
|
+
/**
|
|
72
|
+
* Si es `true`, el callback se ejecuta inmediatamente con el valor
|
|
73
|
+
* actual antes de que haya ningún cambio. Por defecto: `false`.
|
|
74
|
+
*/
|
|
75
|
+
immediate?: boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Si es `true`, el watcher se elimina automáticamente después de la
|
|
78
|
+
* primera vez que el callback se dispara. Por defecto: `false`.
|
|
79
|
+
*/
|
|
80
|
+
once?: boolean;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Observa una fuente reactiva y ejecuta `callback(newValue, oldValue)` cada
|
|
84
|
+
* vez que cambia.
|
|
85
|
+
*
|
|
86
|
+
* La fuente puede ser:
|
|
87
|
+
* - Un getter: `() => count.value + other.value`
|
|
88
|
+
* - Una Signal directamente: `count`
|
|
89
|
+
*
|
|
90
|
+
* Retorna una función `dispose()` para detener la observación.
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* const stop = watch(
|
|
94
|
+
* () => user.value.name,
|
|
95
|
+
* (newName, oldName) => console.log(newName, oldName),
|
|
96
|
+
* { immediate: true }
|
|
97
|
+
* );
|
|
98
|
+
* stop(); // deja de observar
|
|
99
|
+
*/
|
|
100
|
+
export declare function watch<T>(source: Signal<T> | (() => T), callback: (newValue: T, oldValue: T | undefined) => void, options?: WatchOptions): () => void;
|
|
101
|
+
/**
|
|
102
|
+
* Espera a que todos los efectos síncronos pendientes hayan corrido y el
|
|
103
|
+
* DOM esté actualizado, devolviendo una promesa que resuelve en el próximo
|
|
104
|
+
* microtask.
|
|
105
|
+
*
|
|
106
|
+
* Úsala cuando necesitas leer el DOM *después* de un cambio reactivo:
|
|
107
|
+
*
|
|
108
|
+
* count.value++;
|
|
109
|
+
* await nextTick();
|
|
110
|
+
* console.log(el.textContent); // ya refleja el nuevo valor
|
|
111
|
+
*
|
|
112
|
+
* También acepta un callback opcional:
|
|
113
|
+
*
|
|
114
|
+
* nextTick(() => el.focus());
|
|
115
|
+
*/
|
|
116
|
+
export declare function nextTick(fn?: () => void): Promise<void>;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type { Signal } from "./reactivity";
|
|
2
|
+
import { NixComponent } from "./lifecycle";
|
|
3
|
+
import type { NixTemplate } from "./template";
|
|
4
|
+
export interface RouteRecord {
|
|
5
|
+
/**
|
|
6
|
+
* Segmento de ruta. Soporta:
|
|
7
|
+
* - Literal: "/about", "/users"
|
|
8
|
+
* - Parámetro: "/users/:id", "/posts/:slug/comments/:cid"
|
|
9
|
+
* - Wildcard: "*" (fallback global o de prefijo con children)
|
|
10
|
+
*
|
|
11
|
+
* Los paths de children se concatenan con el del padre.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* { path: "/users/:id", component: UserDetail }
|
|
15
|
+
* // Navegar a "/users/42" → params.value = { id: "42" }
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* { path: "/dash", component: DashLayout, children: [
|
|
19
|
+
* { path: "/users", component: UsersPage },
|
|
20
|
+
* ]}
|
|
21
|
+
* // Genera las rutas planas: /dash, /dash/users
|
|
22
|
+
*/
|
|
23
|
+
path: string;
|
|
24
|
+
/** Factory que devuelve la vista a renderizar en este nivel */
|
|
25
|
+
component: () => NixTemplate | NixComponent;
|
|
26
|
+
/**
|
|
27
|
+
* Rutas hijas. Sus paths se unen con el del padre.
|
|
28
|
+
* El componente padre debe incluir `new RouterView(1)` para renderizarlas.
|
|
29
|
+
*/
|
|
30
|
+
children?: RouteRecord[];
|
|
31
|
+
}
|
|
32
|
+
export interface Router {
|
|
33
|
+
/** Señal con la ruta activa actual (pathname, p.ej. "/users/42") */
|
|
34
|
+
readonly current: Signal<string>;
|
|
35
|
+
/**
|
|
36
|
+
* Señal con los parámetros dinámicos de la ruta activa (:id, :slug…).
|
|
37
|
+
* Se actualiza síncronamente con cada `navigate()`.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* // Ruta: "/users/:id" → navigate("/users/42")
|
|
41
|
+
* router.params.value // { id: "42" }
|
|
42
|
+
*/
|
|
43
|
+
readonly params: Signal<Record<string, string>>;
|
|
44
|
+
/**
|
|
45
|
+
* Señal con los query params de la URL (?clave=valor…).
|
|
46
|
+
* Se actualiza síncronamente con cada `navigate()`.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* router.navigate("/users?page=2&sort=name")
|
|
50
|
+
* router.query.value // { page: "2", sort: "name" }
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* router.navigate("/users", { page: 2, sort: "name" })
|
|
54
|
+
* router.query.value // { page: "2", sort: "name" }
|
|
55
|
+
*/
|
|
56
|
+
readonly query: Signal<Record<string, string>>;
|
|
57
|
+
/**
|
|
58
|
+
* Navegar a una ruta nueva (pushState + actualiza señales síncronamente).
|
|
59
|
+
*
|
|
60
|
+
* @param path Ruta destino. Puede incluir query string: "/users?page=2"
|
|
61
|
+
* @param query Query params como objeto. Se mezclan con los del path.
|
|
62
|
+
* Un valor `null`/`undefined` elimina el parámetro.
|
|
63
|
+
*/
|
|
64
|
+
navigate(path: string, query?: Record<string, string | number | boolean | null | undefined>): void;
|
|
65
|
+
/** Árbol de rutas original (tal como se pasó a createRouter) */
|
|
66
|
+
readonly routes: RouteRecord[];
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Crea el router History API y lo establece como singleton activo del módulo.
|
|
70
|
+
* Usa `history.pushState` — URLs limpias sin `#`.
|
|
71
|
+
* `RouterView` y `Link` lo consumen automáticamente — no necesitan que se los pases.
|
|
72
|
+
*
|
|
73
|
+
* @note En producción el servidor debe responder con `index.html` para cualquier
|
|
74
|
+
* ruta no-archivo. Vite dev y `vite preview` lo hacen automáticamente.
|
|
75
|
+
*/
|
|
76
|
+
export declare function createRouter(routes: RouteRecord[]): Router;
|
|
77
|
+
/**
|
|
78
|
+
* Devuelve el router activo (singleton).
|
|
79
|
+
* Útil dentro de componentes para acceder a `params` y `current` sin prop-drilling.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* class UserDetail extends NixComponent {
|
|
83
|
+
* render() {
|
|
84
|
+
* return html`<div>User: ${() => useRouter().params.value.id}</div>`;
|
|
85
|
+
* }
|
|
86
|
+
* }
|
|
87
|
+
*/
|
|
88
|
+
export declare function useRouter(): Router;
|
|
89
|
+
/**
|
|
90
|
+
* Renderiza el componente de la ruta activa en el nivel `depth`.
|
|
91
|
+
*
|
|
92
|
+
* - `new RouterView()` → nivel raíz (depth 0).
|
|
93
|
+
* - `new RouterView(1)` → primer nivel de rutas anidadas. Úsalo dentro del
|
|
94
|
+
* componente padre para que renderice el hijo correspondiente.
|
|
95
|
+
*
|
|
96
|
+
* Consume el router singleton — no requiere que se le pase el router.
|
|
97
|
+
*/
|
|
98
|
+
export declare class RouterView extends NixComponent {
|
|
99
|
+
private _depth;
|
|
100
|
+
constructor(depth?: number);
|
|
101
|
+
render(): NixTemplate;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Enlace de navegación reactivo que se estiliza como activo/inactivo según la
|
|
105
|
+
* ruta actual. Consume el router singleton — no requiere que se le pase.
|
|
106
|
+
*
|
|
107
|
+
* @example
|
|
108
|
+
* new Link("/about", "About")
|
|
109
|
+
*/
|
|
110
|
+
export declare class Link extends NixComponent {
|
|
111
|
+
private _to;
|
|
112
|
+
private _label;
|
|
113
|
+
constructor(to: string, label: string);
|
|
114
|
+
render(): NixTemplate;
|
|
115
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Signal } from "./reactivity";
|
|
2
|
+
/** Transforma cada propiedad del estado inicial en su Signal correspondiente. */
|
|
3
|
+
export type StoreSignals<T extends Record<string, unknown>> = {
|
|
4
|
+
readonly [K in keyof T]: Signal<T[K]>;
|
|
5
|
+
};
|
|
6
|
+
/** Tipo del store tal como lo ve el usuario. */
|
|
7
|
+
export type Store<T extends Record<string, unknown>, A extends Record<string, unknown> = Record<never, never>> = StoreSignals<T> & A & {
|
|
8
|
+
/**
|
|
9
|
+
* Restaura todos los signals a sus valores iniciales.
|
|
10
|
+
* Equivalente a hacer `signal.value = initialValue` en cada propiedad.
|
|
11
|
+
*/
|
|
12
|
+
$reset(): void;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Crea un store reactivo global.
|
|
16
|
+
*
|
|
17
|
+
* @param initialState Objeto plano con los valores iniciales.
|
|
18
|
+
* @param actionsFactory Función que recibe los signals y retorna acciones.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* // Sin acciones
|
|
22
|
+
* const theme = createStore({ dark: false, fontSize: 16 });
|
|
23
|
+
* theme.dark.value = true;
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* // Con acciones
|
|
27
|
+
* const cart = createStore(
|
|
28
|
+
* { items: [] as string[], total: 0 },
|
|
29
|
+
* (s) => ({
|
|
30
|
+
* add: (item: string) => s.items.update(arr => [...arr, item]),
|
|
31
|
+
* clear: () => cart.$reset(),
|
|
32
|
+
* })
|
|
33
|
+
* );
|
|
34
|
+
*
|
|
35
|
+
* cart.add("Manzana");
|
|
36
|
+
* cart.items.value; // ["Manzana"]
|
|
37
|
+
* cart.clear();
|
|
38
|
+
* cart.items.value; // []
|
|
39
|
+
*/
|
|
40
|
+
export declare function createStore<T extends Record<string, unknown>, A extends Record<string, unknown> = Record<never, never>>(initialState: T, actionsFactory?: (signals: StoreSignals<T>) => A): Store<T, A>;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { NixComponent } from "./lifecycle";
|
|
2
|
+
export interface NixTemplate {
|
|
3
|
+
readonly __isNixTemplate: true;
|
|
4
|
+
/** Monta el template en un contenedor (uso externo / raíz). */
|
|
5
|
+
mount(container: Element | string): NixMountHandle;
|
|
6
|
+
/**
|
|
7
|
+
* @internal — Renderiza el template antes del nodo `before` (o al final
|
|
8
|
+
* de `parent` si `before` es null). Retorna una función de limpieza.
|
|
9
|
+
*/
|
|
10
|
+
_render(parent: Node, before: Node | null): () => void;
|
|
11
|
+
}
|
|
12
|
+
export interface NixMountHandle {
|
|
13
|
+
unmount(): void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Contenedor para una referencia directa a un elemento DOM.
|
|
17
|
+
* Se asigna automáticamente cuando el template se monta y se limpia al
|
|
18
|
+
* desmontarse.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* const inputRef = ref<HTMLInputElement>();
|
|
22
|
+
* html`<input ref=${inputRef} />`
|
|
23
|
+
* // después del mount:
|
|
24
|
+
* inputRef.el?.focus();
|
|
25
|
+
*/
|
|
26
|
+
export interface NixRef<T extends Element = Element> {
|
|
27
|
+
el: T | null;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Crea un objeto `NixRef` vacío.
|
|
31
|
+
* Pásalo como valor del atributo especial `ref` en un template para que
|
|
32
|
+
* Nix.js rellene automáticamente `ref.el` con el elemento real del DOM.
|
|
33
|
+
*/
|
|
34
|
+
export declare function ref<T extends Element = Element>(): NixRef<T>;
|
|
35
|
+
/**
|
|
36
|
+
* Resultado de `repeat()` — lista con keys para diffing eficiente.
|
|
37
|
+
* El template engine lo reconoce y solo añade/mueve/elimina los nodos
|
|
38
|
+
* que realmente cambiaron, preservando el DOM de los items estables.
|
|
39
|
+
*/
|
|
40
|
+
export interface KeyedList<T = unknown> {
|
|
41
|
+
readonly __isKeyedList: true;
|
|
42
|
+
readonly items: T[];
|
|
43
|
+
readonly keyFn: (item: T, index: number) => string | number;
|
|
44
|
+
readonly renderFn: (item: T, index: number) => NixTemplate | NixComponent;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Crea una lista con keys para diffing eficiente.
|
|
48
|
+
* Úsalo en lugar de `.map()` cuando la lista cambia frecuentemente.
|
|
49
|
+
*
|
|
50
|
+
* @param items Array reactivo de datos
|
|
51
|
+
* @param keyFn Devuelve una clave única por item (p.ej. `item => item.id`)
|
|
52
|
+
* @param renderFn Devuelve el template/componente para cada item
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ${() => repeat(
|
|
56
|
+
* users.value,
|
|
57
|
+
* u => u.id,
|
|
58
|
+
* u => html`<li>${u.name}</li>`
|
|
59
|
+
* )}
|
|
60
|
+
*/
|
|
61
|
+
export declare function repeat<T>(items: T[], keyFn: (item: T, index: number) => string | number, renderFn: (item: T, index: number) => NixTemplate | NixComponent): KeyedList<T>;
|
|
62
|
+
export declare function html(strings: TemplateStringsArray, ...values: unknown[]): NixTemplate;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=null,t=[],n=null,r=[],i=0,a=new Set,o=class{_value;_subs=new Set;constructor(e){this._value=e}get value(){return e&&(this._subs.add(e),n?.add(this)),this._value}set value(e){Object.is(this._value,e)||(this._value=e,this._notify())}update(e){this.value=e(this._value)}peek(){return this._value}_removeSub(e){this._subs.delete(e)}_notify(){let e=[...this._subs];i>0?e.forEach(e=>a.add(e)):e.forEach(e=>e())}dispose(){this._subs.clear()}};function s(e){return new o(e)}function c(i){let a,o=new Set,s=()=>{typeof a==`function`&&a(),o.forEach(e=>e._removeSub(s)),o=new Set,t.push(e),r.push(n),e=s,n=o;try{a=i()}finally{e=t.pop()||null,n=r.pop()||null}};return s(),()=>{typeof a==`function`&&a(),o.forEach(e=>e._removeSub(s)),o.clear()}}function l(e){let t=new o(void 0);return c(()=>{t.value=e()}),t}function u(e){i++;try{e()}finally{if(i--,i===0){let e=[...a];a.clear(),e.forEach(e=>e())}}}function d(t){let r=e,i=n;e=null,n=null;try{return t()}finally{e=r,n=i}}function f(e,t,n={}){let{immediate:r=!1,once:i=!1}=n,a=e instanceof o?()=>e.value:e,s,l=!0,u=!1,f=c(()=>{let e=a();if(l){if(l=!1,r&&!u){let n=e;d(()=>t(n,void 0)),i&&(u=!0,Promise.resolve().then(f))}s=e;return}if(!u){let n=e,r=s;s=e,d(()=>t(n,r)),i&&(u=!0,Promise.resolve().then(f))}});return()=>{u=!0,f()}}function p(e){return e?Promise.resolve().then(e):Promise.resolve()}var m=class{__isNixComponent=!0};function h(e){return typeof e==`object`&&!!e&&e.__isNixComponent===!0}function g(e){return Symbol(e)}var _=[];function v(){return[..._]}function y(){_.push(new Map)}function b(){_.pop()}function x(e,t){let n=_.splice(0);e.forEach(e=>_.push(e)),_.push(new Map);try{return t()}finally{_.splice(0),n.forEach(e=>_.push(e))}}function S(e,t){let n=_[_.length-1];if(!n)throw Error(`[Nix] provide() debe llamarse dentro de onInit() de un NixComponent.`);n.set(e,t)}function C(e){for(let t=_.length-1;t>=0;t--)if(_[t].has(e))return _[t].get(e)}function w(){return{el:null}}function T(e,t,n){return{__isKeyedList:!0,items:e,keyFn:t,renderFn:n}}function E(e){let t=e.lastIndexOf(`>`),n=e.lastIndexOf(`<`);if(n<=t)return{type:`node`};let r=e.slice(n+1),i=r.match(/@([\w:.-]+)=["']?$/);if(i){let e=i[1].split(`.`);return{type:`event`,eventName:e[0],modifiers:e.slice(1),hadOpenQuote:i[0].endsWith(`"`)||i[0].endsWith(`'`)}}let a=r.match(/([\w:.-]+)=["']?$/);return a?{type:`attr`,attrName:a[1],hadOpenQuote:a[0].endsWith(`"`)||a[0].endsWith(`'`)}:{type:`node`}}function D(e,t){let n=Array(e.length).fill(0),r=``;for(let i=0;i<e.length;i++){let a=e[i];if(n[i]===1&&(a[0]===`"`||a[0]===`'`)&&(a=a.slice(1)),i<t.length){let e=t[i];if(e.type===`node`)r+=a+`<!--nix-${i}-->`;else if(e.type===`event`){let t=`@${e.modifiers.length?`${e.eventName}.${e.modifiers.join(`.`)}`:e.eventName}=`.length+(e.hadOpenQuote?1:0);r+=a.slice(0,-t)+` data-nix-e-${i}="${e.eventName}"`,e.hadOpenQuote&&(n[i+1]=1)}else{let t=`${e.attrName}=`.length+(e.hadOpenQuote?1:0);r+=a.slice(0,-t)+` data-nix-a-${i}="${e.attrName}"`,e.hadOpenQuote&&(n[i+1]=1)}}else r+=a}return r}function O(e){return typeof e==`object`&&!!e&&e.__isNixTemplate===!0}function k(e){return typeof e==`object`&&!!e&&e.__isKeyedList===!0}function A(e){let t=new Map,n=document.createTreeWalker(e,NodeFilter.SHOW_COMMENT),r;for(;r=n.nextNode();){let e=r,n=e.nodeValue?.match(/^nix-(\d+)$/);n&&t.set(parseInt(n[1]),e)}return t}function j(e){let t=new Map;return e.querySelectorAll(`*`).forEach(e=>{let n=Array.from(e.attributes);for(let r of n){let n=r.name.match(/^data-nix-e-(\d+)$/);if(n){t.set(parseInt(n[1]),{el:e,type:`event`,name:r.value}),e.removeAttribute(r.name);continue}n=r.name.match(/^data-nix-a-(\d+)$/),n&&(t.set(parseInt(n[1]),{el:e,type:`attr`,name:r.value}),e.removeAttribute(r.name))}}),t}function M(e,t,n){let r=[],i=[],a=A(e),o=j(e);for(let e=0;e<t.length;e++){let s=t[e],l=n[e];if(s.type===`event`){let t=o.get(e);if(!t)continue;let{el:n,name:i}=t,a=l,c=s.modifiers,u={};c.includes(`once`)&&(u.once=!0),c.includes(`capture`)&&(u.capture=!0),c.includes(`passive`)&&(u.passive=!0);let d={enter:`Enter`,escape:`Escape`,space:` `,tab:`Tab`,delete:`Delete`,backspace:`Backspace`,up:`ArrowUp`,down:`ArrowDown`,left:`ArrowLeft`,right:`ArrowRight`},f=e=>{if(c.includes(`prevent`)&&e.preventDefault(),c.includes(`stop`)&&e.stopPropagation(),!(c.includes(`self`)&&e.target!==e.currentTarget)){if(`key`in e){let t=e;for(let e of c){let n=d[e];if(n!==void 0&&t.key!==n||!d[e]&&e.length===1&&t.key.toLowerCase()!==e)return}}a(e)}};n.addEventListener(i,f,u),r.push(()=>n.removeEventListener(i,f,u));continue}if(s.type===`attr`){let t=o.get(e);if(!t)continue;let{el:n,name:i}=t;if(i===`ref`){l.el=n,r.push(()=>{l.el=null});continue}if(typeof l==`function`){let e=c(()=>{let e=l();e==null||e===!1?n.removeAttribute(i):n.setAttribute(i,String(e))});r.push(e)}else l!=null&&l!==!1&&n.setAttribute(i,String(l));continue}let u=a.get(e);if(!u)continue;if(typeof l!=`function`){if(h(l)){let e=l;y();let t;try{try{e.onInit?.()}catch(t){if(e.onError)e.onError(t);else throw t}t=e.render()._render(u.parentNode,u)}finally{b()}let n;i.push(()=>{try{let t=e.onMount?.();typeof t==`function`&&(n=t)}catch(t){if(e.onError)e.onError(t);else throw t}}),r.push(()=>{try{e.onUnmount?.()}catch{}try{n?.()}catch{}t()})}else if(O(l))l._render(u.parentNode,u);else if(Array.isArray(l))for(let e of l)if(h(e)){let t;y();try{try{e.onInit?.()}catch(t){if(e.onError)e.onError(t);else throw t}t=e.render()._render(u.parentNode,u)}finally{b()}let n;i.push(()=>{try{let t=e.onMount?.();typeof t==`function`&&(n=t)}catch(t){if(e.onError)e.onError(t);else throw t}}),r.push(()=>{try{e.onUnmount?.()}catch{}try{n?.()}catch{}t()})}else O(e)?e._render(u.parentNode,u):e!=null&&e!==!1&&u.parentNode.insertBefore(document.createTextNode(String(e)),u);else l!=null&&l!==!1&&u.parentNode.insertBefore(document.createTextNode(String(l)),u);continue}let d=null,f=null,p=null,m=v(),g=c(()=>{let e=l();if(typeof e==`string`||typeof e==`number`){f&&=(f(),null),d?d.nodeValue=String(e):(d=document.createTextNode(String(e)),u.parentNode.insertBefore(d,u));return}if(d&&=(d.parentNode?.removeChild(d),null),f&&=(f(),null),!(e==null||e===!1))if(O(e))f=e._render(u.parentNode,u);else if(h(e)){let t=e,n;x(m,()=>{try{t.onInit?.()}catch(e){if(t.onError)t.onError(e);else throw e}n=t.render()._render(u.parentNode,u)});let r;try{let e=t.onMount?.();typeof e==`function`&&(r=e)}catch(e){if(t.onError)t.onError(e);else throw e}f=()=>{try{t.onUnmount?.()}catch{}try{r?.()}catch{}n()}}else if(k(e)){p||=new Map;let t=u.parentNode,n=e.items.map((t,n)=>e.keyFn(t,n)),r=new Set(n);for(let[e,n]of p)if(!r.has(e)){n.cleanup();let r=n.start;for(;r!==n.end;){let e=r.nextSibling;t.removeChild(r),r=e}t.removeChild(n.end),p.delete(e)}let i=u;for(let r=n.length-1;r>=0;r--){let a=n[r],o=e.items[r];if(p.has(a)){let e=p.get(a);if(e.end.nextSibling!==i){let n=[],r=e.start;for(;n.push(r),r!==e.end;)r=r.nextSibling;for(let e of n)t.insertBefore(e,i)}i=e.start}else{let n=document.createComment(`nix-ke`),s=document.createComment(`nix-ks`);t.insertBefore(n,i),t.insertBefore(s,n);let c,l=e.renderFn(o,r);if(h(l)){let e;x(m,()=>{try{l.onInit?.()}catch(e){if(l.onError)l.onError(e);else throw e}e=l.render()._render(t,n)});let r;try{let e=l.onMount?.();typeof e==`function`&&(r=e)}catch(e){if(l.onError)l.onError(e);else throw e}c=()=>{try{l.onUnmount?.()}catch{}try{r?.()}catch{}e()}}else c=l._render(t,n);p.set(a,{start:s,end:n,cleanup:c}),i=s}}}else if(Array.isArray(e)){let t=[];for(let n of e)if(h(n)){try{n.onInit?.()}catch(e){if(n.onError)n.onError(e);else throw e}let e=n.render()._render(u.parentNode,u),r;try{let e=n.onMount?.();typeof e==`function`&&(r=e)}catch(e){if(n.onError)n.onError(e);else throw e}t.push(()=>{try{n.onUnmount?.()}catch{}try{r?.()}catch{}e()})}else if(O(n))t.push(n._render(u.parentNode,u));else if(n!=null&&n!==!1){let e=document.createTextNode(String(n));u.parentNode.insertBefore(e,u),t.push(()=>e.parentNode?.removeChild(e))}f=()=>t.forEach(e=>e())}else d=document.createTextNode(String(e)),u.parentNode.insertBefore(d,u)});r.push(()=>{if(g(),f&&=(f(),null),d&&=(d.parentNode?.removeChild(d),null),p){for(let e of p.values())e.cleanup();p=null}})}return{disposes:r,postMountHooks:i}}function N(e,...t){let n=[],r=``;for(let t=0;t<e.length-1;t++){r+=e[t];let i=E(r);n.push(i),r+=`__nix__`}let i=D(e,n);function a(e,r){let a=document.createElement(`template`);a.innerHTML=i;let o=a.content,{disposes:s,postMountHooks:c}=M(o,n,t),l=document.createComment(`nix-scope`);e.insertBefore(l,r);let u=o.firstChild;for(;u;){let t=u.nextSibling;e.insertBefore(u,r),u=t}return c.forEach(e=>e()),()=>{s.forEach(e=>e());let e=l.nextSibling;for(;e&&e!==r;){let t=e.nextSibling;e.parentNode?.removeChild(e),e=t}l.parentNode?.removeChild(l)}}return{__isNixTemplate:!0,_render:a,mount(e){let t=typeof e==`string`?document.querySelector(e):e;if(!t)throw Error(`[Nix] mount: contenedor no encontrado: ${e}`);let n=a(t,null);return{unmount(){n()}}}}}function P(e,t){if(h(e)){let n=typeof t==`string`?document.querySelector(t):t;if(!n)throw Error(`[Nix] mount: contenedor no encontrado: ${t}`);y();let r;try{try{e.onInit?.()}catch(t){if(e.onError)e.onError(t);else throw t}r=e.render()._render(n,null)}finally{b()}let i;try{let t=e.onMount?.();typeof t==`function`&&(i=t)}catch(t){if(e.onError)e.onError(t);else throw t}return{unmount(){try{e.onUnmount?.()}catch{}try{i?.()}catch{}r()}}}return e.mount(t)}function F(e,t){let n={};for(let t of Object.keys(e))n[t]=s(e[t]);let r=n;function i(){for(let t of Object.keys(e))n[t].value=e[t]}let a=Object.assign(Object.create(null),r,{$reset:i});if(t){let e=t(r);Object.assign(a,e)}return a}var I=null;function L(){if(!I)throw Error(`[Nix] No hay router activo. Llama a createRouter() antes.`);return I}function R(e){let t={};return new URLSearchParams(e).forEach((e,n)=>{t[n]=e}),t}function z(e){let t=new URLSearchParams;for(let[n,r]of Object.entries(e))r!=null&&r!==!1&&t.set(n,String(r));let n=t.toString();return n?`?`+n:``}function B(e){return e===`*`?[{kind:`wildcard`}]:e.split(`/`).filter(Boolean).map(e=>e===`*`?{kind:`wildcard`}:e.startsWith(`:`)?{kind:`param`,name:e.slice(1)}:{kind:`literal`,value:e})}function V(e,t){return t===`*`?e===``?`*`:e+`/*`:(e+(t.startsWith(`/`)?t:`/`+t)).replace(/\/+/g,`/`)||`/`}function H(e,t=``,n=[]){let r=[];for(let i of e){let e=V(t,i.path),a=[...n,i.component],o=B(e);r.push({fullPath:e,segments:o,chain:a}),i.children?.length&&r.push(...H(i.children,e,a))}return r}function U(e,t){let n=e.split(`/`).filter(Boolean),r=t.segments;if(r.length===1&&r[0].kind===`wildcard`)return{};let i=r.length>0&&r[r.length-1].kind===`wildcard`,a=i?r.slice(0,-1):r;if(i){if(n.length<a.length)return null}else if(n.length!==a.length)return null;let o={};for(let e=0;e<a.length;e++){let t=a[e];if(t.kind===`literal`){if(n[e]!==t.value)return null}else t.kind===`param`&&(o[t.name]=decodeURIComponent(n[e]??``))}return o}function W(e){return e.segments.reduce((e,t)=>t.kind===`literal`?e+2:t.kind===`param`?e+1:e,0)}function G(e,t){let n,r={},i=-1;for(let a of t){let t=U(e,a);if(t===null)continue;let o=W(a);o>i&&(n=a,r=t,i=o)}return n?{route:n,params:r}:void 0}function K(e){function t(){return window.location.pathname||`/`}let n=t(),r=H(e),i=G(n,r),a=s(n),o=s(i?.params??{}),c=s(R(window.location.search));window.addEventListener(`popstate`,()=>{let e=t();o.value=G(e,r)?.params??{},c.value=R(window.location.search),a.value=e});function l(e,t){let n=e.indexOf(`?`),i=n===-1?e:e.slice(0,n),s=n===-1?{}:R(e.slice(n)),l=t?{...s,...t}:s,u={};for(let[e,t]of Object.entries(l))t!=null&&t!==!1&&(u[e]=String(t));o.value=G(i,r)?.params??{},c.value=u,a.value=i;let d=i+z(u);history.pushState(null,``,d)}let u={current:a,params:o,query:c,navigate:l,routes:e,_flat:r};return I=u,u}function q(){return L()}var J=class extends m{_depth;constructor(e=0){super(),this._depth=e}render(){let e=this._depth;return N`<div class="router-view">${()=>{let t=L(),n=G(t.current.value,t._flat);return n?e>=n.route.chain.length?N`<span></span>`:n.route.chain[e]():N`<div style="color:#f87171;padding:16px 0">
|
|
2
|
+
404 — Ruta no encontrada: <strong>${t.current.value}</strong>
|
|
3
|
+
</div>`}}</div>`}},Y=class extends m{_to;_label;constructor(e,t){super(),this._to=e,this._label=t}render(){let e=this._to;return N`<a
|
|
4
|
+
href=${e}
|
|
5
|
+
style=${()=>L().current.value===e?`color:#38bdf8;font-weight:700;text-decoration:none;cursor:pointer;padding:4px 10px;border-radius:4px;background:#0c2a3a`:`color:#a3a3a3;text-decoration:none;cursor:pointer;padding:4px 10px;border-radius:4px`}
|
|
6
|
+
@click=${t=>{t.preventDefault(),L().navigate(e)}}
|
|
7
|
+
>${this._label}</a>`}};function X(e,t,n={}){let{fallback:r,errorFallback:i,resetOnRefresh:a=!1}=n,o=r??N`
|
|
8
|
+
<span style="color:#52525b;font-size:13px;display:inline-flex;align-items:center;gap:6px">
|
|
9
|
+
<span class="nix-spinner" style="
|
|
10
|
+
display:inline-block;width:14px;height:14px;border-radius:50%;
|
|
11
|
+
border:2px solid #38bdf840;border-top-color:#38bdf8;
|
|
12
|
+
animation:nix-spin .7s linear infinite
|
|
13
|
+
"></span>
|
|
14
|
+
Cargando…
|
|
15
|
+
</span>
|
|
16
|
+
<style>@keyframes nix-spin{to{transform:rotate(360deg)}}</style>
|
|
17
|
+
`,c=i??(e=>N`
|
|
18
|
+
<span style="color:#f87171;font-size:13px">
|
|
19
|
+
⚠ ${e instanceof Error?e.message:String(e)}
|
|
20
|
+
</span>
|
|
21
|
+
`);class l extends m{_state=s({status:`pending`});onMount(){this._run()}_run(){(a||this._state.value.status===`pending`)&&(this._state.value={status:`pending`}),e().then(e=>{this._state.value={status:`resolved`,data:e}},e=>{this._state.value={status:`error`,error:e}})}render(){return N`<div class="nix-suspense" style="display:contents">${()=>{let e=this._state.value;return e.status===`pending`?o:e.status===`error`?c(e.error):t(e.data)}}</div>`}}return new l}function Z(e,t){let n=null;return()=>n?new n:X(async()=>(n=(await e()).default,n),e=>new e,{fallback:t})}exports.Link=Y,exports.NixComponent=m,exports.RouterView=J,exports.Signal=o,exports.batch=u,exports.computed=l,exports.createInjectionKey=g,exports.createRouter=K,exports.createStore=F,exports.effect=c,exports.html=N,exports.inject=C,exports.lazy=Z,exports.mount=P,exports.nextTick=p,exports.provide=S,exports.ref=w,exports.repeat=T,exports.signal=s,exports.suspend=X,exports.untrack=d,exports.useRouter=q,exports.watch=f;
|
|
22
|
+
//# sourceMappingURL=nix-js.cjs.map
|