nativescript-web-adapter 0.1.2 → 0.1.3

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 (97) hide show
  1. package/README.md +218 -246
  2. package/core/components/AbsoluteLayout.vue +11 -0
  3. package/core/components/ActionBar.vue +11 -0
  4. package/core/components/ActionItem.vue +11 -0
  5. package/core/components/ActivityIndicator.vue +15 -0
  6. package/core/components/Button.vue +41 -0
  7. package/core/components/DatePicker.vue +27 -0
  8. package/core/components/DockLayout.vue +23 -0
  9. package/core/components/FlexboxLayout.vue +11 -0
  10. package/core/components/Frame.vue +11 -0
  11. package/core/components/GridLayout.vue +85 -0
  12. package/core/components/HtmlView.vue +13 -0
  13. package/core/components/Image.vue +12 -0
  14. package/core/components/ImageCacheIt.vue +12 -0
  15. package/core/components/Label.vue +15 -0
  16. package/core/components/ListPicker.vue +21 -0
  17. package/core/components/ListView.vue +12 -0
  18. package/core/components/NavigationButton.vue +28 -0
  19. package/core/components/Page.vue +18 -0
  20. package/core/components/Placeholder.vue +11 -0
  21. package/core/components/Progress.vue +12 -0
  22. package/core/components/RootLayout.vue +11 -0
  23. package/core/components/ScrollView.vue +11 -0
  24. package/core/components/SearchBar.vue +22 -0
  25. package/core/components/SegmentedBar.vue +50 -0
  26. package/core/components/SegmentedBarItem.vue +21 -0
  27. package/core/components/Slider.vue +18 -0
  28. package/core/components/StackLayout.vue +11 -0
  29. package/core/components/Switch.vue +26 -0
  30. package/core/components/TabView.vue +48 -0
  31. package/core/components/TabViewItem.vue +27 -0
  32. package/core/components/TextField.vue +15 -0
  33. package/core/components/TextView.vue +18 -0
  34. package/core/components/TimePicker.vue +21 -0
  35. package/core/components/WebView.vue +13 -0
  36. package/core/components/WrapLayout.vue +11 -0
  37. package/core/components/index.js +3 -0
  38. package/core/components/index.ts +35 -0
  39. package/core/composables/dialogs.ts +31 -0
  40. package/core/composables/index.js +3 -0
  41. package/core/composables/index.ts +4 -0
  42. package/core/composables/useActionBar.js +7 -0
  43. package/core/composables/useActionBar.ts +19 -0
  44. package/core/composables/useFrame.js +8 -0
  45. package/core/composables/useFrame.ts +25 -0
  46. package/core/composables/usePage.js +8 -0
  47. package/core/composables/usePage.ts +25 -0
  48. package/core/env.d.ts +7 -0
  49. package/core/index.js +4 -0
  50. package/core/index.ts +85 -0
  51. package/core/types.ts +12 -0
  52. package/dist/nativescript-web-adapter.es.js +83 -0
  53. package/dist/nativescript-web-adapter.umd.js +1 -0
  54. package/dist/style.css +1 -0
  55. package/package.json +35 -49
  56. package/tools/cli.cjs +45 -0
  57. package/tools/create-web-platform.cjs +76 -0
  58. package/tools/create-web-platform.js +196 -0
  59. package/tools/modules/appPatch.cjs +27 -0
  60. package/tools/modules/copy.cjs +84 -0
  61. package/tools/modules/router.cjs +46 -0
  62. package/tools/modules/templates.cjs +130 -0
  63. package/tools/modules/transform.cjs +93 -0
  64. package/dist/core.cjs +0 -3
  65. package/dist/core.cjs.map +0 -1
  66. package/dist/core.js +0 -2
  67. package/dist/core.js.map +0 -1
  68. package/dist/index.cjs +0 -377
  69. package/dist/index.cjs.map +0 -1
  70. package/dist/index.css +0 -172
  71. package/dist/index.js +0 -361
  72. package/dist/index.js.map +0 -1
  73. package/dist/types/core/index.d.ts +0 -8
  74. package/dist/types/index.d.ts +0 -1
  75. package/dist/types/index.types.d.ts +0 -1
  76. package/dist/types/vue/components/ActionBar.d.ts +0 -5
  77. package/dist/types/vue/components/ActionItem.d.ts +0 -15
  78. package/dist/types/vue/components/Button.d.ts +0 -26
  79. package/dist/types/vue/components/ContentView.d.ts +0 -3
  80. package/dist/types/vue/components/FlexboxLayout.d.ts +0 -35
  81. package/dist/types/vue/components/Frame.d.ts +0 -3
  82. package/dist/types/vue/components/GridLayout.d.ts +0 -26
  83. package/dist/types/vue/components/ImageCacheIt.d.ts +0 -23
  84. package/dist/types/vue/components/Label.d.ts +0 -26
  85. package/dist/types/vue/components/ListView.d.ts +0 -24
  86. package/dist/types/vue/components/Page.d.ts +0 -5
  87. package/dist/types/vue/components/StackLayout.d.ts +0 -5
  88. package/dist/types/vue/components/TabView.d.ts +0 -26
  89. package/dist/types/vue/components/TabViewItem.d.ts +0 -24
  90. package/dist/types/vue/index.d.ts +0 -18
  91. package/dist/types/vue/index.types.d.ts +0 -17
  92. package/dist/types/vue.d.ts +0 -266
  93. package/dist/vue.cjs +0 -377
  94. package/dist/vue.cjs.map +0 -1
  95. package/dist/vue.css +0 -172
  96. package/dist/vue.js +0 -361
  97. package/dist/vue.js.map +0 -1
