@lingxia/vue 0.17.0 → 0.19.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/LxMediaSwiper.vue +22 -28
- package/dist/LxNavigator.vue +6 -0
- package/dist/LxPicker.vue +10 -1
- package/dist/entry.d.ts +13 -0
- package/dist/entry.js +16 -0
- package/dist/hook.d.ts +37 -41
- package/dist/hook.js +59 -69
- package/dist/index.d.ts +4 -3
- package/dist/index.js +1 -1
- package/dist/types.d.ts +18 -30
- package/package.json +10 -5
package/dist/LxMediaSwiper.vue
CHANGED
|
@@ -4,6 +4,9 @@ import {
|
|
|
4
4
|
buildMediaSwiperNativeAttrs,
|
|
5
5
|
MEDIA_SWIPER_DOM_EVENT_MAP,
|
|
6
6
|
registerMediaSwiperComponent,
|
|
7
|
+
unwrapNativeEventPayload,
|
|
8
|
+
type LxMediaSwiperEventPayloads as Payloads,
|
|
9
|
+
type LxMediaSwiperHandle,
|
|
7
10
|
} from '@lingxia/elements';
|
|
8
11
|
import { bindElementEvents, unbindElementEvents } from './text_component_shared.js';
|
|
9
12
|
import type { LxMediaSwiperProps } from './types.js';
|
|
@@ -23,31 +26,31 @@ const props = withDefaults(defineProps<LxMediaSwiperProps>(), {
|
|
|
23
26
|
const attrs = useAttrs();
|
|
24
27
|
|
|
25
28
|
const emit = defineEmits<{
|
|
26
|
-
change: [
|
|
27
|
-
transitionEnd: [
|
|
28
|
-
endReached: [
|
|
29
|
-
tap: [
|
|
30
|
-
videoEnded: [
|
|
31
|
-
error: [
|
|
29
|
+
change: [payload: Payloads['onChange']];
|
|
30
|
+
transitionEnd: [payload: Payloads['onTransitionEnd']];
|
|
31
|
+
endReached: [payload: Payloads['onEndReached']];
|
|
32
|
+
tap: [payload: Payloads['onTap']];
|
|
33
|
+
videoEnded: [payload: Payloads['onVideoEnded']];
|
|
34
|
+
error: [payload: Payloads['onError']];
|
|
32
35
|
}>();
|
|
33
36
|
|
|
34
37
|
if (typeof window !== 'undefined') {
|
|
35
38
|
registerMediaSwiperComponent();
|
|
36
39
|
}
|
|
37
40
|
|
|
38
|
-
const elementRef = ref<HTMLElement | null>(null);
|
|
41
|
+
const elementRef = ref<(HTMLElement & LxMediaSwiperHandle) | null>(null);
|
|
39
42
|
const vueId = useId();
|
|
40
43
|
let boundElement: HTMLElement | null = null;
|
|
41
44
|
|
|
42
45
|
const resolvedId = computed(() => props.id || `lx-media-swiper-${vueId.replace(/[:]/g, '')}`);
|
|
43
46
|
|
|
44
47
|
const eventListeners: Record<string, EventListenerObject> = {
|
|
45
|
-
[MEDIA_SWIPER_DOM_EVENT_MAP.onChange]: { handleEvent: (event: Event) => emit('change', event) },
|
|
46
|
-
[MEDIA_SWIPER_DOM_EVENT_MAP.onTransitionEnd]: { handleEvent: (event: Event) => emit('transitionEnd', event) },
|
|
47
|
-
[MEDIA_SWIPER_DOM_EVENT_MAP.onEndReached]: { handleEvent: (event: Event) => emit('endReached', event) },
|
|
48
|
-
[MEDIA_SWIPER_DOM_EVENT_MAP.onTap]: { handleEvent: (event: Event) => emit('tap', event) },
|
|
49
|
-
[MEDIA_SWIPER_DOM_EVENT_MAP.onVideoEnded]: { handleEvent: (event: Event) => emit('videoEnded', event) },
|
|
50
|
-
[MEDIA_SWIPER_DOM_EVENT_MAP.onError]: { handleEvent: (event: Event) => emit('error', event) },
|
|
48
|
+
[MEDIA_SWIPER_DOM_EVENT_MAP.onChange]: { handleEvent: (event: Event) => emit('change', unwrapNativeEventPayload(event)) },
|
|
49
|
+
[MEDIA_SWIPER_DOM_EVENT_MAP.onTransitionEnd]: { handleEvent: (event: Event) => emit('transitionEnd', unwrapNativeEventPayload(event)) },
|
|
50
|
+
[MEDIA_SWIPER_DOM_EVENT_MAP.onEndReached]: { handleEvent: (event: Event) => emit('endReached', unwrapNativeEventPayload(event)) },
|
|
51
|
+
[MEDIA_SWIPER_DOM_EVENT_MAP.onTap]: { handleEvent: (event: Event) => emit('tap', unwrapNativeEventPayload(event)) },
|
|
52
|
+
[MEDIA_SWIPER_DOM_EVENT_MAP.onVideoEnded]: { handleEvent: (event: Event) => emit('videoEnded', unwrapNativeEventPayload(event)) },
|
|
53
|
+
[MEDIA_SWIPER_DOM_EVENT_MAP.onError]: { handleEvent: (event: Event) => emit('error', unwrapNativeEventPayload(event)) },
|
|
51
54
|
};
|
|
52
55
|
|
|
53
56
|
watch(elementRef, (element) => {
|
|
@@ -58,16 +61,6 @@ onBeforeUnmount(() => {
|
|
|
58
61
|
unbindElementEvents(boundElement, eventListeners);
|
|
59
62
|
});
|
|
60
63
|
|
|
61
|
-
watch(
|
|
62
|
-
[elementRef, () => props.pageBindings],
|
|
63
|
-
() => {
|
|
64
|
-
const el = elementRef.value as any;
|
|
65
|
-
if (el) {
|
|
66
|
-
el.pageBindings = props.pageBindings ?? {};
|
|
67
|
-
}
|
|
68
|
-
},
|
|
69
|
-
{ immediate: true }
|
|
70
|
-
);
|
|
71
64
|
|
|
72
65
|
const domProps = computed(() => {
|
|
73
66
|
const result = buildMediaSwiperNativeAttrs({
|
|
@@ -81,12 +74,13 @@ const domProps = computed(() => {
|
|
|
81
74
|
};
|
|
82
75
|
});
|
|
83
76
|
|
|
84
|
-
|
|
77
|
+
const handle: LxMediaSwiperHandle & { el: typeof elementRef } = {
|
|
85
78
|
el: elementRef,
|
|
86
|
-
next: () =>
|
|
87
|
-
previous: () =>
|
|
88
|
-
goToIndex: (index: number) =>
|
|
89
|
-
}
|
|
79
|
+
next: () => elementRef.value?.next(),
|
|
80
|
+
previous: () => elementRef.value?.previous(),
|
|
81
|
+
goToIndex: (index: number) => elementRef.value?.goToIndex(index),
|
|
82
|
+
};
|
|
83
|
+
defineExpose(handle);
|
|
90
84
|
|
|
91
85
|
const render = () => h('lx-media-swiper', { ref: elementRef, ...domProps.value });
|
|
92
86
|
</script>
|
package/dist/LxNavigator.vue
CHANGED
|
@@ -61,6 +61,12 @@ const render = () => h(
|
|
|
61
61
|
target: props.target,
|
|
62
62
|
delta: props.delta,
|
|
63
63
|
query: props.query,
|
|
64
|
+
as: props.as,
|
|
65
|
+
edge: props.edge,
|
|
66
|
+
position: props.position,
|
|
67
|
+
chrome: props.chrome,
|
|
68
|
+
size: props.size,
|
|
69
|
+
interaction: props.interaction,
|
|
64
70
|
appId: props.appId,
|
|
65
71
|
channel: props.channel,
|
|
66
72
|
targetVersion: props.targetVersion,
|
package/dist/LxPicker.vue
CHANGED
|
@@ -131,7 +131,16 @@ const renderPicker = () => visible.value ? h('lx-picker', { ref: pickerRef, ...p
|
|
|
131
131
|
|
|
132
132
|
<template>
|
|
133
133
|
<slot :open="handleClick" :disabled="props.disabled">
|
|
134
|
-
<div
|
|
134
|
+
<div
|
|
135
|
+
:class="props.class ?? attrs.class"
|
|
136
|
+
:style="[triggerStyle, props.style ?? attrs.style]"
|
|
137
|
+
role="button"
|
|
138
|
+
:tabindex="props.disabled ? -1 : 0"
|
|
139
|
+
:aria-disabled="props.disabled || undefined"
|
|
140
|
+
@click="handleClick"
|
|
141
|
+
@keydown.enter.prevent="handleClick"
|
|
142
|
+
@keydown.space.prevent="handleClick"
|
|
143
|
+
>
|
|
135
144
|
<span :style="{ color: modelValue ? '#111' : '#9ca3af' }">{{ displayText || placeholder }}</span>
|
|
136
145
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#9ca3af" stroke-width="2">
|
|
137
146
|
<path d="M6 9l6 6 6-6" />
|
package/dist/entry.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Component } from "vue";
|
|
2
|
+
/**
|
|
3
|
+
* Mount a page's View. The CLI's generated entry calls this; pages never do.
|
|
4
|
+
*
|
|
5
|
+
* With `waitForState` — the page has Logic — the View mounts only once the
|
|
6
|
+
* page's first state has arrived, so `useLxPage().data` is whole from the first
|
|
7
|
+
* render. If that takes longer than 10 seconds, a panel names the page
|
|
8
|
+
* instead of a blank screen — and if the state arrives after all (a slow cold
|
|
9
|
+
* start, a paused debugger), the panel goes and the page mounts.
|
|
10
|
+
*/
|
|
11
|
+
export declare function mountPage(App: Component, options: {
|
|
12
|
+
waitForState: boolean;
|
|
13
|
+
}): Promise<void>;
|
package/dist/entry.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createApp } from "vue";
|
|
2
|
+
import { waitForPageState } from "@lingxia/page-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Mount a page's View. The CLI's generated entry calls this; pages never do.
|
|
5
|
+
*
|
|
6
|
+
* With `waitForState` — the page has Logic — the View mounts only once the
|
|
7
|
+
* page's first state has arrived, so `useLxPage().data` is whole from the first
|
|
8
|
+
* render. If that takes longer than 10 seconds, a panel names the page
|
|
9
|
+
* instead of a blank screen — and if the state arrives after all (a slow cold
|
|
10
|
+
* start, a paused debugger), the panel goes and the page mounts.
|
|
11
|
+
*/
|
|
12
|
+
export async function mountPage(App, options) {
|
|
13
|
+
if (options.waitForState)
|
|
14
|
+
await waitForPageState();
|
|
15
|
+
createApp(App).mount("#app");
|
|
16
|
+
}
|
package/dist/hook.d.ts
CHANGED
|
@@ -1,20 +1,39 @@
|
|
|
1
1
|
import { type Ref } from "vue";
|
|
2
2
|
import type { LxChannel, LxBridgeError, LxStream } from "@lingxia/bridge";
|
|
3
|
-
import { type
|
|
4
|
-
import { type
|
|
3
|
+
import { type LxHost } from "@lingxia/bridge";
|
|
4
|
+
import { type ChannelIn, type ChannelOut, type MethodParams, type OptionsArg, type ParamsOption, type ParamsSource, type StreamData, type StreamResult } from "@lingxia/bridge/invocation";
|
|
5
|
+
import { type ActionMap, type PageActions, type DeepReadonly, type Snapshot } from "@lingxia/page-runtime";
|
|
5
6
|
type MethodSource<T> = T | Ref<T>;
|
|
7
|
+
/**
|
|
8
|
+
* This page's Logic state and actions — `this.data` and the page's methods.
|
|
9
|
+
* The page mounts once its first state has arrived, so `data` is whole from
|
|
10
|
+
* the first render. `data` is deep-reactive, readonly and updated in place, so
|
|
11
|
+
* it may be destructured; keep editable state in a `ref` and send it with an
|
|
12
|
+
* action. Call during component setup; pass actions into shared helpers
|
|
13
|
+
* instead of reading at module load.
|
|
14
|
+
*/
|
|
6
15
|
export declare function useLxPage<TData = Snapshot, TActions extends ActionMap = ActionMap>(): {
|
|
7
|
-
data: TData
|
|
8
|
-
actions: TActions
|
|
16
|
+
data: DeepReadonly<TData>;
|
|
17
|
+
actions: PageActions<TActions>;
|
|
9
18
|
};
|
|
10
|
-
/**
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
19
|
+
/**
|
|
20
|
+
* What the host decided for this page: `sizeClass`, `aside`,
|
|
21
|
+
* `displayLanguage`, `formFactor`, `os`, `runner` — a readonly reactive object
|
|
22
|
+
* that changes only when one of them does, never while a window is dragged.
|
|
23
|
+
* Read `host.sizeClass`; destructuring takes a snapshot. Geometry is CSS:
|
|
24
|
+
* `--lx-page-chrome-*` and container queries. Callable anywhere.
|
|
25
|
+
*/
|
|
26
|
+
export declare function useLxHost(): Readonly<LxHost>;
|
|
27
|
+
type StreamMethod = (...args: any[]) => LxStream<any, any>;
|
|
28
|
+
type ChannelMethod = (...args: any[]) => Promise<LxChannel<any, any>>;
|
|
29
|
+
export type LxStreamOptions<TMethod> = ParamsOption<TMethod, ParamsSource<MethodParams<TMethod>>> & {
|
|
14
30
|
manual?: boolean;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
31
|
+
};
|
|
32
|
+
/** A reducer folds chunks into `data`, starting from `initial`. */
|
|
33
|
+
export type LxReducedStreamOptions<TMethod, TReduced> = LxStreamOptions<TMethod> & {
|
|
34
|
+
reduce: (accumulated: TReduced, chunk: StreamData<TMethod>) => TReduced;
|
|
35
|
+
initial: TReduced;
|
|
36
|
+
};
|
|
18
37
|
export interface LxStreamState<TData, TResult = unknown> {
|
|
19
38
|
data: Ref<TData | undefined>;
|
|
20
39
|
result: Ref<TResult | undefined>;
|
|
@@ -23,43 +42,20 @@ export interface LxStreamState<TData, TResult = unknown> {
|
|
|
23
42
|
cancel: () => void;
|
|
24
43
|
start: () => void;
|
|
25
44
|
}
|
|
26
|
-
export declare function useLxStream<TMethod extends
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
export interface LxChannelOptions {
|
|
30
|
-
params?: unknown | (() => unknown);
|
|
45
|
+
export declare function useLxStream<TMethod extends StreamMethod, TReduced>(method: MethodSource<TMethod>, options: LxReducedStreamOptions<TMethod, TReduced>): LxStreamState<TReduced, StreamResult<TMethod>>;
|
|
46
|
+
export declare function useLxStream<TMethod extends StreamMethod>(method: MethodSource<TMethod>, ...options: OptionsArg<TMethod, LxStreamOptions<TMethod>>): LxStreamState<StreamData<TMethod>, StreamResult<TMethod>>;
|
|
47
|
+
export type LxChannelOptions<TMethod> = ParamsOption<TMethod, ParamsSource<MethodParams<TMethod>>> & {
|
|
31
48
|
manual?: boolean;
|
|
32
|
-
}
|
|
49
|
+
};
|
|
33
50
|
export interface LxChannelState<TData, TOut = TData> {
|
|
34
51
|
last: Ref<TData | undefined>;
|
|
35
52
|
error: Ref<LxBridgeError | undefined>;
|
|
36
53
|
connecting: Ref<boolean>;
|
|
37
54
|
connected: Ref<boolean>;
|
|
38
|
-
|
|
55
|
+
/** Sends when connected; `false` when there is no open channel to send on. */
|
|
56
|
+
send: (payload: TOut) => boolean;
|
|
39
57
|
close: (code?: string, reason?: string) => void;
|
|
40
58
|
reopen: () => void;
|
|
41
59
|
}
|
|
42
|
-
export declare function useLxChannel<TMethod extends (...args:
|
|
43
|
-
params?: ParamsSource<MethodParams<TMethod>>;
|
|
44
|
-
}): LxChannelState<ChannelIn<TMethod>, ChannelOut<TMethod>>;
|
|
45
|
-
export interface LxPlatform {
|
|
46
|
-
os: string;
|
|
47
|
-
isIOS: boolean;
|
|
48
|
-
isMacOS: boolean;
|
|
49
|
-
isApple: boolean;
|
|
50
|
-
isAndroid: boolean;
|
|
51
|
-
isHarmony: boolean;
|
|
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
|
-
*/
|
|
58
|
-
isDesktop: boolean;
|
|
59
|
-
isMobile: boolean;
|
|
60
|
-
isRunner: boolean;
|
|
61
|
-
}
|
|
62
|
-
export declare function usePlatform(): LxPlatform;
|
|
63
|
-
/** Effective product language selected by the host; follows a change. */
|
|
64
|
-
export declare function useDisplayLanguage(): Readonly<Ref<string>>;
|
|
60
|
+
export declare function useLxChannel<TMethod extends ChannelMethod>(method: MethodSource<TMethod>, ...args: OptionsArg<TMethod, LxChannelOptions<TMethod>>): LxChannelState<ChannelIn<TMethod>, ChannelOut<TMethod>>;
|
|
65
61
|
export {};
|
package/dist/hook.js
CHANGED
|
@@ -1,43 +1,62 @@
|
|
|
1
|
-
import { onUnmounted,
|
|
2
|
-
import {
|
|
1
|
+
import { onUnmounted, reactive, readonly, ref, unref, watch, } from "vue";
|
|
2
|
+
import { getHost, subscribeHost } from "@lingxia/bridge";
|
|
3
3
|
import { getMethodKey, invokeMethod, resolveParams, stableParamKey, toBridgeError, } from "@lingxia/bridge/invocation";
|
|
4
|
-
import {
|
|
4
|
+
import { getPageActions, getPageSnapshot, subscribePageSnapshot, } from "@lingxia/page-runtime";
|
|
5
5
|
function resolveMethod(source) {
|
|
6
6
|
return unref(source);
|
|
7
7
|
}
|
|
8
|
+
// One reactive copy of the page's data for the document, updated in place so
|
|
9
|
+
// a destructured `data` stays live.
|
|
8
10
|
const reactiveSnapshot = reactive({});
|
|
9
11
|
let snapshotSubscribed = false;
|
|
10
|
-
function
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
for (const key of Object.keys(reactiveSnapshot)) {
|
|
17
|
-
if (!Object.prototype.hasOwnProperty.call(normalized, key)) {
|
|
18
|
-
delete reactiveSnapshot[key];
|
|
19
|
-
}
|
|
12
|
+
function syncSnapshot() {
|
|
13
|
+
const next = getPageSnapshot();
|
|
14
|
+
const normalized = next && typeof next === "object" ? next : {};
|
|
15
|
+
for (const key of Object.keys(reactiveSnapshot)) {
|
|
16
|
+
if (!Object.prototype.hasOwnProperty.call(normalized, key)) {
|
|
17
|
+
delete reactiveSnapshot[key];
|
|
20
18
|
}
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
}
|
|
20
|
+
Object.assign(reactiveSnapshot, normalized);
|
|
23
21
|
}
|
|
22
|
+
// What pages get: Logic owns the data, so a View write is refused (Vue warns
|
|
23
|
+
// in development) while the sync above keeps updating the same object.
|
|
24
|
+
const readonlySnapshot = readonly(reactiveSnapshot);
|
|
25
|
+
/**
|
|
26
|
+
* This page's Logic state and actions — `this.data` and the page's methods.
|
|
27
|
+
* The page mounts once its first state has arrived, so `data` is whole from
|
|
28
|
+
* the first render. `data` is deep-reactive, readonly and updated in place, so
|
|
29
|
+
* it may be destructured; keep editable state in a `ref` and send it with an
|
|
30
|
+
* action. Call during component setup; pass actions into shared helpers
|
|
31
|
+
* instead of reading at module load.
|
|
32
|
+
*/
|
|
24
33
|
export function useLxPage() {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
34
|
+
if (!snapshotSubscribed) {
|
|
35
|
+
snapshotSubscribed = true;
|
|
36
|
+
syncSnapshot();
|
|
37
|
+
subscribePageSnapshot(syncSnapshot);
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
data: readonlySnapshot,
|
|
41
|
+
actions: getPageActions(),
|
|
42
|
+
};
|
|
28
43
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
44
|
+
const hostState = reactive({ ...getHost() });
|
|
45
|
+
let hostSubscribed = false;
|
|
46
|
+
/**
|
|
47
|
+
* What the host decided for this page: `sizeClass`, `aside`,
|
|
48
|
+
* `displayLanguage`, `formFactor`, `os`, `runner` — a readonly reactive object
|
|
49
|
+
* that changes only when one of them does, never while a window is dragged.
|
|
50
|
+
* Read `host.sizeClass`; destructuring takes a snapshot. Geometry is CSS:
|
|
51
|
+
* `--lx-page-chrome-*` and container queries. Callable anywhere.
|
|
52
|
+
*/
|
|
53
|
+
export function useLxHost() {
|
|
54
|
+
if (!hostSubscribed) {
|
|
55
|
+
hostSubscribed = true;
|
|
56
|
+
Object.assign(hostState, getHost());
|
|
57
|
+
subscribeHost(() => Object.assign(hostState, getHost()));
|
|
35
58
|
}
|
|
36
|
-
|
|
37
|
-
layout.value = next;
|
|
38
|
-
});
|
|
39
|
-
onUnmounted(unsubscribe);
|
|
40
|
-
return layout;
|
|
59
|
+
return readonly(hostState);
|
|
41
60
|
}
|
|
42
61
|
export function useLxStream(method, options) {
|
|
43
62
|
const data = ref((options?.reduce ? options.initial : undefined));
|
|
@@ -122,7 +141,8 @@ export function useLxStream(method, options) {
|
|
|
122
141
|
});
|
|
123
142
|
return { data, result, error, streaming, cancel, start };
|
|
124
143
|
}
|
|
125
|
-
export function useLxChannel(method,
|
|
144
|
+
export function useLxChannel(method, ...args) {
|
|
145
|
+
const options = args[0];
|
|
126
146
|
const last = ref(undefined);
|
|
127
147
|
const error = ref(undefined);
|
|
128
148
|
const connecting = ref(false);
|
|
@@ -130,7 +150,10 @@ export function useLxChannel(method, options) {
|
|
|
130
150
|
let ch = null;
|
|
131
151
|
let runId = 0;
|
|
132
152
|
function send(payload) {
|
|
133
|
-
ch
|
|
153
|
+
if (!ch)
|
|
154
|
+
return false;
|
|
155
|
+
ch.send(payload);
|
|
156
|
+
return true;
|
|
134
157
|
}
|
|
135
158
|
function close(code, reason) {
|
|
136
159
|
runId += 1;
|
|
@@ -147,7 +170,11 @@ export function useLxChannel(method, options) {
|
|
|
147
170
|
error.value = undefined;
|
|
148
171
|
connecting.value = true;
|
|
149
172
|
connected.value = false;
|
|
150
|
-
|
|
173
|
+
// In the executor: a method or params getter that throws synchronously
|
|
174
|
+
// lands in `.catch`.
|
|
175
|
+
new Promise((resolve) => {
|
|
176
|
+
resolve(invokeMethod(resolveMethod(method), resolveParams(options?.params)));
|
|
177
|
+
})
|
|
151
178
|
.then((nextChannel) => {
|
|
152
179
|
if (runId !== thisRunId) {
|
|
153
180
|
nextChannel.close();
|
|
@@ -205,40 +232,3 @@ export function useLxChannel(method, options) {
|
|
|
205
232
|
});
|
|
206
233
|
return { last, error, connecting, connected, send, close, reopen };
|
|
207
234
|
}
|
|
208
|
-
function readPlatform() {
|
|
209
|
-
const p = window.LingXiaBridge?.platform;
|
|
210
|
-
const desktop = p?.isDesktop() ?? false;
|
|
211
|
-
return {
|
|
212
|
-
os: p?.getOS() ?? "unknown",
|
|
213
|
-
isIOS: p?.isIOS() ?? false,
|
|
214
|
-
isMacOS: p?.isMacOS() ?? false,
|
|
215
|
-
isApple: p?.isApple() ?? false,
|
|
216
|
-
isAndroid: p?.isAndroid() ?? false,
|
|
217
|
-
isHarmony: p?.isHarmony() ?? false,
|
|
218
|
-
isWindows: p?.isWindows() ?? false,
|
|
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,
|
|
223
|
-
isRunner: p?.isRunner() ?? false,
|
|
224
|
-
};
|
|
225
|
-
}
|
|
226
|
-
// Typed platform detection for pages, so they never reach for the window global
|
|
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.
|
|
229
|
-
export function usePlatform() {
|
|
230
|
-
return readPlatform();
|
|
231
|
-
}
|
|
232
|
-
/** Effective product language selected by the host; follows a change. */
|
|
233
|
-
export function useDisplayLanguage() {
|
|
234
|
-
const language = shallowRef(getDisplayLanguage());
|
|
235
|
-
if (!getCurrentInstance()) {
|
|
236
|
-
console.warn("useDisplayLanguage() must be called during component setup");
|
|
237
|
-
return language;
|
|
238
|
-
}
|
|
239
|
-
const unsubscribe = subscribeDisplayLanguage(() => {
|
|
240
|
-
language.value = getDisplayLanguage();
|
|
241
|
-
});
|
|
242
|
-
onUnmounted(unsubscribe);
|
|
243
|
-
return language;
|
|
244
|
-
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export { useLxPage,
|
|
1
|
+
export { useLxPage, useLxHost, useLxStream, useLxChannel, type LxStreamOptions, type LxReducedStreamOptions, type LxStreamState, type LxChannelOptions, type LxChannelState, } from "./hook.js";
|
|
2
|
+
export type { LxHost } from "@lingxia/bridge";
|
|
3
|
+
export type { DeepReadonly } from "@lingxia/page-runtime";
|
|
2
4
|
export { default as LxVideo } from "./LxVideo.vue";
|
|
3
5
|
export { default as LxNativeRoot } from "./LxNativeRoot.vue";
|
|
4
6
|
export { default as LxNativeView } from "./LxNativeView.vue";
|
|
@@ -9,6 +11,5 @@ export { default as LxMediaSwiper } from "./LxMediaSwiper.vue";
|
|
|
9
11
|
export { default as LxPicker } from "./LxPicker.vue";
|
|
10
12
|
export { default as LxNavigator } from "./LxNavigator.vue";
|
|
11
13
|
export type { LxVideoProps, LxNativeRootProps, LxNativeViewProps, LxNativeCoverProps, LxNativeTextProps, LxNativeButtonProps, LxMediaSwiperProps, LxPickerProps, LxNavigatorProps, LxNavigatorEvent, } from "./types.js";
|
|
12
|
-
export type {
|
|
13
|
-
export type { LxVideoEventPayloads, LxVideoEventHandlers, NativeActionIcon } from "@lingxia/elements";
|
|
14
|
+
export type { LxVideoEventPayloads, LxVideoEventHandlers, LxMediaSwiperEventPayloads, LxMediaSwiperEventHandlers, LxMediaSwiperHandle, LxMediaSwiperItem, NativeActionIcon, } from "@lingxia/elements";
|
|
14
15
|
export type { NativeStyle } from "./types.js";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { useLxPage,
|
|
1
|
+
export { useLxPage, useLxHost, useLxStream, useLxChannel, } from "./hook.js";
|
|
2
2
|
export { default as LxVideo } from "./LxVideo.vue";
|
|
3
3
|
export { default as LxNativeRoot } from "./LxNativeRoot.vue";
|
|
4
4
|
export { default as LxNativeView } from "./LxNativeView.vue";
|
package/dist/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { CSSProperties } from 'vue';
|
|
2
|
-
import type { LxNavigatorEvent, LxVideoEventPayloads, NativeActionIcon, NativeStyleProperty, NavigatorChannel, NavigatorOpenType, NavigatorQuery, NavigatorTarget } from '@lingxia/elements';
|
|
2
|
+
import type { LxMediaSwiperEventPayloads, LxMediaSwiperItem, LxPickerColumns, LxVideoQuality, LxNavigatorEvent, LxVideoEventPayloads, NativeActionIcon, NativeStyleProperty, NavigatorChannel, NavigatorOpenType, NavigatorQuery, NavigatorTarget, NavigatorEdge, NavigatorFloatPosition, NavigatorInteraction, NavigatorPlacement, NavigatorSize, NavigatorWindowChrome } from '@lingxia/elements';
|
|
3
3
|
export type NativeStyle = Omit<Pick<CSSProperties, NativeStyleProperty>, "borderStyle"> & {
|
|
4
4
|
borderStyle?: "solid" | "none";
|
|
5
5
|
};
|
|
@@ -16,11 +16,8 @@ export interface LxVideoProps {
|
|
|
16
16
|
progressBar?: boolean;
|
|
17
17
|
live?: boolean;
|
|
18
18
|
volume?: string | number;
|
|
19
|
-
qualities?:
|
|
20
|
-
|
|
21
|
-
url?: string;
|
|
22
|
-
}>;
|
|
23
|
-
playbackRates?: number[];
|
|
19
|
+
qualities?: readonly LxVideoQuality[];
|
|
20
|
+
playbackRates?: readonly number[];
|
|
24
21
|
class?: string;
|
|
25
22
|
style?: NativeStyle;
|
|
26
23
|
onPlayRequest?: (payload: LxVideoEventPayloads["onPlayRequest"]) => void;
|
|
@@ -37,7 +34,6 @@ export interface LxVideoProps {
|
|
|
37
34
|
onQualityChange?: (payload: LxVideoEventPayloads["onQualityChange"]) => void;
|
|
38
35
|
onRateChange?: (payload: LxVideoEventPayloads["onRateChange"]) => void;
|
|
39
36
|
onVolumeChange?: (payload: LxVideoEventPayloads["onVolumeChange"]) => void;
|
|
40
|
-
pageBindings?: Record<string, string>;
|
|
41
37
|
}
|
|
42
38
|
export interface LxNativeNodeProps {
|
|
43
39
|
id?: string;
|
|
@@ -82,21 +78,9 @@ export interface LxNativeButtonProps extends LxNativeNodeProps {
|
|
|
82
78
|
loading?: boolean;
|
|
83
79
|
tabIndex?: 0 | -1;
|
|
84
80
|
}
|
|
85
|
-
type LxMediaSwiperItem = {
|
|
86
|
-
id?: string;
|
|
87
|
-
type: 'image';
|
|
88
|
-
src: string;
|
|
89
|
-
} | {
|
|
90
|
-
id?: string;
|
|
91
|
-
type: 'video';
|
|
92
|
-
src: string;
|
|
93
|
-
poster?: string;
|
|
94
|
-
controls?: boolean;
|
|
95
|
-
muted?: boolean;
|
|
96
|
-
};
|
|
97
81
|
export interface LxMediaSwiperProps {
|
|
98
82
|
id?: string;
|
|
99
|
-
items?: LxMediaSwiperItem[];
|
|
83
|
+
items?: readonly LxMediaSwiperItem[];
|
|
100
84
|
index?: number;
|
|
101
85
|
initialIndex?: number;
|
|
102
86
|
loop?: boolean;
|
|
@@ -120,21 +104,20 @@ export interface LxMediaSwiperProps {
|
|
|
120
104
|
};
|
|
121
105
|
class?: string;
|
|
122
106
|
style?: CSSProperties;
|
|
123
|
-
onChange?: (
|
|
124
|
-
onTransitionEnd?: (
|
|
125
|
-
onEndReached?: (
|
|
126
|
-
onTap?: (
|
|
127
|
-
onVideoEnded?: (
|
|
128
|
-
onError?: (
|
|
129
|
-
pageBindings?: Record<string, string>;
|
|
107
|
+
onChange?: (payload: LxMediaSwiperEventPayloads["onChange"]) => void;
|
|
108
|
+
onTransitionEnd?: (payload: LxMediaSwiperEventPayloads["onTransitionEnd"]) => void;
|
|
109
|
+
onEndReached?: (payload: LxMediaSwiperEventPayloads["onEndReached"]) => void;
|
|
110
|
+
onTap?: (payload: LxMediaSwiperEventPayloads["onTap"]) => void;
|
|
111
|
+
onVideoEnded?: (payload: LxMediaSwiperEventPayloads["onVideoEnded"]) => void;
|
|
112
|
+
onError?: (payload: LxMediaSwiperEventPayloads["onError"]) => void;
|
|
130
113
|
}
|
|
131
114
|
export interface LxPickerProps {
|
|
132
|
-
columns?:
|
|
115
|
+
columns?: LxPickerColumns;
|
|
133
116
|
mode?: 'date' | 'time';
|
|
134
117
|
start?: string;
|
|
135
118
|
end?: string;
|
|
136
119
|
fields?: 'year' | 'month' | 'day' | 'range';
|
|
137
|
-
modelValue?: string | string[];
|
|
120
|
+
modelValue?: string | readonly string[];
|
|
138
121
|
placeholder?: string;
|
|
139
122
|
class?: string;
|
|
140
123
|
style?: CSSProperties;
|
|
@@ -145,7 +128,6 @@ export interface LxPickerProps {
|
|
|
145
128
|
confirmText?: string;
|
|
146
129
|
confirmTextColor?: string;
|
|
147
130
|
confirmButtonColor?: string;
|
|
148
|
-
pageBindings?: Record<string, string>;
|
|
149
131
|
}
|
|
150
132
|
export interface LxNavigatorProps {
|
|
151
133
|
url?: string;
|
|
@@ -154,6 +136,12 @@ export interface LxNavigatorProps {
|
|
|
154
136
|
target?: NavigatorTarget;
|
|
155
137
|
delta?: number;
|
|
156
138
|
query?: NavigatorQuery;
|
|
139
|
+
as?: NavigatorPlacement;
|
|
140
|
+
edge?: NavigatorEdge;
|
|
141
|
+
position?: NavigatorFloatPosition;
|
|
142
|
+
chrome?: NavigatorWindowChrome;
|
|
143
|
+
size?: NavigatorSize;
|
|
144
|
+
interaction?: NavigatorInteraction;
|
|
157
145
|
appId?: string;
|
|
158
146
|
channel?: NavigatorChannel;
|
|
159
147
|
targetVersion?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lingxia/vue",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "LingXia Vue runtime and components for lxapp pages",
|
|
6
6
|
"type": "module",
|
|
@@ -11,18 +11,23 @@
|
|
|
11
11
|
"types": "./dist/index.d.ts",
|
|
12
12
|
"default": "./dist/index.js"
|
|
13
13
|
},
|
|
14
|
+
"./entry": {
|
|
15
|
+
"types": "./dist/entry.d.ts",
|
|
16
|
+
"default": "./dist/entry.js"
|
|
17
|
+
},
|
|
14
18
|
"./package.json": "./package.json"
|
|
15
19
|
},
|
|
16
20
|
"scripts": {
|
|
17
21
|
"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
22
|
"clean": "rm -rf dist",
|
|
19
23
|
"prepublishOnly": "npm run build",
|
|
20
|
-
"test:components": "npm run build && node tests/native-components.mjs && node tests/native-aria-attributes.mjs"
|
|
24
|
+
"test:components": "npm run build && node tests/native-components.mjs && node tests/native-aria-attributes.mjs",
|
|
25
|
+
"test:hooks": "rolldown -c tests/rolldown.hooks.config.mjs && node tests/page-hooks.mjs"
|
|
21
26
|
},
|
|
22
27
|
"dependencies": {
|
|
23
|
-
"@lingxia/bridge": "~0.
|
|
24
|
-
"@lingxia/elements": "~0.
|
|
25
|
-
"@lingxia/page-runtime": "~0.
|
|
28
|
+
"@lingxia/bridge": "~0.19.0",
|
|
29
|
+
"@lingxia/elements": "~0.19.0",
|
|
30
|
+
"@lingxia/page-runtime": "~0.19.0"
|
|
26
31
|
},
|
|
27
32
|
"peerDependencies": {
|
|
28
33
|
"vue": ">=3.5.0"
|