@lingxia/page-runtime 0.5.0 → 0.6.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.
Files changed (54) hide show
  1. package/dist/index.d.ts +1 -1
  2. package/dist/index.js +1 -1
  3. package/dist/shared/runtime.d.ts +1 -12
  4. package/dist/shared/runtime.js +72 -43
  5. package/package.json +6 -32
  6. package/dist/react/LxInput.d.ts +0 -47
  7. package/dist/react/LxInput.js +0 -128
  8. package/dist/react/LxNavigator.d.ts +0 -23
  9. package/dist/react/LxNavigator.js +0 -61
  10. package/dist/react/LxPicker.d.ts +0 -27
  11. package/dist/react/LxPicker.js +0 -113
  12. package/dist/react/LxTextarea.d.ts +0 -47
  13. package/dist/react/LxTextarea.js +0 -118
  14. package/dist/react/LxVideo.d.ts +0 -5
  15. package/dist/react/LxVideo.js +0 -113
  16. package/dist/react/hook.d.ts +0 -39
  17. package/dist/react/hook.js +0 -212
  18. package/dist/react/index.d.ts +0 -6
  19. package/dist/react/index.js +0 -6
  20. package/dist/react/text_component_shared.d.ts +0 -5
  21. package/dist/react/text_component_shared.js +0 -33
  22. package/dist/vue/LxInput.vue +0 -92
  23. package/dist/vue/LxNavigator.vue +0 -79
  24. package/dist/vue/LxPicker.vue +0 -144
  25. package/dist/vue/LxTextarea.vue +0 -90
  26. package/dist/vue/LxVideo.vue +0 -111
  27. package/dist/vue/hook.d.ts +0 -42
  28. package/dist/vue/hook.js +0 -194
  29. package/dist/vue/index.d.ts +0 -7
  30. package/dist/vue/index.js +0 -6
  31. package/dist/vue/text_component_shared.d.ts +0 -3
  32. package/dist/vue/text_component_shared.js +0 -26
  33. package/dist/vue/types.d.ts +0 -101
  34. package/dist/vue/types.js +0 -1
  35. package/src/index.ts +0 -21
  36. package/src/react/LxInput.tsx +0 -224
  37. package/src/react/LxNavigator.tsx +0 -132
  38. package/src/react/LxPicker.tsx +0 -205
  39. package/src/react/LxTextarea.tsx +0 -216
  40. package/src/react/LxVideo.tsx +0 -166
  41. package/src/react/hook.ts +0 -317
  42. package/src/react/index.ts +0 -14
  43. package/src/react/text_component_shared.ts +0 -43
  44. package/src/shared/runtime.ts +0 -186
  45. package/src/vue/LxInput.vue +0 -92
  46. package/src/vue/LxNavigator.vue +0 -79
  47. package/src/vue/LxPicker.vue +0 -144
  48. package/src/vue/LxTextarea.vue +0 -90
  49. package/src/vue/LxVideo.vue +0 -111
  50. package/src/vue/hook.ts +0 -313
  51. package/src/vue/index.ts +0 -22
  52. package/src/vue/shims-vue.d.ts +0 -5
  53. package/src/vue/text_component_shared.ts +0 -33
  54. package/src/vue/types.ts +0 -107