package/README.md CHANGED
@@ -1,270 +1,242 @@
1
1
  # NativeScript for Web
2
2
 
3
- Read this in Chinese: [README_ZH.md](README_ZH.md)
3
+ 中文: [README_ZH.md](README_ZH.md)
4
4
 
5
- Map common NativeScript UI tags to browser-ready Vue 3 components, enabling the same SFC to run on both Native and Web. Inspired by React Native for Web.
5
+ [![npm](https://img.shields.io/npm/v/nativescript-web-adapter.svg?logo=npm&label=npm)](https://www.npmjs.com/package/nativescript-web-adapter)
6
+ [![MIT License](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
6
7
 
7
- Ideal for quickly previewing, debugging, or shipping a simplified web version of existing NativeScript Vue projects.
8
+ This project is a “web adapter” for NativeScript‑Vue‑Vite. It can transform native app code into a pure Vue Web project that runs in the browser (generated under `platforms/web/`).
8
9
 
9
- ## Features
10
+ ---
10
11
 
11
- - Same tag names: use `Page`, `ActionBar`, `GridLayout`, `Label`, `Button`, `ImageCacheIt` directly in SFCs.
12
- - Prop and event mapping: common props/events are translated to DOM (e.g., `tap` → `click`).
13
- - Lightweight implementation: focuses on frequently used layouts and controls.
14
- - Pluggable: registered as a Vue plugin; no invasive app changes.
12
+ ## Quick Start
15
13
 
16
- ## Installation
14
+ Temporarily add the local bin to `PATH` to make the `ns-web` command available:
17
15
 
18
- Install the adapter from npm:
19
-
20
- ```
21
- npm install nativescript-web-adapter
22
- ```
23
-
24
- This package expects `vue` as a peer dependency. If not already present:
25
-
26
- ```
27
- npm install vue@^3.4.0
16
+ ```bash
17
+ export PATH="$PWD/node_modules/.bin:$PATH"
28
18
  ```
29
19
 
30
- ## Quick Start (Web)
31
-
32
- 1) Register the plugin
33
-
34
- ```ts
35
- // src/web/main.ts
36
- import { createApp } from 'vue';
37
- import { NativeScriptWebPlugin } from 'nativescript-web-adapter';
38
- import Home from '@/components/Home.vue';
39
- import '@/app.css';
20
+ Compile the web template – install dependencies – start the web project's dev server:
40
21
 
41
- const app = createApp(Home);
42
- app.use(NativeScriptWebPlugin);
43
- app.mount('#app');
44
- ```
22
+ Web
45
23
 
46
- 2) Vite aliases (map NS deps to the adapter for browser)
47
-
48
- ```ts
49
- // vite.web.config.ts
50
- import { defineConfig } from 'vite';
51
- import vue from '@vitejs/plugin-vue';
52
- import path from 'path';
53
-
54
- export default defineConfig({
55
- plugins: [vue()],
56
- resolve: {
57
- alias: {
58
- '@': path.resolve(__dirname, 'src'),
59
- '~': path.resolve(__dirname, 'src'),
60
- // map SFC imports of nativescript-vue to browser vue
61
- 'nativescript-vue': 'vue',
62
- // map @nativescript/core types/APIs to adapter core (browser-only)
63
- '@nativescript/core': 'nativescript-web-adapter/core'
64
- }
65
- }
66
- });
24
+ ```bash
25
+ ns-web dev
67
26
  ```
68
27
 
69
- 3) Start the dev server
28
+ iOS
70
29
 
71
30
  ```bash
72
- npm run dev:web
31
+ ns run ios
73
32
  ```
74
33
 
75
- ## Usage Example
76
-
77
- ```vue
78
- <template>
79
- <Frame>
80
- <Page class="bg-[#251353]">
81
- <ActionBar>
82
- <Label text="ViteConf 2025" class="font-bold text-lg" />
83
- </ActionBar>
84
-
85
- <GridLayout rows="auto,*">
86
- <ImageCacheIt
87
- src="https://example.com/cover.jpg"
88
- stretch="aspectFill"
89
- class="align-top"
90
- style="width:100dvw"
91
- />
92
-
93
- <GridLayout row="1" rows="*,auto,*" class="gradient-purple p-6">
94
- <Label
95
- class="text-xl align-middle text-center text-[#77c9fa] font-bold"
96
- text="Hype Counter: 31485"
97
- />
98
-
99
- <Button
100
- row="1"
101
- class="p-6 text-white font-bold border-4 border-[#77c9fa] rounded-lg text-xl gradient-light-purple"
102
- horizontalAlignment="center"
103
- >
104
- Enter Now
105
- </Button>
106
- </GridLayout>
107
- </GridLayout>
108
- </Page>
109
- </Frame>
110
- </template>
111
- ```
34
+ Android
112
35
 
113
- ## Component Mapping
114
-
115
- - `Page` → DOM `main`
116
- - `ActionBar` → DOM `header`
117
- - `Frame` → DOM `div`
118
- - `Label` → DOM `span`
119
- - `Button` → DOM `button`
120
- - `StackLayout` → DOM `div` (`display:flex; flex-direction:column`)
121
- - `FlexboxLayout` → DOM `div` (`display:flex`; supports `flexDirection`, `justifyContent`, `alignItems`)
122
- - `GridLayout` → DOM `div` (`display:grid`; details below)
123
- - `ImageCacheIt` → DOM `img` (simple replacement; uses `img` with `stretch` support)
124
-
125
- ## Newly Supported Components
126
-
127
- - `ActionItem` → DOM `div` inside `ActionBar`
128
- - Renders slot content (e.g., a `Button`)
129
- - Supports `ios.position="right"` to push the item to the right (`margin-left:auto`)
130
-
131
- - `ContentView` → DOM `div`
132
- - A simple container that passes classes and styles through
133
-
134
- - `ListView` → DOM `div`
135
- - Accepts `:items` (array) and renders the default slot for each item
136
- - Supports `separatorColor` (e.g., `transparent` or `rgba(...)`)
137
- - Minimal, performant rendering aimed at common list use cases
138
-
139
- ## Custom CSS Usage
140
-
141
- - Built-in base classes are provided for web rendering in `dist/vue.css`.
142
- - Optional import (recommended for consistent base styles):
143
-
144
- ```ts
145
- // src/web/main.ts
146
- import 'nativescript-web-adapter/dist/vue.css';
36
+ ```bash
37
+ ns run android
147
38
  ```
148
39
 
149
- - You can define your own classes in `src/app.css` and apply them to NS tags.
150
- - Example list styling that pairs well with `ListView` and `GridLayout`:
151
-
152
- ```css
153
- /* src/app.css */
154
- .list-container {}
155
- .list-item { display:grid; grid-template-columns:1fr auto; align-items:center; padding:12px 16px; border-bottom:1px solid rgba(255,255,255,0.12); }
156
- .list-item:hover { background:rgba(255,255,255,0.06); border-radius:12px; }
157
- .list-title { font-size:18px; color:#fff; }
158
- .list-dot { width:20px; height:20px; border-radius:9999px; background:#fff; }
159
- .back-button { padding:8px 12px; color:#fff; font-weight:600; border:2px solid #77c9fa; border-radius:12px; font-size:14px; background:linear-gradient(to bottom, #6544b7, #251353); }
160
- ```
40
+ ## Table of Contents
41
+
42
+ - Background & Goals
43
+ - Tech Stack & Dependencies
44
+ - Native Side (NativeScript)
45
+ - Web Side (Generated Vue Project)
46
+ - Web Adapter (Generator & Package)
47
+ - Run & Build
48
+ - Transformation & Adaptation Rules (Detailed)
49
+ - Styles & Tailwind Configuration
50
+ - Types & TS Configuration
51
+ - HMR (Hot Module Replacement)
52
+ - FAQ & Limitations
53
+ - Improvements & Upgrade Suggestions
54
+
55
+ ---
56
+
57
+ ## Background & Goals
58
+
59
+ - Provide a native app example using `nativescript-vue` + `@nativescript/vite`, showcasing development and HMR on iOS/Android.
60
+ - Provide a “web adapter” (local package `nativescript-web-adapter`) that scans and transforms the project's `src/` code to generate a Vue application that runs in the browser, enabling quick preview and collaboration on desktop browsers.
61
+ - The generated Web project lives in `platforms/web/` with its own Vite config, dependencies, and entry files, without affecting the native side.
62
+
63
+ ---
64
+
65
+ ## Tech Stack & Dependencies
66
+
67
+ - Native side (NativeScript):
68
+ - `nativescript-vue@3.0.1` (uses `patch-package` to inject HMR helpers)
69
+ - `@nativescript/core@alpha`, `@nativescript/vite@^0.0.1-alpha.7` (NativeScript v9 prerelease)
70
+ - Example native plugins: `@triniwiz/nativescript-image-cache-it`, `@valor/nativescript-websockets`, `nativescript-inappbrowser`
71
+ - Web side (generated project):
72
+ - `vue@^3.4`, `vue-router@^4.2`
73
+ - `vite@^5`, `@vitejs/plugin-vue@^5`
74
+ - `tailwindcss@^3.4`, `postcss`, `autoprefixer`
75
+ - Adapter package (local):
76
+ - `nativescript-web-adapter/` uses Vite library mode to build UMD/ESM, with built-in generator scripts and a simple CLI.
77
+
78
+ ---
79
+
80
+ ## Native Side (NativeScript)
81
+
82
+ - Entry `src/app.ts`:
83
+ - Starts the native app via `createApp(Home).start()` from `nativescript-vue`.
84
+ - Registers the native element `ImageCacheIt`.
85
+ - On Android, uses `Application.on(Application.launchEvent)` to adjust system status/navigation bar styles.
86
+ - Page `src/components/Home.vue`:
87
+ - Uses NS layouts and components such as `Frame/Page/ActionBar/GridLayout/Label/Button/ImageCacheIt`.
88
+ - Uses `@tap` to open native links (iOS uses `UIApplication.openURL`, Android uses `Intent`).
89
+ - Maintains a simple counter in `mounted/unmounted` to demonstrate HMR and state refresh.
90
+ - Global init `src/globals.ts`:
91
+ - Defines touch animations (iOS: `UIView.animate`, Android: `View.animate`), replaced by a no‑op shim on the Web side.
92
+ - Native Vite config `vite.config.ts`:
93
+ - `export default defineConfig(({ mode }) => mergeConfig(vueConfig({ mode }), {}))` merges the NS official Vite template to support HMR and build.
94
+ - Tailwind & styles:
95
+ - `src/app.css` defines theme colors and gradient classes (`gradient-purple/gradient-light-purple`), and sets the `ActionBar` primary color.
96
+ - `tailwind.config.js` uses `darkMode: ["class", ".ns-dark"]` and disables `preflight` (matching native rendering).
97
+
98
+ ---
99
+
100
+ ## Web Side (Generated Vue Project)
101
+
102
+ - Output location: `platforms/web/`
103
+ - Example structure:
161
104
 
162
- - Example usage in a SFC:
163
-
164
- ```vue
165
- <template>
166
- <Page>
167
- <ActionBar title="Details">
168
- <!-- Web-only back button; native uses system back -->
169
- <ActionItem>
170
- <Button text="Back" class="back-button" @tap="goBack" />
171
- </ActionItem>
172
- </ActionBar>
173
-
174
- <ListView :items="items" separatorColor="rgba(255,255,255,0.12)" class="list-container">
175
- <template #default="{ item }">
176
- <GridLayout columns="*, auto" class="list-item">
177
- <Label :text="item" class="list-title" />
178
- <ContentView col="1" class="list-dot" />
179
- </GridLayout>
180
- </template>
181
- </ListView>
182
- </Page>
183
- </template>
105
+ ```
106
+ platforms/web/
107
+ package.json # generated (includes vue + vue-router)
108
+ vite.config.ts # generated (server.port = 3005, strictPort = true)
109
+ index.html
110
+ postcss.config.js
111
+ tailwind.config.js
112
+ src/
113
+ App.vue # root component (<router-view />)
114
+ app.ts # entry (register adapter web components, mount '#app')
115
+ router/index.ts # default route (Home)
116
+ globals.ts # web shim: initGlobals() no-op
117
+ components/
118
+ Home.vue # copied and transformed from native
119
+ websfc/ # adapter web components (ActionBar/Page/Frame)
120
+ composables/
121
+ websfc/ # adapter composables (useActionBar/usePage/useFrame)
184
122
  ```
185
123
 
186
- ## Extending the Adapter & Contributing
187
-
188
- ### Add a New Component
189
-
190
- 1. Create the component under `src/vue/components/YourComponent.ts` using `defineComponent` and map props/events to DOM.
191
- 2. Register it in `src/vue/index.ts` under the plugin so it becomes available in Vue.
192
- 3. Export its types in `src/vue/index.types.ts` to keep type parity.
193
- 4. Add baseline styles in `src/vue/adapter.css` (class name convention: `.ns-your-component`).
194
- 5. Build the adapter with `npm run build` and test in the demo project (`npm run dev:web`).
195
-
196
- ### PR Guidelines
197
-
198
- - Keep implementations lightweight and focused on common use cases.
199
- - Preserve NativeScript semantics where reasonable; document any deviations.
200
- - Map events consistently (e.g., `tap` → `click`).
201
- - Include type exports, baseline CSS, and an example snippet in the docs.
202
- - Add or update tests where applicable (`tests/*`).
203
- - Keep code style consistent with existing files; avoid introducing heavy dependencies.
204
-
205
- ## GridLayout: Design & Behavior
206
-
207
- - Container styles
208
- - `display: grid`
209
- - `grid-template-columns`: defaults to single column `1fr` when `columns` is not provided
210
- - `grid-template-rows`: parsed from `rows` (optional)
211
- - `grid-auto-flow: row`: auto-stacks vertically by rows
212
- - `width: 100%`, `height: 100%`
213
-
214
- - Track parsing (`rows`/`columns`)
215
- - Comma-separated: e.g., `"auto,*"`, `"*,auto,*"`
216
- - `*` → `1fr`, `auto` → `auto`, numbers → pixels (e.g., `60` → `60px`)
217
- - Example: `rows="auto,*"` → `grid-template-rows: auto 1fr`
218
-
219
- - Child placement & span
220
- - Indexing: NativeScript is 0-based; CSS Grid is 1-based. `row=0` `grid-row-start:1`, `col=0` → `grid-column-start:1`
221
- - Default column: if `col`/`column` is not set, we enforce `grid-column-start:1` to avoid implicit multi-column side-by-side layout
222
- - Span: `rowSpan` `grid-row-end: span n`; `colSpan` → `grid-column-end: span n`
223
-
224
- - Alignment
225
- - Horizontal: `horizontalAlignment` (`left|center|right|stretch`) `justify-self`
226
- - Vertical: `verticalAlignment` (`top|center|bottom|stretch`) `align-self`
227
-
228
- ## Other Props & Events
229
-
230
- - Events: `tap` DOM `click` (the adapter emits `tap` on `onClick`)
231
- - `Label` alignment: `horizontalAlignment="center"` `text-align:center`
232
- - `ImageCacheIt`:
233
- - `stretch="aspectFill"` `object-fit: cover`
234
- - `stretch="aspectFit"` → `object-fit: contain`
235
- - default styles: `width:100%`, `display:block`, `object-position:center`
236
-
237
- ## Layout Tips (Aligning Web with iOS)
238
-
239
- - Make the outer `main` full viewport height: `main { height: 100vh; }` to match Grid remaining-space behavior.
240
- - For full-width images: use `style="width:100dvw"` or container `width:100%`; ensure no implicit columns. Optionally set inner `GridLayout` `columns="1*"`.
241
- - If children appear side-by-side: check if `columns` is declared or `col` is set; by default we fix to column 1.
242
-
243
- ## Compatibility & Limitations
244
-
245
- - The adapter focuses on common UI/layout features; complex native measurements, animations, and platform APIs are out of scope for the browser.
246
- - Visual differences (fonts, line height, shadows) exist between iOS/Android and browsers; tweak via Tailwind/CSS.
247
- - Events follow the DOM model; certain native events are not applicable.
248
-
249
- ## Development & Build
250
-
251
- - Build the adapter: `npm run build` (outputs `dist/index.js`, `dist/vue.js`, `dist/core.js` and types)
252
- - Run tests: `npm run test`
253
- - Demo project in this repo: `npm run dev:web` starts the browser preview.
254
-
255
- ## Package Structure (Adapter Subpackage)
256
-
257
- - `src/vue/components/*`: implementation of UI components
258
- - `src/vue/index.ts`: Vue plugin entry (registers all components)
259
- - `src/core`: minimal types/placeholders for `@nativescript/core` in browser
260
- - `dist/*`: build outputs and type declarations
261
-
262
- ## Design Rationale
263
-
264
- - Keep NativeScript tag parity to reduce migration and dual-edge maintenance costs.
265
- - Use standard web layout primitives (Flex/Grid) for debuggability and extensibility.
266
- - Clear mapping rules: 0→1 index conversion, `*`/`auto`/px track parsing, and alignment/span mapping — minimal surprises.
267
-
268
- ## Feedback & Improvements
269
-
270
- Try it in your projects and share feedback. If you need more components or refined behaviors (absolute positioning, interactions), add implementations under `src/vue/components` following the existing pattern, and submit a PR.
124
+ - Default dev URL: `http://localhost:3005/` (if the port is taken, it fails directly; set `strictPort` to `false` in `vite.config.ts` to enable fallback).
125
+
126
+ ---
127
+
128
+ ## Web Adapter (Generator & Package)
129
+
130
+ - Location: `nativescript-web-adapter/`
131
+ - Key files:
132
+ - `tools/create-web-platform.cjs`: generation script (copy, transform, write templates).
133
+ - `core/components/*.vue`: web SFC containers (`ActionBar/Page/Frame`).
134
+ - `core/composables/*.ts`: composables (`useActionBar/usePage/useFrame`).
135
+ - `core/types.ts`: component type aliases and composable type exports.
136
+ - `index.ts`: adapter installer (`install(app)` registers components and attaches `$ns`).
137
+ - `vite.config.ts`: library mode build (`external: ['vue']`, outputs UMD/ESM).
138
+ - CLI: `tools/cli.cjs`
139
+ - Local command: `node nativescript-web-adapter/tools/cli.cjs init`
140
+ - Includes a `create:web` NPM script (for the root project to call).
141
+
142
+ ---
143
+
144
+ ## Run & Build
145
+
146
+ - Native side (with HMR):
147
+ - `npm run dev:ios`: run Vite (port `5173`) and NS iOS debug in parallel.
148
+ - `npm run dev:android`: run Vite and NS Android debug in parallel.
149
+ - `npm run ios` / `npm run android`: use `ns debug` for debugging builds.
150
+ - Generate and run the Web project:
151
+ - `npm run dev:web`: run the adapter generator, then enter `platforms/web`, install deps, and start the Web Vite dev server.
152
+ - On first run, it creates `platforms/web` along with required templates and configuration.
153
+
154
+ ---
155
+
156
+ ## Transformation & Adaptation Rules (Detailed)
157
+
158
+ The generator’s `transformContent()` currently performs only necessary code‑level replacements and no longer replaces NS tags in SFC templates with native HTML tags; the UI is handled by custom web components.
159
+
160
+ - Import replacements and removals:
161
+ - `from 'nativescript-vue'` → `from 'vue'`
162
+ - Remove `import ... from '@nativescript/core'` (the web build does not load the native runtime)
163
+ - Remove `import ... from '@nativescript/web-adapter'` (the generated web project uses local components directly)
164
+ - Platform declarations and native calls cleanup:
165
+ - Remove common native declarations (e.g., `declare var com;`).
166
+ - Remove `Application.on(...)` and similar platform event registrations (including those with `__ANDROID__` or `Application.launchEvent`).
167
+ - Template retains NS tags:
168
+ - Components kept and registered on the Web: `ActionBar/Page/Frame/StackLayout/GridLayout/FlexboxLayout/WrapLayout/ScrollView/Label/Button/Image/HtmlView/ImageCacheIt`.
169
+ - Special downgrade: `ImageCacheIt` is implemented as a simple `<img>` on the Web (also provided as a web component of the same name for consistent usage).
170
+ - Unified native link opening logic:
171
+ - Replace the example `enterNow(...)` with the browser implementation: `window.open('https://viteconf.amsterdam', '_blank')`.
172
+ - Other cleanup:
173
+ - Remove lines involving `android.*`, `UIApplication`, `NSURL`, `NSDictionary`, `intent`, etc.
174
+ - Remove leftover `else { ... }` native branch blocks.
175
+ - Comment out `registerElement(...)` (not needed on the Web).
176
+ - Special file handling:
177
+ - Replace `globals.ts` with a no‑op shim: `export function initGlobals() { /* web shim: no-op */ }`.
178
+
179
+ > Tip: The current transformation is regex‑driven and covers common patterns. For complex conditional branches, dynamic templates, and advanced native APIs, consider moving to TypeScript/Vue SFC AST‑based transformations to improve accuracy and maintainability.
180
+
181
+ ---
182
+
183
+ ## Styles & Tailwind Configuration
184
+
185
+ - Native side:
186
+ - `src/app.css` uses `@tailwind base/components/utilities` and defines theme styles and gradient backgrounds.
187
+ - `tailwind.config.js`:
188
+ - `content: ["./src/**/*.{css,vue,ts,tsx}"]`
189
+ - `darkMode: ["class", ".ns-dark"]`
190
+ - `corePlugins.preflight: false` (disables browser preset resets)
191
+ - Web side (generated):
192
+ - `tailwind.config.js` scans `./index.html` and `./src/**/*.{vue,js,ts,jsx,tsx}` and uses standard browser presets.
193
+ - `postcss.config.js`: enables `tailwindcss` and `autoprefixer`.
194
+
195
+ ---
196
+
197
+ ## Types & TS Configuration
198
+
199
+ - Root `tsconfig.json`:
200
+ - `strict: true`, target and module set to `esnext`.
201
+ - Path aliases: `~/*`, `@/*` → `src/*`.
202
+ - `vueCompilerOptions.lib = "nativescript-vue"` instructs SFC compilation for the NS environment.
203
+ - Type declarations:
204
+ - Native side `types/shims.vue.d.ts`: points `*.vue` types to `nativescript-vue`’s `DefineComponent`.
205
+ - Adapter side `core/env.d.ts`: points `*.vue` types to `vue`’s `DefineComponent`, consistent with browser compilation.
206
+ - Adapter `core/types.ts`: provides type aliases for `ActionBar/Page/Frame` components and exports state types for `useActionBar/usePage/useFrame`.
207
+
208
+ ---
209
+
210
+ ## HMR (Hot Module Replacement)
211
+
212
+ - Native side:
213
+ - Uses `@nativescript/vite` with `vite serve -- --env.hmr` to establish an HMR channel, pushing changes to the device.
214
+ - `patches/nativescript-vue+3.0.1.patch` injects within `app.start`: `globalThis.__NS_VUE_APP__ = app`, helping restore state in deep navigation stacks (e.g., when returning during HMR).
215
+ - Web side:
216
+ - Independent Vite (`platforms/web/vite.config.ts`) runs on port `3005`, using standard Vue HMR and route refresh.
217
+
218
+ ---
219
+
220
+ ## FAQ & Limitations
221
+
222
+ - Native APIs & plugins:
223
+ - Complex native interactions (platform‑specific modules, system services) cannot be automatically converted to the Web. They require manual replacement or browser fallback implementations (e.g., `InAppBrowser` → `window.open` wrapper).
224
+ - Layout & semantic mapping is limited:
225
+ - Basic web components are provided (`ActionBar/Page/Frame/Grid/Stack/Flex/Wrap/Scroll/Label/Button/Image/HtmlView/ImageCacheIt`). More detailed property‑to‑style mappings will be added later (e.g., `flexDirection/row`, grid rows/columns).
226
+ - Regex‑driven transformation:
227
+ - Edge cases may exist for complex code and templates. Gradually moving to AST‑level transformation is recommended.
228
+ - Generator template duplicate writes:
229
+ - The generator currently writes `platforms/web/package.json` twice (with different dependency versions). This can be streamlined into a single write to reduce maintenance cost.
230
+
231
+ ---
232
+
233
+ ## Improvements & Upgrade Suggestions
234
+
235
+ 1. Transformation engine upgrade:
236
+ - Replace regex with TypeScript and Vue SFC AST to precisely handle imports, calls, templates, and directive mappings.
237
+ 2. Global initialization & animations:
238
+ - Provide optional web animation implementations (CSS transitions/GSAP) for `globals.ts` to keep interaction behavior consistent.
239
+ 3. Tests & validation:
240
+ - Add unit tests and e2e tests for transformation rules and template generation to ensure stability across different project structures.
241
+
242
+ ---
@@ -0,0 +1,11 @@
1
+ <template>
2
+ <div class="ns-absolute"><slot /></div>
3
+ </template>
4
+
5
+ <script setup lang="ts">
6
+ defineOptions({ name: 'AbsoluteLayout' });
7
+ </script>
8
+
9
+ <style scoped>
10
+ .ns-absolute { position: relative; width: 100%; height: 100%; }
11
+ </style>
@@ -0,0 +1,11 @@
1
+ <template>
2
+ <header class="ns-actionbar"><slot /></header>
3
+ </template>
4
+
5
+ <script setup lang="ts">
6
+ defineOptions({ name: 'ActionBar' });
7
+ </script>
8
+
9
+ <style scoped>
10
+ .ns-actionbar { background: #1f1140; color: white; padding: 12px; }
11
+ </style>
@@ -0,0 +1,11 @@
1
+ <template>
2
+ <button class="ns-actionitem"><slot /></button>
3
+ </template>
4
+
5
+ <script setup lang="ts">
6
+ defineOptions({ name: 'ActionItem' });
7
+ </script>
8
+
9
+ <style scoped>
10
+ .ns-actionitem { background: transparent; border: none; color: inherit; cursor: pointer; padding: 8px; }
11
+ </style>
@@ -0,0 +1,15 @@
1
+ <template>
2
+ <div class="ns-activity-indicator" :class="{ busy }" />
3
+ </template>
4
+
5
+ <script setup lang="ts">
6
+ const props = defineProps<{ busy?: boolean }>();
7
+ const busy = props.busy ?? true;
8
+ defineOptions({ name: 'ActivityIndicator' });
9
+ </script>
10
+
11
+ <style scoped>
12
+ .ns-activity-indicator { width: 20px; height: 20px; border-radius: 50%; border: 2px solid rgba(255,255,255,0.3); border-top-color: currentColor; opacity: 0.8; }
13
+ .ns-activity-indicator.busy { animation: ns-spin 0.8s linear infinite; }
14
+ @keyframes ns-spin { to { transform: rotate(360deg) } }
15
+ </style>
@@ -0,0 +1,41 @@
1
+ <template>
2
+ <button class="ns-button" :style="btnStyle" @click="$emit('tap', $event)"><slot /></button>
3
+
4
+ </template>
5
+
6
+ <script setup lang="ts">
7
+ import { computed } from 'vue';
8
+ defineOptions({ name: 'Button' });
9
+ const emit = defineEmits<{ (e: 'tap', evt: MouseEvent): void }>();
10
+ const props = defineProps<{ horizontalAlignment?: string }>();
11
+
12
+ const btnStyle = computed<Record<string, string>>(() => {
13
+ const style: Record<string, string> = {};
14
+ const h = props.horizontalAlignment?.toLowerCase();
15
+ if (h === 'center') {
16
+ style.display = 'block';
17
+ style.width = 'fit-content';
18
+ style.marginLeft = 'auto';
19
+ style.marginRight = 'auto';
20
+ style.alignSelf = 'center';
21
+ style.justifySelf = 'center';
22
+ } else if (h === 'right') {
23
+ style.display = 'block';
24
+ style.width = 'fit-content';
25
+ style.marginLeft = 'auto';
26
+ style.alignSelf = 'flex-end';
27
+ style.justifySelf = 'end';
28
+ } else if (h === 'left') {
29
+ style.display = 'block';
30
+ style.width = 'fit-content';
31
+ style.marginRight = 'auto';
32
+ style.alignSelf = 'flex-start';
33
+ style.justifySelf = 'start';
34
+ }
35
+ return style;
36
+ });
37
+ </script>
38
+
39
+ <style scoped>
40
+ .ns-button { cursor: pointer; }
41
+ </style>
@@ -0,0 +1,27 @@
1
+ <template>
2
+ <input class="ns-datepicker" type="date" :value="valueStr" @input="onInput" />
3
+ </template>
4
+
5
+ <script setup lang="ts">
6
+ import { computed } from 'vue';
7
+ defineOptions({ name: 'DatePicker' });
8
+ const props = defineProps<{ date?: string | Date }>();
9
+ const emit = defineEmits<{ (e: 'update:date', v: string | Date): void; (e: 'change', v: string | Date): void }>();
10
+
11
+ function pad(n: number) { return n < 10 ? `0${n}` : String(n); }
12
+ const valueStr = computed(() => {
13
+ if (!props.date) return '';
14
+ const d = typeof props.date === 'string' ? new Date(props.date) : props.date;
15
+ if (isNaN(d.getTime())) return '';
16
+ return `${d.getFullYear()}-${pad(d.getMonth()+1)}-${pad(d.getDate())}`;
17
+ });
18
+ function onInput(e: Event) {
19
+ const v = (e.target as HTMLInputElement).value;
20
+ emit('update:date', v);
21
+ emit('change', v);
22
+ }
23
+ </script>
24
+
25
+ <style scoped>
26
+ .ns-datepicker { padding: 6px 8px; }
27
+ </style>
@@ -0,0 +1,23 @@
1
+ <template>
2
+ <div class="ns-dock">
3
+ <div class="ns-dock-top"><slot name="top" /></div>
4
+ <div class="ns-dock-middle">
5
+ <div class="ns-dock-left"><slot name="left" /></div>
6
+ <div class="ns-dock-center"><slot /></div>
7
+ <div class="ns-dock-right"><slot name="right" /></div>
8
+ </div>
9
+ <div class="ns-dock-bottom"><slot name="bottom" /></div>
10
+ </div>
11
+ </template>
12
+
13
+ <script setup lang="ts">
14
+ defineOptions({ name: 'DockLayout' });
15
+ </script>
16
+
17
+ <style scoped>
18
+ .ns-dock { display: flex; flex-direction: column; width: 100%; height: 100%; }
19
+ .ns-dock-top, .ns-dock-bottom { flex: 0 0 auto; }
20
+ .ns-dock-middle { display: flex; flex: 1 1 auto; min-height: 0; }
21
+ .ns-dock-left, .ns-dock-right { flex: 0 0 auto; }
22
+ .ns-dock-center { flex: 1 1 auto; min-width: 0; }
23
+ </style>