@seed-design/lynx-react 0.3.1 → 0.4.1
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/lib/components/Field/Field.d.ts +47 -0
- package/lib/components/Field/Field.d.ts.map +1 -0
- package/lib/components/Field/Field.jsx +121 -0
- package/lib/components/Field/Field.namespace.d.ts +2 -0
- package/lib/components/Field/Field.namespace.d.ts.map +1 -0
- package/lib/components/Field/Field.namespace.js +16 -0
- package/lib/components/Field/context.d.ts +19 -0
- package/lib/components/Field/context.d.ts.map +1 -0
- package/lib/components/Field/context.js +10 -0
- package/lib/components/Field/index.d.ts +3 -0
- package/lib/components/Field/index.d.ts.map +1 -0
- package/lib/components/KeyboardAvoidingScrollView/KeyboardAvoidingScrollView.d.ts +42 -0
- package/lib/components/KeyboardAvoidingScrollView/KeyboardAvoidingScrollView.d.ts.map +1 -0
- package/lib/components/KeyboardAvoidingScrollView/KeyboardAvoidingScrollView.jsx +140 -0
- package/lib/components/KeyboardAvoidingScrollView/context.d.ts +17 -0
- package/lib/components/KeyboardAvoidingScrollView/context.d.ts.map +1 -0
- package/lib/components/KeyboardAvoidingScrollView/context.js +12 -0
- package/lib/components/KeyboardAvoidingScrollView/engine.d.ts +50 -0
- package/lib/components/KeyboardAvoidingScrollView/engine.d.ts.map +1 -0
- package/lib/components/KeyboardAvoidingScrollView/engine.js +259 -0
- package/lib/components/KeyboardAvoidingScrollView/geometry.d.ts +50 -0
- package/lib/components/KeyboardAvoidingScrollView/geometry.d.ts.map +1 -0
- package/lib/components/KeyboardAvoidingScrollView/geometry.js +90 -0
- package/lib/components/KeyboardAvoidingScrollView/index.d.ts +2 -0
- package/lib/components/KeyboardAvoidingScrollView/index.d.ts.map +1 -0
- package/lib/components/KeyboardAvoidingScrollView/keyboard-event-source.d.ts +11 -0
- package/lib/components/KeyboardAvoidingScrollView/keyboard-event-source.d.ts.map +1 -0
- package/lib/components/KeyboardAvoidingScrollView/keyboard-event-source.js +43 -0
- package/lib/components/KeyboardAvoidingScrollView/native-driver.d.ts +34 -0
- package/lib/components/KeyboardAvoidingScrollView/native-driver.d.ts.map +1 -0
- package/lib/components/KeyboardAvoidingScrollView/native-driver.js +133 -0
- package/lib/components/ProgressCircle/ProgressCircle.d.ts.map +1 -1
- package/lib/components/ProgressCircle/ProgressCircle.jsx +36 -5
- package/lib/components/Stack/Stack.d.ts.map +1 -1
- package/lib/components/Stack/Stack.jsx +10 -1
- package/lib/components/TagGroup/TagGroup.d.ts +2 -1
- package/lib/components/TagGroup/TagGroup.d.ts.map +1 -1
- package/lib/components/TagGroup/TagGroup.jsx +2 -1
- package/lib/components/TextField/TextField.d.ts +131 -0
- package/lib/components/TextField/TextField.d.ts.map +1 -0
- package/lib/components/TextField/TextField.jsx +434 -0
- package/lib/components/TextField/TextField.namespace.d.ts +2 -0
- package/lib/components/TextField/TextField.namespace.d.ts.map +1 -0
- package/lib/components/TextField/TextField.namespace.js +14 -0
- package/lib/components/TextField/context.d.ts +22 -0
- package/lib/components/TextField/context.d.ts.map +1 -0
- package/lib/components/TextField/context.js +7 -0
- package/lib/components/TextField/index.d.ts +4 -0
- package/lib/components/TextField/index.d.ts.map +1 -0
- package/lib/components/TextField/useTextFieldWithGraphemes.d.ts +24 -0
- package/lib/components/TextField/useTextFieldWithGraphemes.d.ts.map +1 -0
- package/lib/components/TextField/useTextFieldWithGraphemes.js +47 -0
- package/lib/components/index.d.ts +3 -0
- package/lib/components/index.d.ts.map +1 -1
- package/lib/index.js +7 -1
- package/lib/node_modules/.bun/unicode-segmenter@0.14.5/node_modules/unicode-segmenter/_grapheme_data.js +8 -0
- package/lib/node_modules/.bun/unicode-segmenter@0.14.5/node_modules/unicode-segmenter/_incb_data.js +14 -0
- package/lib/node_modules/.bun/unicode-segmenter@0.14.5/node_modules/unicode-segmenter/core.js +68 -0
- package/lib/node_modules/.bun/unicode-segmenter@0.14.5/node_modules/unicode-segmenter/grapheme.js +175 -0
- package/package.json +7 -5
- package/src/components/Field/Field.namespace.ts +19 -0
- package/src/components/Field/Field.test.tsx +81 -0
- package/src/components/Field/Field.tsx +252 -0
- package/src/components/Field/context.ts +26 -0
- package/src/components/Field/index.ts +21 -0
- package/src/components/KeyboardAvoidingScrollView/KeyboardAvoidingScrollView.test.tsx +267 -0
- package/src/components/KeyboardAvoidingScrollView/KeyboardAvoidingScrollView.tsx +299 -0
- package/src/components/KeyboardAvoidingScrollView/context.ts +24 -0
- package/src/components/KeyboardAvoidingScrollView/engine.test.ts +451 -0
- package/src/components/KeyboardAvoidingScrollView/engine.ts +417 -0
- package/src/components/KeyboardAvoidingScrollView/geometry.test.ts +315 -0
- package/src/components/KeyboardAvoidingScrollView/geometry.ts +194 -0
- package/src/components/KeyboardAvoidingScrollView/index.ts +5 -0
- package/src/components/KeyboardAvoidingScrollView/keyboard-event-source.test.ts +122 -0
- package/src/components/KeyboardAvoidingScrollView/keyboard-event-source.ts +75 -0
- package/src/components/KeyboardAvoidingScrollView/native-driver.test.ts +223 -0
- package/src/components/KeyboardAvoidingScrollView/native-driver.ts +248 -0
- package/src/components/ProgressCircle/ProgressCircle.test.tsx +58 -0
- package/src/components/ProgressCircle/ProgressCircle.tsx +42 -5
- package/src/components/Stack/Stack.test.tsx +67 -0
- package/src/components/Stack/Stack.tsx +15 -1
- package/src/components/TagGroup/TagGroup.test.tsx +73 -0
- package/src/components/TagGroup/TagGroup.tsx +4 -2
- package/src/components/TextField/TextField.namespace.ts +16 -0
- package/src/components/TextField/TextField.test.tsx +1052 -0
- package/src/components/TextField/TextField.tsx +954 -0
- package/src/components/TextField/context.ts +33 -0
- package/src/components/TextField/index.ts +23 -0
- package/src/components/TextField/useTextFieldWithGraphemes.test.tsx +80 -0
- package/src/components/TextField/useTextFieldWithGraphemes.ts +78 -0
- package/src/components/index.ts +3 -0
|
@@ -0,0 +1,434 @@
|
|
|
1
|
+
import { createSlotRecipeContext } from "../../utils/create-slot-recipe-context.jsx";
|
|
2
|
+
import { InternalIcon } from "../Icon/Icon.jsx";
|
|
3
|
+
import { useFieldContext } from "../Field/context.js";
|
|
4
|
+
import { useKeyboardAvoidanceActions } from "../KeyboardAvoidingScrollView/context.js";
|
|
5
|
+
import { NATIVE_TEXT_MAX_LENGTH_UNLIMITED, TextFieldContext } from "./context.js";
|
|
6
|
+
import { textInput } from "@seed-design/lynx-css/vars/component";
|
|
7
|
+
import clsx from "clsx";
|
|
8
|
+
import * as React from "@lynx-js/react";
|
|
9
|
+
import { textInput as textInput$1 } from "@seed-design/lynx-css/recipes/text-input";
|
|
10
|
+
//#region src/components/TextField/TextField.tsx
|
|
11
|
+
var ANDROID_TEXTAREA_DEFAULT_LINE_SPACING = "3.2px";
|
|
12
|
+
function getRuntimePlatform() {
|
|
13
|
+
return (globalThis.SystemInfo ?? (typeof SystemInfo === "undefined" ? void 0 : SystemInfo))?.platform;
|
|
14
|
+
}
|
|
15
|
+
function isAndroidRuntime() {
|
|
16
|
+
return getRuntimePlatform() === "Android";
|
|
17
|
+
}
|
|
18
|
+
function isIOSRuntime() {
|
|
19
|
+
return getRuntimePlatform() === "iOS";
|
|
20
|
+
}
|
|
21
|
+
var { ClassNamesProvider, useClassNames } = createSlotRecipeContext(textInput$1);
|
|
22
|
+
var TextFieldRoot = React.forwardRef((props, forwardedRef) => {
|
|
23
|
+
const [variantProps, otherProps] = textInput$1.splitVariantProps(props);
|
|
24
|
+
const { children, className, value: controlledValue, defaultValue = "", onValueChange, nativeInsertionMaxLength, required: requiredProp, name, ...nativeProps } = otherProps;
|
|
25
|
+
const fieldContext = useFieldContext({ strict: false });
|
|
26
|
+
const rootRef = React.useRef(null);
|
|
27
|
+
const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue);
|
|
28
|
+
const [localFocused, setLocalFocused] = React.useState(false);
|
|
29
|
+
const isControlled = controlledValue !== void 0;
|
|
30
|
+
const value = isControlled ? controlledValue : uncontrolledValue;
|
|
31
|
+
const disabled = variantProps.disabled ?? fieldContext?.disabled ?? false;
|
|
32
|
+
const invalid = variantProps.invalid ?? fieldContext?.invalid ?? false;
|
|
33
|
+
const readOnly = variantProps.readOnly ?? fieldContext?.readOnly ?? false;
|
|
34
|
+
const required = requiredProp ?? fieldContext?.required ?? false;
|
|
35
|
+
const focused = fieldContext?.focused ?? localFocused;
|
|
36
|
+
const variant = variantProps.variant ?? "outline";
|
|
37
|
+
const size = variantProps.size ?? "large";
|
|
38
|
+
const valueRef = React.useRef(value);
|
|
39
|
+
const controlledRef = React.useRef(isControlled);
|
|
40
|
+
const onValueChangeRef = React.useRef(onValueChange);
|
|
41
|
+
const fieldContextRef = React.useRef(fieldContext);
|
|
42
|
+
valueRef.current = value;
|
|
43
|
+
controlledRef.current = isControlled;
|
|
44
|
+
onValueChangeRef.current = onValueChange;
|
|
45
|
+
fieldContextRef.current = fieldContext;
|
|
46
|
+
const classes = textInput$1({
|
|
47
|
+
...variantProps,
|
|
48
|
+
variant,
|
|
49
|
+
size,
|
|
50
|
+
disabled,
|
|
51
|
+
focused: focused && !readOnly,
|
|
52
|
+
invalid,
|
|
53
|
+
readOnly
|
|
54
|
+
});
|
|
55
|
+
const mergedRef = React.useCallback((node) => {
|
|
56
|
+
"background only";
|
|
57
|
+
rootRef.current = node;
|
|
58
|
+
if (typeof forwardedRef === "function") forwardedRef(node);
|
|
59
|
+
else if (forwardedRef) forwardedRef.current = node;
|
|
60
|
+
}, [forwardedRef]);
|
|
61
|
+
const setFocused = React.useCallback((nextFocused) => {
|
|
62
|
+
"background only";
|
|
63
|
+
setLocalFocused(nextFocused);
|
|
64
|
+
fieldContextRef.current?.setFocused(nextFocused);
|
|
65
|
+
}, []);
|
|
66
|
+
const setValue = React.useCallback((nextValue) => {
|
|
67
|
+
"background only";
|
|
68
|
+
if (!controlledRef.current) setUncontrolledValue(nextValue);
|
|
69
|
+
if (nextValue !== valueRef.current) onValueChangeRef.current?.(nextValue);
|
|
70
|
+
}, []);
|
|
71
|
+
const contextValue = React.useMemo(() => ({
|
|
72
|
+
rootRef,
|
|
73
|
+
value,
|
|
74
|
+
controlled: isControlled,
|
|
75
|
+
nativeInsertionMaxLength,
|
|
76
|
+
disabled,
|
|
77
|
+
invalid,
|
|
78
|
+
readOnly,
|
|
79
|
+
required,
|
|
80
|
+
name,
|
|
81
|
+
focused,
|
|
82
|
+
setValue,
|
|
83
|
+
setFocused
|
|
84
|
+
}), [
|
|
85
|
+
disabled,
|
|
86
|
+
focused,
|
|
87
|
+
invalid,
|
|
88
|
+
name,
|
|
89
|
+
nativeInsertionMaxLength,
|
|
90
|
+
readOnly,
|
|
91
|
+
required,
|
|
92
|
+
setFocused,
|
|
93
|
+
setValue,
|
|
94
|
+
value,
|
|
95
|
+
isControlled
|
|
96
|
+
]);
|
|
97
|
+
return <TextFieldContext.Provider value={contextValue}>
|
|
98
|
+
<ClassNamesProvider value={classes}>
|
|
99
|
+
<view ref={mergedRef} className={clsx(classes.root, className)} {...nativeProps}>
|
|
100
|
+
<view className={classes.baseStroke} accessibility-elements-hidden={true} />
|
|
101
|
+
<view className={classes.stroke} accessibility-elements-hidden={true} />
|
|
102
|
+
{children}
|
|
103
|
+
</view>
|
|
104
|
+
</ClassNamesProvider>
|
|
105
|
+
</TextFieldContext.Provider>;
|
|
106
|
+
});
|
|
107
|
+
TextFieldRoot.displayName = "TextFieldRoot";
|
|
108
|
+
function resolveNativeMaxLength(explicitMaxLength, insertionMaxLength) {
|
|
109
|
+
if (explicitMaxLength === void 0) return insertionMaxLength;
|
|
110
|
+
if (insertionMaxLength === void 0) return explicitMaxLength;
|
|
111
|
+
return Math.min(explicitMaxLength, insertionMaxLength);
|
|
112
|
+
}
|
|
113
|
+
function useWasDefined(value) {
|
|
114
|
+
const isDefined = value !== void 0;
|
|
115
|
+
const [wasDefined, setWasDefined] = React.useState(isDefined);
|
|
116
|
+
React.useEffect(() => {
|
|
117
|
+
if (isDefined) setWasDefined(true);
|
|
118
|
+
}, [isDefined]);
|
|
119
|
+
return wasDefined || isDefined;
|
|
120
|
+
}
|
|
121
|
+
function useResolvedNativeMaxLength(explicitMaxLength, insertionMaxLength) {
|
|
122
|
+
if (!useWasDefined(explicitMaxLength !== void 0 || insertionMaxLength !== void 0 ? true : void 0)) return void 0;
|
|
123
|
+
return resolveNativeMaxLength(explicitMaxLength, insertionMaxLength ?? 2147483647);
|
|
124
|
+
}
|
|
125
|
+
function useNativeTextControl({ forwardedRef, disabled: disabledProp, readOnly: readOnlyProp, bindinput, bindfocus, bindblur }) {
|
|
126
|
+
const textFieldContext = React.useContext(TextFieldContext);
|
|
127
|
+
if (!textFieldContext) throw new Error("TextField input components must be rendered inside <TextField.Root>.");
|
|
128
|
+
const fieldContext = useFieldContext({ strict: false });
|
|
129
|
+
const keyboardAvoidance = useKeyboardAvoidanceActions();
|
|
130
|
+
const disabled = disabledProp ?? textFieldContext.disabled;
|
|
131
|
+
const readOnly = readOnlyProp ?? textFieldContext.readOnly;
|
|
132
|
+
const nativeRef = React.useRef(null);
|
|
133
|
+
const initialNativeValueRef = React.useRef(textFieldContext.value);
|
|
134
|
+
const ownerRef = React.useRef({});
|
|
135
|
+
const lastNativeValueRef = React.useRef(initialNativeValueRef.current);
|
|
136
|
+
const committedValueRef = React.useRef(textFieldContext.value);
|
|
137
|
+
const controlledRef = React.useRef(textFieldContext.controlled);
|
|
138
|
+
const readOnlyRef = React.useRef(readOnly);
|
|
139
|
+
const isComposingRef = React.useRef(false);
|
|
140
|
+
const canApplyInsertionMaxLengthRef = React.useRef(true);
|
|
141
|
+
const reconciliationRevisionRef = React.useRef(0);
|
|
142
|
+
const [canApplyInsertionMaxLength, setCanApplyInsertionMaxLength] = React.useState(true);
|
|
143
|
+
const wasInsertionMaxLengthManaged = useWasDefined(textFieldContext.nativeInsertionMaxLength);
|
|
144
|
+
committedValueRef.current = textFieldContext.value;
|
|
145
|
+
controlledRef.current = textFieldContext.controlled;
|
|
146
|
+
readOnlyRef.current = readOnly;
|
|
147
|
+
const syncNativeValue = React.useCallback((node, value) => {
|
|
148
|
+
"background only";
|
|
149
|
+
if (lastNativeValueRef.current === value || typeof node.invoke !== "function") return;
|
|
150
|
+
lastNativeValueRef.current = value;
|
|
151
|
+
try {
|
|
152
|
+
node.invoke({
|
|
153
|
+
method: "setValue",
|
|
154
|
+
params: { value },
|
|
155
|
+
fail() {
|
|
156
|
+
"background only";
|
|
157
|
+
if (lastNativeValueRef.current === value) lastNativeValueRef.current = null;
|
|
158
|
+
}
|
|
159
|
+
}).exec();
|
|
160
|
+
} catch {
|
|
161
|
+
lastNativeValueRef.current = null;
|
|
162
|
+
}
|
|
163
|
+
}, []);
|
|
164
|
+
const mergedRef = React.useCallback((node) => {
|
|
165
|
+
"background only";
|
|
166
|
+
nativeRef.current = node;
|
|
167
|
+
if (typeof forwardedRef === "function") forwardedRef(node);
|
|
168
|
+
else if (forwardedRef) forwardedRef.current = node;
|
|
169
|
+
}, [forwardedRef]);
|
|
170
|
+
const updateEditingState = React.useCallback((selectionStart, selectionEnd, isComposing = isComposingRef.current) => {
|
|
171
|
+
"background only";
|
|
172
|
+
isComposingRef.current = isComposing;
|
|
173
|
+
const nextCanApplyInsertionMaxLength = !isComposing && selectionStart >= 0 && selectionStart === selectionEnd;
|
|
174
|
+
if (canApplyInsertionMaxLengthRef.current === nextCanApplyInsertionMaxLength) return;
|
|
175
|
+
canApplyInsertionMaxLengthRef.current = nextCanApplyInsertionMaxLength;
|
|
176
|
+
setCanApplyInsertionMaxLength(nextCanApplyInsertionMaxLength);
|
|
177
|
+
}, []);
|
|
178
|
+
const reconcileControlledValue = React.useCallback((nativeValue) => {
|
|
179
|
+
"background only";
|
|
180
|
+
if (!controlledRef.current) return;
|
|
181
|
+
reconciliationRevisionRef.current += 1;
|
|
182
|
+
const revision = reconciliationRevisionRef.current;
|
|
183
|
+
const nodeAtInput = nativeRef.current;
|
|
184
|
+
Promise.resolve().then(() => {
|
|
185
|
+
"background only";
|
|
186
|
+
}).then(() => {
|
|
187
|
+
"background only";
|
|
188
|
+
if (revision !== reconciliationRevisionRef.current || !controlledRef.current || readOnlyRef.current || nativeRef.current !== nodeAtInput) return;
|
|
189
|
+
const committedValue = committedValueRef.current;
|
|
190
|
+
if (committedValue === nativeValue) return;
|
|
191
|
+
const node = nativeRef.current;
|
|
192
|
+
if (node) syncNativeValue(node, committedValue);
|
|
193
|
+
});
|
|
194
|
+
}, [syncNativeValue]);
|
|
195
|
+
React.useEffect(() => {
|
|
196
|
+
if (readOnly) return;
|
|
197
|
+
if (lastNativeValueRef.current === textFieldContext.value) return;
|
|
198
|
+
const node = nativeRef.current;
|
|
199
|
+
if (node) syncNativeValue(node, textFieldContext.value);
|
|
200
|
+
}, [
|
|
201
|
+
readOnly,
|
|
202
|
+
syncNativeValue,
|
|
203
|
+
textFieldContext.value
|
|
204
|
+
]);
|
|
205
|
+
React.useEffect(() => () => {
|
|
206
|
+
keyboardAvoidance?.unregister(ownerRef.current);
|
|
207
|
+
reconciliationRevisionRef.current += 1;
|
|
208
|
+
}, [keyboardAvoidance]);
|
|
209
|
+
const handleInput = React.useCallback((event) => {
|
|
210
|
+
"background only";
|
|
211
|
+
const { value: nextValue, selectionStart, selectionEnd, isComposing } = event.detail;
|
|
212
|
+
if (disabled || readOnly) {
|
|
213
|
+
lastNativeValueRef.current = nextValue;
|
|
214
|
+
if (nextValue !== committedValueRef.current) {
|
|
215
|
+
const node = nativeRef.current;
|
|
216
|
+
if (node) syncNativeValue(node, committedValueRef.current);
|
|
217
|
+
}
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
updateEditingState(selectionStart, selectionEnd, isComposing === true);
|
|
221
|
+
lastNativeValueRef.current = nextValue;
|
|
222
|
+
textFieldContext.setValue(nextValue);
|
|
223
|
+
bindinput?.(event);
|
|
224
|
+
reconcileControlledValue(nextValue);
|
|
225
|
+
}, [
|
|
226
|
+
bindinput,
|
|
227
|
+
disabled,
|
|
228
|
+
readOnly,
|
|
229
|
+
reconcileControlledValue,
|
|
230
|
+
syncNativeValue,
|
|
231
|
+
textFieldContext.setValue,
|
|
232
|
+
updateEditingState
|
|
233
|
+
]);
|
|
234
|
+
const handleSelectionChange = React.useCallback((detail) => {
|
|
235
|
+
"background only";
|
|
236
|
+
updateEditingState(detail.selectionStart, detail.selectionEnd);
|
|
237
|
+
}, [updateEditingState]);
|
|
238
|
+
const handleFocus = React.useCallback((event) => {
|
|
239
|
+
"background only";
|
|
240
|
+
textFieldContext.setFocused(true);
|
|
241
|
+
keyboardAvoidance?.focus({
|
|
242
|
+
owner: ownerRef.current,
|
|
243
|
+
nativeRef,
|
|
244
|
+
controlRef: textFieldContext.rootRef,
|
|
245
|
+
fieldRef: fieldContext?.rootRef,
|
|
246
|
+
enabled: !disabled && !readOnly
|
|
247
|
+
});
|
|
248
|
+
bindfocus?.(event);
|
|
249
|
+
}, [
|
|
250
|
+
bindfocus,
|
|
251
|
+
disabled,
|
|
252
|
+
fieldContext?.rootRef,
|
|
253
|
+
keyboardAvoidance,
|
|
254
|
+
readOnly,
|
|
255
|
+
textFieldContext.rootRef,
|
|
256
|
+
textFieldContext.setFocused
|
|
257
|
+
]);
|
|
258
|
+
const handleBlur = React.useCallback((event) => {
|
|
259
|
+
"background only";
|
|
260
|
+
textFieldContext.setFocused(false);
|
|
261
|
+
keyboardAvoidance?.blur(ownerRef.current);
|
|
262
|
+
bindblur?.(event);
|
|
263
|
+
}, [
|
|
264
|
+
bindblur,
|
|
265
|
+
keyboardAvoidance,
|
|
266
|
+
textFieldContext.setFocused
|
|
267
|
+
]);
|
|
268
|
+
const notifyLayoutChanged = React.useCallback(() => {
|
|
269
|
+
"background only";
|
|
270
|
+
keyboardAvoidance?.layoutChanged(ownerRef.current);
|
|
271
|
+
}, [keyboardAvoidance]);
|
|
272
|
+
const focusNativeControl = React.useCallback(() => {
|
|
273
|
+
"background only";
|
|
274
|
+
const node = nativeRef.current;
|
|
275
|
+
if (!node || typeof node.invoke !== "function") return;
|
|
276
|
+
try {
|
|
277
|
+
node.invoke({ method: "focus" }).exec();
|
|
278
|
+
} catch {}
|
|
279
|
+
}, []);
|
|
280
|
+
return {
|
|
281
|
+
context: textFieldContext,
|
|
282
|
+
disabled,
|
|
283
|
+
readOnly,
|
|
284
|
+
defaultValueProps: { "default-value": initialNativeValueRef.current },
|
|
285
|
+
mergedRef,
|
|
286
|
+
handleInput,
|
|
287
|
+
handleFocus,
|
|
288
|
+
handleBlur,
|
|
289
|
+
notifyLayoutChanged,
|
|
290
|
+
focusNativeControl,
|
|
291
|
+
handleSelectionChange,
|
|
292
|
+
nativeInsertionMaxLength: wasInsertionMaxLengthManaged && canApplyInsertionMaxLength && textFieldContext.nativeInsertionMaxLength !== void 0 ? textFieldContext.nativeInsertionMaxLength : wasInsertionMaxLengthManaged ? NATIVE_TEXT_MAX_LENGTH_UNLIMITED : void 0
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
function getAccessibilityProps(props) {
|
|
296
|
+
return {
|
|
297
|
+
"accessibility-label": props["accessibility-label"],
|
|
298
|
+
"accessibility-traits": props["accessibility-traits"],
|
|
299
|
+
"accessibility-element": props["accessibility-element"],
|
|
300
|
+
"accessibility-value": props["accessibility-value"],
|
|
301
|
+
"accessibility-role-description": props["accessibility-role-description"],
|
|
302
|
+
"accessibility-elements-hidden": props["accessibility-elements-hidden"],
|
|
303
|
+
"accessibility-heading": props["accessibility-heading"],
|
|
304
|
+
"accessibility-actions": props["accessibility-actions"],
|
|
305
|
+
"accessibility-exclusive-focus": props["accessibility-exclusive-focus"],
|
|
306
|
+
"ios-platform-accessibility-id": props["ios-platform-accessibility-id"]
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
function getReadOnlyTextStyle({ style, disabled, placeholder, multiline }) {
|
|
310
|
+
return {
|
|
311
|
+
...style,
|
|
312
|
+
...multiline ? {
|
|
313
|
+
whiteSpace: "normal",
|
|
314
|
+
wordBreak: "break-all"
|
|
315
|
+
} : { alignSelf: "center" },
|
|
316
|
+
...placeholder ? { color: disabled ? textInput.base.disabled.placeholder.color : textInput.base.enabled.placeholder.color } : {}
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
var TextFieldInput = React.forwardRef((props, ref) => {
|
|
320
|
+
const classes = useClassNames();
|
|
321
|
+
const { className, disabled, readonly, name, maxlength, bindinput, bindselection, bindfocus, bindblur, "show-soft-input-on-focus": showSoftInputOnFocus, "android-set-soft-input-mode": androidSetSoftInputMode, ...nativeProps } = props;
|
|
322
|
+
const control = useNativeTextControl({
|
|
323
|
+
forwardedRef: ref,
|
|
324
|
+
disabled,
|
|
325
|
+
readOnly: readonly,
|
|
326
|
+
bindinput,
|
|
327
|
+
bindfocus,
|
|
328
|
+
bindblur
|
|
329
|
+
});
|
|
330
|
+
const resolvedMaxLength = useResolvedNativeMaxLength(maxlength, control.nativeInsertionMaxLength);
|
|
331
|
+
const handleSelection = React.useCallback((event) => {
|
|
332
|
+
"background only";
|
|
333
|
+
control.handleSelectionChange(event.detail);
|
|
334
|
+
bindselection?.(event);
|
|
335
|
+
}, [bindselection, control.handleSelectionChange]);
|
|
336
|
+
if (control.readOnly) {
|
|
337
|
+
const value = control.context.value;
|
|
338
|
+
const isPlaceholder = value === "";
|
|
339
|
+
const displayValue = isPlaceholder ? props.placeholder : props.type === "password" ? Array.from(value, () => "•").join("") : value;
|
|
340
|
+
return <text ref={control.mergedRef} id={props.id} hidden={props.hidden} flatten={props.flatten} focusable={props.focusable} bindlayoutchange={props.bindlayoutchange} main-thread:bindlayoutchange={props["main-thread:bindlayoutchange"]} className={clsx(classes.value, className)} style={getReadOnlyTextStyle({
|
|
341
|
+
style: props.style,
|
|
342
|
+
disabled: control.disabled,
|
|
343
|
+
placeholder: isPlaceholder,
|
|
344
|
+
multiline: false
|
|
345
|
+
})} {...getAccessibilityProps(props)}>
|
|
346
|
+
{displayValue}
|
|
347
|
+
</text>;
|
|
348
|
+
}
|
|
349
|
+
return <input {...control.defaultValueProps} ref={control.mergedRef} className={clsx(classes.value, className)} disabled={control.disabled} readonly={control.readOnly} show-soft-input-on-focus={showSoftInputOnFocus ?? true} android-set-soft-input-mode={androidSetSoftInputMode ?? "unspecified"} name={name ?? control.context.name} {...resolvedMaxLength === void 0 ? {} : { maxlength: resolvedMaxLength }} bindinput={control.handleInput} bindselection={handleSelection} bindfocus={control.handleFocus} bindblur={control.handleBlur} {...nativeProps} />;
|
|
350
|
+
});
|
|
351
|
+
TextFieldInput.displayName = "TextFieldInput";
|
|
352
|
+
var TextFieldTextarea = React.forwardRef((props, ref) => {
|
|
353
|
+
const classes = useClassNames();
|
|
354
|
+
const { className, disabled, readonly, name, maxlength, bindinput, bindselection, bindfocus, bindblur, bindlayoutchange, "show-soft-input-on-focus": showSoftInputOnFocus, bounces, "line-spacing": lineSpacing, "android-fullscreen-mode": androidFullscreenMode, "android-set-soft-input-mode": androidSetSoftInputMode, autoresize = true, ...nativeProps } = props;
|
|
355
|
+
const control = useNativeTextControl({
|
|
356
|
+
forwardedRef: ref,
|
|
357
|
+
disabled,
|
|
358
|
+
readOnly: readonly,
|
|
359
|
+
bindinput,
|
|
360
|
+
bindfocus,
|
|
361
|
+
bindblur
|
|
362
|
+
});
|
|
363
|
+
const resolvedMaxLength = useResolvedNativeMaxLength(maxlength, control.nativeInsertionMaxLength);
|
|
364
|
+
const isAndroid = isAndroidRuntime();
|
|
365
|
+
const usesIOSAutoresizeWrapper = autoresize && isIOSRuntime();
|
|
366
|
+
const resolvedLineSpacing = lineSpacing !== void 0 ? lineSpacing : isAndroid ? ANDROID_TEXTAREA_DEFAULT_LINE_SPACING : void 0;
|
|
367
|
+
const handleSelection = React.useCallback((event) => {
|
|
368
|
+
"background only";
|
|
369
|
+
control.handleSelectionChange(event.detail);
|
|
370
|
+
bindselection?.(event);
|
|
371
|
+
}, [bindselection, control.handleSelectionChange]);
|
|
372
|
+
const handleLayoutChange = React.useCallback((event) => {
|
|
373
|
+
"background only";
|
|
374
|
+
if (autoresize) control.notifyLayoutChanged();
|
|
375
|
+
bindlayoutchange?.(event);
|
|
376
|
+
}, [
|
|
377
|
+
autoresize,
|
|
378
|
+
bindlayoutchange,
|
|
379
|
+
control.notifyLayoutChanged
|
|
380
|
+
]);
|
|
381
|
+
const handleTextareaRootTap = React.useCallback((event) => {
|
|
382
|
+
"background only";
|
|
383
|
+
if (control.disabled || event.target.uid !== event.currentTarget.uid) return;
|
|
384
|
+
control.focusNativeControl();
|
|
385
|
+
}, [control.disabled, control.focusNativeControl]);
|
|
386
|
+
if (control.readOnly) {
|
|
387
|
+
const value = control.context.value;
|
|
388
|
+
const isPlaceholder = value === "";
|
|
389
|
+
return <text ref={control.mergedRef} id={props.id} hidden={props.hidden} flatten={props.flatten} focusable={props.focusable} bindlayoutchange={props.bindlayoutchange} main-thread:bindlayoutchange={props["main-thread:bindlayoutchange"]} className={clsx(classes.value, classes.textareaValue, classes.textareaFixed, className)} style={getReadOnlyTextStyle({
|
|
390
|
+
style: props.style,
|
|
391
|
+
disabled: control.disabled,
|
|
392
|
+
placeholder: isPlaceholder,
|
|
393
|
+
multiline: true
|
|
394
|
+
})} {...getAccessibilityProps(props)}>
|
|
395
|
+
{isPlaceholder ? props.placeholder : value}
|
|
396
|
+
</text>;
|
|
397
|
+
}
|
|
398
|
+
const textarea = <textarea {...control.defaultValueProps} ref={control.mergedRef} className={clsx(classes.value, classes.textareaValue, !autoresize && classes.textareaFixed, usesIOSAutoresizeWrapper && classes.textareaNativeAutoresize, autoresize && !usesIOSAutoresizeWrapper && classes.textareaAndroidAutoresize, className)} disabled={control.disabled} readonly={control.readOnly} show-soft-input-on-focus={showSoftInputOnFocus ?? true} bounces={bounces ?? (autoresize ? false : void 0)} line-spacing={resolvedLineSpacing} android-fullscreen-mode={androidFullscreenMode ?? false} android-set-soft-input-mode={androidSetSoftInputMode ?? "unspecified"} name={name ?? control.context.name} {...resolvedMaxLength === void 0 ? {} : { maxlength: resolvedMaxLength }} bindinput={control.handleInput} bindselection={handleSelection} bindfocus={control.handleFocus} bindblur={control.handleBlur} bindlayoutchange={usesIOSAutoresizeWrapper ? bindlayoutchange : handleLayoutChange} {...nativeProps} />;
|
|
399
|
+
if (!usesIOSAutoresizeWrapper) return textarea;
|
|
400
|
+
return <view ignore-focus={true} className={clsx(classes.textareaRoot, classes.textareaAutoresizeRoot)} bindtap={handleTextareaRootTap} bindlayoutchange={control.notifyLayoutChanged}>
|
|
401
|
+
{textarea}
|
|
402
|
+
</view>;
|
|
403
|
+
});
|
|
404
|
+
TextFieldTextarea.displayName = "TextFieldTextarea";
|
|
405
|
+
var TextFieldPrefixIcon = React.forwardRef((props, ref) => {
|
|
406
|
+
const classes = useClassNames();
|
|
407
|
+
const { className, ...otherProps } = props;
|
|
408
|
+
return <InternalIcon ref={ref} className={clsx(classes.prefixIcon, className)} {...otherProps} />;
|
|
409
|
+
});
|
|
410
|
+
TextFieldPrefixIcon.displayName = "TextFieldPrefixIcon";
|
|
411
|
+
var TextFieldPrefixText = React.forwardRef((props, ref) => {
|
|
412
|
+
const classes = useClassNames();
|
|
413
|
+
const { children, className, ...nativeProps } = props;
|
|
414
|
+
return <text {...ref ? { ref } : {}} className={clsx(classes.prefixText, className)} {...nativeProps}>
|
|
415
|
+
{children}
|
|
416
|
+
</text>;
|
|
417
|
+
});
|
|
418
|
+
TextFieldPrefixText.displayName = "TextFieldPrefixText";
|
|
419
|
+
var TextFieldSuffixIcon = React.forwardRef((props, ref) => {
|
|
420
|
+
const classes = useClassNames();
|
|
421
|
+
const { className, ...otherProps } = props;
|
|
422
|
+
return <InternalIcon ref={ref} className={clsx(classes.suffixIcon, className)} {...otherProps} />;
|
|
423
|
+
});
|
|
424
|
+
TextFieldSuffixIcon.displayName = "TextFieldSuffixIcon";
|
|
425
|
+
var TextFieldSuffixText = React.forwardRef((props, ref) => {
|
|
426
|
+
const classes = useClassNames();
|
|
427
|
+
const { children, className, ...nativeProps } = props;
|
|
428
|
+
return <text {...ref ? { ref } : {}} className={clsx(classes.suffixText, className)} {...nativeProps}>
|
|
429
|
+
{children}
|
|
430
|
+
</text>;
|
|
431
|
+
});
|
|
432
|
+
TextFieldSuffixText.displayName = "TextFieldSuffixText";
|
|
433
|
+
//#endregion
|
|
434
|
+
export { TextFieldInput, TextFieldPrefixIcon, TextFieldPrefixText, TextFieldRoot, TextFieldSuffixIcon, TextFieldSuffixText, TextFieldTextarea };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { TextFieldPrefixIcon as PrefixIcon, TextFieldPrefixText as PrefixText, TextFieldRoot as Root, TextFieldSuffixIcon as SuffixIcon, TextFieldSuffixText as SuffixText, TextFieldInput as Input, TextFieldTextarea as Textarea, type TextFieldPrefixIconProps as PrefixIconProps, type TextFieldPrefixTextProps as PrefixTextProps, type TextFieldRootProps as RootProps, type TextFieldSuffixIconProps as SuffixIconProps, type TextFieldSuffixTextProps as SuffixTextProps, type TextFieldInputProps as InputProps, type TextFieldTextareaProps as TextareaProps, } from './TextField';
|
|
2
|
+
//# sourceMappingURL=TextField.namespace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TextField.namespace.d.ts","sourceRoot":"","sources":["../../../src/components/TextField/TextField.namespace.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,IAAI,UAAU,EACjC,mBAAmB,IAAI,UAAU,EACjC,aAAa,IAAI,IAAI,EACrB,mBAAmB,IAAI,UAAU,EACjC,mBAAmB,IAAI,UAAU,EACjC,cAAc,IAAI,KAAK,EACvB,iBAAiB,IAAI,QAAQ,EAC7B,KAAK,wBAAwB,IAAI,eAAe,EAChD,KAAK,wBAAwB,IAAI,eAAe,EAChD,KAAK,kBAAkB,IAAI,SAAS,EACpC,KAAK,wBAAwB,IAAI,eAAe,EAChD,KAAK,wBAAwB,IAAI,eAAe,EAChD,KAAK,mBAAmB,IAAI,UAAU,EACtC,KAAK,sBAAsB,IAAI,aAAa,GAC7C,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { __exportAll } from "../../_virtual/_rolldown/runtime.js";
|
|
2
|
+
import { TextFieldInput, TextFieldPrefixIcon, TextFieldPrefixText, TextFieldRoot, TextFieldSuffixIcon, TextFieldSuffixText, TextFieldTextarea } from "./TextField.jsx";
|
|
3
|
+
//#region src/components/TextField/TextField.namespace.ts
|
|
4
|
+
var TextField_namespace_exports = /* @__PURE__ */ __exportAll({
|
|
5
|
+
Input: () => TextFieldInput,
|
|
6
|
+
PrefixIcon: () => TextFieldPrefixIcon,
|
|
7
|
+
PrefixText: () => TextFieldPrefixText,
|
|
8
|
+
Root: () => TextFieldRoot,
|
|
9
|
+
SuffixIcon: () => TextFieldSuffixIcon,
|
|
10
|
+
SuffixText: () => TextFieldSuffixText,
|
|
11
|
+
Textarea: () => TextFieldTextarea
|
|
12
|
+
});
|
|
13
|
+
//#endregion
|
|
14
|
+
export { TextField_namespace_exports };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { NodesRef } from '@lynx-js/types';
|
|
2
|
+
import * as React from "@lynx-js/react";
|
|
3
|
+
/** iOS와 Android의 32비트 `maxlength` setter에서 사용하는 무제한 센티널. */
|
|
4
|
+
export declare const NATIVE_TEXT_MAX_LENGTH_UNLIMITED = 2147483647;
|
|
5
|
+
export interface TextFieldContextValue {
|
|
6
|
+
rootRef: React.RefObject<NodesRef | null>;
|
|
7
|
+
value: string;
|
|
8
|
+
/** @internal controlled 입력의 native value 조정 여부를 판별한다. */
|
|
9
|
+
controlled: boolean;
|
|
10
|
+
nativeInsertionMaxLength?: number;
|
|
11
|
+
disabled: boolean;
|
|
12
|
+
invalid: boolean;
|
|
13
|
+
readOnly: boolean;
|
|
14
|
+
required: boolean;
|
|
15
|
+
name?: string;
|
|
16
|
+
focused: boolean;
|
|
17
|
+
setValue: (value: string) => void;
|
|
18
|
+
setFocused: (focused: boolean) => void;
|
|
19
|
+
}
|
|
20
|
+
export declare const TextFieldContext: React.Context<TextFieldContextValue | null>;
|
|
21
|
+
export declare function useTextFieldContext(): TextFieldContextValue;
|
|
22
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/components/TextField/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,gBAAgB,CAAC;AACxC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,4DAA4D;AAC5D,eAAO,MAAM,gCAAgC,aAAgB,CAAC;AAE9D,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,yDAAyD;IACzD,UAAU,EAAE,OAAO,CAAC;IACpB,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC;AAED,eAAO,MAAM,gBAAgB,6CAA0D,CAAC;AAExF,wBAAgB,mBAAmB,IAAI,qBAAqB,CAQ3D"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as React from "@lynx-js/react";
|
|
2
|
+
//#region src/components/TextField/context.ts
|
|
3
|
+
/** iOS와 Android의 32비트 `maxlength` setter에서 사용하는 무제한 센티널. */
|
|
4
|
+
var NATIVE_TEXT_MAX_LENGTH_UNLIMITED = 2147483647;
|
|
5
|
+
var TextFieldContext = React.createContext(null);
|
|
6
|
+
//#endregion
|
|
7
|
+
export { NATIVE_TEXT_MAX_LENGTH_UNLIMITED, TextFieldContext };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { TextFieldPrefixIcon, TextFieldPrefixText, TextFieldRoot, TextFieldSuffixIcon, TextFieldSuffixText, TextFieldInput, TextFieldTextarea, type TextFieldPrefixIconProps, type TextFieldPrefixTextProps, type TextFieldRootProps, type TextFieldSuffixIconProps, type TextFieldSuffixTextProps, type TextFieldInputProps, type TextFieldTextareaProps, } from './TextField';
|
|
2
|
+
export { useTextFieldWithGraphemes, type UseTextFieldWithGraphemesParams, } from './useTextFieldWithGraphemes';
|
|
3
|
+
export * as TextField from './TextField.namespace';
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/TextField/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,mBAAmB,EACnB,mBAAmB,EACnB,cAAc,EACd,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC7B,KAAK,kBAAkB,EACvB,KAAK,wBAAwB,EAC7B,KAAK,wBAAwB,EAC7B,KAAK,mBAAmB,EACxB,KAAK,sBAAsB,GAC5B,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,yBAAyB,EACzB,KAAK,+BAA+B,GACrC,MAAM,6BAA6B,CAAC;AAErC,OAAO,KAAK,SAAS,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface UseTextFieldWithGraphemesParams {
|
|
2
|
+
maxGraphemeCount?: number;
|
|
3
|
+
value?: string;
|
|
4
|
+
defaultValue?: string;
|
|
5
|
+
onValueChange?: (values: {
|
|
6
|
+
value: string;
|
|
7
|
+
graphemes: string[];
|
|
8
|
+
slicedValue: string;
|
|
9
|
+
slicedGraphemes: string[];
|
|
10
|
+
}) => void;
|
|
11
|
+
}
|
|
12
|
+
export declare function useTextFieldWithGraphemes({ maxGraphemeCount, value: controlledValue, defaultValue, onValueChange, }: UseTextFieldWithGraphemesParams): {
|
|
13
|
+
textFieldRootProps: {
|
|
14
|
+
value: string;
|
|
15
|
+
onValueChange: (nextValue: string) => void;
|
|
16
|
+
nativeInsertionMaxLength: number | undefined;
|
|
17
|
+
};
|
|
18
|
+
counterProps: {
|
|
19
|
+
current: number;
|
|
20
|
+
max: number;
|
|
21
|
+
};
|
|
22
|
+
graphemes: string[];
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=useTextFieldWithGraphemes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useTextFieldWithGraphemes.d.ts","sourceRoot":"","sources":["../../../src/components/TextField/useTextFieldWithGraphemes.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,+BAA+B;IAC9C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,CAAC,MAAM,EAAE;QACvB,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,EAAE,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;QACpB,eAAe,EAAE,MAAM,EAAE,CAAC;KAC3B,KAAK,IAAI,CAAC;CACZ;AAaD,wBAAgB,yBAAyB,CAAC,EACxC,gBAAgB,EAChB,KAAK,EAAE,eAAe,EACtB,YAAiB,EACjB,aAAa,GACd,EAAE,+BAA+B;;;mCAOlB,MAAM;;;;;;;;EAqCrB"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { NATIVE_TEXT_MAX_LENGTH_UNLIMITED } from "./context.js";
|
|
2
|
+
import { splitGraphemes } from "../../node_modules/.bun/unicode-segmenter@0.14.5/node_modules/unicode-segmenter/grapheme.js";
|
|
3
|
+
import * as React from "@lynx-js/react";
|
|
4
|
+
//#region src/components/TextField/useTextFieldWithGraphemes.ts
|
|
5
|
+
var cachedValue = "";
|
|
6
|
+
var cachedGraphemes = [];
|
|
7
|
+
function getGraphemes(value) {
|
|
8
|
+
if (value === cachedValue) return cachedGraphemes;
|
|
9
|
+
cachedValue = value;
|
|
10
|
+
cachedGraphemes = Array.from(splitGraphemes(value));
|
|
11
|
+
return cachedGraphemes;
|
|
12
|
+
}
|
|
13
|
+
function useTextFieldWithGraphemes({ maxGraphemeCount, value: controlledValue, defaultValue = "", onValueChange }) {
|
|
14
|
+
const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultValue);
|
|
15
|
+
const isControlled = controlledValue !== void 0;
|
|
16
|
+
const value = isControlled ? controlledValue : uncontrolledValue;
|
|
17
|
+
const graphemes = React.useMemo(() => getGraphemes(value), [value]);
|
|
18
|
+
return {
|
|
19
|
+
textFieldRootProps: {
|
|
20
|
+
value,
|
|
21
|
+
onValueChange: React.useCallback((nextValue) => {
|
|
22
|
+
"background only";
|
|
23
|
+
const nextGraphemes = getGraphemes(nextValue);
|
|
24
|
+
const slicedGraphemes = maxGraphemeCount === void 0 ? nextGraphemes : nextGraphemes.slice(0, maxGraphemeCount);
|
|
25
|
+
if (!isControlled) setUncontrolledValue(nextValue);
|
|
26
|
+
onValueChange?.({
|
|
27
|
+
value: nextValue,
|
|
28
|
+
graphemes: nextGraphemes,
|
|
29
|
+
slicedValue: slicedGraphemes.join(""),
|
|
30
|
+
slicedGraphemes
|
|
31
|
+
});
|
|
32
|
+
}, [
|
|
33
|
+
isControlled,
|
|
34
|
+
maxGraphemeCount,
|
|
35
|
+
onValueChange
|
|
36
|
+
]),
|
|
37
|
+
nativeInsertionMaxLength: maxGraphemeCount === void 0 ? void 0 : graphemes.length >= maxGraphemeCount ? value.length : NATIVE_TEXT_MAX_LENGTH_UNLIMITED
|
|
38
|
+
},
|
|
39
|
+
counterProps: {
|
|
40
|
+
current: graphemes.length,
|
|
41
|
+
max: maxGraphemeCount ?? 0
|
|
42
|
+
},
|
|
43
|
+
graphemes
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
47
|
+
export { useTextFieldWithGraphemes };
|
|
@@ -4,11 +4,14 @@ export * from './Badge';
|
|
|
4
4
|
export * from './Box';
|
|
5
5
|
export * from './BottomSheet';
|
|
6
6
|
export * from './Checkbox';
|
|
7
|
+
export * from './Field';
|
|
7
8
|
export * from './Icon';
|
|
9
|
+
export * from './KeyboardAvoidingScrollView';
|
|
8
10
|
export * from './ProgressCircle';
|
|
9
11
|
export * from './RadioGroup';
|
|
10
12
|
export * from './Stack';
|
|
11
13
|
export * from './Switch';
|
|
12
14
|
export * from './TagGroup';
|
|
13
15
|
export * from './Text';
|
|
16
|
+
export * from './TextField';
|
|
14
17
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,OAAO,CAAC;AACtB,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,UAAU,CAAC;AACzB,cAAc,SAAS,CAAC;AACxB,cAAc,OAAO,CAAC;AACtB,cAAc,eAAe,CAAC;AAC9B,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kBAAkB,CAAC;AACjC,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,QAAQ,CAAC;AACvB,cAAc,aAAa,CAAC"}
|
package/lib/index.js
CHANGED
|
@@ -17,6 +17,9 @@ import { useControllableState } from "./hooks/useControllableState.js";
|
|
|
17
17
|
import { splitMultipleVariantsProps } from "./utils/split-multiple-variants-props.js";
|
|
18
18
|
import { CheckboxControl, CheckboxGroup, CheckboxIndicator, CheckboxLabel, CheckboxRoot } from "./components/Checkbox/Checkbox.jsx";
|
|
19
19
|
import { Checkbox_namespace_exports } from "./components/Checkbox/Checkbox.namespace.js";
|
|
20
|
+
import { FieldCharacterCount, FieldDescription, FieldErrorMessage, FieldFooter, FieldHeader, FieldIndicatorText, FieldLabel, FieldRequiredIndicator, FieldRoot } from "./components/Field/Field.jsx";
|
|
21
|
+
import { Field_namespace_exports } from "./components/Field/Field.namespace.js";
|
|
22
|
+
import { KeyboardAvoidingScrollView } from "./components/KeyboardAvoidingScrollView/KeyboardAvoidingScrollView.jsx";
|
|
20
23
|
import { RadioGroupItem, RadioGroupItemControl, RadioGroupItemIndicator, RadioGroupItemLabel, RadioGroupRoot } from "./components/RadioGroup/RadioGroup.jsx";
|
|
21
24
|
import { RadioGroup_namespace_exports } from "./components/RadioGroup/RadioGroup.namespace.js";
|
|
22
25
|
import { HStack, VStack } from "./components/Stack/Stack.jsx";
|
|
@@ -25,6 +28,9 @@ import { Switch_namespace_exports } from "./components/Switch/Switch.namespace.j
|
|
|
25
28
|
import { TagGroupItem, TagGroupItemLabel, TagGroupRoot } from "./components/TagGroup/TagGroup.jsx";
|
|
26
29
|
import { TagGroup_namespace_exports } from "./components/TagGroup/TagGroup.namespace.js";
|
|
27
30
|
import { Text } from "./components/Text/Text.jsx";
|
|
31
|
+
import { TextFieldInput, TextFieldPrefixIcon, TextFieldPrefixText, TextFieldRoot, TextFieldSuffixIcon, TextFieldSuffixText, TextFieldTextarea } from "./components/TextField/TextField.jsx";
|
|
32
|
+
import { useTextFieldWithGraphemes } from "./components/TextField/useTextFieldWithGraphemes.js";
|
|
33
|
+
import { TextField_namespace_exports } from "./components/TextField/TextField.namespace.js";
|
|
28
34
|
import { getSeedClassName } from "./utils/get-seed-class-name.js";
|
|
29
35
|
import { useSeedClassName } from "./hooks/useSeedClassName.js";
|
|
30
|
-
export { ActionButton, AppBar_namespace_exports as AppBar, AppBarIconButton, AppBarLeft, AppBarMain, AppBarRight, AppBarRoot, AppBarSlot, AppBarSubtitle, AppBarTitle, Badge, BottomSheet_namespace_exports as BottomSheet, BottomSheetBackdrop, BottomSheetBody, BottomSheetContent, BottomSheetDescription, BottomSheetFooter, BottomSheetHandle, BottomSheetHeader, BottomSheetPositioner, BottomSheetRoot, BottomSheetTitle, BottomSheetTrigger, Box, Checkbox_namespace_exports as Checkbox, CheckboxControl, CheckboxGroup, CheckboxIndicator, CheckboxLabel, CheckboxRoot, HStack, Icon, PrefixIcon, ProgressCircle_namespace_exports as ProgressCircle, ProgressCircleRange, ProgressCircleRoot, RadioGroup_namespace_exports as RadioGroup, RadioGroupItem, RadioGroupItemControl, RadioGroupItemIndicator, RadioGroupItemLabel, RadioGroupRoot, SuffixIcon, Switch_namespace_exports as Switch, SwitchControl, SwitchLabel, SwitchRoot, SwitchThumb, TagGroup_namespace_exports as TagGroup, TagGroupItem, TagGroupItemLabel, TagGroupRoot, Text, VStack, capitalize, createSlotRecipeContext, getSeedClassName, resolveRecipeToken, splitMultipleVariantsProps, useControllableState, useIconColor, usePressTap, useSafeArea, useSeedClassName };
|
|
36
|
+
export { ActionButton, AppBar_namespace_exports as AppBar, AppBarIconButton, AppBarLeft, AppBarMain, AppBarRight, AppBarRoot, AppBarSlot, AppBarSubtitle, AppBarTitle, Badge, BottomSheet_namespace_exports as BottomSheet, BottomSheetBackdrop, BottomSheetBody, BottomSheetContent, BottomSheetDescription, BottomSheetFooter, BottomSheetHandle, BottomSheetHeader, BottomSheetPositioner, BottomSheetRoot, BottomSheetTitle, BottomSheetTrigger, Box, Checkbox_namespace_exports as Checkbox, CheckboxControl, CheckboxGroup, CheckboxIndicator, CheckboxLabel, CheckboxRoot, Field_namespace_exports as Field, FieldCharacterCount, FieldDescription, FieldErrorMessage, FieldFooter, FieldHeader, FieldIndicatorText, FieldLabel, FieldRequiredIndicator, FieldRoot, HStack, Icon, KeyboardAvoidingScrollView, PrefixIcon, ProgressCircle_namespace_exports as ProgressCircle, ProgressCircleRange, ProgressCircleRoot, RadioGroup_namespace_exports as RadioGroup, RadioGroupItem, RadioGroupItemControl, RadioGroupItemIndicator, RadioGroupItemLabel, RadioGroupRoot, SuffixIcon, Switch_namespace_exports as Switch, SwitchControl, SwitchLabel, SwitchRoot, SwitchThumb, TagGroup_namespace_exports as TagGroup, TagGroupItem, TagGroupItemLabel, TagGroupRoot, Text, TextField_namespace_exports as TextField, TextFieldInput, TextFieldPrefixIcon, TextFieldPrefixText, TextFieldRoot, TextFieldSuffixIcon, TextFieldSuffixText, TextFieldTextarea, VStack, capitalize, createSlotRecipeContext, getSeedClassName, resolveRecipeToken, splitMultipleVariantsProps, useControllableState, useIconColor, usePressTap, useSafeArea, useSeedClassName, useTextFieldWithGraphemes };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { decodeUnicodeData } from "./core.js";
|
|
2
|
+
//#region ../../node_modules/.bun/unicode-segmenter@0.14.5/node_modules/unicode-segmenter/_grapheme_data.js
|
|
3
|
+
/**
|
|
4
|
+
* @type {GraphemeCategoryRange[]}
|
|
5
|
+
*/
|
|
6
|
+
var grapheme_ranges = decodeUnicodeData(",9,a,,b,1,d,,e,h,3j,w,4p,,4t,,4u,,lc,33,w3,6,13l,18,14v,,14x,1,150,1,153,,16o,5,174,a,17g,,18r,k,19s,,1cm,6,1ct,,1cv,5,1d3,1,1d6,3,1e7,,1e9,,1f4,q,1ie,a,1kb,8,1kt,,1li,3,1ln,8,1lx,2,1m1,4,1nd,2,1ow,1,1p3,8,1qi,n,1r6,,1r7,v,1s3,,1tm,,1tn,,1to,,1tq,2,1tt,7,1u1,3,1u5,,1u6,1,1u9,6,1uq,1,1vl,,1vm,1,1x8,,1xa,,1xb,1,1xd,3,1xj,1,1xn,1,1xp,,1xz,,1ya,1,1z2,,1z5,1,1z7,,20s,,20u,2,20x,1,213,1,217,2,21d,,228,1,22d,,22p,1,22r,,24c,,24e,2,24h,4,24n,1,24p,,24r,1,24t,,25e,1,262,5,269,,26a,1,27w,,27y,1,280,,281,3,287,1,28b,1,28d,,28l,2,28y,1,29u,,2bi,,2bj,,2bk,,2bl,1,2bq,2,2bu,2,2bx,,2c7,,2dc,,2dd,2,2dg,,2f0,,2f2,2,2f5,3,2fa,2,2fe,3,2fp,1,2g2,1,2gx,,2gy,1,2ik,,2im,,2in,1,2ip,,2iq,,2ir,1,2iu,2,2iy,3,2j9,1,2jm,1,2k3,,2kg,1,2ki,1,2m3,1,2m6,,2m7,1,2m9,3,2me,2,2mi,2,2ml,,2mm,,2mv,,2n6,1,2o1,,2o2,1,2q2,,2q7,,2q8,1,2qa,2,2qe,,2qg,6,2qn,,2r6,1,2sx,,2sz,,2t0,6,2tj,7,2wh,,2wj,,2wk,8,2x4,6,2zc,1,305,,307,,309,,30e,1,31t,d,327,,328,4,32e,1,32l,a,32x,z,346,,371,3,375,,376,5,37d,1,37f,1,37h,1,386,1,388,1,38e,2,38x,3,39e,,39g,,39h,1,39p,,3a5,,3cw,2n,3fk,1z,3hk,2f,3tp,2,4k2,3,4ky,2,4lu,1,4mq,1,4ok,1,4om,,4on,6,4ou,7,4p2,,4p3,1,4p5,a,4pp,,4qz,2,4r2,,4r3,,4ud,1,4vd,,4yo,2,4yr,3,4yv,1,4yx,2,4z4,1,4z6,,4z7,5,4zd,2,55j,1,55l,1,55n,,579,,57a,,57b,,57c,6,57k,,57m,,57p,7,57x,5,583,9,58f,,59s,u,5c0,3,5c4,,5dg,9,5dq,3,5du,2,5ez,8,5fk,1,5fm,,5gh,,5gi,3,5gm,1,5go,5,5ie,,5if,,5ig,1,5ii,2,5il,,5im,,5in,4,5k4,7,5kc,7,5kk,1,5km,1,5ow,2,5p0,c,5pd,,5pe,6,5pp,,5pw,,5pz,,5q0,1,5vk,1r,6bv,,6bw,,6bx,,6by,1,6co,6,6d8,,6dl,,6e8,f,6hc,w,6jm,,6k9,,6ms,5,6nd,1,6xm,1,6y0,,70o,,72n,,73d,a,73s,2,79e,,7fu,1,7g6,,7gg,,7i3,3,7i8,5,7if,b,7is,35,7m8,39,7pk,a,7pw,,7py,,7q5,,7q9,,7qg,,7qr,1,7r8,,7rb,,7rg,,7ri,,7rn,2,7rr,,7s3,4,7th,2,7tt,,7u8,,7un,,850,1,8hx,2,8ij,1,8k0,,8k5,,8vj,2,8zj,,928,v,wvj,3,wvo,9,wwu,1,wz4,1,x6q,,x6u,,x6z,,x7n,1,x7p,1,x7r,,x7w,,xa8,1,xbo,f,xc4,1,xcw,h,xdr,,xeu,7,xfr,a,xg2,,xg3,,xgg,s,xhc,2,xhf,,xir,,xis,1,xiu,3,xiy,1,xj0,1,xj2,1,xj4,,xk5,,xm1,5,xm7,1,xm9,1,xmb,1,xmd,1,xmr,,xn0,,xn1,,xoc,,xps,,xpu,2,xpz,1,xq6,1,xq9,,xrf,,xrg,1,xri,1,xrp,,xrq,,xyb,1,xyd,,xye,1,xyg,,xyh,1,xyk,,xyl,,1e68,f,1e74,f,1edb,,1ehq,1,1ek0,b,1eyl,,1f4w,,1f92,4,1gjl,2,1gjp,1,1gjw,3,1gl4,2,1glb,,1gpx,1,1h5w,3,1h7t,4,1hgr,1,1hj0,3,1hl2,a,1hmq,3,1hq8,,1hq9,,1hqa,,1hrs,e,1htc,,1htf,1,1htr,2,1htu,,1hv4,2,1hv7,3,1hvb,1,1hvd,1,1hvh,,1hvm,,1hvx,,1hxc,2,1hyf,4,1hyk,,1hyl,7,1hz9,1,1i0j,,1i0w,1,1i0y,,1i2b,2,1i2e,8,1i2n,,1i2o,,1i2q,1,1i2x,3,1i32,,1i33,,1i5o,2,1i5r,2,1i5u,1,1i5w,3,1i66,,1i69,,1ian,,1iao,2,1iar,7,1ibk,1,1ibm,1,1id7,1,1ida,,1idb,,1idc,,1idd,3,1idj,1,1idn,1,1idp,,1idz,,1iea,1,1iee,6,1ieo,4,1igo,,1igp,1,1igr,5,1igy,,1ih1,,1ih3,2,1ih6,,1ih8,1,1iha,2,1ihd,,1ihe,,1iht,1,1ik5,2,1ik8,7,1ikg,1,1iki,2,1ikl,,1ikm,,1ila,,1ink,,1inl,1,1inn,5,1int,,1inu,,1inv,1,1inx,,1iny,,1inz,1,1io1,,1io2,1,1iun,,1iuo,1,1iuq,3,1iuw,3,1iv0,1,1iv2,,1iv3,1,1ivw,1,1iy8,2,1iyb,7,1iyj,1,1iyl,,1iym,,1iyn,1,1j1n,,1j1o,,1j1p,,1j1q,1,1j1s,7,1j4t,,1j4u,,1j4v,,1j4y,3,1j52,,1j53,4,1jcc,2,1jcf,8,1jco,,1jcp,1,1jjk,,1jjl,4,1jjr,1,1jjv,3,1jjz,,1jk0,,1jk1,,1jk2,,1jk3,,1jo1,2,1jo4,3,1joa,1,1joc,3,1jog,,1jok,,1jpd,9,1jqr,5,1jqx,,1jqy,,1jqz,3,1jrb,,1jrl,5,1jrr,1,1jrt,2,1jt0,5,1jt6,c,1jtj,,1jtk,1,1k4v,,1k4w,6,1k54,5,1k5a,,1k5b,,1k7m,l,1k89,,1k8a,6,1k8h,,1k8i,1,1k8k,,1k8l,1,1kc1,5,1kca,,1kcc,1,1kcf,6,1kcm,,1kcn,,1kei,4,1keo,1,1ker,1,1ket,,1keu,,1kev,,1koj,1,1kol,1,1kow,1,1koy,,1koz,,1kqc,1,1kqe,4,1kqm,1,1kqo,2,1kre,,1ovk,f,1ow0,,1ow7,e,1xr2,b,1xre,2,1xrh,2,1zow,4,1zqo,6,206b,,206f,3,20jz,,20k1,1i,20lr,3,20o4,,20og,1,2ftp,1,2fts,3,2jgg,19,2jhs,m,2jxh,4,2jxp,5,2jxv,7,2jy3,7,2jyd,6,2jze,3,2k3m,2,2lmo,1i,2lob,1d,2lpx,,2lqc,,2lqz,4,2lr5,e,2mtc,6,2mtk,g,2mu3,6,2mub,1,2mue,4,2mxb,,2n1s,6,2nce,,2ne4,3,2nsc,3,2nzi,1,2ok0,6,2on8,6,2pz4,73,2q6l,2,2q7j,,2q98,5,2q9q,1,2qa6,,2qa9,9,2qb1,1k,2qcm,p,2qdd,e,2qe2,,2qen,,2qeq,8,2qf0,3,2qfd,c1,2qrf,4,2qrk,8t,2r0m,7d,2r9c,3j,2rg4,b,2rit,16,2rkc,3,2rm0,7,2rmi,5,2rns,7,2rou,29,2rrg,1a,2rss,9,2rt3,c8,2scg,sd,jny8,v,jnz4,2n,jo1s,3j,jo5c,6n,joc0,2rz", "262122424333333393233393339333333333393393b3b3b3b3b333b33b3bb33333b3b3333333b3b33bb3333b33b3bb33333b3bbb333b333b33333b3b3b3b3333b3b33b3bb39333b33b33b3b3b333b333333b3b333333b33b3b3333b3335dc333333b3b3b33323333b3bb3b33b3b3b3333b3333b3b333bb3b33b3b3b3b3b333b333b3323e2244234444444444444444444444444444444444444444443333333333b3b3bb33333b353b3b3b3b333b3b333b333333b3bb3b3b3bb333232333333333333333b3b3333bb3b393933b3b33bb3b393b3b3b3333b33b33b3bbb33b333b3333bb3933b3b3b333b3b3b3b3b33b3b3b33b3b3b33b3b33b33b3b3b33bb39b9b3b33b3b33b9333b393b3b33b33b3b3b3333393b3b3b33b39bb3b332333b333dd3b33332333323333333333333333333333344444444a44444434444444444444423232");
|
|
7
|
+
//#endregion
|
|
8
|
+
export { grapheme_ranges };
|