@@ -1,43 +0,0 @@
1
- import type { ForwardedRef } from "react";
2
-
3
- export function getCustomEventDetail<T>(event: Event): T {
4
- return ((event as CustomEvent).detail ?? {}) as T;
5
- }
6
-
7
- export function assignForwardedRef<T>(ref: ForwardedRef<T>, value: T | null): void {
8
- if (typeof ref === "function") {
9
- ref(value);
10
- return;
11
- }
12
- if (ref) {
13
- ref.current = value;
14
- }
15
- }
16
-
17
- export function bindElementEvents(
18
- boundElement: HTMLElement | null,
19
- nextElement: HTMLElement | null,
20
- listeners: Record<string, EventListenerObject>
21
- ): HTMLElement | null {
22
- if (boundElement && boundElement !== nextElement) {
23
- unbindElementEvents(boundElement, listeners);
24
- boundElement = null;
25
- }
26
- if (nextElement && boundElement !== nextElement) {
27
- for (const [event, listener] of Object.entries(listeners)) {
28
- nextElement.addEventListener(event, listener);
29
- }
30
- boundElement = nextElement;
31
- }
32
- return boundElement;
33
- }
34
-
35
- export function unbindElementEvents(
36
- boundElement: HTMLElement | null,
37
- listeners: Record<string, EventListenerObject>
38
- ): void {
39
- if (!boundElement) return;
40
- for (const [event, listener] of Object.entries(listeners)) {
41
- boundElement.removeEventListener(event, listener);
42
- }
43
- }
@@ -1,186 +0,0 @@
1
- import type {
2
- DataSubscriber,
3
- LxBridgeError,
4
- LxChannel,
5
- LxStream,
6
- StateInfo,
7
- } from "@lingxia/bridge";
8
-
9
- export type ActionMap = Record<string, (...args: unknown[]) => unknown>;
10
- export type Snapshot = Record<string, unknown>;
11
- export type Listener = () => void;
12
- export type ParamsSource<T> = T | (() => T);
13
- export type MethodParams<TMethod> = TMethod extends () => any
14
- ? undefined
15
- : TMethod extends (params: infer P) => any
16
- ? P
17
- : never;
18
- export type StreamData<TMethod> =
19
- TMethod extends (...args: any[]) => LxStream<infer TData, any> ? TData : never;
20
- export type StreamResult<TMethod> =
21
- TMethod extends (...args: any[]) => LxStream<any, infer TResult>
22
- ? TResult
23
- : never;
24
- export type ChannelIn<TMethod> =
25
- TMethod extends (...args: any[]) => Promise<LxChannel<infer TIn, any>>
26
- ? TIn
27
- : never;
28
- export type ChannelOut<TMethod> =
29
- TMethod extends (...args: any[]) => Promise<LxChannel<any, infer TOut>>
30
- ? TOut
31
- : never;
32
-
33
- let snapshot: Snapshot = {};
34
- let stateInfo: StateInfo = { rev: -1, initial: true };
35
- let subscribed = false;
36
- let subscribeRetryTimer: ReturnType<typeof setTimeout> | null = null;
37
- let initialSnapshotResolved = false;
38
- let snapshotRequestInFlight = false;
39
- const listeners = new Set<Listener>();
40
-
41
- export function toBridgeError(err: unknown): LxBridgeError {
42
- return err && typeof err === "object" && "code" in err
43
- ? (err as LxBridgeError)
44
- : {
45
- code: "BRIDGE_INTERNAL_ERROR",
46
- message: err instanceof Error ? err.message : String(err),
47
- };
48
- }
49
-
50
- export function resolveParams<T>(source?: ParamsSource<T>): T | undefined {
51
- if (typeof source === "function") {
52
- return (source as () => T)();
53
- }
54
- return source;
55
- }
56
-
57
- export function stableParamKey(value: unknown): string {
58
- if (value === undefined) return "undefined";
59
- try {
60
- return JSON.stringify(value) ?? "undefined";
61
- } catch {
62
- return String(value);
63
- }
64
- }
65
-
66
- export function invokeMethod<TMethod extends (...args: any[]) => any>(
67
- method: TMethod,
68
- params: unknown,
69
- ): ReturnType<TMethod> {
70
- if (params === undefined) {
71
- return method() as ReturnType<TMethod>;
72
- }
73
- return method(params) as ReturnType<TMethod>;
74
- }
75
-
76
- export function getMethodKey(method: unknown): string | undefined {
77
- if (typeof method !== "function") return undefined;
78
- const candidate = (method as { __funcName?: unknown }).__funcName;
79
- return typeof candidate === "string" && candidate !== "" ? candidate : undefined;
80
- }
81
-
82
- function notifyListeners(): void {
83
- listeners.forEach((listener) => {
84
- try {
85
- listener();
86
- } catch {
87
- // Ignore listener errors to avoid breaking state fanout.
88
- }
89
- });
90
- }
91
-
92
- function updateSnapshot(next: unknown, info: StateInfo): void {
93
- snapshot = next && typeof next === "object" ? (next as Snapshot) : {};
94
- stateInfo = info;
95
- notifyListeners();
96
- }
97
-
98
- function scheduleSubscribeRetry(): void {
99
- if (subscribeRetryTimer !== null || subscribed) return;
100
- subscribeRetryTimer = setTimeout(() => {
101
- subscribeRetryTimer = null;
102
- ensurePageBridgeSubscription();
103
- }, 10);
104
- }
105
-
106
- function requestInitialSnapshot(bridge: Window["LingXiaBridge"] | undefined): void {
107
- if (initialSnapshotResolved || snapshotRequestInFlight) return;
108
- if (!bridge?.call) return;
109
- snapshotRequestInFlight = true;
110
- bridge
111
- .call("state.getSnapshot", { scope: "page" })
112
- .then(() => {
113
- initialSnapshotResolved = true;
114
- })
115
- .catch(() => {
116
- scheduleSubscribeRetry();
117
- })
118
- .finally(() => {
119
- snapshotRequestInFlight = false;
120
- });
121
- }
122
-
123
- export function ensurePageBridgeSubscription(): void {
124
- if (subscribed) return;
125
- const bridge = window.LingXiaBridge;
126
- const subscribeState = bridge?.state?.subscribe;
127
- if (!subscribeState) {
128
- scheduleSubscribeRetry();
129
- return;
130
- }
131
- subscribeState((next, info) => {
132
- updateSnapshot(next, info);
133
- });
134
- subscribed = true;
135
- requestInitialSnapshot(bridge);
136
- }
137
-
138
- export function subscribePageSnapshot(listener: Listener): () => void {
139
- ensurePageBridgeSubscription();
140
- listeners.add(listener);
141
- return () => {
142
- listeners.delete(listener);
143
- };
144
- }
145
-
146
- export function subscribePageData(
147
- callback: DataSubscriber,
148
- ): () => void {
149
- if (typeof callback !== "function") return () => {};
150
- ensurePageBridgeSubscription();
151
-
152
- if (stateInfo.rev >= 0) {
153
- callback(snapshot, { rev: stateInfo.rev, initial: true });
154
- }
155
-
156
- return subscribePageSnapshot(() => {
157
- callback(snapshot, stateInfo);
158
- });
159
- }
160
-
161
- export function getPageSnapshot<TData = Snapshot>(): TData {
162
- ensurePageBridgeSubscription();
163
- return snapshot as TData;
164
- }
165
-
166
- export function getPageActions<TActions extends ActionMap>(): TActions {
167
- const actions: ActionMap = {};
168
- const bridge = window.__pageBridge;
169
- if (!bridge?.__names) {
170
- return actions as TActions;
171
- }
172
-
173
- for (const name of bridge.__names) {
174
- if (typeof name !== "string") continue;
175
- const fn = bridge[name];
176
- if (typeof fn === "function") {
177
- actions[name] = fn as (...args: unknown[]) => unknown;
178
- }
179
- }
180
-
181
- return actions as TActions;
182
- }
183
-
184
- export function getPageStateInfo(): StateInfo {
185
- return stateInfo;
186
- }
@@ -1,92 +0,0 @@
1
- <script setup lang="ts">
2
- import { computed, h, onBeforeUnmount, ref, useAttrs, watch } from 'vue';
3
- import { registerInputComponent } from '@lingxia/elements';
4
- import { buildInputNativeAttrs } from '@lingxia/elements';
5
- import type { LxInputProps } from './types.js';
6
- import {
7
- bindElementEvents,
8
- getCustomEventDetail,
9
- unbindElementEvents,
10
- } from './text_component_shared.js';
11
-
12
- const props = withDefaults(defineProps<LxInputProps>(), {
13
- type: 'text',
14
- disabled: false,
15
- confirmType: 'done',
16
- });
17
- const attrs = useAttrs();
18
-
19
- const emit = defineEmits<{
20
- 'update:modelValue': [value: string];
21
- input: [detail: Record<string, unknown>];
22
- change: [detail: Record<string, unknown>];
23
- focus: [detail: Record<string, unknown>];
24
- blur: [detail: Record<string, unknown>];
25
- confirm: [detail: Record<string, unknown>];
26
- keyboardHeightChange: [detail: Record<string, unknown>];
27
- nicknameReview: [detail: Record<string, unknown>];
28
- }>();
29
-
30
- if (typeof window !== 'undefined') {
31
- registerInputComponent();
32
- }
33
-
34
- const elementRef = ref<HTMLElement | null>(null);
35
- let boundElement: HTMLElement | null = null;
36
-
37
- const inputEventListeners: Record<string, EventListenerObject> = {
38
- input: {
39
- handleEvent: (event: Event) => {
40
- const detail = getCustomEventDetail<Record<string, unknown>>(event);
41
- if (typeof detail.value === 'string') {
42
- emit('update:modelValue', detail.value);
43
- }
44
- emit('input', detail);
45
- },
46
- },
47
- change: {
48
- handleEvent: (event: Event) => emit('change', getCustomEventDetail<Record<string, unknown>>(event)),
49
- },
50
- focus: {
51
- handleEvent: (event: Event) => emit('focus', getCustomEventDetail<Record<string, unknown>>(event)),
52
- },
53
- blur: {
54
- handleEvent: (event: Event) => emit('blur', getCustomEventDetail<Record<string, unknown>>(event)),
55
- },
56
- confirm: {
57
- handleEvent: (event: Event) => emit('confirm', getCustomEventDetail<Record<string, unknown>>(event)),
58
- },
59
- keyboardheightchange: {
60
- handleEvent: (event: Event) => emit('keyboardHeightChange', getCustomEventDetail<Record<string, unknown>>(event)),
61
- },
62
- nicknamereview: {
63
- handleEvent: (event: Event) => emit('nicknameReview', getCustomEventDetail<Record<string, unknown>>(event)),
64
- },
65
- };
66
-
67
- watch(elementRef, (element) => {
68
- boundElement = bindElementEvents(boundElement, element, inputEventListeners);
69
- });
70
-
71
- onBeforeUnmount(() => {
72
- unbindElementEvents(boundElement, inputEventListeners);
73
- });
74
-
75
- const inputProps = computed<Record<string, unknown>>(() => {
76
- const result: Record<string, unknown> = buildInputNativeAttrs({
77
- ...props,
78
- id: props.id ?? (typeof attrs.id === 'string' ? attrs.id : undefined),
79
- }, attrs as Record<string, unknown>, elementRef.value !== null);
80
- result.class = props.class ?? attrs.class;
81
- result.style = props.style ?? attrs.style;
82
- return result;
83
- });
84
-
85
- defineExpose({ el: elementRef });
86
-
87
- const renderInput = () => h('lx-input', { ref: elementRef, ...inputProps.value });
88
- </script>
89
-
90
- <template>
91
- <renderInput />
92
- </template>
@@ -1,79 +0,0 @@
1
- <script setup lang="ts">
2
- import { ref, h, onMounted, onBeforeUnmount, useAttrs } from 'vue';
3
- import type { LxNavigatorEvent } from '@lingxia/elements';
4
- import { buildNavigatorNativeAttrs } from '@lingxia/elements';
5
- import type { LxNavigatorProps } from './types.js';
6
- import '@lingxia/elements';
7
-
8
- const props = withDefaults(defineProps<LxNavigatorProps>(), {
9
- openType: 'navigate',
10
- delta: 1,
11
- hoverClass: 'navigator-hover',
12
- hoverStopPropagation: false,
13
- hoverStartTime: 20,
14
- hoverStayTime: 70,
15
- });
16
-
17
- const slots = defineSlots();
18
- const attrs = useAttrs();
19
-
20
- const emit = defineEmits<{
21
- success: [e: LxNavigatorEvent];
22
- fail: [e: LxNavigatorEvent];
23
- complete: [e: LxNavigatorEvent];
24
- }>();
25
-
26
- const elementRef = ref<HTMLElement | null>(null);
27
-
28
- const handleSuccess = (e: Event) => emit('success', e as LxNavigatorEvent);
29
- const handleFail = (e: Event) => emit('fail', e as LxNavigatorEvent);
30
- const handleComplete = (e: Event) => emit('complete', e as LxNavigatorEvent);
31
- const successListener: EventListenerObject = { handleEvent: handleSuccess };
32
- const failListener: EventListenerObject = { handleEvent: handleFail };
33
- const completeListener: EventListenerObject = { handleEvent: handleComplete };
34
-
35
- onMounted(() => {
36
- const el = elementRef.value;
37
- if (!el) return;
38
- el.addEventListener('success', successListener);
39
- el.addEventListener('fail', failListener);
40
- el.addEventListener('complete', completeListener);
41
- });
42
-
43
- onBeforeUnmount(() => {
44
- const el = elementRef.value;
45
- if (!el) return;
46
- el.removeEventListener('success', successListener);
47
- el.removeEventListener('fail', failListener);
48
- el.removeEventListener('complete', completeListener);
49
- });
50
-
51
- defineExpose({ el: elementRef });
52
-
53
- const render = () => h(
54
- 'lx-navigator',
55
- {
56
- ref: elementRef,
57
- ...buildNavigatorNativeAttrs({
58
- url: props.url,
59
- openType: props.openType,
60
- target: props.target,
61
- delta: props.delta,
62
- appId: props.appId,
63
- path: props.path,
64
- phoneNumber: props.phoneNumber,
65
- hoverClass: props.hoverClass,
66
- hoverStopPropagation: props.hoverStopPropagation,
67
- hoverStartTime: props.hoverStartTime,
68
- hoverStayTime: props.hoverStayTime,
69
- }, attrs as Record<string, unknown>),
70
- class: props.class ?? attrs.class,
71
- style: props.style ?? attrs.style,
72
- },
73
- slots.default?.()
74
- );
75
- </script>
76
-
77
- <template>
78
- <render />
79
- </template>
@@ -1,144 +0,0 @@
1
- <script setup lang="ts">
2
- import { ref, computed, h, onBeforeUnmount, useAttrs, useId, watch } from 'vue';
3
- import { registerPickerComponent } from '@lingxia/elements';
4
- import {
5
- buildPickerNativeAttrs,
6
- getPickerDisplayText,
7
- getPickerValueFromIndex,
8
- } from '@lingxia/elements';
9
- import { bindElementEvents, getCustomEventDetail, unbindElementEvents } from './text_component_shared.js';
10
- import type { LxPickerProps } from './types.js';
11
-
12
- const props = withDefaults(defineProps<LxPickerProps>(), {
13
- placeholder: 'Please select',
14
- disabled: false,
15
- });
16
- const attrs = useAttrs();
17
-
18
- const slots = defineSlots();
19
-
20
- const emit = defineEmits<{
21
- 'update:modelValue': [value: string | string[]];
22
- confirm: [value: string | string[]];
23
- cancel: [];
24
- scroll: [value: string | string[]];
25
- }>();
26
-
27
- if (typeof window !== 'undefined') {
28
- registerPickerComponent();
29
- }
30
-
31
- const visible = ref(false);
32
- const vueId = useId();
33
- const pickerId = computed(() => `lx-picker-${vueId.replace(/[:]/g, '')}`);
34
- const pickerRef = ref<HTMLElement | null>(null);
35
- let boundElement: HTMLElement | null = null;
36
- const pickerEventListeners: Record<string, EventListenerObject> = {
37
- change: {
38
- handleEvent: (event: Event) => handleChange(event),
39
- },
40
- scroll: {
41
- handleEvent: (event: Event) => handleScroll(event),
42
- },
43
- };
44
-
45
- const displayText = computed(() => getPickerDisplayText(props.modelValue, props.fields));
46
-
47
- function handleChange(e: Event) {
48
- props.onChange?.(e);
49
- const detail = getCustomEventDetail<{
50
- confirmed?: boolean;
51
- cancelled?: boolean;
52
- value?: string | string[];
53
- index?: number | number[];
54
- }>(e);
55
- if (detail.confirmed) {
56
- if (props.mode === 'date' || props.mode === 'time') {
57
- const nextValue = detail.value ?? '';
58
- emit('update:modelValue', nextValue);
59
- emit('confirm', nextValue);
60
- } else if (detail.index !== undefined) {
61
- const nextValue = getPickerValueFromIndex(props.columns, detail.index);
62
- emit('update:modelValue', nextValue);
63
- emit('confirm', nextValue);
64
- }
65
- visible.value = false;
66
- } else if (detail.cancelled) {
67
- emit('cancel');
68
- visible.value = false;
69
- }
70
- }
71
-
72
- function handleScroll(e: Event) {
73
- props.onNativeScroll?.(e);
74
- const detail = getCustomEventDetail<{
75
- value?: string | string[];
76
- index?: number | number[];
77
- }>(e);
78
- if (detail.value !== undefined) {
79
- emit('scroll', detail.value);
80
- } else if (detail.index !== undefined) {
81
- emit('scroll', getPickerValueFromIndex(props.columns, detail.index));
82
- }
83
- }
84
-
85
- function handleClick() {
86
- if (!props.disabled) visible.value = true;
87
- }
88
-
89
- watch(pickerRef, (element) => {
90
- boundElement = bindElementEvents(boundElement, element, pickerEventListeners);
91
- });
92
-
93
- onBeforeUnmount(() => {
94
- unbindElementEvents(boundElement, pickerEventListeners);
95
- });
96
-
97
- const pickerProps = computed(() => {
98
- return buildPickerNativeAttrs({
99
- id: pickerId.value,
100
- columns: props.columns,
101
- mode: props.mode,
102
- start: props.start,
103
- end: props.end,
104
- fields: props.fields,
105
- modelValue: props.modelValue,
106
- cancelText: props.cancelText,
107
- cancelTextColor: props.cancelTextColor,
108
- cancelButtonColor: props.cancelButtonColor,
109
- confirmText: props.confirmText,
110
- confirmTextColor: props.confirmTextColor,
111
- confirmButtonColor: props.confirmButtonColor,
112
- }, attrs as Record<string, unknown>);
113
- });
114
-
115
- const triggerStyle = computed(() => ({
116
- display: 'flex',
117
- alignItems: 'center',
118
- justifyContent: 'space-between',
119
- padding: '12px 14px',
120
- backgroundColor: '#fff',
121
- border: '1px solid #e5e7eb',
122
- borderRadius: '8px',
123
- cursor: props.disabled ? 'not-allowed' : 'pointer',
124
- opacity: props.disabled ? 0.5 : 1,
125
- width: '100%',
126
- boxSizing: 'border-box',
127
- }));
128
-
129
- defineExpose({ el: pickerRef });
130
-
131
- const renderPicker = () => visible.value ? h('lx-picker', { ref: pickerRef, ...pickerProps.value }) : null;
132
- </script>
133
-
134
- <template>
135
- <slot :open="handleClick" :disabled="props.disabled">
136
- <div :class="props.class ?? attrs.class" :style="[triggerStyle, props.style ?? attrs.style]" @click="handleClick">
137
- <span :style="{ color: modelValue ? '#111' : '#9ca3af' }">{{ displayText || placeholder }}</span>
138
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#9ca3af" stroke-width="2">
139
- <path d="M6 9l6 6 6-6" />
140
- </svg>
141
- </div>
142
- </slot>
143
- <renderPicker />
144
- </template>
@@ -1,90 +0,0 @@
1
- <script setup lang="ts">
2
- import { computed, h, onBeforeUnmount, ref, useAttrs, watch } from 'vue';
3
- import { registerTextareaComponent } from '@lingxia/elements';
4
- import { buildTextareaNativeAttrs } from '@lingxia/elements';
5
- import type { LxTextareaProps } from './types.js';
6
- import {
7
- bindElementEvents,
8
- getCustomEventDetail,
9
- unbindElementEvents,
10
- } from './text_component_shared.js';
11
-
12
- const props = withDefaults(defineProps<LxTextareaProps>(), {
13
- disabled: false,
14
- });
15
- const attrs = useAttrs();
16
-
17
- const emit = defineEmits<{
18
- 'update:modelValue': [value: string];
19
- input: [detail: Record<string, unknown>];
20
- change: [detail: Record<string, unknown>];
21
- focus: [detail: Record<string, unknown>];
22
- blur: [detail: Record<string, unknown>];
23
- confirm: [detail: Record<string, unknown>];
24
- lineChange: [detail: Record<string, unknown>];
25
- keyboardHeightChange: [detail: Record<string, unknown>];
26
- }>();
27
-
28
- if (typeof window !== 'undefined') {
29
- registerTextareaComponent();
30
- }
31
-
32
- const elementRef = ref<HTMLElement | null>(null);
33
- let boundElement: HTMLElement | null = null;
34
-
35
- const textareaEventListeners: Record<string, EventListenerObject> = {
36
- input: {
37
- handleEvent: (event: Event) => {
38
- const detail = getCustomEventDetail<Record<string, unknown>>(event);
39
- if (typeof detail.value === 'string') {
40
- emit('update:modelValue', detail.value);
41
- }
42
- emit('input', detail);
43
- },
44
- },
45
- change: {
46
- handleEvent: (event: Event) => emit('change', getCustomEventDetail<Record<string, unknown>>(event)),
47
- },
48
- focus: {
49
- handleEvent: (event: Event) => emit('focus', getCustomEventDetail<Record<string, unknown>>(event)),
50
- },
51
- blur: {
52
- handleEvent: (event: Event) => emit('blur', getCustomEventDetail<Record<string, unknown>>(event)),
53
- },
54
- confirm: {
55
- handleEvent: (event: Event) => emit('confirm', getCustomEventDetail<Record<string, unknown>>(event)),
56
- },
57
- linechange: {
58
- handleEvent: (event: Event) => emit('lineChange', getCustomEventDetail<Record<string, unknown>>(event)),
59
- },
60
- keyboardheightchange: {
61
- handleEvent: (event: Event) => emit('keyboardHeightChange', getCustomEventDetail<Record<string, unknown>>(event)),
62
- },
63
- };
64
-
65
- watch(elementRef, (element) => {
66
- boundElement = bindElementEvents(boundElement, element, textareaEventListeners);
67
- });
68
-
69
- onBeforeUnmount(() => {
70
- unbindElementEvents(boundElement, textareaEventListeners);
71
- });
72
-
73
- const textareaProps = computed<Record<string, unknown>>(() => {
74
- const result: Record<string, unknown> = buildTextareaNativeAttrs({
75
- ...props,
76
- id: props.id ?? (typeof attrs.id === 'string' ? attrs.id : undefined),
77
- }, attrs as Record<string, unknown>, elementRef.value !== null);
78
- result.class = props.class ?? attrs.class;
79
- result.style = props.style ?? attrs.style;
80
- return result;
81
- });
82
-
83
- defineExpose({ el: elementRef });
84
-
85
- const renderTextarea = () => h('lx-textarea', { ref: elementRef, ...textareaProps.value });
86
- </script>
87
-
88
- <template>
89
- <renderTextarea />
90
- </template>