@lingxia/elements 0.5.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.
- package/dist/component.d.ts +50 -0
- package/dist/component.js +139 -0
- package/dist/dom.d.ts +10 -0
- package/dist/dom.js +70 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +9 -0
- package/dist/input.d.ts +117 -0
- package/dist/input.js +699 -0
- package/dist/native_component_wrapper_shared.d.ts +74 -0
- package/dist/native_component_wrapper_shared.js +193 -0
- package/dist/nativecomponent.d.ts +6 -0
- package/dist/nativecomponent.js +82 -0
- package/dist/navigator.d.ts +83 -0
- package/dist/navigator.js +388 -0
- package/dist/picker-web.d.ts +2 -0
- package/dist/picker-web.js +727 -0
- package/dist/picker.d.ts +77 -0
- package/dist/picker.js +342 -0
- package/dist/platform.d.ts +6 -0
- package/dist/platform.js +24 -0
- package/dist/text_component_native_attrs.d.ts +53 -0
- package/dist/text_component_native_attrs.js +111 -0
- package/dist/text_component_shared.d.ts +7 -0
- package/dist/text_component_shared.js +148 -0
- package/dist/textarea.d.ts +129 -0
- package/dist/textarea.js +841 -0
- package/dist/types.d.ts +21 -0
- package/dist/types.js +1 -0
- package/dist/video.d.ts +134 -0
- package/dist/video.js +741 -0
- package/package.json +39 -0
- package/src/component.ts +164 -0
- package/src/dom.ts +83 -0
- package/src/index.ts +69 -0
- package/src/input.ts +799 -0
- package/src/native_component_wrapper_shared.ts +243 -0
- package/src/nativecomponent.ts +97 -0
- package/src/navigator.ts +533 -0
- package/src/picker-web.ts +719 -0
- package/src/picker.ts +418 -0
- package/src/platform.ts +25 -0
- package/src/text_component_native_attrs.ts +137 -0
- package/src/text_component_shared.ts +147 -0
- package/src/textarea.ts +959 -0
- package/src/types.ts +20 -0
- package/src/video.ts +855 -0
package/src/navigator.ts
ADDED
|
@@ -0,0 +1,533 @@
|
|
|
1
|
+
// LxNavigator - Navigation component for LingXia apps
|
|
2
|
+
// Similar to WeChat mini program navigator component
|
|
3
|
+
|
|
4
|
+
export type NavigatorOpenType =
|
|
5
|
+
| 'navigate' // Push new page (default)
|
|
6
|
+
| 'redirect' // Replace current page
|
|
7
|
+
| 'navigateBack' // Go back
|
|
8
|
+
| 'reLaunch' // Restart app with new page
|
|
9
|
+
| 'switchTab' // Switch to tab page
|
|
10
|
+
| 'exit' // Exit current lxapp
|
|
11
|
+
| 'openUrl' // Open external URL or lxapp
|
|
12
|
+
| 'tel'; // Make a phone call
|
|
13
|
+
|
|
14
|
+
export type NavigatorTarget =
|
|
15
|
+
| 'self' // Navigate within current lxapp (default)
|
|
16
|
+
| 'lxapp' // Open another lxapp
|
|
17
|
+
| 'browser'; // Open in external browser
|
|
18
|
+
|
|
19
|
+
export interface LxNavigatorEventDetail {
|
|
20
|
+
success?: boolean;
|
|
21
|
+
errMsg?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface LxNavigatorEvent extends CustomEvent<LxNavigatorEventDetail> {
|
|
25
|
+
detail: LxNavigatorEventDetail;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type LxNavigatorAttributes = {
|
|
29
|
+
// Navigation
|
|
30
|
+
url?: string; // Target URL or path
|
|
31
|
+
'open-type'?: NavigatorOpenType; // Navigation type
|
|
32
|
+
target?: NavigatorTarget; // Navigation target (auto-inferred if not specified)
|
|
33
|
+
delta?: number; // Pages to go back (for navigateBack)
|
|
34
|
+
|
|
35
|
+
// Open external lxapp
|
|
36
|
+
'app-id'?: string; // Target lxapp ID
|
|
37
|
+
path?: string; // Path in target lxapp (supports query string)
|
|
38
|
+
|
|
39
|
+
// Phone call
|
|
40
|
+
'phone-number'?: string; // Phone number for tel open-type
|
|
41
|
+
|
|
42
|
+
// Hover effect
|
|
43
|
+
'hover-class'?: string; // CSS class for hover state
|
|
44
|
+
'hover-stop-propagation'?: boolean; // Prevent hover propagation
|
|
45
|
+
'hover-start-time'?: number; // Hover start delay (ms)
|
|
46
|
+
'hover-stay-time'?: number; // Hover stay duration (ms)
|
|
47
|
+
|
|
48
|
+
// Styling
|
|
49
|
+
className?: string;
|
|
50
|
+
style?: any;
|
|
51
|
+
|
|
52
|
+
// Events
|
|
53
|
+
onSuccess?: (e: LxNavigatorEvent) => void;
|
|
54
|
+
onFail?: (e: LxNavigatorEvent) => void;
|
|
55
|
+
onComplete?: (e: LxNavigatorEvent) => void;
|
|
56
|
+
|
|
57
|
+
// React
|
|
58
|
+
ref?: any;
|
|
59
|
+
children?: any;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
declare global {
|
|
63
|
+
namespace JSX {
|
|
64
|
+
interface IntrinsicElements {
|
|
65
|
+
"lx-navigator": LxNavigatorAttributes;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Component implementation
|
|
71
|
+
export class LxNavigatorElement extends HTMLElement {
|
|
72
|
+
static get observedAttributes() {
|
|
73
|
+
return [
|
|
74
|
+
"url",
|
|
75
|
+
"open-type",
|
|
76
|
+
"target",
|
|
77
|
+
"delta",
|
|
78
|
+
"app-id",
|
|
79
|
+
"path",
|
|
80
|
+
"phone-number",
|
|
81
|
+
"hover-class",
|
|
82
|
+
"hover-stop-propagation",
|
|
83
|
+
"hover-start-time",
|
|
84
|
+
"hover-stay-time"
|
|
85
|
+
];
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private hoverClass: string = 'navigator-hover';
|
|
89
|
+
private hoverStopPropagation: boolean = false;
|
|
90
|
+
private hoverStartTime: number = 20;
|
|
91
|
+
private hoverStayTime: number = 70;
|
|
92
|
+
private hoverTimer: number | null = null;
|
|
93
|
+
private isHovering: boolean = false;
|
|
94
|
+
private readonly onClick = (e: MouseEvent) => this.handleClick(e);
|
|
95
|
+
private readonly onTouchStart = (e: TouchEvent) => this.handleTouchStart(e);
|
|
96
|
+
private readonly onTouchEnd = (e: TouchEvent) => this.handleTouchEnd(e);
|
|
97
|
+
private readonly onTouchCancel = (e: TouchEvent) => this.handleTouchCancel(e);
|
|
98
|
+
private readonly onMouseEnter = (e: MouseEvent) => this.handleMouseEnter(e);
|
|
99
|
+
private readonly onMouseLeave = (e: MouseEvent) => this.handleMouseLeave(e);
|
|
100
|
+
private readonly clickListener: EventListenerObject = {
|
|
101
|
+
handleEvent: (event: Event): void => this.onClick(event as MouseEvent),
|
|
102
|
+
};
|
|
103
|
+
private readonly touchStartListener: EventListenerObject = {
|
|
104
|
+
handleEvent: (event: Event): void => this.onTouchStart(event as TouchEvent),
|
|
105
|
+
};
|
|
106
|
+
private readonly touchEndListener: EventListenerObject = {
|
|
107
|
+
handleEvent: (event: Event): void => this.onTouchEnd(event as TouchEvent),
|
|
108
|
+
};
|
|
109
|
+
private readonly touchCancelListener: EventListenerObject = {
|
|
110
|
+
handleEvent: (event: Event): void => this.onTouchCancel(event as TouchEvent),
|
|
111
|
+
};
|
|
112
|
+
private readonly mouseEnterListener: EventListenerObject = {
|
|
113
|
+
handleEvent: (event: Event): void => this.onMouseEnter(event as MouseEvent),
|
|
114
|
+
};
|
|
115
|
+
private readonly mouseLeaveListener: EventListenerObject = {
|
|
116
|
+
handleEvent: (event: Event): void => this.onMouseLeave(event as MouseEvent),
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
connectedCallback() {
|
|
120
|
+
this.setupHoverEffect();
|
|
121
|
+
this.setupClickHandler();
|
|
122
|
+
this.applyDefaultStyles();
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
disconnectedCallback() {
|
|
126
|
+
this.clearHoverTimer();
|
|
127
|
+
this.removeEventListener('click', this.clickListener);
|
|
128
|
+
this.removeEventListener('touchstart', this.touchStartListener);
|
|
129
|
+
this.removeEventListener('touchend', this.touchEndListener);
|
|
130
|
+
this.removeEventListener('touchcancel', this.touchCancelListener);
|
|
131
|
+
this.removeEventListener('mouseenter', this.mouseEnterListener);
|
|
132
|
+
this.removeEventListener('mouseleave', this.mouseLeaveListener);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null) {
|
|
136
|
+
if (oldValue === newValue) return;
|
|
137
|
+
|
|
138
|
+
switch (name) {
|
|
139
|
+
case 'hover-class':
|
|
140
|
+
this.hoverClass = newValue || 'navigator-hover';
|
|
141
|
+
break;
|
|
142
|
+
case 'hover-stop-propagation':
|
|
143
|
+
this.hoverStopPropagation = newValue === 'true';
|
|
144
|
+
break;
|
|
145
|
+
case 'hover-start-time':
|
|
146
|
+
this.hoverStartTime = parseInt(newValue || '20', 10);
|
|
147
|
+
break;
|
|
148
|
+
case 'hover-stay-time':
|
|
149
|
+
this.hoverStayTime = parseInt(newValue || '70', 10);
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private applyDefaultStyles() {
|
|
155
|
+
if (!this.hasAttribute('style') && !this.className) {
|
|
156
|
+
this.style.display = 'inline-block';
|
|
157
|
+
this.style.cursor = 'pointer';
|
|
158
|
+
this.style.userSelect = 'none';
|
|
159
|
+
(this.style as any).webkitTapHighlightColor = 'transparent';
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
private setupHoverEffect() {
|
|
164
|
+
this.addEventListener('touchstart', this.touchStartListener, { passive: true });
|
|
165
|
+
this.addEventListener('touchend', this.touchEndListener, { passive: true });
|
|
166
|
+
this.addEventListener('touchcancel', this.touchCancelListener, { passive: true });
|
|
167
|
+
|
|
168
|
+
// Desktop hover
|
|
169
|
+
this.addEventListener('mouseenter', this.mouseEnterListener);
|
|
170
|
+
this.addEventListener('mouseleave', this.mouseLeaveListener);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
private setupClickHandler() {
|
|
174
|
+
this.addEventListener('click', this.clickListener);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private handleTouchStart(e: TouchEvent) {
|
|
178
|
+
if (this.hoverStopPropagation) {
|
|
179
|
+
e.stopPropagation();
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
this.clearHoverTimer();
|
|
183
|
+
this.hoverTimer = window.setTimeout(() => {
|
|
184
|
+
this.addHoverClass();
|
|
185
|
+
}, this.hoverStartTime);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
private handleTouchEnd(_e: TouchEvent) {
|
|
189
|
+
this.clearHoverTimer();
|
|
190
|
+
if (this.isHovering) {
|
|
191
|
+
window.setTimeout(() => {
|
|
192
|
+
this.removeHoverClass();
|
|
193
|
+
}, this.hoverStayTime);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
private handleTouchCancel(_e: TouchEvent) {
|
|
198
|
+
this.clearHoverTimer();
|
|
199
|
+
this.removeHoverClass();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
private handleMouseEnter(_e: MouseEvent) {
|
|
203
|
+
this.clearHoverTimer();
|
|
204
|
+
this.hoverTimer = window.setTimeout(() => {
|
|
205
|
+
this.addHoverClass();
|
|
206
|
+
}, this.hoverStartTime);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
private handleMouseLeave(_e: MouseEvent) {
|
|
210
|
+
this.clearHoverTimer();
|
|
211
|
+
if (this.isHovering) {
|
|
212
|
+
window.setTimeout(() => {
|
|
213
|
+
this.removeHoverClass();
|
|
214
|
+
}, this.hoverStayTime);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
private addHoverClass() {
|
|
219
|
+
if (this.hoverClass && this.hoverClass !== 'none') {
|
|
220
|
+
this.classList.add(this.hoverClass);
|
|
221
|
+
this.isHovering = true;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
private removeHoverClass() {
|
|
226
|
+
if (this.hoverClass && this.hoverClass !== 'none') {
|
|
227
|
+
this.classList.remove(this.hoverClass);
|
|
228
|
+
this.isHovering = false;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
private clearHoverTimer() {
|
|
233
|
+
if (this.hoverTimer !== null) {
|
|
234
|
+
window.clearTimeout(this.hoverTimer);
|
|
235
|
+
this.hoverTimer = null;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
private handleClick(e: MouseEvent) {
|
|
240
|
+
e.preventDefault();
|
|
241
|
+
|
|
242
|
+
const url = this.getAttribute('url') || '';
|
|
243
|
+
const openType = (this.getAttribute('open-type') || 'navigate') as NavigatorOpenType;
|
|
244
|
+
const explicitTarget = this.getAttribute('target') as NavigatorTarget | null;
|
|
245
|
+
const delta = parseInt(this.getAttribute('delta') || '1', 10);
|
|
246
|
+
const appId = this.getAttribute('app-id');
|
|
247
|
+
const path = this.getAttribute('path');
|
|
248
|
+
const phoneNumber = this.getAttribute('phone-number');
|
|
249
|
+
|
|
250
|
+
// Auto-infer target if not explicitly specified
|
|
251
|
+
const target = this.inferTarget(explicitTarget, url, appId);
|
|
252
|
+
|
|
253
|
+
void this.navigate({
|
|
254
|
+
url,
|
|
255
|
+
openType,
|
|
256
|
+
target,
|
|
257
|
+
delta,
|
|
258
|
+
appId,
|
|
259
|
+
path,
|
|
260
|
+
phoneNumber
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Auto-infer navigation target based on context
|
|
266
|
+
* Priority: explicit target > appId > HTTPS URL > default (self)
|
|
267
|
+
*/
|
|
268
|
+
private inferTarget(
|
|
269
|
+
explicitTarget: NavigatorTarget | null,
|
|
270
|
+
url: string,
|
|
271
|
+
appId: string | null
|
|
272
|
+
): NavigatorTarget {
|
|
273
|
+
// 1. Explicit target has highest priority
|
|
274
|
+
if (explicitTarget) {
|
|
275
|
+
return explicitTarget;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// 2. If appId is specified, target is another lxapp
|
|
279
|
+
if (appId) {
|
|
280
|
+
return 'lxapp';
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// 3. If URL starts with http:// or https://, open in browser
|
|
284
|
+
if (/^https?:\/\//i.test(url)) {
|
|
285
|
+
return 'browser';
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// 4. Default: navigate within current lxapp
|
|
289
|
+
return 'self';
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
private async navigate(options: {
|
|
293
|
+
url: string;
|
|
294
|
+
openType: NavigatorOpenType;
|
|
295
|
+
target: NavigatorTarget;
|
|
296
|
+
delta: number;
|
|
297
|
+
appId?: string | null;
|
|
298
|
+
path?: string | null;
|
|
299
|
+
phoneNumber?: string | null;
|
|
300
|
+
}) {
|
|
301
|
+
try {
|
|
302
|
+
await this.performNavigation(options);
|
|
303
|
+
this.dispatchSuccess();
|
|
304
|
+
} catch (error) {
|
|
305
|
+
this.dispatchFail(error);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
private dispatchSuccess() {
|
|
310
|
+
const successEvent = new CustomEvent('success', {
|
|
311
|
+
detail: {
|
|
312
|
+
success: true
|
|
313
|
+
},
|
|
314
|
+
bubbles: true,
|
|
315
|
+
composed: true
|
|
316
|
+
});
|
|
317
|
+
this.dispatchEvent(successEvent);
|
|
318
|
+
|
|
319
|
+
const completeEvent = new CustomEvent('complete', {
|
|
320
|
+
detail: {
|
|
321
|
+
success: true
|
|
322
|
+
},
|
|
323
|
+
bubbles: true,
|
|
324
|
+
composed: true
|
|
325
|
+
});
|
|
326
|
+
this.dispatchEvent(completeEvent);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
private resolveErrorMessage(error: unknown): string {
|
|
330
|
+
if (error instanceof Error) {
|
|
331
|
+
const message = error.message.trim();
|
|
332
|
+
return message || 'Unknown error';
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (typeof error === 'string') {
|
|
336
|
+
const message = error.trim();
|
|
337
|
+
return message || 'Unknown error';
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (error && typeof error === 'object') {
|
|
341
|
+
const message = (error as { message?: unknown }).message;
|
|
342
|
+
if (typeof message === 'string' && message.trim()) {
|
|
343
|
+
return message;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return 'Unknown error';
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
private dispatchFail(error: unknown) {
|
|
351
|
+
const errMsg = this.resolveErrorMessage(error);
|
|
352
|
+
const failEvent = new CustomEvent('fail', {
|
|
353
|
+
detail: {
|
|
354
|
+
success: false,
|
|
355
|
+
errMsg
|
|
356
|
+
},
|
|
357
|
+
bubbles: true,
|
|
358
|
+
composed: true
|
|
359
|
+
});
|
|
360
|
+
this.dispatchEvent(failEvent);
|
|
361
|
+
|
|
362
|
+
const completeEvent = new CustomEvent('complete', {
|
|
363
|
+
detail: {
|
|
364
|
+
success: false,
|
|
365
|
+
errMsg
|
|
366
|
+
},
|
|
367
|
+
bubbles: true,
|
|
368
|
+
composed: true
|
|
369
|
+
});
|
|
370
|
+
this.dispatchEvent(completeEvent);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
private getHostApi() {
|
|
374
|
+
const host = (window as any).host;
|
|
375
|
+
if (!host || typeof host !== 'object') {
|
|
376
|
+
return null;
|
|
377
|
+
}
|
|
378
|
+
return host as {
|
|
379
|
+
navigation?: {
|
|
380
|
+
navigateTo?: (params: { url: string }) => Promise<void>;
|
|
381
|
+
navigateBack?: (params: { delta: number }) => Promise<void>;
|
|
382
|
+
redirectTo?: (params: { url: string }) => Promise<void>;
|
|
383
|
+
switchTab?: (params: { url: string }) => Promise<void>;
|
|
384
|
+
reLaunch?: (params: { url: string }) => Promise<void>;
|
|
385
|
+
};
|
|
386
|
+
navigator?: {
|
|
387
|
+
navigateToLxApp?: (params: { appId: string; path?: string }) => Promise<void>;
|
|
388
|
+
navigateBackLxApp?: () => Promise<void>;
|
|
389
|
+
};
|
|
390
|
+
device?: {
|
|
391
|
+
makePhoneCall?: (params: { phoneNumber: string }) => Promise<void>;
|
|
392
|
+
openUrl?: (params: { url: string; target?: 'external' | 'self' | 'new_browser_tab' }) => Promise<void>;
|
|
393
|
+
};
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
private async performNavigation(options: {
|
|
398
|
+
url: string;
|
|
399
|
+
openType: NavigatorOpenType;
|
|
400
|
+
target: NavigatorTarget;
|
|
401
|
+
delta: number;
|
|
402
|
+
appId?: string | null;
|
|
403
|
+
path?: string | null;
|
|
404
|
+
phoneNumber?: string | null;
|
|
405
|
+
}) {
|
|
406
|
+
const host = this.getHostApi();
|
|
407
|
+
if (!host) {
|
|
408
|
+
throw new Error('LingXia bridge not available');
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const url = options.url || '';
|
|
412
|
+
const delta = Number.isFinite(options.delta) && options.delta > 0 ? options.delta : 1;
|
|
413
|
+
|
|
414
|
+
if (options.openType === 'tel') {
|
|
415
|
+
if (!options.phoneNumber) {
|
|
416
|
+
throw new Error('tel requires phone-number attribute');
|
|
417
|
+
}
|
|
418
|
+
if (typeof host.device?.makePhoneCall !== 'function') {
|
|
419
|
+
throw new Error('host.device.makePhoneCall is not available');
|
|
420
|
+
}
|
|
421
|
+
await host.device.makePhoneCall({ phoneNumber: options.phoneNumber });
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
if (options.openType === 'exit') {
|
|
426
|
+
if (typeof host.navigator?.navigateBackLxApp !== 'function') {
|
|
427
|
+
throw new Error('host.navigator.navigateBackLxApp is not available');
|
|
428
|
+
}
|
|
429
|
+
await host.navigator.navigateBackLxApp();
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
if (options.openType === 'navigateBack') {
|
|
434
|
+
if (options.target === 'lxapp') {
|
|
435
|
+
if (typeof host.navigator?.navigateBackLxApp !== 'function') {
|
|
436
|
+
throw new Error('host.navigator.navigateBackLxApp is not available');
|
|
437
|
+
}
|
|
438
|
+
await host.navigator.navigateBackLxApp();
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
if (options.target === 'browser') {
|
|
442
|
+
throw new Error('navigateBack is not supported for browser target');
|
|
443
|
+
}
|
|
444
|
+
if (typeof host.navigation?.navigateBack !== 'function') {
|
|
445
|
+
throw new Error('host.navigation.navigateBack is not available');
|
|
446
|
+
}
|
|
447
|
+
await host.navigation.navigateBack({ delta });
|
|
448
|
+
return;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
if (options.target === 'browser') {
|
|
452
|
+
if (!url) {
|
|
453
|
+
throw new Error('openUrl requires url');
|
|
454
|
+
}
|
|
455
|
+
if (typeof host.device?.openUrl !== 'function') {
|
|
456
|
+
throw new Error('host.device.openUrl is not available');
|
|
457
|
+
}
|
|
458
|
+
await host.device.openUrl({ url, target: 'external' });
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
if (options.target === 'lxapp') {
|
|
463
|
+
if (!options.appId) {
|
|
464
|
+
throw new Error('navigateToLxApp requires app-id');
|
|
465
|
+
}
|
|
466
|
+
const lxappPath = options.path || '';
|
|
467
|
+
if (typeof host.navigator?.navigateToLxApp !== 'function') {
|
|
468
|
+
throw new Error('host.navigator.navigateToLxApp is not available');
|
|
469
|
+
}
|
|
470
|
+
await host.navigator.navigateToLxApp({ appId: options.appId, path: lxappPath });
|
|
471
|
+
return;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
if (options.target === 'self' && /^https?:\/\//i.test(url)) {
|
|
475
|
+
if (!url) {
|
|
476
|
+
throw new Error('openUrl requires url');
|
|
477
|
+
}
|
|
478
|
+
if (typeof host.device?.openUrl !== 'function') {
|
|
479
|
+
throw new Error('host.device.openUrl is not available');
|
|
480
|
+
}
|
|
481
|
+
await host.device.openUrl({ url, target: 'self' });
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
if (!url) {
|
|
486
|
+
throw new Error(`${options.openType} requires url`);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
switch (options.openType) {
|
|
490
|
+
case 'navigate':
|
|
491
|
+
if (typeof host.navigation?.navigateTo !== 'function') {
|
|
492
|
+
throw new Error('host.navigation.navigateTo is not available');
|
|
493
|
+
}
|
|
494
|
+
await host.navigation.navigateTo({ url });
|
|
495
|
+
break;
|
|
496
|
+
case 'redirect':
|
|
497
|
+
if (typeof host.navigation?.redirectTo !== 'function') {
|
|
498
|
+
throw new Error('host.navigation.redirectTo is not available');
|
|
499
|
+
}
|
|
500
|
+
await host.navigation.redirectTo({ url });
|
|
501
|
+
break;
|
|
502
|
+
case 'switchTab':
|
|
503
|
+
if (typeof host.navigation?.switchTab !== 'function') {
|
|
504
|
+
throw new Error('host.navigation.switchTab is not available');
|
|
505
|
+
}
|
|
506
|
+
await host.navigation.switchTab({ url });
|
|
507
|
+
break;
|
|
508
|
+
case 'reLaunch':
|
|
509
|
+
if (typeof host.navigation?.reLaunch !== 'function') {
|
|
510
|
+
throw new Error('host.navigation.reLaunch is not available');
|
|
511
|
+
}
|
|
512
|
+
await host.navigation.reLaunch({ url });
|
|
513
|
+
break;
|
|
514
|
+
case 'openUrl':
|
|
515
|
+
if (typeof host.device?.openUrl !== 'function') {
|
|
516
|
+
throw new Error('host.device.openUrl is not available');
|
|
517
|
+
}
|
|
518
|
+
await host.device.openUrl({
|
|
519
|
+
url,
|
|
520
|
+
target: options.target === 'self' ? 'self' : 'external'
|
|
521
|
+
});
|
|
522
|
+
break;
|
|
523
|
+
default:
|
|
524
|
+
throw new Error(`Unsupported openType: ${options.openType}`);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
// Register custom element
|
|
531
|
+
if (typeof customElements !== 'undefined' && !customElements.get('lx-navigator')) {
|
|
532
|
+
customElements.define('lx-navigator', LxNavigatorElement);
|
|
533
|
+
}
|