create-nix-app 1.0.5 → 1.0.7
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/index.js +1 -0
- package/package.json +1 -1
- package/template-nix-ionic/README.md +19 -0
- package/template-nix-ionic/capacitor.config.ts +9 -0
- package/template-nix-ionic/favicon.ico +0 -0
- package/template-nix-ionic/index.html +17 -0
- package/template-nix-ionic/package.json +23 -0
- package/template-nix-ionic/public/nix-js-logo.png +0 -0
- package/template-nix-ionic/src/main.ts +28 -0
- package/template-nix-ionic/src/pages/detail-page.ts +80 -0
- package/template-nix-ionic/src/pages/home-page.ts +68 -0
- package/template-nix-ionic/src/style.css +79 -0
- package/template-nix-ionic/tsconfig.json +25 -0
- package/template-nix-ionic/vite.config.ts +12 -0
- package/template-vanilla-js/index.html +3 -2
- package/template-vanilla-ts/index.html +3 -2
- package/template-vanilla-ts/package.json +1 -1
- package/template-vite-js/index.html +2 -1
- package/template-vite-js/package.json +2 -2
- package/template-vite-ts/index.html +2 -1
- package/template-vite-ts/package.json +2 -2
package/index.js
CHANGED
|
@@ -24,6 +24,7 @@ async function init() {
|
|
|
24
24
|
choices: [
|
|
25
25
|
{ title: yellow('Vite + TypeScript'), value: 'vite-ts', description: 'Recomendado para DX rápida y tipado estricto' },
|
|
26
26
|
{ title: yellow('Vite + JavaScript'), value: 'vite-js', description: 'Vite sin compilación de TS' },
|
|
27
|
+
{ title: blue('Ionic + Nix.js (Capacitor)'), value: 'nix-ionic', description: 'Template oficial con nix-ionic (Nix.js + Ionic + Capacitor)' },
|
|
27
28
|
{ title: blue('Vanilla TypeScript'), value: 'vanilla-ts', description: 'Sin bundler, puro TSC' },
|
|
28
29
|
{ title: blue('Vanilla JavaScript'), value: 'vanilla-js', description: 'Cero build, import maps directo en navegador' }
|
|
29
30
|
]
|
package/package.json
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# ❄️ Nix.js Project
|
|
2
|
+
|
|
3
|
+
Este proyecto fue generado con `create-nix-app`.
|
|
4
|
+
|
|
5
|
+
## Desarrollo
|
|
6
|
+
|
|
7
|
+
Para comenzar a desarrollar:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install
|
|
11
|
+
npm run dev
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Estructura del Proyecto
|
|
15
|
+
|
|
16
|
+
- `src/`: Código fuente del proyecto.
|
|
17
|
+
- `src/main.js`: Punto de entrada principal.
|
|
18
|
+
- `src/style.css`: Estilos globales.
|
|
19
|
+
- `index.html`: Punto de entrada HTML.
|
|
Binary file
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8">
|
|
6
|
+
<link rel="icon" href="/favicon.ico">
|
|
7
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
8
|
+
<title>Nix.js + Vite TS</title>
|
|
9
|
+
<link rel="stylesheet" href="/src/style.css">
|
|
10
|
+
</head>
|
|
11
|
+
|
|
12
|
+
<body>
|
|
13
|
+
<div id="app"></div>
|
|
14
|
+
<script type="module" src="/src/main.ts"></script>
|
|
15
|
+
</body>
|
|
16
|
+
|
|
17
|
+
</html>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "nix-js-ionic-template",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "vite",
|
|
7
|
+
"build": "tsc --noEmit && vite build",
|
|
8
|
+
"preview": "vite preview"
|
|
9
|
+
},
|
|
10
|
+
"dependencies": {
|
|
11
|
+
"@capacitor/android": "^8.2.0",
|
|
12
|
+
"@capacitor/cli": "^8.2.0",
|
|
13
|
+
"@capacitor/core": "^8.2.0",
|
|
14
|
+
"@deijose/nix-ionic": "^0.1.4",
|
|
15
|
+
"@deijose/nix-js": "^1.7.7",
|
|
16
|
+
"@ionic/core": "^8.8.1",
|
|
17
|
+
"install": "^0.13.0"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"typescript": "~5.9.3",
|
|
21
|
+
"vite": "^8.0.0"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { defineCustomElements } from "@ionic/core/loader";
|
|
2
|
+
defineCustomElements();
|
|
3
|
+
|
|
4
|
+
import "@ionic/core/css/core.css";
|
|
5
|
+
import "@ionic/core/css/normalize.css";
|
|
6
|
+
import "@ionic/core/css/structure.css";
|
|
7
|
+
import "@ionic/core/css/typography.css";
|
|
8
|
+
import "@ionic/core/css/padding.css";
|
|
9
|
+
import "@ionic/core/css/flex-utils.css";
|
|
10
|
+
import "@ionic/core/css/display.css";
|
|
11
|
+
|
|
12
|
+
import { NixComponent, html, mount } from "@deijose/nix-js";
|
|
13
|
+
import { IonRouterOutlet } from "@deijose/nix-ionic";
|
|
14
|
+
import { HomePage } from "./pages/home-page";
|
|
15
|
+
import { DetailPage } from "./pages/detail-page";
|
|
16
|
+
|
|
17
|
+
const outlet = new IonRouterOutlet([
|
|
18
|
+
{ path: "/", component: (ctx) => new HomePage(ctx) },
|
|
19
|
+
{ path: "/detail/:id", component: (ctx) => new DetailPage(ctx) },
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
class App extends NixComponent {
|
|
23
|
+
render() {
|
|
24
|
+
return html`<ion-app>${outlet}</ion-app>`;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
mount(new App(), "#app");
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { html, signal, batch } from "@deijose/nix-js";
|
|
2
|
+
import type { NixTemplate } from "@deijose/nix-js";
|
|
3
|
+
import { IonPage, IonBackButton } from "@deijose/nix-ionic";
|
|
4
|
+
import type { PageContext } from "@deijose/nix-ionic";
|
|
5
|
+
|
|
6
|
+
interface Post { id: number; title: string; body: string; userId: number; }
|
|
7
|
+
|
|
8
|
+
export class DetailPage extends IonPage {
|
|
9
|
+
private post = signal<Post | null>(null);
|
|
10
|
+
private loading = signal(true);
|
|
11
|
+
private elapsed = signal(0);
|
|
12
|
+
private _timer = 0;
|
|
13
|
+
private _id: string;
|
|
14
|
+
|
|
15
|
+
constructor({ lc, params }: PageContext) {
|
|
16
|
+
super(lc);
|
|
17
|
+
this._id = params["id"] ?? "1";
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
override onInit(): void {
|
|
21
|
+
super.onInit();
|
|
22
|
+
this._loadPost(this._id);
|
|
23
|
+
console.log("DETAIL INIT (Solo se debe ver una vez por instancia)");
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
override ionViewWillEnter(): void {
|
|
27
|
+
this.elapsed.value = 0;
|
|
28
|
+
this._timer = setInterval(
|
|
29
|
+
() => this.elapsed.update((n) => n + 1), 1000
|
|
30
|
+
) as unknown as number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
override ionViewWillLeave(): void {
|
|
34
|
+
clearInterval(this._timer);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private async _loadPost(id: string): Promise<void> {
|
|
38
|
+
this.loading.value = true;
|
|
39
|
+
try {
|
|
40
|
+
const res = await fetch(`https://jsonplaceholder.typicode.com/posts/${id}`);
|
|
41
|
+
const data = await res.json() as Post;
|
|
42
|
+
batch(() => { this.post.value = data; this.loading.value = false; });
|
|
43
|
+
} catch { this.loading.value = false; }
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
override render(): NixTemplate {
|
|
47
|
+
return html`
|
|
48
|
+
<ion-header>
|
|
49
|
+
<ion-toolbar color="primary">
|
|
50
|
+
<ion-buttons slot="start">
|
|
51
|
+
${IonBackButton()}
|
|
52
|
+
</ion-buttons>
|
|
53
|
+
<ion-title>Detalle</ion-title>
|
|
54
|
+
</ion-toolbar>
|
|
55
|
+
</ion-header>
|
|
56
|
+
<ion-content class="ion-padding">
|
|
57
|
+
${() => this.loading.value
|
|
58
|
+
? html`<ion-spinner name="crescent"></ion-spinner>`
|
|
59
|
+
: html`
|
|
60
|
+
<ion-card>
|
|
61
|
+
<ion-card-header>
|
|
62
|
+
<ion-card-title>${() => this.post.value?.title ?? ""}</ion-card-title>
|
|
63
|
+
<ion-card-subtitle>
|
|
64
|
+
Post #${() => this.post.value?.id ?? ""}
|
|
65
|
+
· Usuario ${() => this.post.value?.userId ?? ""}
|
|
66
|
+
</ion-card-subtitle>
|
|
67
|
+
</ion-card-header>
|
|
68
|
+
<ion-card-content>
|
|
69
|
+
${() => this.post.value?.body ?? ""}
|
|
70
|
+
<p style="margin-top:12px;color:var(--ion-color-medium);">
|
|
71
|
+
⏱ ${() => this.elapsed.value}s en vista
|
|
72
|
+
</p>
|
|
73
|
+
</ion-card-content>
|
|
74
|
+
</ion-card>
|
|
75
|
+
`
|
|
76
|
+
}
|
|
77
|
+
</ion-content>
|
|
78
|
+
`;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { html, signal, batch } from "@deijose/nix-js";
|
|
2
|
+
import type { NixTemplate } from "@deijose/nix-js";
|
|
3
|
+
import { IonPage, useRouter } from "@deijose/nix-ionic";
|
|
4
|
+
import type { PageContext } from "@deijose/nix-ionic";
|
|
5
|
+
|
|
6
|
+
interface Post { id: number; title: string; body: string; }
|
|
7
|
+
|
|
8
|
+
export class HomePage extends IonPage {
|
|
9
|
+
private posts = signal<Post[]>([]);
|
|
10
|
+
private loading = signal(false);
|
|
11
|
+
private visits = signal(0);
|
|
12
|
+
|
|
13
|
+
constructor({ lc }: PageContext) { super(lc); }
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
override onInit(): void {
|
|
17
|
+
super.onInit();
|
|
18
|
+
this.visits.update((n) => n + 1);
|
|
19
|
+
this._loadPosts();
|
|
20
|
+
|
|
21
|
+
console.log("HOME INIT (Solo se debe ver una vez por instancia)");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
private async _loadPosts(): Promise<void> {
|
|
25
|
+
this.loading.value = true;
|
|
26
|
+
try {
|
|
27
|
+
const res = await fetch("https://jsonplaceholder.typicode.com/posts?_limit=5");
|
|
28
|
+
const data = await res.json() as Post[];
|
|
29
|
+
batch(() => { this.posts.value = data; this.loading.value = false; });
|
|
30
|
+
} catch { this.loading.value = false; }
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
override render(): NixTemplate {
|
|
34
|
+
const router = useRouter();
|
|
35
|
+
return html`
|
|
36
|
+
<ion-header>
|
|
37
|
+
<ion-toolbar color="primary">
|
|
38
|
+
<ion-title>Home</ion-title>
|
|
39
|
+
</ion-toolbar>
|
|
40
|
+
</ion-header>
|
|
41
|
+
<ion-content class="ion-padding">
|
|
42
|
+
<ion-note color="medium" style="display:block;margin-bottom:12px;">
|
|
43
|
+
Visitas: <strong>${() => this.visits.value}</strong>
|
|
44
|
+
</ion-note>
|
|
45
|
+
${() => this.loading.value
|
|
46
|
+
? html`<ion-spinner name="crescent"></ion-spinner>`
|
|
47
|
+
: html`
|
|
48
|
+
<ion-list>
|
|
49
|
+
${() => this.posts.value.map((post) => html`
|
|
50
|
+
<ion-item button detail
|
|
51
|
+
@click=${() => router.navigate(`/detail/${post.id}`)}>
|
|
52
|
+
<ion-label>
|
|
53
|
+
<h2>${post.title}</h2>
|
|
54
|
+
<p>${post.body.slice(0, 60)}…</p>
|
|
55
|
+
</ion-label>
|
|
56
|
+
</ion-item>
|
|
57
|
+
`)}
|
|
58
|
+
</ion-list>
|
|
59
|
+
`
|
|
60
|
+
}
|
|
61
|
+
<ion-button expand="block" style="margin-top:16px;"
|
|
62
|
+
@click=${() => router.navigate("/profile")}>
|
|
63
|
+
Ver perfil
|
|
64
|
+
</ion-button>
|
|
65
|
+
</ion-content>
|
|
66
|
+
`;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
3
|
+
line-height: 1.5;
|
|
4
|
+
font-weight: 400;
|
|
5
|
+
|
|
6
|
+
color-scheme: light dark;
|
|
7
|
+
color: rgba(255, 255, 255, 0.87);
|
|
8
|
+
background-color: #242424;
|
|
9
|
+
|
|
10
|
+
font-synthesis: none;
|
|
11
|
+
text-rendering: optimizeLegibility;
|
|
12
|
+
-webkit-font-smoothing: antialiased;
|
|
13
|
+
-moz-osx-font-smoothing: grayscale;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
body {
|
|
17
|
+
margin: 0;
|
|
18
|
+
display: flex;
|
|
19
|
+
place-items: center;
|
|
20
|
+
min-width: 320px;
|
|
21
|
+
min-height: 100vh;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
#app {
|
|
25
|
+
max-width: 1280px;
|
|
26
|
+
margin: 0 auto;
|
|
27
|
+
padding: 2rem;
|
|
28
|
+
text-align: center;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
h1 {
|
|
32
|
+
font-size: 3.2em;
|
|
33
|
+
line-height: 1.1;
|
|
34
|
+
background: linear-gradient(45deg, #646cff, #60efff);
|
|
35
|
+
-webkit-background-clip: text;
|
|
36
|
+
background-clip: text;
|
|
37
|
+
-webkit-text-fill-color: transparent;
|
|
38
|
+
display: flex;
|
|
39
|
+
align-items: center;
|
|
40
|
+
justify-content: center;
|
|
41
|
+
gap: 16px;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
h1 img {
|
|
45
|
+
height: 1.2em;
|
|
46
|
+
width: auto;
|
|
47
|
+
filter: drop-shadow(0 0 10px rgba(100, 108, 255, 0.4));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
button {
|
|
51
|
+
border-radius: 8px;
|
|
52
|
+
border: 1px solid transparent;
|
|
53
|
+
padding: 0.6em 1.2em;
|
|
54
|
+
font-size: 1em;
|
|
55
|
+
font-weight: 500;
|
|
56
|
+
font-family: inherit;
|
|
57
|
+
background-color: #1a1a1a;
|
|
58
|
+
cursor: pointer;
|
|
59
|
+
transition: border-color 0.25s;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
button:hover {
|
|
63
|
+
border-color: #646cff;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
button:focus,
|
|
67
|
+
button:focus-visible {
|
|
68
|
+
outline: 4px auto -webkit-focus-ring-color;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@media (prefers-color-scheme: light) {
|
|
72
|
+
:root {
|
|
73
|
+
color: #213547;
|
|
74
|
+
background-color: #ffffff;
|
|
75
|
+
}
|
|
76
|
+
button {
|
|
77
|
+
background-color: #f9f9f9;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"lib": [
|
|
7
|
+
"ES2022",
|
|
8
|
+
"DOM",
|
|
9
|
+
"DOM.Iterable"
|
|
10
|
+
],
|
|
11
|
+
"skipLibCheck": true,
|
|
12
|
+
"moduleResolution": "bundler",
|
|
13
|
+
"allowImportingTsExtensions": true,
|
|
14
|
+
"resolveJsonModule": true,
|
|
15
|
+
"isolatedModules": true,
|
|
16
|
+
"noEmit": true,
|
|
17
|
+
"strict": true,
|
|
18
|
+
"noUnusedLocals": true,
|
|
19
|
+
"noUnusedParameters": true,
|
|
20
|
+
"noFallthroughCasesInSwitch": true
|
|
21
|
+
},
|
|
22
|
+
"include": [
|
|
23
|
+
"src"
|
|
24
|
+
]
|
|
25
|
+
}
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
|
+
<link rel="icon" href="/public/favicon.ico">
|
|
5
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title
|
|
7
|
+
<title>¡Bienvenido a Nix.js!</title>
|
|
7
8
|
<script type="importmap">
|
|
8
9
|
{
|
|
9
10
|
"imports": {
|
|
10
|
-
"@deijose/nix-js": "https://cdn.jsdelivr.net/npm/@deijose/nix-js@1.7.
|
|
11
|
+
"@deijose/nix-js": "https://cdn.jsdelivr.net/npm/@deijose/nix-js@1.7.7/+esm"
|
|
11
12
|
}
|
|
12
13
|
}
|
|
13
14
|
</script>
|
|
@@ -3,12 +3,13 @@
|
|
|
3
3
|
|
|
4
4
|
<head>
|
|
5
5
|
<meta charset="UTF-8">
|
|
6
|
+
<link rel="icon" href="/public/favicon.ico">
|
|
6
7
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
-
<title
|
|
8
|
+
<title>Nix.js Vanilla TS</title>
|
|
8
9
|
<script type="importmap">
|
|
9
10
|
{
|
|
10
11
|
"imports": {
|
|
11
|
-
"@deijose/nix-js": "https://cdn.jsdelivr.net/npm/@deijose/nix-js@1.7.
|
|
12
|
+
"@deijose/nix-js": "https://cdn.jsdelivr.net/npm/@deijose/nix-js@1.7.7/+esm"
|
|
12
13
|
}
|
|
13
14
|
}
|
|
14
15
|
</script>
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
<html lang="en">
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="UTF-8">
|
|
5
|
+
<link rel="icon" href="/public/favicon.ico">
|
|
5
6
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
-
<title
|
|
7
|
+
<title>Nix.js + Vite JS</title>
|
|
7
8
|
<link rel="stylesheet" href="./src/style.css">
|
|
8
9
|
</head>
|
|
9
10
|
|
|
@@ -3,8 +3,9 @@
|
|
|
3
3
|
|
|
4
4
|
<head>
|
|
5
5
|
<meta charset="UTF-8">
|
|
6
|
+
<link rel="icon" href="/public/favicon.ico">
|
|
6
7
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
-
<title
|
|
8
|
+
<title>Nix.js + Vite TS</title>
|
|
8
9
|
<link rel="stylesheet" href="/src/style.css">
|
|
9
10
|
</head>
|
|
10
11
|
|