create-switch-framework-app 0.1.0 → 0.2.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.
Files changed (37) hide show
  1. package/README.md +25 -25
  2. package/bin/create-switch-framework-app.js +510 -502
  3. package/package.json +31 -31
  4. package/templates/electron/base/app/(tabs)/+not-found.js +157 -157
  5. package/templates/electron/base/app/(tabs)/_layout.js +57 -93
  6. package/templates/electron/base/app/(tabs)/explore.js +55 -44
  7. package/templates/electron/base/app/(tabs)/index.js +10 -24
  8. package/templates/electron/base/app/+not-found.js +148 -158
  9. package/templates/electron/base/app/_layout.js +24 -44
  10. package/templates/electron/base/app/index.js +16 -30
  11. package/templates/electron/base/assets/logo.svg +5 -5
  12. package/templates/electron/base/components/SwSplashScreen.js +1 -1
  13. package/templates/electron/base/components/SwStarterSplashScreen.js +130 -140
  14. package/templates/electron/base/components/SwTabBar.js +146 -153
  15. package/templates/electron/base/electron/electron-builder.json +19 -19
  16. package/templates/electron/base/electron/main.js +30 -30
  17. package/templates/electron/base/electron/preload.js +5 -5
  18. package/templates/electron/base/index.js +2 -3
  19. package/templates/electron/base/main.js +1 -1
  20. package/templates/electron/base/preload.js +1 -1
  21. package/templates/electron/base/server.js +27 -42
  22. package/templates/web/base/app/(tabs)/+not-found.js +157 -157
  23. package/templates/web/base/app/(tabs)/_layout.js +57 -93
  24. package/templates/web/base/app/(tabs)/explore.js +55 -44
  25. package/templates/web/base/app/(tabs)/index.js +10 -24
  26. package/templates/web/base/app/+not-found.js +148 -158
  27. package/templates/web/base/app/_layout.js +24 -44
  28. package/templates/web/base/app/index.js +16 -30
  29. package/templates/web/base/assets/logo.svg +5 -5
  30. package/templates/web/base/components/SwSplashScreen.js +1 -1
  31. package/templates/web/base/components/SwStarterSplashScreen.js +130 -140
  32. package/templates/web/base/components/SwTabBar.js +146 -153
  33. package/templates/web/base/index.js +2 -3
  34. package/templates/electron/base/app/(tabs)/register.js +0 -12
  35. package/templates/electron/base/app/register.js +0 -12
  36. package/templates/web/base/app/(tabs)/register.js +0 -12
  37. package/templates/web/base/app/register.js +0 -12
