@lingxia/vue 0.14.0 → 0.16.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/LxNativeButton.vue +63 -0
- package/dist/LxNativeCover.vue +37 -0
- package/dist/LxNativeRoot.vue +63 -0
- package/dist/LxNativeText.vue +41 -0
- package/dist/LxNativeView.vue +35 -0
- package/dist/LxNavigator.vue +1 -1
- package/dist/LxVideo.vue +29 -27
- package/dist/hook.d.ts +6 -0
- package/dist/hook.js +7 -2
- package/dist/index.d.ts +8 -1
- package/dist/index.js +5 -0
- package/dist/text_component_shared.d.ts +20 -0
- package/dist/text_component_shared.js +40 -0
- package/dist/types.d.ts +63 -16
- package/package.json +6 -5
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { LxNativeButtonProps } from './types.js';
|
|
3
|
+
import { h, onBeforeUnmount, useAttrs, useSlots, watch } from 'vue';
|
|
4
|
+
import {
|
|
5
|
+
registerNativeButtonComponent,
|
|
6
|
+
unwrapNativeEventPayload,
|
|
7
|
+
type PressPayload,
|
|
8
|
+
} from '@lingxia/elements';
|
|
9
|
+
import { bindElementEvents, unbindElementEvents, useNativeHostElement } from './text_component_shared.js';
|
|
10
|
+
|
|
11
|
+
const props = defineProps<LxNativeButtonProps>();
|
|
12
|
+
const slots = useSlots();
|
|
13
|
+
const attrs = useAttrs();
|
|
14
|
+
|
|
15
|
+
const emit = defineEmits<{
|
|
16
|
+
press: [payload: PressPayload];
|
|
17
|
+
}>();
|
|
18
|
+
|
|
19
|
+
if (typeof window !== 'undefined') {
|
|
20
|
+
registerNativeButtonComponent();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const elementRef = useNativeHostElement(props);
|
|
24
|
+
let bound: HTMLElement | null = null;
|
|
25
|
+
const listeners: Record<string, EventListenerObject> = {
|
|
26
|
+
press: { handleEvent: (event) => emit('press', unwrapNativeEventPayload(event)) },
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
watch(elementRef, (element) => {
|
|
30
|
+
bound = bindElementEvents(bound, element, listeners);
|
|
31
|
+
});
|
|
32
|
+
onBeforeUnmount(() => unbindElementEvents(bound, listeners));
|
|
33
|
+
|
|
34
|
+
const render = () => h('lx-native-button', {
|
|
35
|
+
...attrs,
|
|
36
|
+
ref: elementRef,
|
|
37
|
+
id: props.id,
|
|
38
|
+
class: props.class,
|
|
39
|
+
style: props.style,
|
|
40
|
+
'aria-label': props['aria-label'],
|
|
41
|
+
'aria-description': props['aria-description'],
|
|
42
|
+
'aria-hidden': props['aria-hidden'],
|
|
43
|
+
'automation-id': props.automationId,
|
|
44
|
+
label: props.label,
|
|
45
|
+
icon: props.icon,
|
|
46
|
+
'icon-position': props.iconPosition,
|
|
47
|
+
intent: props.intent,
|
|
48
|
+
emphasis: props.emphasis,
|
|
49
|
+
size: props.size,
|
|
50
|
+
'hit-slop': props.hitSlop,
|
|
51
|
+
disabled: props.disabled,
|
|
52
|
+
pressed: props.pressed,
|
|
53
|
+
expanded: props.expanded,
|
|
54
|
+
loading: props.loading,
|
|
55
|
+
tabindex: props.tabIndex,
|
|
56
|
+
'pointer-events': props.pointerEvents,
|
|
57
|
+
hidden: props.hidden,
|
|
58
|
+
}, slots.default?.());
|
|
59
|
+
</script>
|
|
60
|
+
|
|
61
|
+
<template>
|
|
62
|
+
<render />
|
|
63
|
+
</template>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { LxNativeCoverProps } from './types.js';
|
|
3
|
+
import { h, useAttrs, useSlots } from 'vue';
|
|
4
|
+
import { registerNativeCoverComponent } from '@lingxia/elements';
|
|
5
|
+
import { useNativeHostElement } from './text_component_shared.js';
|
|
6
|
+
|
|
7
|
+
const props = defineProps<LxNativeCoverProps>();
|
|
8
|
+
const slots = useSlots();
|
|
9
|
+
const attrs = useAttrs();
|
|
10
|
+
|
|
11
|
+
if (typeof window !== 'undefined') {
|
|
12
|
+
registerNativeCoverComponent();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const elementRef = useNativeHostElement(props);
|
|
16
|
+
|
|
17
|
+
const render = () => h('lx-native-cover', {
|
|
18
|
+
...attrs,
|
|
19
|
+
ref: elementRef,
|
|
20
|
+
id: props.id,
|
|
21
|
+
class: props.class,
|
|
22
|
+
style: props.style,
|
|
23
|
+
'aria-label': props['aria-label'],
|
|
24
|
+
'aria-description': props['aria-description'],
|
|
25
|
+
'aria-hidden': props['aria-hidden'],
|
|
26
|
+
'automation-id': props.automationId,
|
|
27
|
+
'pointer-events': props.pointerEvents,
|
|
28
|
+
hidden: props.hidden,
|
|
29
|
+
scrim: props.scrim,
|
|
30
|
+
'scrim-opacity': props.scrimOpacity,
|
|
31
|
+
role: props.role,
|
|
32
|
+
}, slots.default?.());
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<template>
|
|
36
|
+
<render />
|
|
37
|
+
</template>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { LxNativeRootProps } from './types.js';
|
|
3
|
+
import { h, onBeforeUnmount, useAttrs, useSlots, watch } from 'vue';
|
|
4
|
+
import { registerNativeRootComponent, unwrapNativeEventPayload, type NativeError } from '@lingxia/elements';
|
|
5
|
+
import { bindElementEvents, unbindElementEvents, useNativeHostElement } from './text_component_shared.js';
|
|
6
|
+
|
|
7
|
+
const props = defineProps<LxNativeRootProps>();
|
|
8
|
+
const slots = useSlots();
|
|
9
|
+
const attrs = useAttrs();
|
|
10
|
+
|
|
11
|
+
const emit = defineEmits<{
|
|
12
|
+
ready: [payload: Record<string, never>];
|
|
13
|
+
error: [payload: NativeError];
|
|
14
|
+
}>();
|
|
15
|
+
|
|
16
|
+
if (typeof window !== 'undefined') {
|
|
17
|
+
registerNativeRootComponent();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const elementRef = useNativeHostElement(props);
|
|
21
|
+
let bound: HTMLElement | null = null;
|
|
22
|
+
const listeners: Record<string, EventListenerObject> = {
|
|
23
|
+
ready: { handleEvent: (event) => emit('ready', unwrapNativeEventPayload(event)) },
|
|
24
|
+
error: { handleEvent: (event) => emit('error', unwrapNativeEventPayload(event)) },
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
watch(elementRef, (element) => {
|
|
28
|
+
bound = bindElementEvents(bound, element, listeners);
|
|
29
|
+
});
|
|
30
|
+
onBeforeUnmount(() => unbindElementEvents(bound, listeners));
|
|
31
|
+
|
|
32
|
+
const retry = async () => {
|
|
33
|
+
const el = elementRef.value as { retry?: () => Promise<void> } | null;
|
|
34
|
+
await el?.retry?.();
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
defineExpose({ retry, el: elementRef });
|
|
38
|
+
|
|
39
|
+
const render = () => h('lx-native-root', {
|
|
40
|
+
...attrs,
|
|
41
|
+
ref: elementRef,
|
|
42
|
+
id: props.id,
|
|
43
|
+
class: props.class,
|
|
44
|
+
style: props.style,
|
|
45
|
+
'aria-label': props['aria-label'],
|
|
46
|
+
'aria-description': props['aria-description'],
|
|
47
|
+
'aria-hidden': props['aria-hidden'],
|
|
48
|
+
'pointer-events': props.pointerEvents,
|
|
49
|
+
hidden: props.hidden,
|
|
50
|
+
'automation-id': props.automationId,
|
|
51
|
+
}, [
|
|
52
|
+
slots.default?.(),
|
|
53
|
+
slots.fallback ? h('div', {
|
|
54
|
+
'data-lx-native-fallback': '',
|
|
55
|
+
hidden: true,
|
|
56
|
+
'aria-hidden': 'true',
|
|
57
|
+
}, slots.fallback()) : null,
|
|
58
|
+
]);
|
|
59
|
+
</script>
|
|
60
|
+
|
|
61
|
+
<template>
|
|
62
|
+
<render />
|
|
63
|
+
</template>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { LxNativeTextProps } from './types.js';
|
|
3
|
+
import { h, useAttrs, useSlots } from 'vue';
|
|
4
|
+
import { registerNativeTextComponent } from '@lingxia/elements';
|
|
5
|
+
import { useNativeHostElement } from './text_component_shared.js';
|
|
6
|
+
|
|
7
|
+
const props = defineProps<LxNativeTextProps>();
|
|
8
|
+
const slots = useSlots();
|
|
9
|
+
const attrs = useAttrs();
|
|
10
|
+
|
|
11
|
+
if (typeof window !== 'undefined') {
|
|
12
|
+
registerNativeTextComponent();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const elementRef = useNativeHostElement(props);
|
|
16
|
+
|
|
17
|
+
const render = () => h('lx-native-text', {
|
|
18
|
+
...attrs,
|
|
19
|
+
ref: elementRef,
|
|
20
|
+
id: props.id,
|
|
21
|
+
class: props.class,
|
|
22
|
+
style: props.style,
|
|
23
|
+
'aria-label': props['aria-label'],
|
|
24
|
+
'aria-description': props['aria-description'],
|
|
25
|
+
'aria-hidden': props['aria-hidden'],
|
|
26
|
+
'automation-id': props.automationId,
|
|
27
|
+
'pointer-events': props.pointerEvents,
|
|
28
|
+
hidden: props.hidden,
|
|
29
|
+
'max-lines': props.maxLines,
|
|
30
|
+
dir: props.dir,
|
|
31
|
+
'font-size': props.fontSize,
|
|
32
|
+
'font-weight': props.fontWeight,
|
|
33
|
+
'line-height': props.lineHeight,
|
|
34
|
+
'text-align': props.textAlign,
|
|
35
|
+
color: props.color,
|
|
36
|
+
}, slots.default?.());
|
|
37
|
+
</script>
|
|
38
|
+
|
|
39
|
+
<template>
|
|
40
|
+
<render />
|
|
41
|
+
</template>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import type { LxNativeViewProps } from './types.js';
|
|
3
|
+
import { h, useAttrs, useSlots } from 'vue';
|
|
4
|
+
import { registerNativeViewComponent } from '@lingxia/elements';
|
|
5
|
+
import { useNativeHostElement } from './text_component_shared.js';
|
|
6
|
+
|
|
7
|
+
const props = defineProps<LxNativeViewProps>();
|
|
8
|
+
const slots = useSlots();
|
|
9
|
+
const attrs = useAttrs();
|
|
10
|
+
|
|
11
|
+
if (typeof window !== 'undefined') {
|
|
12
|
+
registerNativeViewComponent();
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const elementRef = useNativeHostElement(props);
|
|
16
|
+
|
|
17
|
+
const render = () => h('lx-native-view', {
|
|
18
|
+
...attrs,
|
|
19
|
+
ref: elementRef,
|
|
20
|
+
id: props.id,
|
|
21
|
+
class: props.class,
|
|
22
|
+
style: props.style,
|
|
23
|
+
'aria-label': props['aria-label'],
|
|
24
|
+
'aria-description': props['aria-description'],
|
|
25
|
+
'aria-hidden': props['aria-hidden'],
|
|
26
|
+
'automation-id': props.automationId,
|
|
27
|
+
'pointer-events': props.pointerEvents,
|
|
28
|
+
hidden: props.hidden,
|
|
29
|
+
role: props.role,
|
|
30
|
+
}, slots.default?.());
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<template>
|
|
34
|
+
<render />
|
|
35
|
+
</template>
|
package/dist/LxNavigator.vue
CHANGED
package/dist/LxVideo.vue
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { ref, computed, h, onBeforeUnmount, useAttrs, useId, watch } from 'vue';
|
|
3
|
-
import { registerVideoComponent } from '@lingxia/elements';
|
|
3
|
+
import { registerVideoComponent, unwrapNativeEventPayload, type LxVideoEventPayloads } from '@lingxia/elements';
|
|
4
4
|
import {
|
|
5
5
|
buildVideoNativeAttrs,
|
|
6
6
|
VIDEO_DOM_EVENT_MAP,
|
|
@@ -19,19 +19,20 @@ const props = withDefaults(defineProps<LxVideoProps>(), {
|
|
|
19
19
|
const attrs = useAttrs();
|
|
20
20
|
|
|
21
21
|
const emit = defineEmits<{
|
|
22
|
-
playRequest: [
|
|
23
|
-
play: [
|
|
24
|
-
playing: [
|
|
25
|
-
pause: [
|
|
26
|
-
stop: [
|
|
27
|
-
ended: [
|
|
28
|
-
timeUpdate: [
|
|
29
|
-
error: [
|
|
30
|
-
loadedMetadata: [
|
|
31
|
-
fullscreenChange: [
|
|
32
|
-
waiting: [
|
|
33
|
-
qualityChange: [
|
|
34
|
-
rateChange: [
|
|
22
|
+
playRequest: [payload: LxVideoEventPayloads["onPlayRequest"]];
|
|
23
|
+
play: [payload: LxVideoEventPayloads["onPlay"]];
|
|
24
|
+
playing: [payload: LxVideoEventPayloads["onPlaying"]];
|
|
25
|
+
pause: [payload: LxVideoEventPayloads["onPause"]];
|
|
26
|
+
stop: [payload: LxVideoEventPayloads["onStop"]];
|
|
27
|
+
ended: [payload: LxVideoEventPayloads["onEnded"]];
|
|
28
|
+
timeUpdate: [payload: LxVideoEventPayloads["onTimeUpdate"]];
|
|
29
|
+
error: [payload: LxVideoEventPayloads["onError"]];
|
|
30
|
+
loadedMetadata: [payload: LxVideoEventPayloads["onLoadedMetadata"]];
|
|
31
|
+
fullscreenChange: [payload: LxVideoEventPayloads["onFullscreenChange"]];
|
|
32
|
+
waiting: [payload: LxVideoEventPayloads["onWaiting"]];
|
|
33
|
+
qualityChange: [payload: LxVideoEventPayloads["onQualityChange"]];
|
|
34
|
+
rateChange: [payload: LxVideoEventPayloads["onRateChange"]];
|
|
35
|
+
volumeChange: [payload: LxVideoEventPayloads["onVolumeChange"]];
|
|
35
36
|
}>();
|
|
36
37
|
|
|
37
38
|
if (typeof window !== 'undefined') {
|
|
@@ -45,19 +46,20 @@ let boundElement: HTMLElement | null = null;
|
|
|
45
46
|
const resolvedId = computed(() => props.id || `lx-video-${vueId.replace(/[:]/g, '')}`);
|
|
46
47
|
|
|
47
48
|
const videoEventListeners: Record<string, EventListenerObject> = {
|
|
48
|
-
[VIDEO_DOM_EVENT_MAP.onPlayRequest]: { handleEvent: (event: Event) => emit('playRequest', event) },
|
|
49
|
-
[VIDEO_DOM_EVENT_MAP.onPlay]: { handleEvent: (event: Event) => emit('play', event) },
|
|
50
|
-
[VIDEO_DOM_EVENT_MAP.onPlaying]: { handleEvent: (event: Event) => emit('playing', event) },
|
|
51
|
-
[VIDEO_DOM_EVENT_MAP.onPause]: { handleEvent: (event: Event) => emit('pause', event) },
|
|
52
|
-
[VIDEO_DOM_EVENT_MAP.onStop]: { handleEvent: (event: Event) => emit('stop', event) },
|
|
53
|
-
[VIDEO_DOM_EVENT_MAP.onEnded]: { handleEvent: (event: Event) => emit('ended', event) },
|
|
54
|
-
[VIDEO_DOM_EVENT_MAP.onTimeUpdate]: { handleEvent: (event: Event) => emit('timeUpdate', event) },
|
|
55
|
-
[VIDEO_DOM_EVENT_MAP.onError]: { handleEvent: (event: Event) => emit('error', event) },
|
|
56
|
-
[VIDEO_DOM_EVENT_MAP.onLoadedMetadata]: { handleEvent: (event: Event) => emit('loadedMetadata', event) },
|
|
57
|
-
[VIDEO_DOM_EVENT_MAP.onFullscreenChange]: { handleEvent: (event: Event) => emit('fullscreenChange', event) },
|
|
58
|
-
[VIDEO_DOM_EVENT_MAP.onWaiting]: { handleEvent: (event: Event) => emit('waiting', event) },
|
|
59
|
-
[VIDEO_DOM_EVENT_MAP.onQualityChange]: { handleEvent: (event: Event) => emit('qualityChange', event) },
|
|
60
|
-
[VIDEO_DOM_EVENT_MAP.
|
|
49
|
+
[VIDEO_DOM_EVENT_MAP.onPlayRequest]: { handleEvent: (event: Event) => emit('playRequest', unwrapNativeEventPayload(event)) },
|
|
50
|
+
[VIDEO_DOM_EVENT_MAP.onPlay]: { handleEvent: (event: Event) => emit('play', unwrapNativeEventPayload(event)) },
|
|
51
|
+
[VIDEO_DOM_EVENT_MAP.onPlaying]: { handleEvent: (event: Event) => emit('playing', unwrapNativeEventPayload(event)) },
|
|
52
|
+
[VIDEO_DOM_EVENT_MAP.onPause]: { handleEvent: (event: Event) => emit('pause', unwrapNativeEventPayload(event)) },
|
|
53
|
+
[VIDEO_DOM_EVENT_MAP.onStop]: { handleEvent: (event: Event) => emit('stop', unwrapNativeEventPayload(event)) },
|
|
54
|
+
[VIDEO_DOM_EVENT_MAP.onEnded]: { handleEvent: (event: Event) => emit('ended', unwrapNativeEventPayload(event)) },
|
|
55
|
+
[VIDEO_DOM_EVENT_MAP.onTimeUpdate]: { handleEvent: (event: Event) => emit('timeUpdate', unwrapNativeEventPayload(event)) },
|
|
56
|
+
[VIDEO_DOM_EVENT_MAP.onError]: { handleEvent: (event: Event) => emit('error', unwrapNativeEventPayload(event)) },
|
|
57
|
+
[VIDEO_DOM_EVENT_MAP.onLoadedMetadata]: { handleEvent: (event: Event) => emit('loadedMetadata', unwrapNativeEventPayload(event)) },
|
|
58
|
+
[VIDEO_DOM_EVENT_MAP.onFullscreenChange]: { handleEvent: (event: Event) => emit('fullscreenChange', unwrapNativeEventPayload(event)) },
|
|
59
|
+
[VIDEO_DOM_EVENT_MAP.onWaiting]: { handleEvent: (event: Event) => emit('waiting', unwrapNativeEventPayload(event)) },
|
|
60
|
+
[VIDEO_DOM_EVENT_MAP.onQualityChange]: { handleEvent: (event: Event) => emit('qualityChange', unwrapNativeEventPayload(event)) },
|
|
61
|
+
[VIDEO_DOM_EVENT_MAP.onVolumeChange]: { handleEvent: (event: Event) => emit('volumeChange', unwrapNativeEventPayload(event)) },
|
|
62
|
+
[VIDEO_DOM_EVENT_MAP.onRateChange]: { handleEvent: (event: Event) => emit('rateChange', unwrapNativeEventPayload(event)) },
|
|
61
63
|
};
|
|
62
64
|
|
|
63
65
|
watch(elementRef, (element) => {
|
package/dist/hook.d.ts
CHANGED
|
@@ -50,7 +50,13 @@ export interface LxPlatform {
|
|
|
50
50
|
isAndroid: boolean;
|
|
51
51
|
isHarmony: boolean;
|
|
52
52
|
isWindows: boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Form factor, not OS. This, not `isMacOS`/`isWindows`, is what a layout
|
|
55
|
+
* decision is usually about: the Runner reports macOS while simulating a
|
|
56
|
+
* phone, and a narrowed desktop window is still a desktop.
|
|
57
|
+
*/
|
|
53
58
|
isDesktop: boolean;
|
|
59
|
+
isMobile: boolean;
|
|
54
60
|
isRunner: boolean;
|
|
55
61
|
}
|
|
56
62
|
export declare function usePlatform(): LxPlatform;
|
package/dist/hook.js
CHANGED
|
@@ -207,6 +207,7 @@ export function useLxChannel(method, options) {
|
|
|
207
207
|
}
|
|
208
208
|
function readPlatform() {
|
|
209
209
|
const p = window.LingXiaBridge?.platform;
|
|
210
|
+
const desktop = p?.isDesktop() ?? false;
|
|
210
211
|
return {
|
|
211
212
|
os: p?.getOS() ?? "unknown",
|
|
212
213
|
isIOS: p?.isIOS() ?? false,
|
|
@@ -215,12 +216,16 @@ function readPlatform() {
|
|
|
215
216
|
isAndroid: p?.isAndroid() ?? false,
|
|
216
217
|
isHarmony: p?.isHarmony() ?? false,
|
|
217
218
|
isWindows: p?.isWindows() ?? false,
|
|
218
|
-
isDesktop:
|
|
219
|
+
isDesktop: desktop,
|
|
220
|
+
// Derived, not read, so that a host too old to answer `isMobile` reports
|
|
221
|
+
// one of the two rather than neither.
|
|
222
|
+
isMobile: p?.isMobile?.() ?? !desktop,
|
|
219
223
|
isRunner: p?.isRunner() ?? false,
|
|
220
224
|
};
|
|
221
225
|
}
|
|
222
226
|
// Typed platform detection for pages, so they never reach for the window global
|
|
223
|
-
// or hand-roll an OS check. Fixed for the session, so it resolves once
|
|
227
|
+
// or hand-roll an OS check. Fixed for the session, so it resolves once — the
|
|
228
|
+
// Runner re-serves the page when its simulated device changes form factor.
|
|
224
229
|
export function usePlatform() {
|
|
225
230
|
return readPlatform();
|
|
226
231
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
export { useLxPage, useLxPageChrome, useLxStream, useLxChannel, usePlatform, useDisplayLanguage, type LxStreamOptions, type LxStreamState, type LxChannelOptions, type LxChannelState, type LxPlatform, } from "./hook.js";
|
|
2
2
|
export { default as LxVideo } from "./LxVideo.vue";
|
|
3
|
+
export { default as LxNativeRoot } from "./LxNativeRoot.vue";
|
|
4
|
+
export { default as LxNativeView } from "./LxNativeView.vue";
|
|
5
|
+
export { default as LxNativeCover } from "./LxNativeCover.vue";
|
|
6
|
+
export { default as LxNativeText } from "./LxNativeText.vue";
|
|
7
|
+
export { default as LxNativeButton } from "./LxNativeButton.vue";
|
|
3
8
|
export { default as LxMediaSwiper } from "./LxMediaSwiper.vue";
|
|
4
9
|
export { default as LxPicker } from "./LxPicker.vue";
|
|
5
10
|
export { default as LxNavigator } from "./LxNavigator.vue";
|
|
6
|
-
export type { LxVideoProps, LxMediaSwiperProps, LxPickerProps, LxNavigatorProps, LxNavigatorEvent, } from "./types.js";
|
|
11
|
+
export type { LxVideoProps, LxNativeRootProps, LxNativeViewProps, LxNativeCoverProps, LxNativeTextProps, LxNativeButtonProps, LxMediaSwiperProps, LxPickerProps, LxNavigatorProps, LxNavigatorEvent, } from "./types.js";
|
|
7
12
|
export type { LxPageChrome, PageChromeLayoutListener, PageChromeLayoutSnapshot, PageChromeRect, } from "@lingxia/page-runtime";
|
|
13
|
+
export type { LxVideoEventPayloads, LxVideoEventHandlers, NativeActionIcon } from "@lingxia/elements";
|
|
14
|
+
export type { NativeStyle } from "./types.js";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
export { useLxPage, useLxPageChrome, useLxStream, useLxChannel, usePlatform, useDisplayLanguage, } from "./hook.js";
|
|
2
2
|
export { default as LxVideo } from "./LxVideo.vue";
|
|
3
|
+
export { default as LxNativeRoot } from "./LxNativeRoot.vue";
|
|
4
|
+
export { default as LxNativeView } from "./LxNativeView.vue";
|
|
5
|
+
export { default as LxNativeCover } from "./LxNativeCover.vue";
|
|
6
|
+
export { default as LxNativeText } from "./LxNativeText.vue";
|
|
7
|
+
export { default as LxNativeButton } from "./LxNativeButton.vue";
|
|
3
8
|
export { default as LxMediaSwiper } from "./LxMediaSwiper.vue";
|
|
4
9
|
export { default as LxPicker } from "./LxPicker.vue";
|
|
5
10
|
export { default as LxNavigator } from "./LxNavigator.vue";
|
|
@@ -1,3 +1,23 @@
|
|
|
1
|
+
import { type Ref } from "vue";
|
|
1
2
|
export declare function getCustomEventDetail<T>(event: Event): T;
|
|
3
|
+
type NativeAriaProps = {
|
|
4
|
+
"aria-label"?: string;
|
|
5
|
+
ariaLabel?: string;
|
|
6
|
+
"aria-description"?: string;
|
|
7
|
+
"aria-hidden"?: boolean;
|
|
8
|
+
automationId?: string;
|
|
9
|
+
};
|
|
10
|
+
export declare function useNativeHostElement(props: NativeAriaProps): Ref<HTMLElement | null>;
|
|
2
11
|
export declare function bindElementEvents(currentBoundElement: HTMLElement | null, nextElement: HTMLElement | null, listeners: Record<string, EventListenerObject>): HTMLElement | null;
|
|
3
12
|
export declare function unbindElementEvents(boundElement: HTMLElement | null, listeners: Record<string, EventListenerObject>): void;
|
|
13
|
+
export declare function setOptionalDomAttribute(el: HTMLElement, name: string, value: string | number | boolean | undefined | null): void;
|
|
14
|
+
/** Vue's custom-element patch may assign `el['aria-label']` as an expando.
|
|
15
|
+
* UI Automation and the island compiler only see the reflected attribute. */
|
|
16
|
+
export declare function applyNativeAriaAttributes(el: HTMLElement | null, props: {
|
|
17
|
+
"aria-label"?: string;
|
|
18
|
+
ariaLabel?: string;
|
|
19
|
+
"aria-description"?: string;
|
|
20
|
+
"aria-hidden"?: boolean;
|
|
21
|
+
automationId?: string;
|
|
22
|
+
}): void;
|
|
23
|
+
export {};
|
|
@@ -1,6 +1,20 @@
|
|
|
1
|
+
import { ref, watch } from "vue";
|
|
1
2
|
export function getCustomEventDetail(event) {
|
|
2
3
|
return (event.detail ?? {});
|
|
3
4
|
}
|
|
5
|
+
export function useNativeHostElement(props) {
|
|
6
|
+
const elementRef = ref(null);
|
|
7
|
+
const apply = () => applyNativeAriaAttributes(elementRef.value, props);
|
|
8
|
+
watch(elementRef, apply);
|
|
9
|
+
watch(() => [
|
|
10
|
+
props["aria-label"],
|
|
11
|
+
props.ariaLabel,
|
|
12
|
+
props["aria-description"],
|
|
13
|
+
props["aria-hidden"],
|
|
14
|
+
props.automationId,
|
|
15
|
+
], apply);
|
|
16
|
+
return elementRef;
|
|
17
|
+
}
|
|
4
18
|
export function bindElementEvents(currentBoundElement, nextElement, listeners) {
|
|
5
19
|
if (currentBoundElement && currentBoundElement !== nextElement) {
|
|
6
20
|
for (const [event, listener] of Object.entries(listeners)) {
|
|
@@ -23,3 +37,29 @@ export function unbindElementEvents(boundElement, listeners) {
|
|
|
23
37
|
boundElement.removeEventListener(event, listener);
|
|
24
38
|
}
|
|
25
39
|
}
|
|
40
|
+
export function setOptionalDomAttribute(el, name, value) {
|
|
41
|
+
if (value === undefined || value === null || value === false) {
|
|
42
|
+
el.removeAttribute(name);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (typeof value === "boolean") {
|
|
46
|
+
el.setAttribute(name, value ? "true" : "false");
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
el.setAttribute(name, String(value));
|
|
50
|
+
}
|
|
51
|
+
/** Vue's custom-element patch may assign `el['aria-label']` as an expando.
|
|
52
|
+
* UI Automation and the island compiler only see the reflected attribute. */
|
|
53
|
+
export function applyNativeAriaAttributes(el, props) {
|
|
54
|
+
if (!el)
|
|
55
|
+
return;
|
|
56
|
+
setOptionalDomAttribute(el, "aria-label", props["aria-label"] ?? props.ariaLabel);
|
|
57
|
+
setOptionalDomAttribute(el, "aria-description", props["aria-description"]);
|
|
58
|
+
if (props["aria-hidden"] === undefined) {
|
|
59
|
+
el.removeAttribute("aria-hidden");
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
setOptionalDomAttribute(el, "aria-hidden", props["aria-hidden"]);
|
|
63
|
+
}
|
|
64
|
+
setOptionalDomAttribute(el, "automation-id", props.automationId);
|
|
65
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { CSSProperties } from 'vue';
|
|
2
|
-
import type { LxNavigatorEvent,
|
|
2
|
+
import type { LxNavigatorEvent, LxVideoEventPayloads, NativeActionIcon, NativeStyleProperty, NavigatorChannel, NavigatorOpenType, NavigatorQuery, NavigatorTarget } from '@lingxia/elements';
|
|
3
|
+
export type NativeStyle = Omit<Pick<CSSProperties, NativeStyleProperty>, "borderStyle"> & {
|
|
4
|
+
borderStyle?: "solid" | "none";
|
|
5
|
+
};
|
|
3
6
|
export interface LxVideoProps {
|
|
4
7
|
id?: string;
|
|
5
8
|
src?: string;
|
|
@@ -19,22 +22,66 @@ export interface LxVideoProps {
|
|
|
19
22
|
}>;
|
|
20
23
|
playbackRates?: number[];
|
|
21
24
|
class?: string;
|
|
22
|
-
style?:
|
|
23
|
-
onPlayRequest?: (
|
|
24
|
-
onPlay?: (
|
|
25
|
-
onPlaying?: (
|
|
26
|
-
onPause?: (
|
|
27
|
-
onStop?: (
|
|
28
|
-
onEnded?: (
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
onQualityChange?: (
|
|
35
|
-
onRateChange?: (
|
|
25
|
+
style?: NativeStyle;
|
|
26
|
+
onPlayRequest?: (payload: LxVideoEventPayloads["onPlayRequest"]) => void;
|
|
27
|
+
onPlay?: (payload: LxVideoEventPayloads["onPlay"]) => void;
|
|
28
|
+
onPlaying?: (payload: LxVideoEventPayloads["onPlaying"]) => void;
|
|
29
|
+
onPause?: (payload: LxVideoEventPayloads["onPause"]) => void;
|
|
30
|
+
onStop?: (payload: LxVideoEventPayloads["onStop"]) => void;
|
|
31
|
+
onEnded?: (payload: LxVideoEventPayloads["onEnded"]) => void;
|
|
32
|
+
onWaiting?: (payload: LxVideoEventPayloads["onWaiting"]) => void;
|
|
33
|
+
onTimeUpdate?: (payload: LxVideoEventPayloads["onTimeUpdate"]) => void;
|
|
34
|
+
onError?: (payload: LxVideoEventPayloads["onError"]) => void;
|
|
35
|
+
onLoadedMetadata?: (payload: LxVideoEventPayloads["onLoadedMetadata"]) => void;
|
|
36
|
+
onFullscreenChange?: (payload: LxVideoEventPayloads["onFullscreenChange"]) => void;
|
|
37
|
+
onQualityChange?: (payload: LxVideoEventPayloads["onQualityChange"]) => void;
|
|
38
|
+
onRateChange?: (payload: LxVideoEventPayloads["onRateChange"]) => void;
|
|
39
|
+
onVolumeChange?: (payload: LxVideoEventPayloads["onVolumeChange"]) => void;
|
|
36
40
|
pageBindings?: Record<string, string>;
|
|
37
41
|
}
|
|
42
|
+
export interface LxNativeNodeProps {
|
|
43
|
+
id?: string;
|
|
44
|
+
automationId?: string;
|
|
45
|
+
class?: string;
|
|
46
|
+
style?: NativeStyle;
|
|
47
|
+
pointerEvents?: 'auto' | 'none' | 'box-only' | 'box-none';
|
|
48
|
+
hidden?: boolean;
|
|
49
|
+
'aria-label'?: string;
|
|
50
|
+
'aria-description'?: string;
|
|
51
|
+
'aria-hidden'?: boolean;
|
|
52
|
+
}
|
|
53
|
+
export interface LxNativeRootProps extends LxNativeNodeProps {
|
|
54
|
+
}
|
|
55
|
+
export interface LxNativeViewProps extends LxNativeNodeProps {
|
|
56
|
+
role?: 'group' | 'region' | 'status' | 'presentation' | 'none';
|
|
57
|
+
}
|
|
58
|
+
export interface LxNativeCoverProps extends LxNativeViewProps {
|
|
59
|
+
scrim?: 'none' | 'top' | 'bottom' | 'full';
|
|
60
|
+
scrimOpacity?: number;
|
|
61
|
+
}
|
|
62
|
+
export interface LxNativeTextProps extends LxNativeNodeProps {
|
|
63
|
+
maxLines?: number;
|
|
64
|
+
dir?: 'ltr' | 'rtl' | 'auto';
|
|
65
|
+
fontSize?: number | string;
|
|
66
|
+
fontWeight?: number | string;
|
|
67
|
+
lineHeight?: number | string;
|
|
68
|
+
textAlign?: 'start' | 'center' | 'end';
|
|
69
|
+
color?: string;
|
|
70
|
+
}
|
|
71
|
+
export interface LxNativeButtonProps extends LxNativeNodeProps {
|
|
72
|
+
label?: string;
|
|
73
|
+
icon?: NativeActionIcon;
|
|
74
|
+
iconPosition?: 'start' | 'end';
|
|
75
|
+
intent?: 'neutral' | 'accent' | 'destructive';
|
|
76
|
+
emphasis?: 'primary' | 'secondary' | 'quiet';
|
|
77
|
+
size?: 'compact' | 'regular';
|
|
78
|
+
hitSlop?: number;
|
|
79
|
+
disabled?: boolean;
|
|
80
|
+
pressed?: boolean;
|
|
81
|
+
expanded?: boolean;
|
|
82
|
+
loading?: boolean;
|
|
83
|
+
tabIndex?: 0 | -1;
|
|
84
|
+
}
|
|
38
85
|
type LxMediaSwiperItem = {
|
|
39
86
|
id?: string;
|
|
40
87
|
type: 'image';
|
|
@@ -108,7 +155,7 @@ export interface LxNavigatorProps {
|
|
|
108
155
|
delta?: number;
|
|
109
156
|
query?: NavigatorQuery;
|
|
110
157
|
appId?: string;
|
|
111
|
-
|
|
158
|
+
channel?: NavigatorChannel;
|
|
112
159
|
targetVersion?: string;
|
|
113
160
|
phoneNumber?: string;
|
|
114
161
|
hoverClass?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lingxia/vue",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "LingXia Vue runtime and components for lxapp pages",
|
|
6
6
|
"type": "module",
|
|
@@ -16,12 +16,13 @@
|
|
|
16
16
|
"scripts": {
|
|
17
17
|
"build": "npm run clean && npm --prefix ../lingxia-elements run build && npm --prefix ../lingxia-page-runtime run build && tsc -p tsconfig.json && node scripts/copy-sfc-assets.mjs",
|
|
18
18
|
"clean": "rm -rf dist",
|
|
19
|
-
"prepublishOnly": "npm run build"
|
|
19
|
+
"prepublishOnly": "npm run build",
|
|
20
|
+
"test:components": "npm run build && node tests/native-components.mjs && node tests/native-aria-attributes.mjs"
|
|
20
21
|
},
|
|
21
22
|
"dependencies": {
|
|
22
|
-
"@lingxia/bridge": "~0.
|
|
23
|
-
"@lingxia/elements": "~0.
|
|
24
|
-
"@lingxia/page-runtime": "~0.
|
|
23
|
+
"@lingxia/bridge": "~0.16.0",
|
|
24
|
+
"@lingxia/elements": "~0.16.0",
|
|
25
|
+
"@lingxia/page-runtime": "~0.16.0"
|
|
25
26
|
},
|
|
26
27
|
"peerDependencies": {
|
|
27
28
|
"vue": ">=3.5.0"
|