@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,26 +0,0 @@
1
- export function getCustomEventDetail(event) {
2
- var _a;
3
- return ((_a = event.detail) !== null && _a !== void 0 ? _a : {});
4
- }
5
- export function bindElementEvents(currentBoundElement, nextElement, listeners) {
6
- if (currentBoundElement && currentBoundElement !== nextElement) {
7
- for (const [event, listener] of Object.entries(listeners)) {
8
- currentBoundElement.removeEventListener(event, listener);
9
- }
10
- currentBoundElement = null;
11
- }
12
- if (nextElement && currentBoundElement !== nextElement) {
13
- for (const [event, listener] of Object.entries(listeners)) {
14
- nextElement.addEventListener(event, listener);
15
- }
16
- currentBoundElement = nextElement;
17
- }
18
- return currentBoundElement;
19
- }
20
- export function unbindElementEvents(boundElement, listeners) {
21
- if (!boundElement)
22
- return;
23
- for (const [event, listener] of Object.entries(listeners)) {
24
- boundElement.removeEventListener(event, listener);
25
- }
26
- }
@@ -1,101 +0,0 @@
1
- import type { CSSProperties } from 'vue';
2
- import type { LxVideoAttributes } from '@lingxia/elements';
3
- import type { LxNavigatorEvent, NavigatorOpenType, NavigatorTarget } from '@lingxia/elements';
4
- export interface LxVideoProps extends Omit<LxVideoAttributes, 'ref' | 'className' | 'style'> {
5
- class?: string;
6
- style?: CSSProperties;
7
- }
8
- export interface LxPickerProps {
9
- columns?: string[][] | [string[], Record<string, string[]>];
10
- mode?: 'date' | 'time';
11
- start?: string;
12
- end?: string;
13
- fields?: 'year' | 'month' | 'day' | 'range';
14
- modelValue?: string | string[];
15
- placeholder?: string;
16
- class?: string;
17
- style?: CSSProperties;
18
- disabled?: boolean;
19
- cancelText?: string;
20
- cancelTextColor?: string;
21
- cancelButtonColor?: string;
22
- confirmText?: string;
23
- confirmTextColor?: string;
24
- confirmButtonColor?: string;
25
- onChange?: (event: Event) => void;
26
- onNativeScroll?: (event: Event) => void;
27
- pageBindings?: Record<string, string>;
28
- }
29
- export interface LxNavigatorProps {
30
- url?: string;
31
- openType?: NavigatorOpenType;
32
- target?: NavigatorTarget;
33
- delta?: number;
34
- appId?: string;
35
- path?: string;
36
- phoneNumber?: string;
37
- hoverClass?: string;
38
- hoverStopPropagation?: boolean;
39
- hoverStartTime?: number;
40
- hoverStayTime?: number;
41
- class?: string;
42
- style?: CSSProperties;
43
- }
44
- export interface LxInputProps {
45
- id?: string;
46
- modelValue?: string;
47
- value?: string;
48
- defaultValue?: string;
49
- type?: 'text' | 'number' | 'password' | 'digit';
50
- password?: boolean;
51
- placeholder?: string;
52
- placeholderStyle?: string;
53
- placeholderClass?: string;
54
- maxlength?: number;
55
- cursorSpacing?: number;
56
- autoFocus?: boolean;
57
- disabled?: boolean;
58
- focus?: boolean;
59
- confirmType?: 'send' | 'search' | 'next' | 'go' | 'done';
60
- alwaysEmbed?: boolean;
61
- confirmHold?: boolean;
62
- cursor?: number;
63
- cursorColor?: string;
64
- selectionStart?: number;
65
- selectionEnd?: number;
66
- adjustPosition?: boolean;
67
- holdKeyboard?: boolean;
68
- class?: string;
69
- style?: CSSProperties;
70
- pageBindings?: Record<string, string>;
71
- }
72
- export interface LxTextareaProps {
73
- id?: string;
74
- modelValue?: string;
75
- value?: string;
76
- defaultValue?: string;
77
- placeholder?: string;
78
- placeholderStyle?: string;
79
- placeholderClass?: string;
80
- maxlength?: number;
81
- disabled?: boolean;
82
- autoFocus?: boolean;
83
- focus?: boolean;
84
- autoHeight?: boolean;
85
- cursorSpacing?: number;
86
- showConfirmBar?: boolean;
87
- adjustPosition?: boolean;
88
- holdKeyboard?: boolean;
89
- disableDefaultPadding?: boolean;
90
- confirmType?: 'send' | 'search' | 'next' | 'go' | 'done' | 'return';
91
- confirmHold?: boolean;
92
- fixed?: boolean;
93
- adjustKeyboardTo?: 'cursor' | 'bottom';
94
- cursor?: number;
95
- selectionStart?: number;
96
- selectionEnd?: number;
97
- class?: string;
98
- style?: CSSProperties;
99
- pageBindings?: Record<string, string>;
100
- }
101
- export type { LxNavigatorEvent };
package/dist/vue/types.js DELETED
@@ -1 +0,0 @@
1
- export {};
package/src/index.ts DELETED
@@ -1,21 +0,0 @@
1
- export {
2
- ensurePageBridgeSubscription,
3
- getPageActions,
4
- getPageSnapshot,
5
- getPageStateInfo,
6
- subscribePageData,
7
- subscribePageSnapshot,
8
- toBridgeError,
9
- resolveParams,
10
- stableParamKey,
11
- invokeMethod,
12
- getMethodKey,
13
- type ActionMap,
14
- type Snapshot,
15
- type ParamsSource,
16
- type MethodParams,
17
- type StreamData,
18
- type StreamResult,
19
- type ChannelIn,
20
- type ChannelOut,
21
- } from "./shared/runtime.js";
@@ -1,224 +0,0 @@
1
- import React, { forwardRef, useCallback, useEffect, useRef } from "react";
2
- import { registerInputComponent } from "@lingxia/elements";
3
- import { buildInputNativeAttrs } from "@lingxia/elements";
4
- import {
5
- assignForwardedRef,
6
- bindElementEvents,
7
- getCustomEventDetail,
8
- unbindElementEvents,
9
- } from "./text_component_shared.js";
10
-
11
- export interface LxInputEventDetail {
12
- value?: string;
13
- cursor?: number;
14
- keyCode?: number;
15
- height?: number;
16
- duration?: number;
17
- encryptedValue?: string;
18
- encryptError?: string;
19
- pass?: boolean;
20
- timeout?: boolean;
21
- }
22
-
23
- export interface LxInputProps {
24
- id?: string;
25
- value?: string;
26
- defaultValue?: string;
27
- type?: "text" | "number" | "password" | "digit";
28
- password?: boolean;
29
- placeholder?: string;
30
- placeholderStyle?: string;
31
- placeholderClass?: string;
32
- maxlength?: number;
33
- cursorSpacing?: number;
34
- autoFocus?: boolean;
35
- disabled?: boolean;
36
- focus?: boolean;
37
- confirmType?: "send" | "search" | "next" | "go" | "done";
38
- alwaysEmbed?: boolean;
39
- confirmHold?: boolean;
40
- cursor?: number;
41
- cursorColor?: string;
42
- selectionStart?: number;
43
- selectionEnd?: number;
44
- adjustPosition?: boolean;
45
- holdKeyboard?: boolean;
46
-
47
- onInput?: (detail: LxInputEventDetail) => void;
48
- onChange?: (detail: LxInputEventDetail) => void;
49
- onFocus?: (detail: LxInputEventDetail) => void;
50
- onBlur?: (detail: LxInputEventDetail) => void;
51
- onConfirm?: (detail: LxInputEventDetail) => void;
52
- onKeyboardHeightChange?: (detail: LxInputEventDetail) => void;
53
- onNicknameReview?: (detail: LxInputEventDetail) => void;
54
-
55
- // Logic bindings (CLI-generated)
56
- pageBindings?: Record<string, string>;
57
-
58
- className?: string;
59
- style?: React.CSSProperties;
60
- }
61
-
62
- if (typeof window !== "undefined") {
63
- registerInputComponent();
64
- }
65
-
66
- export const LxInput = forwardRef<HTMLElement, LxInputProps>(({
67
- value,
68
- defaultValue,
69
- type,
70
- password,
71
- placeholder,
72
- placeholderStyle,
73
- placeholderClass,
74
- maxlength,
75
- cursorSpacing,
76
- autoFocus,
77
- disabled,
78
- focus,
79
- confirmType,
80
- alwaysEmbed,
81
- confirmHold,
82
- cursor,
83
- cursorColor,
84
- selectionStart,
85
- selectionEnd,
86
- adjustPosition,
87
- holdKeyboard,
88
- onInput,
89
- onChange,
90
- onFocus,
91
- onBlur,
92
- onConfirm,
93
- onKeyboardHeightChange,
94
- onNicknameReview,
95
- pageBindings,
96
- className,
97
- style,
98
- id,
99
- ...rest
100
- }, ref) => {
101
- const elementRef = useRef<HTMLElement | null>(null);
102
- const boundElementRef = useRef<HTMLElement | null>(null);
103
- const handlerRef = useRef({
104
- onInput,
105
- onChange,
106
- onFocus,
107
- onBlur,
108
- onConfirm,
109
- onKeyboardHeightChange,
110
- onNicknameReview,
111
- });
112
- handlerRef.current = {
113
- onInput,
114
- onChange,
115
- onFocus,
116
- onBlur,
117
- onConfirm,
118
- onKeyboardHeightChange,
119
- onNicknameReview,
120
- };
121
- const listenerMapRef = useRef<Record<string, EventListenerObject>>({
122
- input: {
123
- handleEvent: (event: Event) => handlerRef.current.onInput?.(getCustomEventDetail<LxInputEventDetail>(event)),
124
- },
125
- change: {
126
- handleEvent: (event: Event) => handlerRef.current.onChange?.(getCustomEventDetail<LxInputEventDetail>(event)),
127
- },
128
- focus: {
129
- handleEvent: (event: Event) => handlerRef.current.onFocus?.(getCustomEventDetail<LxInputEventDetail>(event)),
130
- },
131
- blur: {
132
- handleEvent: (event: Event) => handlerRef.current.onBlur?.(getCustomEventDetail<LxInputEventDetail>(event)),
133
- },
134
- confirm: {
135
- handleEvent: (event: Event) => handlerRef.current.onConfirm?.(getCustomEventDetail<LxInputEventDetail>(event)),
136
- },
137
- keyboardheightchange: {
138
- handleEvent: (event: Event) => handlerRef.current.onKeyboardHeightChange?.(getCustomEventDetail<LxInputEventDetail>(event)),
139
- },
140
- nicknamereview: {
141
- handleEvent: (event: Event) => handlerRef.current.onNicknameReview?.(getCustomEventDetail<LxInputEventDetail>(event)),
142
- },
143
- });
144
- const elementRefCallback = useCallback((element: HTMLElement | null) => {
145
- boundElementRef.current = bindElementEvents(boundElementRef.current, element, listenerMapRef.current);
146
- elementRef.current = element;
147
- assignForwardedRef(ref, element);
148
- }, [ref]);
149
-
150
- useEffect(() => () => {
151
- unbindElementEvents(boundElementRef.current, listenerMapRef.current);
152
- boundElementRef.current = null;
153
- elementRef.current = null;
154
- }, []);
155
-
156
- useEffect(() => {
157
- const el = elementRef.current;
158
- if (!el) return;
159
- const setAttr = (name: string, next: string | null) => {
160
- if (next === null) {
161
- el.removeAttribute(name);
162
- return;
163
- }
164
- el.setAttribute(name, next);
165
- };
166
-
167
- if (type && String(type).trim().length > 0) {
168
- el.setAttribute("type", String(type).trim().toLowerCase());
169
- } else {
170
- el.removeAttribute("type");
171
- }
172
- if (password) {
173
- el.setAttribute("password", "true");
174
- } else {
175
- el.removeAttribute("password");
176
- }
177
- setAttr("value", value !== undefined ? String(value) : null);
178
- setAttr("focus", focus !== undefined ? (focus ? "true" : "false") : null);
179
- setAttr("maxlength", maxlength !== undefined ? String(maxlength) : null);
180
- setAttr("placeholder-style", placeholderStyle ? String(placeholderStyle) : null);
181
- }, [type, password, value, focus, maxlength, placeholderStyle]);
182
-
183
- // Set pageBindings property on custom element
184
- useEffect(() => {
185
- const el = elementRef.current as any;
186
- if (el && pageBindings) {
187
- el.pageBindings = pageBindings;
188
- }
189
- }, [pageBindings]);
190
-
191
- const inputProps = buildInputNativeAttrs({
192
- id,
193
- value,
194
- defaultValue,
195
- type,
196
- password,
197
- placeholder,
198
- placeholderStyle,
199
- placeholderClass,
200
- maxlength,
201
- cursorSpacing,
202
- autoFocus,
203
- disabled,
204
- focus,
205
- confirmType,
206
- alwaysEmbed,
207
- confirmHold,
208
- cursor,
209
- cursorColor,
210
- selectionStart,
211
- selectionEnd,
212
- adjustPosition,
213
- holdKeyboard,
214
- }, rest as Record<string, unknown>, boundElementRef.current !== null);
215
-
216
- return React.createElement("lx-input", {
217
- ref: elementRefCallback,
218
- className,
219
- style,
220
- ...inputProps,
221
- });
222
- });
223
-
224
- LxInput.displayName = "LxInput";
@@ -1,132 +0,0 @@
1
- import React from 'react';
2
- import type {
3
- LxNavigatorAttributes,
4
- LxNavigatorEvent,
5
- NavigatorOpenType,
6
- NavigatorTarget
7
- } from '@lingxia/elements';
8
- import { buildNavigatorNativeAttrs } from '@lingxia/elements';
9
-
10
- // Import to ensure custom element is registered
11
- import '@lingxia/elements';
12
-
13
- export interface LxNavigatorProps extends Omit<LxNavigatorAttributes, 'onSuccess' | 'onFail' | 'onComplete'> {
14
- // Navigation
15
- url?: string;
16
- openType?: NavigatorOpenType;
17
- target?: NavigatorTarget; // Auto-inferred if not specified
18
- delta?: number;
19
-
20
- // Open external lxapp
21
- appId?: string;
22
- path?: string; // Supports query string
23
-
24
- // Phone call
25
- phoneNumber?: string;
26
-
27
- // Hover effect
28
- hoverClass?: string;
29
- hoverStopPropagation?: boolean;
30
- hoverStartTime?: number;
31
- hoverStayTime?: number;
32
-
33
- // Styling
34
- className?: string;
35
- style?: React.CSSProperties;
36
-
37
- // Events
38
- onSuccess?: (e: LxNavigatorEvent) => void;
39
- onFail?: (e: LxNavigatorEvent) => void;
40
- onComplete?: (e: LxNavigatorEvent) => void;
41
-
42
- // Children
43
- children?: React.ReactNode;
44
- }
45
-
46
- export const LxNavigator = React.forwardRef<HTMLElement, LxNavigatorProps>(
47
- (props, ref) => {
48
- const {
49
- url,
50
- openType = 'navigate',
51
- target, // Auto-inferred, no default
52
- delta = 1,
53
- appId,
54
- path,
55
- phoneNumber,
56
- hoverClass = 'navigator-hover',
57
- hoverStopPropagation = false,
58
- hoverStartTime = 20,
59
- hoverStayTime = 70,
60
- className,
61
- style,
62
- onSuccess,
63
- onFail,
64
- onComplete,
65
- children,
66
- ...rest
67
- } = props;
68
-
69
- const elementRef = React.useRef<HTMLElement>(null);
70
-
71
- React.useImperativeHandle(ref, () => elementRef.current!);
72
-
73
- React.useEffect(() => {
74
- const element = elementRef.current;
75
- if (!element) return;
76
-
77
- const handleSuccess = (e: Event) => {
78
- if (onSuccess) {
79
- onSuccess(e as LxNavigatorEvent);
80
- }
81
- };
82
-
83
- const handleFail = (e: Event) => {
84
- if (onFail) {
85
- onFail(e as LxNavigatorEvent);
86
- }
87
- };
88
-
89
- const handleComplete = (e: Event) => {
90
- if (onComplete) {
91
- onComplete(e as LxNavigatorEvent);
92
- }
93
- };
94
- const successListener: EventListenerObject = { handleEvent: handleSuccess };
95
- const failListener: EventListenerObject = { handleEvent: handleFail };
96
- const completeListener: EventListenerObject = { handleEvent: handleComplete };
97
-
98
- element.addEventListener('success', successListener);
99
- element.addEventListener('fail', failListener);
100
- element.addEventListener('complete', completeListener);
101
-
102
- return () => {
103
- element.removeEventListener('success', successListener);
104
- element.removeEventListener('fail', failListener);
105
- element.removeEventListener('complete', completeListener);
106
- };
107
- }, [onSuccess, onFail, onComplete]);
108
-
109
- const navigatorProps = buildNavigatorNativeAttrs({
110
- url,
111
- openType,
112
- target,
113
- delta,
114
- appId,
115
- path,
116
- phoneNumber,
117
- hoverClass,
118
- hoverStopPropagation,
119
- hoverStartTime,
120
- hoverStayTime,
121
- }, rest as Record<string, unknown>);
122
-
123
- return React.createElement('lx-navigator', {
124
- ref: elementRef,
125
- className,
126
- style,
127
- ...navigatorProps
128
- }, children);
129
- }
130
- );
131
-
132
- LxNavigator.displayName = 'LxNavigator';
@@ -1,205 +0,0 @@
1
- import React, { forwardRef, useCallback, useId, useRef, useState } from 'react';
2
- import { registerPickerComponent } from '@lingxia/elements';
3
- import {
4
- buildPickerNativeAttrs,
5
- getPickerDisplayText,
6
- getPickerValueFromIndex,
7
- } from '@lingxia/elements';
8
- import {
9
- assignForwardedRef,
10
- bindElementEvents,
11
- getCustomEventDetail,
12
- unbindElementEvents,
13
- } from './text_component_shared.js';
14
-
15
- export interface LxPickerProps extends Omit<React.HTMLAttributes<HTMLElement>, 'onChange' | 'onScroll'> {
16
- // For selector/multiSelector/cascading mode
17
- columns?: string[][] | [string[], Record<string, string[]>];
18
-
19
- // For date/time mode
20
- mode?: 'date' | 'time';
21
- start?: string; // Valid date range start: 'YYYY-MM-DD'
22
- end?: string; // Valid date range end: 'YYYY-MM-DD'
23
- fields?: 'year' | 'month' | 'day' | 'range';
24
-
25
- // Value (type depends on mode)
26
- value?: string | string[];
27
-
28
- // Callbacks
29
- onConfirm?: (value: string | string[]) => void;
30
- onCancel?: () => void;
31
- onScroll?: (value: string | string[]) => void;
32
- onChange?: (event: CustomEvent) => void;
33
- onNativeScroll?: (event: CustomEvent) => void;
34
-
35
- // Logic bindings (CLI-generated)
36
- pageBindings?: Record<string, string>;
37
-
38
- // UI
39
- placeholder?: string;
40
- className?: string;
41
- style?: React.CSSProperties;
42
- disabled?: boolean;
43
-
44
- // Button customization
45
- cancelText?: string;
46
- cancelTextColor?: string;
47
- cancelButtonColor?: string;
48
- confirmText?: string;
49
- confirmTextColor?: string;
50
- confirmButtonColor?: string;
51
-
52
- children?: React.ReactNode;
53
- }
54
-
55
- if (typeof window !== "undefined") {
56
- registerPickerComponent();
57
- }
58
-
59
- export const LxPicker = forwardRef<HTMLElement, LxPickerProps>(({
60
- id,
61
- columns, mode, start, end, fields, value, onConfirm, onCancel, onScroll, placeholder = 'Please select',
62
- onChange, onNativeScroll, pageBindings,
63
- className, style, disabled, cancelText, cancelTextColor, cancelButtonColor,
64
- confirmText, confirmTextColor, confirmButtonColor, children,
65
- ...rest
66
- }, ref) => {
67
- const [visible, setVisible] = useState(false);
68
- const reactId = useId();
69
- const pickerId = id ?? `lx-picker-${reactId.replace(/[:]/g, "")}`;
70
- const elementRef = useRef<HTMLElement | null>(null);
71
- const boundElementRef = useRef<HTMLElement | null>(null);
72
- const handlerRef = useRef({
73
- columns,
74
- mode,
75
- onConfirm,
76
- onCancel,
77
- onScroll,
78
- onChange,
79
- onNativeScroll,
80
- });
81
- handlerRef.current = {
82
- columns,
83
- mode,
84
- onConfirm,
85
- onCancel,
86
- onScroll,
87
- onChange,
88
- onNativeScroll,
89
- };
90
- const listenerMapRef = useRef<Record<string, EventListenerObject>>({
91
- change: {
92
- handleEvent: (event: Event) => {
93
- const detail = getCustomEventDetail<{
94
- confirmed?: boolean;
95
- cancelled?: boolean;
96
- value?: string | string[];
97
- index?: number | number[];
98
- }>(event);
99
- handlerRef.current.onChange?.(event as CustomEvent);
100
- if (detail.confirmed) {
101
- const nextValue =
102
- handlerRef.current.mode === 'date' || handlerRef.current.mode === 'time'
103
- ? (detail.value ?? '')
104
- : detail.index !== undefined
105
- ? getPickerValueFromIndex(handlerRef.current.columns, detail.index)
106
- : '';
107
- handlerRef.current.onConfirm?.(nextValue);
108
- setVisible(false);
109
- return;
110
- }
111
- if (detail.cancelled) {
112
- handlerRef.current.onCancel?.();
113
- setVisible(false);
114
- }
115
- },
116
- },
117
- scroll: {
118
- handleEvent: (event: Event) => {
119
- const detail = getCustomEventDetail<{
120
- value?: string | string[];
121
- index?: number | number[];
122
- }>(event);
123
- handlerRef.current.onNativeScroll?.(event as CustomEvent);
124
- if (detail.value !== undefined) {
125
- handlerRef.current.onScroll?.(detail.value);
126
- return;
127
- }
128
- if (detail.index !== undefined) {
129
- handlerRef.current.onScroll?.(getPickerValueFromIndex(handlerRef.current.columns, detail.index));
130
- }
131
- },
132
- },
133
- });
134
- const elementRefCallback = useCallback((element: HTMLElement | null) => {
135
- boundElementRef.current = bindElementEvents(boundElementRef.current, element, listenerMapRef.current);
136
- elementRef.current = element;
137
- assignForwardedRef(ref, element);
138
-
139
- // Set pageBindings on custom element
140
- if (element && pageBindings) {
141
- (element as any).pageBindings = pageBindings;
142
- }
143
- }, [ref, pageBindings]);
144
- React.useEffect(() => () => {
145
- unbindElementEvents(boundElementRef.current, listenerMapRef.current);
146
- boundElementRef.current = null;
147
- elementRef.current = null;
148
- }, []);
149
-
150
- const handleClick = () => !disabled && setVisible(true);
151
- const pickerProps = buildPickerNativeAttrs({
152
- id: pickerId,
153
- columns,
154
- mode,
155
- start,
156
- end,
157
- fields,
158
- value,
159
- cancelText,
160
- cancelTextColor,
161
- cancelButtonColor,
162
- confirmText,
163
- confirmTextColor,
164
- confirmButtonColor,
165
- }, rest as Record<string, unknown>);
166
- const displayText = getPickerDisplayText(value, fields);
167
-
168
- return (
169
- <>
170
- {children ? (
171
- <div
172
- onClick={handleClick}
173
- className={className}
174
- style={{
175
- cursor: disabled ? 'not-allowed' : 'pointer',
176
- opacity: disabled ? 0.5 : 1,
177
- ...style,
178
- }}
179
- >
180
- {children}
181
- </div>
182
- ) : (
183
- <div
184
- onClick={handleClick}
185
- className={className}
186
- style={{
187
- display: 'flex', alignItems: 'center', justifyContent: 'space-between',
188
- padding: '12px 14px', backgroundColor: '#fff', border: '1px solid #e5e7eb',
189
- borderRadius: '8px', cursor: disabled ? 'not-allowed' : 'pointer',
190
- opacity: disabled ? 0.5 : 1, width: '100%', boxSizing: 'border-box',
191
- ...style,
192
- }}
193
- >
194
- <span style={{ color: value ? '#111' : '#9ca3af' }}>{displayText || placeholder}</span>
195
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="#9ca3af" strokeWidth="2">
196
- <path d="M6 9l6 6 6-6" />
197
- </svg>
198
- </div>
199
- )}
200
- {visible && React.createElement('lx-picker', { ref: elementRefCallback, ...pickerProps })}
201
- </>
202
- );
203
- });
204
-
205
- LxPicker.displayName = 'LxPicker';