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 +80 -0
- package/dist/index.cjs +258 -121
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +172 -0
- package/dist/index.js +255 -123
- package/dist/index.js.map +1 -1
- package/dist/types/index.types.d.ts +1 -0
- package/dist/types/vue/components/ActionItem.d.ts +15 -0
- package/dist/types/vue/components/ContentView.d.ts +3 -0
- package/dist/types/vue/components/GridLayout.d.ts +1 -2
- package/dist/types/vue/components/ListView.d.ts +24 -0
- package/dist/types/vue/components/TabView.d.ts +26 -0
- package/dist/types/vue/components/TabViewItem.d.ts +24 -0
- package/dist/types/vue/index.d.ts +7 -1
- package/dist/types/vue/index.types.d.ts +17 -0
- package/dist/types/vue.d.ts +100 -3
- package/dist/vue.cjs +258 -121
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.css +172 -0
- package/dist/vue.js +255 -123
- package/dist/vue.js.map +1 -1
- package/package.json +6 -4
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
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
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', {
|
|
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
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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 () => {
|
|
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 () => {
|
|
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(
|
|
90
|
-
|
|
91
|
-
const
|
|
92
|
-
|
|
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
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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 () => {
|
|
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
|
-
|
|
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 () => {
|
|
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
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
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
|