nativescript-web-adapter 0.1.1 → 0.1.2

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 CHANGED
@@ -122,6 +122,86 @@ npm run dev:web
122
122
  - `GridLayout` → DOM `div` (`display:grid`; details below)
123
123
  - `ImageCacheIt` → DOM `img` (simple replacement; uses `img` with `stretch` support)
124
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';
147
+ ```
148
+
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
+ ```
161
+
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>
184
+ ```
185
+
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
+
125
205
  ## GridLayout: Design & Behavior
126
206
 
127
207
  - Container styles
package/dist/index.cjs CHANGED
@@ -10,14 +10,16 @@ const Label = vue.defineComponent({
10
10
  },
11
11
  emits: ['tap'],
12
12
  setup(props, { slots, attrs, emit }) {
13
- var _a;
14
- const style = {};
15
- if (props.horizontalAlignment) {
16
- const map = { center: 'center', left: 'left', right: 'right' };
17
- style.textAlign = (_a = map[String(props.horizontalAlignment).toLowerCase()]) !== null && _a !== void 0 ? _a : undefined;
18
- }
13
+ const { class: userClass, style: userStyle, ...rest } = (attrs || {});
14
+ const defaultClass = 'ns-label';
15
+ const defaultStyle = {};
19
16
  const onClick = (e) => emit('tap', { eventName: 'tap', object: e.currentTarget });
20
- return () => vue.h('span', { style, onClick, ...attrs }, slots.default ? slots.default() : props.text);
17
+ return () => vue.h('span', {
18
+ onClick,
19
+ ...rest,
20
+ class: [defaultClass, userClass].filter(Boolean),
21
+ style: { ...defaultStyle, ...userStyle }
22
+ }, slots.default ? slots.default() : props.text);
21
23
  }
22
24
  });
23
25
 
@@ -29,19 +31,32 @@ const Button = vue.defineComponent({
29
31
  },
30
32
  emits: ['tap'],
31
33
  setup(props, { emit, slots, attrs }) {
32
- var _a;
34
+ const { class: userClass, style: userStyle, ...rest } = (attrs || {});
35
+ const defaultClass = 'ns-button';
36
+ const defaultStyle = (() => {
37
+ const style = {};
38
+ if (props.horizontalAlignment === 'center') {
39
+ // Center within GridLayout and StackLayout (column flex)
40
+ style.justifySelf = 'center';
41
+ style.alignSelf = 'center';
42
+ }
43
+ else if (props.horizontalAlignment === 'right') {
44
+ style.justifySelf = 'end';
45
+ style.alignSelf = 'flex-end';
46
+ }
47
+ else if (props.horizontalAlignment === 'left') {
48
+ style.justifySelf = 'start';
49
+ style.alignSelf = 'flex-start';
50
+ }
51
+ return style;
52
+ })();
33
53
  const onClick = (e) => emit('tap', { eventName: 'tap', object: e.currentTarget });
34
- const style = {};
35
- if (props.horizontalAlignment) {
36
- const map = {
37
- center: 'center',
38
- left: 'start',
39
- right: 'end',
40
- stretch: 'stretch'
41
- };
42
- style.justifySelf = (_a = map[String(props.horizontalAlignment).toLowerCase()]) !== null && _a !== void 0 ? _a : undefined;
43
- }
44
- return () => vue.h('button', { onClick, style, ...attrs }, slots.default ? slots.default() : props.text);
54
+ return () => vue.h('button', {
55
+ onClick,
56
+ ...rest,
57
+ class: [defaultClass, userClass].filter(Boolean),
58
+ style: { ...defaultStyle, ...userStyle }
59
+ }, slots.default ? slots.default() : props.text);
45
60
  }
46
61
  });
47
62
 
@@ -49,8 +64,19 @@ const StackLayout = vue.defineComponent({
49
64
  name: 'NSStackLayout',
50
65
  emits: ['tap'],
51
66
  setup(_, { slots, attrs, emit }) {
67
+ const { class: userClass, style: userStyle, ...rest } = (attrs || {});
68
+ const defaultClass = 'ns-stack-layout';
69
+ const defaultStyle = {};
52
70
  const onClick = (e) => emit('tap', { eventName: 'tap', object: e.currentTarget });
53
- return () => { var _a; return vue.h('div', { style: { display: 'flex', flexDirection: 'column' }, onClick, ...attrs }, (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots)); };
71
+ return () => {
72
+ var _a;
73
+ return vue.h('div', {
74
+ onClick,
75
+ ...rest,
76
+ class: [defaultClass, userClass].filter(Boolean),
77
+ style: { ...defaultStyle, ...userStyle }
78
+ }, (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots));
79
+ };
54
80
  }
55
81
  });
56
82
 
@@ -63,22 +89,22 @@ const FlexboxLayout = vue.defineComponent({
63
89
  },
64
90
  emits: ['tap'],
65
91
  setup(props, { slots, attrs, emit }) {
92
+ const { class: userClass, style: userStyle, ...rest } = (attrs || {});
93
+ const defaultClass = 'ns-flexbox-layout';
94
+ const defaultStyle = {};
66
95
  const onClick = (e) => emit('tap', { eventName: 'tap', object: e.currentTarget });
67
- return () => { var _a; return vue.h('div', { style: { display: 'flex', flexDirection: props.flexDirection, justifyContent: props.justifyContent, alignItems: props.alignItems }, onClick, ...attrs }, (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots)); };
96
+ return () => {
97
+ var _a;
98
+ return vue.h('div', {
99
+ onClick,
100
+ ...rest,
101
+ class: [defaultClass, userClass].filter(Boolean),
102
+ style: { ...defaultStyle, ...userStyle }
103
+ }, (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots));
104
+ };
68
105
  }
69
106
  });
70
107
 
71
- function parseTracks(tracks) {
72
- if (!tracks)
73
- return undefined;
74
- return tracks.split(',').map(s => s.trim()).map(t => {
75
- if (t === '*' || t === 'auto')
76
- return t === '*' ? '1fr' : 'auto';
77
- if (/^\d+$/.test(t))
78
- return `${t}px`;
79
- return t;
80
- }).join(' ');
81
- }
82
108
  const GridLayout = vue.defineComponent({
83
109
  name: 'NSGridLayout',
84
110
  props: {
@@ -86,86 +112,19 @@ const GridLayout = vue.defineComponent({
86
112
  columns: { type: String, default: undefined }
87
113
  },
88
114
  emits: ['tap'],
89
- setup(props, { slots, attrs, emit }) {
90
- var _a, _b;
91
- const containerStyle = {
92
- display: 'grid',
93
- // NS 默认一列:确保子项按行堆叠,而不是同一行多列并排
94
- gridTemplateColumns: (_a = parseTracks(props.columns)) !== null && _a !== void 0 ? _a : '1fr',
95
- // 行可选;若未指定,默认自适应内容
96
- gridTemplateRows: (_b = parseTracks(props.rows)) !== null && _b !== void 0 ? _b : undefined,
97
- // 以“按行”自动布局,默认逐行堆叠
98
- gridAutoFlow: 'row',
99
- width: '100%',
100
- height: '100%'
101
- };
102
- const mapChild = (child) => {
103
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
104
- if (!vue.isVNode(child))
105
- return child;
106
- const cprops = { ...(child.props || {}) };
107
- const style = { ...(cprops.style || {}) };
108
- // Row/Column placement: NativeScript uses 0-based indices; CSS Grid is 1-based
109
- const row = (_a = cprops.row) !== null && _a !== void 0 ? _a : cprops['row'];
110
- const col = (_c = (_b = cprops.col) !== null && _b !== void 0 ? _b : cprops['col']) !== null && _c !== void 0 ? _c : cprops.column;
111
- if (row != null) {
112
- const r = Number(row);
113
- if (!isNaN(r))
114
- style.gridRowStart = r + 1;
115
- }
116
- if (col != null) {
117
- const c = Number(col);
118
- if (!isNaN(c))
119
- style.gridColumnStart = c + 1;
120
- }
121
- else {
122
- // 未声明列时,强制放在第 1 列,避免隐式多列导致并排
123
- style.gridColumnStart = 1;
124
- }
125
- // Horizontal alignment mapping
126
- const ha = (_d = cprops.horizontalAlignment) !== null && _d !== void 0 ? _d : cprops['horizontalAlignment'];
127
- if (ha) {
128
- const map = {
129
- center: 'center',
130
- left: 'start',
131
- right: 'end',
132
- stretch: 'stretch'
133
- };
134
- style.justifySelf = (_e = map[String(ha).toLowerCase()]) !== null && _e !== void 0 ? _e : style.justifySelf;
135
- }
136
- // Vertical alignment mapping
137
- const va = (_f = cprops.verticalAlignment) !== null && _f !== void 0 ? _f : cprops['verticalAlignment'];
138
- if (va) {
139
- const map = {
140
- center: 'center',
141
- top: 'start',
142
- bottom: 'end',
143
- stretch: 'stretch'
144
- };
145
- style.alignSelf = (_g = map[String(va).toLowerCase()]) !== null && _g !== void 0 ? _g : style.alignSelf;
146
- }
147
- // Row/Column span mapping
148
- const rowSpan = (_h = cprops.rowSpan) !== null && _h !== void 0 ? _h : cprops['rowSpan'];
149
- if (rowSpan != null) {
150
- const rs = Number(rowSpan);
151
- if (!isNaN(rs) && rs > 1)
152
- style.gridRowEnd = `span ${rs}`;
153
- }
154
- const colSpan = (_j = cprops.colSpan) !== null && _j !== void 0 ? _j : cprops['colSpan'];
155
- if (colSpan != null) {
156
- const cs = Number(colSpan);
157
- if (!isNaN(cs) && cs > 1)
158
- style.gridColumnEnd = `span ${cs}`;
159
- }
160
- cprops.style = style;
161
- return vue.h(child.type, cprops, child.children);
162
- };
115
+ setup(_, { slots, attrs, emit }) {
116
+ const { class: userClass, style: userStyle, ...rest } = (attrs || {});
117
+ const defaultClass = 'ns-grid-layout';
118
+ const defaultStyle = {};
163
119
  const onClick = (e) => emit('tap', { eventName: 'tap', object: e.currentTarget });
164
120
  return () => {
165
- var _a, _b;
166
- const children = (_b = (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots)) !== null && _b !== void 0 ? _b : [];
167
- const mapped = children.map(mapChild);
168
- return vue.h('div', { style: containerStyle, onClick, ...attrs }, mapped);
121
+ var _a;
122
+ return vue.h('div', {
123
+ onClick,
124
+ ...rest,
125
+ class: [defaultClass, userClass].filter(Boolean),
126
+ style: { ...defaultStyle, ...userStyle }
127
+ }, (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots));
169
128
  };
170
129
  }
171
130
  });
@@ -174,15 +133,36 @@ const Page = vue.defineComponent({
174
133
  name: 'NSPage',
175
134
  emits: ['tap'],
176
135
  setup(_, { slots, attrs, emit }) {
136
+ const { class: userClass, style: userStyle, ...rest } = (attrs || {});
137
+ const defaultClass = 'ns-page';
138
+ const defaultStyle = {};
177
139
  const onClick = (e) => emit('tap', { eventName: 'tap', object: e.currentTarget });
178
- return () => { var _a; return vue.h('main', { onClick, ...attrs }, (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots)); };
140
+ return () => {
141
+ var _a;
142
+ return vue.h('main', {
143
+ onClick,
144
+ ...rest,
145
+ class: [defaultClass, userClass].filter(Boolean),
146
+ style: { ...defaultStyle, ...userStyle }
147
+ }, (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots));
148
+ };
179
149
  }
180
150
  });
181
151
 
182
152
  const Frame = vue.defineComponent({
183
153
  name: 'NSFrame',
184
154
  setup(_, { slots, attrs }) {
185
- return () => { var _a; return vue.h('div', { ...attrs }, (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots)); };
155
+ const { class: userClass, style: userStyle, ...rest } = (attrs || {});
156
+ const defaultClass = 'ns-frame';
157
+ const defaultStyle = {};
158
+ return () => {
159
+ var _a;
160
+ return vue.h('div', {
161
+ ...rest,
162
+ class: [defaultClass, userClass].filter(Boolean),
163
+ style: { ...defaultStyle, ...userStyle }
164
+ }, (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots));
165
+ };
186
166
  }
187
167
  });
188
168
 
@@ -190,8 +170,45 @@ const ActionBar = vue.defineComponent({
190
170
  name: 'NSActionBar',
191
171
  emits: ['tap'],
192
172
  setup(_, { slots, attrs, emit }) {
173
+ const { class: userClass, style: userStyle, ...rest } = (attrs || {});
174
+ const defaultClass = 'ns-action-bar';
175
+ const defaultStyle = {};
193
176
  const onClick = (e) => emit('tap', { eventName: 'tap', object: e.currentTarget });
194
- return () => { var _a; return vue.h('header', { onClick, ...attrs }, (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots)); };
177
+ return () => {
178
+ var _a;
179
+ return vue.h('header', {
180
+ onClick,
181
+ ...rest,
182
+ class: [defaultClass, userClass].filter(Boolean),
183
+ style: { ...defaultStyle, ...userStyle }
184
+ }, (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots));
185
+ };
186
+ }
187
+ });
188
+
189
+ const ActionItem = vue.defineComponent({
190
+ name: 'NSActionItem',
191
+ props: {
192
+ iosPosition: { type: String, default: undefined }
193
+ },
194
+ setup(props, { slots, attrs }) {
195
+ var _a;
196
+ const { class: userClass, style: userStyle, ...rest } = (attrs || {});
197
+ // Support attribute `ios.position="right"` via attrs['ios.position']
198
+ const pos = (_a = attrs['ios.position']) !== null && _a !== void 0 ? _a : props.iosPosition;
199
+ const defaultClass = 'ns-action-item';
200
+ const defaultStyle = {};
201
+ if (pos === 'right') {
202
+ defaultStyle.marginLeft = 'auto';
203
+ }
204
+ return () => {
205
+ var _a;
206
+ return vue.h('div', {
207
+ ...rest,
208
+ class: [defaultClass, userClass].filter(Boolean),
209
+ style: { ...defaultStyle, ...userStyle }
210
+ }, (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots));
211
+ };
195
212
  }
196
213
  });
197
214
 
@@ -202,14 +219,124 @@ const ImageCacheIt = vue.defineComponent({
202
219
  stretch: { type: String, default: 'aspectFill' }
203
220
  },
204
221
  setup(props, { attrs }) {
205
- const style = { width: '100%', display: 'block', objectPosition: 'center' };
206
- if (props.stretch === 'aspectFill') {
207
- style.objectFit = 'cover';
208
- }
209
- else if (props.stretch === 'aspectFit') {
210
- style.objectFit = 'contain';
211
- }
212
- return () => vue.h('img', { src: props.src, style, ...attrs });
222
+ var _a;
223
+ const { class: userClass, style: userStyle, ...rest } = (attrs || {});
224
+ const defaultClass = 'ns-image-cache-it';
225
+ const objectFitMap = {};
226
+ const defaultStyle = {
227
+ objectFit: (_a = objectFitMap[props.stretch]) !== null && _a !== void 0 ? _a : 'cover',
228
+ display: 'block'
229
+ };
230
+ return () => vue.h('img', {
231
+ ...rest,
232
+ src: props.src,
233
+ class: [defaultClass, userClass].filter(Boolean),
234
+ style: { ...defaultStyle, ...userStyle }
235
+ });
236
+ }
237
+ });
238
+
239
+ const ContentView = vue.defineComponent({
240
+ name: 'NSContentView',
241
+ setup(_, { slots, attrs }) {
242
+ const { class: userClass, style: userStyle, ...rest } = (attrs || {});
243
+ const defaultClass = 'ns-content-view';
244
+ const defaultStyle = {};
245
+ return () => {
246
+ var _a;
247
+ return vue.h('div', {
248
+ ...rest,
249
+ class: [defaultClass, userClass].filter(Boolean),
250
+ style: { ...defaultStyle, ...userStyle }
251
+ }, (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots));
252
+ };
253
+ }
254
+ });
255
+
256
+ const ListView = vue.defineComponent({
257
+ name: 'NSListView',
258
+ props: {
259
+ items: { type: Array, default: () => [] },
260
+ separatorColor: { type: String, default: 'transparent' }
261
+ },
262
+ setup(props, { slots, attrs }) {
263
+ const { class: userClass, style: userStyle, ...rest } = (attrs || {});
264
+ const defaultClass = 'ns-list-view';
265
+ const defaultStyle = { overflow: 'auto' };
266
+ return () => vue.h('div', { ...rest, class: [defaultClass, userClass].filter(Boolean), style: { ...defaultStyle, ...userStyle } }, props.items.map((item, index) => vue.h('div', { class: 'ns-list-item', style: { borderBottom: `1px solid ${props.separatorColor}` } }, slots.default ? slots.default({ item, index }) : String(item))));
267
+ }
268
+ });
269
+
270
+ const TabView = vue.defineComponent({
271
+ name: 'NSTabView',
272
+ props: {
273
+ selectedIndex: { type: Number, default: 0 },
274
+ androidTabsPosition: { type: String, default: 'bottom' }
275
+ },
276
+ emits: ['selectedIndexChange'],
277
+ setup(props, { slots, emit, attrs }) {
278
+ var _a;
279
+ const { class: userClass, style: userStyle, ...rest } = (attrs || {});
280
+ const defaultClass = 'ns-tab-view';
281
+ const currentIndex = vue.ref((_a = props.selectedIndex) !== null && _a !== void 0 ? _a : 0);
282
+ vue.watch(() => props.selectedIndex, (val) => {
283
+ if (typeof val === 'number')
284
+ currentIndex.value = val;
285
+ });
286
+ const onSelect = (idx) => {
287
+ currentIndex.value = idx;
288
+ emit('selectedIndexChange', { value: idx, object: null });
289
+ };
290
+ return () => {
291
+ var _a, _b;
292
+ const children = (_b = (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots)) !== null && _b !== void 0 ? _b : [];
293
+ const items = children.filter((v) => { var _a, _b; return ((_b = (_a = v === null || v === void 0 ? void 0 : v.type) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : '') === 'NSTabViewItem'; });
294
+ const useChildren = items.length ? items : children;
295
+ const barItems = useChildren.map((v) => {
296
+ var _a, _b, _c;
297
+ const p = v.props || {};
298
+ const title = (_a = p.title) !== null && _a !== void 0 ? _a : '';
299
+ const icon = (_c = (_b = p['android:iconSource']) !== null && _b !== void 0 ? _b : p.iconSource) !== null && _c !== void 0 ? _c : undefined;
300
+ return { title, icon };
301
+ });
302
+ const renderedContent = useChildren.map((v, idx) => {
303
+ var _a, _b;
304
+ return vue.cloneVNode(v, {
305
+ class: ['ns-tab-view-item', (_a = v.props) === null || _a === void 0 ? void 0 : _a.class].filter(Boolean),
306
+ style: { ...(((_b = v.props) === null || _b === void 0 ? void 0 : _b.style) || {}), display: idx === currentIndex.value ? '' : 'none' }
307
+ });
308
+ });
309
+ const tabBar = vue.h('nav', { class: 'ns-tab-bar' }, barItems.map((item, idx) => vue.h('button', {
310
+ class: ['ns-tab-bar-item', idx === currentIndex.value ? 'active' : ''].filter(Boolean),
311
+ onClick: () => onSelect(idx)
312
+ }, item.title || '•')));
313
+ return vue.h('div', {
314
+ ...rest,
315
+ class: [defaultClass, userClass].filter(Boolean),
316
+ style: { ...userStyle }
317
+ }, [vue.h('div', { class: 'ns-tab-content' }, renderedContent), props.androidTabsPosition === 'bottom' ? tabBar : null]);
318
+ };
319
+ }
320
+ });
321
+
322
+ const TabViewItem = vue.defineComponent({
323
+ name: 'NSTabViewItem',
324
+ props: {
325
+ title: { type: String, default: '' },
326
+ iconSource: { type: String, default: undefined }
327
+ },
328
+ setup(_, { slots, attrs }) {
329
+ const { class: userClass, style: userStyle, ...rest } = (attrs || {});
330
+ const defaultClass = 'ns-tab-view-item';
331
+ const defaultStyle = {};
332
+ return () => {
333
+ var _a;
334
+ return vue.h('div', {
335
+ ...rest,
336
+ class: [defaultClass, userClass].filter(Boolean),
337
+ style: { ...defaultStyle, ...userStyle }
338
+ }, (_a = slots.default) === null || _a === void 0 ? void 0 : _a.call(slots));
339
+ };
213
340
  }
214
341
  });
215
342
 
@@ -223,18 +350,28 @@ const NativeScriptWebPlugin = {
223
350
  app.component('Page', Page);
224
351
  app.component('Frame', Frame);
225
352
  app.component('ActionBar', ActionBar);
353
+ app.component('ActionItem', ActionItem);
226
354
  app.component('ImageCacheIt', ImageCacheIt);
355
+ app.component('ContentView', ContentView);
356
+ app.component('ListView', ListView);
357
+ app.component('TabView', TabView);
358
+ app.component('TabViewItem', TabViewItem);
227
359
  }
228
360
  };
229
361
 
230
362
  exports.ActionBar = ActionBar;
363
+ exports.ActionItem = ActionItem;
231
364
  exports.Button = Button;
365
+ exports.ContentView = ContentView;
232
366
  exports.FlexboxLayout = FlexboxLayout;
233
367
  exports.Frame = Frame;
234
368
  exports.GridLayout = GridLayout;
235
369
  exports.ImageCacheIt = ImageCacheIt;
236
370
  exports.Label = Label;
371
+ exports.ListView = ListView;
237
372
  exports.NativeScriptWebPlugin = NativeScriptWebPlugin;
238
373
  exports.Page = Page;
239
374
  exports.StackLayout = StackLayout;
375
+ exports.TabView = TabView;
376
+ exports.TabViewItem = TabViewItem;
240
377
  //# sourceMappingURL=index.cjs.map