create-nix-app 1.0.7 → 1.0.9

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-nix-app",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "Scaffolding tool for Nix.js reactive micro-framework",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,19 +1,61 @@
1
- # ❄️ Nix.js Project
1
+ # Nix-Ionic App
2
2
 
3
- Este proyecto fue generado con `create-nix-app`.
3
+ A mobile-first starter template powered by **[Nix.js](https://www.npmjs.com/package/@deijose/nix-js)** + **[Ionic](https://ionicframework.com/)** + **[Capacitor](https://capacitorjs.com/)**.
4
4
 
5
- ## Desarrollo
6
-
7
- Para comenzar a desarrollar:
5
+ ## Quick Start
8
6
 
9
7
  ```bash
10
8
  npm install
11
9
  npm run dev
12
10
  ```
13
11
 
14
- ## Estructura del Proyecto
12
+ ## Build for Production
13
+
14
+ ```bash
15
+ npm run build
16
+ ```
17
+
18
+ ## Deploy to Android
19
+
20
+ ```bash
21
+ # First build the web app
22
+ npm run build
23
+
24
+ # Sync with Capacitor
25
+ npx cap sync android
26
+
27
+ # Open Android Studio
28
+ npx cap open android
29
+ ```
30
+
31
+ ## Project Structure
32
+
33
+ ```
34
+ src/
35
+ ├── main.ts # Entry point — Ionic setup & router
36
+ ├── style.css # Global styles
37
+ └── pages/
38
+ └── HomePage.ts # Your first page (IonPage)
39
+ ```
40
+
41
+ ## Modular Loading
42
+
43
+ This template uses **nix-ionic v0.3.0** modular component loading.
44
+ Import only the bundles your app needs in `main.ts`:
45
+
46
+ ```ts
47
+ import { layoutComponents } from "@deijose/nix-ionic/bundles/layout";
48
+ import { formComponents } from "@deijose/nix-ionic/bundles/forms";
49
+ import { overlayComponents } from "@deijose/nix-ionic/bundles/overlays";
50
+
51
+ setupNixIonic({ components: [...layoutComponents, ...formComponents] });
52
+ ```
53
+
54
+ Available bundles: `layout`, `navigation`, `forms`, `lists`, `feedback`, `buttons`, `overlays`, `all`.
55
+
56
+ ## Learn More
15
57
 
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.
58
+ - [Nix.js Docs](https://github.com/DeijoseDevelop/nix-js)
59
+ - [Nix-Ionic on npm](https://www.npmjs.com/package/@deijose/nix-ionic)
60
+ - [Ionic Components](https://ionicframework.com/docs/components)
61
+ - [Capacitor Docs](https://capacitorjs.com/docs)
@@ -5,8 +5,9 @@
5
5
  <meta charset="UTF-8">
6
6
  <link rel="icon" href="/favicon.ico">
7
7
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
8
+ <script type="module" src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.esm.js"></script>
9
+ <script nomodule src="https://unpkg.com/ionicons@7.1.0/dist/ionicons/ionicons.js"></script>
8
10
  <title>Nix.js + Vite TS</title>
9
- <link rel="stylesheet" href="/src/style.css">
10
11
  </head>
11
12
 
12
13
  <body>
@@ -1,6 +1,6 @@
1
1
  {
2
- "name": "nix-js-ionic-template",
3
- "version": "1.0.0",
2
+ "name": "nix-ionic-app",
3
+ "version": "0.0.0",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "dev": "vite",
@@ -11,10 +11,10 @@
11
11
  "@capacitor/android": "^8.2.0",
12
12
  "@capacitor/cli": "^8.2.0",
13
13
  "@capacitor/core": "^8.2.0",
14
- "@deijose/nix-ionic": "^0.1.4",
14
+ "@deijose/nix-ionic": "^0.3.0",
15
15
  "@deijose/nix-js": "^1.7.7",
16
16
  "@ionic/core": "^8.8.1",
17
- "install": "^0.13.0"
17
+ "ionicons": "^8.0.13"
18
18
  },
19
19
  "devDependencies": {
20
20
  "typescript": "~5.9.3",
@@ -1,6 +1,4 @@
1
- import { defineCustomElements } from "@ionic/core/loader";
2
- defineCustomElements();
3
-
1
+ // 1. Core Ionic Styles
4
2
  import "@ionic/core/css/core.css";
5
3
  import "@ionic/core/css/normalize.css";
6
4
  import "@ionic/core/css/structure.css";
@@ -8,21 +6,36 @@ import "@ionic/core/css/typography.css";
8
6
  import "@ionic/core/css/padding.css";
9
7
  import "@ionic/core/css/flex-utils.css";
10
8
  import "@ionic/core/css/display.css";
9
+ import "./style.css";
11
10
 
11
+ // 2. Framework
12
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";
13
+ import { setupNixIonic, IonRouterOutlet } from "@deijose/nix-ionic";
14
+
15
+ // 3. Modular component bundles — import only what your app needs
16
+ import { layoutComponents } from "@deijose/nix-ionic/bundles/layout";
17
+ import { formComponents } from "@deijose/nix-ionic/bundles/forms";
18
+ import { listComponents } from "@deijose/nix-ionic/bundles/lists";
19
+
20
+ // 4. Pages
21
+ import { HomePage } from "./pages/HomePage";
22
+
23
+ // Register Ionic components
24
+ setupNixIonic({
25
+ components: [...layoutComponents, ...formComponents, ...listComponents],
26
+ });
16
27
 
28
+ // 5. Router
17
29
  const outlet = new IonRouterOutlet([
18
- { path: "/", component: (ctx) => new HomePage(ctx) },
19
- { path: "/detail/:id", component: (ctx) => new DetailPage(ctx) },
30
+ { path: "/", component: (ctx) => new HomePage(ctx) },
20
31
  ]);
21
32
 
33
+ // 6. Root App Component
22
34
  class App extends NixComponent {
23
- render() {
35
+ override render() {
24
36
  return html`<ion-app>${outlet}</ion-app>`;
25
37
  }
26
38
  }
27
39
 
40
+ // 7. Bootstrap
28
41
  mount(new App(), "#app");
@@ -0,0 +1,31 @@
1
+ import { html } from "@deijose/nix-js";
2
+ import { IonPage } from "@deijose/nix-ionic";
3
+ import type { PageContext } from "@deijose/nix-ionic";
4
+
5
+ export class HomePage extends IonPage {
6
+ constructor(ctx: PageContext) {
7
+ super(ctx.lc);
8
+ }
9
+
10
+ override render() {
11
+ return html`
12
+ <ion-header>
13
+ <ion-toolbar color="primary">
14
+ <ion-title>My Nix-Ionic App</ion-title>
15
+ </ion-toolbar>
16
+ </ion-header>
17
+
18
+ <ion-content class="ion-padding">
19
+ <ion-card>
20
+ <ion-card-header>
21
+ <ion-card-title>Welcome to Nix-Ionic 🚀</ion-card-title>
22
+ <ion-card-subtitle>Powered by Nix.js + Ionic + Capacitor</ion-card-subtitle>
23
+ </ion-card-header>
24
+ <ion-card-content>
25
+ <p>Edit <code>src/pages/HomePage.ts</code> to get started.</p>
26
+ </ion-card-content>
27
+ </ion-card>
28
+ </ion-content>
29
+ `;
30
+ }
31
+ }
@@ -1,79 +1,21 @@
1
+ /* App-level styles */
1
2
  :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;
3
+ --ion-font-family: -apple-system, BlinkMacSystemFont, "Helvetica Neue", "Roboto", sans-serif;
22
4
  }
23
5
 
24
- #app {
25
- max-width: 1280px;
26
- margin: 0 auto;
27
- padding: 2rem;
28
- text-align: center;
6
+ * {
7
+ box-sizing: border-box;
29
8
  }
30
9
 
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;
10
+ ion-card p {
11
+ color: var(--ion-color-medium);
12
+ margin-top: 8px;
42
13
  }
43
14
 
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
- }
15
+ ion-card code {
16
+ font-family: monospace;
17
+ background: var(--ion-color-light);
18
+ padding: 2px 6px;
19
+ border-radius: 4px;
20
+ font-size: 0.9em;
21
+ }
@@ -1,9 +1,6 @@
1
1
  import { defineConfig } from "vite";
2
2
 
3
3
  export default defineConfig({
4
- optimizeDeps: {
5
- exclude: ["@ionic/core"],
6
- },
7
4
  build: {
8
5
  rollupOptions: {
9
6
  output: { manualChunks: undefined },
@@ -1,80 +0,0 @@
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
- }
@@ -1,68 +0,0 @@
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
- }