@@ -1,44 +1,55 @@
1
- export const screen = {
2
- name: 'explore',
3
- path: '/explore',
4
- title: 'Explore',
5
- tag: 'sw-explore-screen',
6
- layout: 'tabs'
7
- };
8
-
9
- export class SwExploreScreen extends HTMLElement {
10
- constructor() {
11
- super();
12
- this.attachShadow({ mode: 'open' });
13
- }
14
-
15
- connectedCallback() {
16
- this.render();
17
- }
18
-
19
- render() {
20
- this.shadowRoot.innerHTML = `
21
- ${this.styleSheet()}
22
- <div class="wrap">
23
- <div class="h">Explore</div>
24
- <div class="p">This is a placeholder tab. Replace it with whatever you want.</div>
25
- </div>
26
- `;
27
- }
28
-
29
- styleSheet() {
30
- return `
31
- <style>
32
- :host{display:block;padding:18px;font-family:var(--font)}
33
- *{box-sizing:border-box;font-family:inherit}
34
- .wrap{max-width:900px;margin:0 auto;display:flex;flex-direction:column;gap:10px}
35
- .h{font-weight:1000;font-size:22px;color:var(--main_text)}
36
- .p{color:var(--sub_text);font-weight:800;line-height:1.5}
37
- </style>
38
- `;
39
- }
40
- }
41
-
42
- if (!customElements.get('sw-explore-screen')) {
43
- customElements.define('sw-explore-screen', SwExploreScreen);
44
- }
1
+ import { SwitchComponent } from 'switch-framework';
2
+
3
+ export class SwExploreScreen extends SwitchComponent {
4
+ static screenName = 'explore';
5
+ static path = '/explore';
6
+ static title = 'Explore';
7
+ static tag = 'sw-explore-screen';
8
+ static layout = 'tabs';
9
+
10
+ render() {
11
+ return `
12
+ <div class="wrap">
13
+ <div class="h">Explore</div>
14
+ <div class="p">This is a placeholder tab. Replace it with whatever you want.</div>
15
+ </div>
16
+ `;
17
+ }
18
+
19
+ styleSheet() {
20
+ return `
21
+ <style>
22
+ :host {
23
+ display: block;
24
+ padding: 18px;
25
+ font-family: var(--font, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
26
+ }
27
+
28
+ * {
29
+ box-sizing: border-box;
30
+ font-family: inherit;
31
+ }
32
+
33
+ .wrap {
34
+ max-width: 900px;
35
+ margin: 0 auto;
36
+ display: flex;
37
+ flex-direction: column;
38
+ gap: 10px;
39
+ }
40
+
41
+ .h {
42
+ font-weight: 1000;
43
+ font-size: 22px;
44
+ color: var(--main_text, #000);
45
+ }
46
+
47
+ .p {
48
+ color: var(--sub_text, #666);
49
+ font-weight: 600;
50
+ line-height: 1.5;
51
+ }
52
+ </style>
53
+ `;
54
+ }
55
+ }
@@ -1,30 +1,20 @@
1
- export const screen = {
2
- name: 'home',
3
- path: '/home',
4
- title: 'Home',
5
- tag: 'sw-home-screen',
6
- layout: 'tabs'
7
- };
8
-
9
- export class SwHomeScreen extends HTMLElement {
10
- constructor() {
11
- super();
12
- this.attachShadow({ mode: 'open' });
13
- }
1
+ import { SwitchComponent } from 'switch-framework';
14
2
 
15
- connectedCallback() {
16
- this.render();
17
- }
3
+ export class SwHomeScreen extends SwitchComponent {
4
+ static screenName = 'home';
5
+ static path = '/home';
6
+ static title = 'Home';
7
+ static tag = 'sw-home-screen';
8
+ static layout = 'tabs';
18
9
 
19
10
  render() {
20
- this.shadowRoot.innerHTML = `
21
- ${this.styleSheet()}
11
+ return `
22
12
  <div class="wrap">
23
13
  <div class="spacer-top"></div>
24
14
 
25
15
  <div class="hero">
26
16
  <div class="logo-container">
27
- <img class="logo" src="/assets/logo.svg" alt="Expo" />
17
+ <img class="logo" src="/assets/logo.svg" alt="Switch Framework" />
28
18
  </div>
29
19
  <div class="title">Tabs View</div>
30
20
  </div>
@@ -37,7 +27,7 @@ export class SwHomeScreen extends HTMLElement {
37
27
  <div class="card">
38
28
  <div class="row">
39
29
  <div class="l">Try editing</div>
40
- <div class="r">src/app/index.tsx</div>
30
+ <div class="r">src/app/(tabs)/index.js</div>
41
31
  </div>
42
32
  <div class="row">
43
33
  <div class="l">Dev tools</div>
@@ -212,7 +202,3 @@ export class SwHomeScreen extends HTMLElement {
212
202
  `;
213
203
  }
214
204
  }
215
-
216
- if (!customElements.get('sw-home-screen')) {
217
- customElements.define('sw-home-screen', SwHomeScreen);
218
- }
@@ -1,158 +1,148 @@
1
- export const screen = {
2
- name: '+not-found',
3
- path: '/+not-found',
4
- title: 'Not Found',
5
- tag: 'sw-user-not-found-screen',
6
- layout: 'stack'
7
- };
8
-
9
- export class SwUserNotFoundScreen extends HTMLElement {
10
- constructor() {
11
- super();
12
- this.attachShadow({ mode: 'open' });
13
- }
14
-
15
- static get observedAttributes() {
16
- return ['path'];
17
- }
18
-
19
- connectedCallback() {
20
- this.render();
21
- }
22
-
23
- attributeChangedCallback() {
24
- this.render();
25
- }
26
-
27
- render() {
28
- const path = this.getAttribute('path') || window.location.pathname || '';
29
-
30
- this.shadowRoot.innerHTML = `
31
- ${this.styleSheet()}
32
- <div class="wrap">
33
- <div class="card">
34
- <div class="code">404</div>
35
- <div class="h">This screen does not exist</div>
36
- <div class="p">No screen is registered for:</div>
37
- <div class="path">${path}</div>
38
-
39
- <div class="row">
40
- <button class="btn" id="home">Go to Home</button>
41
- <button class="btn secondary" id="back">Go Back</button>
42
- </div>
43
- </div>
44
- </div>
45
- `;
46
-
47
- this.shadowRoot.getElementById('home')?.addEventListener('click', () => {
48
- const navigate = globalStates?.getState ? globalStates.getState('navigate') : null;
49
- if (typeof navigate === 'function') navigate('home');
50
- });
51
-
52
- this.shadowRoot.getElementById('back')?.addEventListener('click', () => {
53
- const goBack = globalStates?.getState ? globalStates.getState('go_back') : null;
54
- if (typeof goBack === 'function') goBack();
55
- else window.history.back();
56
- });
57
- }
58
-
59
- styleSheet() {
60
- return `
61
- <style>
62
- :host {
63
- display: block;
64
- width: 100%;
65
- min-height: 100dvh;
66
- font-family: var(--font);
67
- }
68
-
69
- * {
70
- box-sizing: border-box;
71
- font-family: inherit;
72
- }
73
-
74
- .wrap {
75
- min-height: 100vh;
76
- display: flex;
77
- align-items: center;
78
- justify-content: center;
79
- padding: 18px;
80
- }
81
-
82
- .card {
83
- width: min(680px, 100%);
84
- background: transparent;
85
- border: none;
86
- border-radius: 18px;
87
- padding: 18px;
88
- box-shadow: none;
89
- }
90
-
91
- .code {
92
- font-weight: 1000;
93
- font-size: 44px;
94
- line-height: 1;
95
- color: var(--main_text);
96
- }
97
-
98
- .h {
99
- margin-top: 10px;
100
- font-weight: 1000;
101
- font-size: 20px;
102
- color: var(--main_text);
103
- }
104
-
105
- .p {
106
- margin-top: 6px;
107
- color: var(--sub_text);
108
- font-weight: 800;
109
- }
110
-
111
- .path {
112
- margin-top: 10px;
113
- padding: 10px 12px;
114
- border-radius: 14px;
115
- background: var(--surface_2);
116
- border: 1px solid var(--border_light);
117
- font-weight: 900;
118
- color: var(--main_text);
119
- word-break: break-word;
120
- }
121
-
122
- .row {
123
- margin-top: 14px;
124
- display: flex;
125
- gap: 10px;
126
- flex-wrap: wrap;
127
- }
128
-
129
- .btn {
130
- border: none;
131
- background: linear-gradient(135deg, #0091ff 0%, #0073e6 100%);
132
- color: #fff;
133
- font-weight: 1000;
134
- border-radius: 999px;
135
- padding: 10px 14px;
136
- cursor: pointer;
137
- }
138
-
139
- .btn:hover {
140
- opacity: 0.9;
141
- }
142
-
143
- .btn.secondary {
144
- background: var(--surface_2);
145
- color: var(--main_text);
146
- }
147
-
148
- .btn.secondary:hover {
149
- background: var(--surface_3);
150
- }
151
- </style>
152
- `;
153
- }
154
- }
155
-
156
- if (!customElements.get('sw-user-not-found-screen')) {
157
- customElements.define('sw-user-not-found-screen', SwUserNotFoundScreen);
158
- }
1
+ import { SwitchComponent } from 'switch-framework';
2
+ import { navigate, goBack } from 'switch-framework/router';
3
+
4
+ export class SwUserNotFoundScreen extends SwitchComponent {
5
+ static screenName = '+not-found';
6
+ static path = '/+not-found';
7
+ static title = 'Not Found';
8
+ static tag = 'sw-user-not-found-screen';
9
+ static layout = 'stack';
10
+
11
+ static get observedAttributes() {
12
+ return ['path'];
13
+ }
14
+
15
+ attributeChangedCallback(name, oldVal, newVal) {
16
+ if (name === 'path' && oldVal !== newVal) {
17
+ this._renderToShadow();
18
+ }
19
+ }
20
+
21
+ connected() {
22
+ this.shadowRoot.getElementById('home')?.addEventListener('click', () => {
23
+ navigate('home');
24
+ });
25
+
26
+ this.shadowRoot.getElementById('back')?.addEventListener('click', () => {
27
+ goBack();
28
+ });
29
+ }
30
+
31
+ render() {
32
+ const path = this.getAttribute('path') || (typeof window !== 'undefined' ? window.location.pathname : '') || '';
33
+
34
+ return `
35
+ <div class="wrap">
36
+ <div class="card">
37
+ <div class="code">404</div>
38
+ <div class="h">This screen does not exist</div>
39
+ <div class="p">No screen is registered for:</div>
40
+ <div class="path">${path}</div>
41
+
42
+ <div class="row">
43
+ <button class="btn" id="home">Go to Home</button>
44
+ <button class="btn secondary" id="back">Go Back</button>
45
+ </div>
46
+ </div>
47
+ </div>
48
+ `;
49
+ }
50
+
51
+ styleSheet() {
52
+ return `
53
+ <style>
54
+ :host {
55
+ display: block;
56
+ width: 100%;
57
+ min-height: 100dvh;
58
+ font-family: var(--font, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
59
+ }
60
+
61
+ * {
62
+ box-sizing: border-box;
63
+ font-family: inherit;
64
+ }
65
+
66
+ .wrap {
67
+ min-height: 100vh;
68
+ display: flex;
69
+ align-items: center;
70
+ justify-content: center;
71
+ padding: 18px;
72
+ }
73
+
74
+ .card {
75
+ width: min(680px, 100%);
76
+ background: transparent;
77
+ border: none;
78
+ border-radius: 18px;
79
+ padding: 18px;
80
+ box-shadow: none;
81
+ }
82
+
83
+ .code {
84
+ font-weight: 1000;
85
+ font-size: 44px;
86
+ line-height: 1;
87
+ color: var(--main_text, #000);
88
+ }
89
+
90
+ .h {
91
+ margin-top: 10px;
92
+ font-weight: 1000;
93
+ font-size: 20px;
94
+ color: var(--main_text, #000);
95
+ }
96
+
97
+ .p {
98
+ margin-top: 6px;
99
+ color: var(--sub_text, #666);
100
+ font-weight: 800;
101
+ }
102
+
103
+ .path {
104
+ margin-top: 10px;
105
+ padding: 10px 12px;
106
+ border-radius: 14px;
107
+ background: var(--surface_2, #f5f5f5);
108
+ border: 1px solid var(--border_light, #e5e5e5);
109
+ font-weight: 900;
110
+ color: var(--main_text, #000);
111
+ word-break: break-word;
112
+ }
113
+
114
+ .row {
115
+ margin-top: 14px;
116
+ display: flex;
117
+ gap: 10px;
118
+ flex-wrap: wrap;
119
+ }
120
+
121
+ .btn {
122
+ border: none;
123
+ background: linear-gradient(135deg, #0091ff 0%, #0073e6 100%);
124
+ color: #fff;
125
+ font-weight: 1000;
126
+ border-radius: 999px;
127
+ padding: 10px 14px;
128
+ cursor: pointer;
129
+ }
130
+
131
+ .btn:hover {
132
+ opacity: 0.9;
133
+ }
134
+
135
+ .btn.secondary {
136
+ background: var(--surface_2, #f5f5f5);
137
+ color: var(--main_text, #000);
138
+ }
139
+
140
+ .btn.secondary:hover {
141
+ background: var(--surface_3, #eee);
142
+ }
143
+ </style>
144
+ `;
145
+ }
146
+ }
147
+
148
+ export default SwUserNotFoundScreen;
@@ -1,50 +1,30 @@
1
- import { Stack, registerScreens } from '/switch-framework/index.js';
2
- import tabsLayout from './(tabs)/_layout.js';
3
-
4
- const tabScreens = Array.isArray(tabsLayout?.screens) ? tabsLayout.screens : [];
5
-
6
- const stackScreens = [
7
- Stack.screen({
8
- name: 'index',
9
- path: '/',
10
- title: 'Welcome',
11
- tag: 'sw-index-screen'
12
- }),
13
- Stack.screen({
14
- name: '+not-found',
15
- path: '/+not-found',
16
- title: 'Not Found',
17
- tag: 'sw-user-not-found-screen'
18
- })
19
- ];
20
-
21
- const screens = registerScreens({
22
- stackScreens,
23
- tabsLayout,
24
- tabScreens,
25
- validate: true
26
- }).screens;
27
-
28
- const layout = {
29
- splash: 'sw-starter-splash',
30
- initialRoute: 'index',
31
- screens,
32
-
33
- async init({ globalStates, renderSplashscreen }) {
1
+ import { StackLayout, createState, registerComponents } from 'switch-framework';
2
+ import { SwStarterSplashScreen } from '../components/SwStarterSplashScreen.js';
3
+ import { SwTabBar } from '../components/SwTabBar.js';
4
+ import { SwIndexScreen } from './index.js';
5
+ import NotFoundScreen from './+not-found.js';
6
+ import { SwTabsLayout } from './(tabs)/_layout.js';
7
+
8
+ registerComponents([SwStarterSplashScreen, SwTabBar]);
9
+
10
+ export class SwStackLayout extends StackLayout {
11
+ static tag = 'sw-stack-layout';
12
+ static stackScreens = [SwIndexScreen, NotFoundScreen];
13
+ static tabsLayout = SwTabsLayout;
14
+ static splash = 'sw-starter-splash';
15
+ static initialRoute = 'index';
16
+
17
+ static async init({ globalStates, renderSplashscreen }) {
34
18
  renderSplashscreen('sw-starter-splash');
35
19
 
36
- // your async operation here that made splashscreen appear
37
- await new Promise((resolve) => setTimeout(resolve, 3000));
20
+ // Example: create app-level state
21
+ createState(0, 'example-counter');
38
22
 
39
- globalStates.setState({
40
- tabsLayout
41
- });
23
+ // Simulate async init (e.g. load config, auth check)
24
+ await new Promise((resolve) => setTimeout(resolve, 3000));
42
25
 
43
- return {
44
- splash: 'sw-starter-splash',
45
- initialRoute: 'index'
46
- };
26
+ return { splash: 'sw-starter-splash', initialRoute: 'index' };
47
27
  }
48
- };
28
+ }
49
29
 
50
- export default layout;
30
+ export default SwStackLayout.getAppLayout();
@@ -1,37 +1,27 @@
1
- export const screen = {
2
- name: 'index',
3
- path: '/',
4
- title: 'Welcome',
5
- tag: 'sw-index-screen',
6
- layout: 'stack'
7
- };
8
-
9
- export class SwIndexScreen extends HTMLElement {
10
- constructor() {
11
- super();
12
- this.attachShadow({ mode: 'open' });
13
- }
14
-
15
- async connectedCallback() {
16
- this.render();
17
-
18
- const replace = globalStates?.getState ? globalStates.getState('replace') : null;
19
- const redirect = globalStates?.getState ? globalStates.getState('redirect') : null;
20
-
21
- this.shadowRoot.querySelector('#go_home').addEventListener('click', () => {
22
- if (typeof replace === 'function') return replace('home');
1
+ import { SwitchComponent } from 'switch-framework';
2
+ import { navigate } from 'switch-framework/router';
3
+
4
+ export class SwIndexScreen extends SwitchComponent {
5
+ static screenName = 'index';
6
+ static path = '/';
7
+ static title = 'Welcome';
8
+ static tag = 'sw-index-screen';
9
+ static layout = 'stack';
10
+
11
+ connected() {
12
+ this.shadowRoot.querySelector('#go_home')?.addEventListener('click', () => {
13
+ navigate('home');
23
14
  });
24
15
  }
25
16
 
26
17
  render() {
27
- this.shadowRoot.innerHTML = `
28
- ${this.styleSheet()}
18
+ return `
29
19
  <div class="wrap">
30
20
  <div class="spacer-top"></div>
31
21
 
32
22
  <div class="hero">
33
23
  <div class="logo-container">
34
- <img class="logo" src="/assets/logo.svg" alt="Expo" />
24
+ <img class="logo" src="/assets/logo.svg" alt="Switch Framework" />
35
25
  </div>
36
26
  <div class="title">Introducing<br>Switch Framework</div>
37
27
  </div>
@@ -44,7 +34,7 @@ export class SwIndexScreen extends HTMLElement {
44
34
  <div class="card">
45
35
  <div class="row">
46
36
  <div class="l">Try editing</div>
47
- <div class="r">src/app/index.tsx</div>
37
+ <div class="r">src/app/index.js</div>
48
38
  </div>
49
39
  <div class="row">
50
40
  <div class="l">Dev tools</div>
@@ -259,7 +249,3 @@ export class SwIndexScreen extends HTMLElement {
259
249
  `;
260
250
  }
261
251
  }
262
-
263
- if (!customElements.get('sw-index-screen')) {
264
- customElements.define('sw-index-screen', SwIndexScreen);
265
- }
@@ -1,5 +1,5 @@
1
- <svg width="160" height="160" viewBox="0 0 160 160" fill="none" xmlns="http://www.w3.org/2000/svg">
2
- <rect x="8" y="8" width="144" height="144" rx="36" fill="#E60023"/>
3
- <path d="M53 59C53 49.6112 60.6112 42 70 42H90C99.3888 42 107 49.6112 107 59V63C107 72.3888 99.3888 80 90 80H78C72.4772 80 68 84.4772 68 90V94C68 103.389 60.3888 111 51 111H50" stroke="white" stroke-width="12" stroke-linecap="round"/>
4
- <path d="M110 111H94" stroke="white" stroke-width="12" stroke-linecap="round"/>
5
- </svg>
1
+ <svg width="160" height="160" viewBox="0 0 160 160" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <rect x="8" y="8" width="144" height="144" rx="36" fill="#E60023"/>
3
+ <path d="M53 59C53 49.6112 60.6112 42 70 42H90C99.3888 42 107 49.6112 107 59V63C107 72.3888 99.3888 80 90 80H78C72.4772 80 68 84.4772 68 90V94C68 103.389 60.3888 111 51 111H50" stroke="white" stroke-width="12" stroke-linecap="round"/>
4
+ <path d="M110 111H94" stroke="white" stroke-width="12" stroke-linecap="round"/>
5
+ </svg>
@@ -1 +1 @@
1
- export { SwStarterSplashScreen as SwSplashScreen } from './SwStarterSplashScreen.js';
1
+ export { SwStarterSplashScreen as SwSplashScreen } from './SwStarterSplashScreen.js';