@particle-network/ui-native 0.0.2

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 (168) hide show
  1. package/README.md +57 -0
  2. package/dist/components/ProgressWrapper/index.d.ts +35 -0
  3. package/dist/components/ProgressWrapper/index.js +120 -0
  4. package/dist/components/Text/index.d.ts +2 -0
  5. package/dist/components/Text/index.js +2 -0
  6. package/dist/components/Text/text.d.ts +4 -0
  7. package/dist/components/Text/text.js +196 -0
  8. package/dist/components/Text/text.types.d.ts +109 -0
  9. package/dist/components/Text/text.types.js +77 -0
  10. package/dist/components/UXButton/button.d.ts +3 -0
  11. package/dist/components/UXButton/button.js +74 -0
  12. package/dist/components/UXButton/button.styles.d.ts +53 -0
  13. package/dist/components/UXButton/button.styles.js +157 -0
  14. package/dist/components/UXButton/button.types.d.ts +18 -0
  15. package/dist/components/UXButton/button.types.js +0 -0
  16. package/dist/components/UXButton/index.d.ts +2 -0
  17. package/dist/components/UXButton/index.js +1 -0
  18. package/dist/components/UXCheckbox/checkbox-group.d.ts +8 -0
  19. package/dist/components/UXCheckbox/checkbox-group.js +30 -0
  20. package/dist/components/UXCheckbox/checkbox.d.ts +10 -0
  21. package/dist/components/UXCheckbox/checkbox.js +78 -0
  22. package/dist/components/UXCheckbox/context.d.ts +8 -0
  23. package/dist/components/UXCheckbox/context.js +8 -0
  24. package/dist/components/UXCheckbox/index.d.ts +4 -0
  25. package/dist/components/UXCheckbox/index.js +3 -0
  26. package/dist/components/UXCheckbox/types.d.ts +6 -0
  27. package/dist/components/UXCheckbox/types.js +0 -0
  28. package/dist/components/UXChip/chip.d.ts +3 -0
  29. package/dist/components/UXChip/chip.js +48 -0
  30. package/dist/components/UXChip/index.d.ts +2 -0
  31. package/dist/components/UXChip/index.js +1 -0
  32. package/dist/components/UXChip/styles.d.ts +24 -0
  33. package/dist/components/UXChip/styles.js +70 -0
  34. package/dist/components/UXChip/types.d.ts +11 -0
  35. package/dist/components/UXChip/types.js +0 -0
  36. package/dist/components/UXDivider/index.d.ts +8 -0
  37. package/dist/components/UXDivider/index.js +34 -0
  38. package/dist/components/UXHint/index.d.ts +7 -0
  39. package/dist/components/UXHint/index.js +19 -0
  40. package/dist/components/UXModal/index.d.ts +24 -0
  41. package/dist/components/UXModal/index.js +271 -0
  42. package/dist/components/UXPressable/index.d.ts +4 -0
  43. package/dist/components/UXPressable/index.js +36 -0
  44. package/dist/components/UXRadio/context.d.ts +7 -0
  45. package/dist/components/UXRadio/context.js +10 -0
  46. package/dist/components/UXRadio/index.d.ts +2 -0
  47. package/dist/components/UXRadio/index.js +2 -0
  48. package/dist/components/UXRadio/radio-group.d.ts +5 -0
  49. package/dist/components/UXRadio/radio-group.js +21 -0
  50. package/dist/components/UXRadio/radio.d.ts +5 -0
  51. package/dist/components/UXRadio/radio.js +67 -0
  52. package/dist/components/UXRadio/types.d.ts +10 -0
  53. package/dist/components/UXRadio/types.js +0 -0
  54. package/dist/components/UXSwitch/index.d.ts +2 -0
  55. package/dist/components/UXSwitch/index.js +1 -0
  56. package/dist/components/UXSwitch/styles.d.ts +16 -0
  57. package/dist/components/UXSwitch/styles.js +58 -0
  58. package/dist/components/UXSwitch/switch.d.ts +3 -0
  59. package/dist/components/UXSwitch/switch.js +103 -0
  60. package/dist/components/UXSwitch/types.d.ts +11 -0
  61. package/dist/components/UXSwitch/types.js +0 -0
  62. package/dist/components/UXTabs/context.d.ts +5 -0
  63. package/dist/components/UXTabs/context.js +8 -0
  64. package/dist/components/UXTabs/index.d.ts +4 -0
  65. package/dist/components/UXTabs/index.js +3 -0
  66. package/dist/components/UXTabs/styles.d.ts +30 -0
  67. package/dist/components/UXTabs/styles.js +191 -0
  68. package/dist/components/UXTabs/tab.d.ts +3 -0
  69. package/dist/components/UXTabs/tab.js +55 -0
  70. package/dist/components/UXTabs/tabs.d.ts +3 -0
  71. package/dist/components/UXTabs/tabs.js +66 -0
  72. package/dist/components/UXTabs/types.d.ts +23 -0
  73. package/dist/components/UXTabs/types.js +0 -0
  74. package/dist/components/UXTooltip/index.d.ts +6 -0
  75. package/dist/components/UXTooltip/index.js +32 -0
  76. package/dist/components/UXTouchableOpacity/index.d.ts +4 -0
  77. package/dist/components/UXTouchableOpacity/index.js +24 -0
  78. package/dist/components/index.d.ts +22 -0
  79. package/dist/components/index.js +22 -0
  80. package/dist/components/input/index.d.ts +3 -0
  81. package/dist/components/input/index.js +2 -0
  82. package/dist/components/input/input.d.ts +3 -0
  83. package/dist/components/input/input.js +138 -0
  84. package/dist/components/input/number-input.d.ts +3 -0
  85. package/dist/components/input/number-input.js +231 -0
  86. package/dist/components/input/styles.d.ts +31 -0
  87. package/dist/components/input/styles.js +102 -0
  88. package/dist/components/input/types.d.ts +61 -0
  89. package/dist/components/input/types.js +0 -0
  90. package/dist/components/layout/Box/box.d.ts +12 -0
  91. package/dist/components/layout/Box/box.js +89 -0
  92. package/dist/components/layout/Box/index.d.ts +3 -0
  93. package/dist/components/layout/Box/index.js +2 -0
  94. package/dist/components/layout/Box/useBox.style.d.ts +3 -0
  95. package/dist/components/layout/Box/useBox.style.js +141 -0
  96. package/dist/components/layout/Box/useBox.type.d.ts +292 -0
  97. package/dist/components/layout/Box/useBox.type.js +0 -0
  98. package/dist/components/layout/Center.d.ts +5 -0
  99. package/dist/components/layout/Center.js +10 -0
  100. package/dist/components/layout/Circle.d.ts +7 -0
  101. package/dist/components/layout/Circle.js +14 -0
  102. package/dist/components/layout/Flex/flex.d.ts +6 -0
  103. package/dist/components/layout/Flex/flex.js +33 -0
  104. package/dist/components/layout/Flex/index.d.ts +4 -0
  105. package/dist/components/layout/Flex/index.js +3 -0
  106. package/dist/components/layout/Flex/useFlex.style.d.ts +3 -0
  107. package/dist/components/layout/Flex/useFlex.style.js +122 -0
  108. package/dist/components/layout/Flex/useFlex.type.d.ts +65 -0
  109. package/dist/components/layout/Flex/useFlex.type.js +0 -0
  110. package/dist/components/layout/Flex/useFlexBox.style.d.ts +134 -0
  111. package/dist/components/layout/Flex/useFlexBox.style.js +26 -0
  112. package/dist/components/layout/HStack.d.ts +5 -0
  113. package/dist/components/layout/HStack.js +11 -0
  114. package/dist/components/layout/Square.d.ts +9 -0
  115. package/dist/components/layout/Square.js +14 -0
  116. package/dist/components/layout/VStack.d.ts +5 -0
  117. package/dist/components/layout/VStack.js +14 -0
  118. package/dist/hooks/index.d.ts +5 -0
  119. package/dist/hooks/index.js +5 -0
  120. package/dist/hooks/useColors.d.ts +7 -0
  121. package/dist/hooks/useColors.js +18 -0
  122. package/dist/hooks/useKeyboard.d.ts +4 -0
  123. package/dist/hooks/useKeyboard.js +29 -0
  124. package/dist/hooks/useRadius.d.ts +7 -0
  125. package/dist/hooks/useRadius.js +16 -0
  126. package/dist/hooks/useSpacing.d.ts +7 -0
  127. package/dist/hooks/useSpacing.js +16 -0
  128. package/dist/hooks/useTheme.d.ts +5 -0
  129. package/dist/hooks/useTheme.js +6 -0
  130. package/dist/icons/CheckboxOffIcon.d.ts +4 -0
  131. package/dist/icons/CheckboxOffIcon.js +21 -0
  132. package/dist/icons/CheckboxOnIcon.d.ts +4 -0
  133. package/dist/icons/CheckboxOnIcon.js +26 -0
  134. package/dist/icons/DotIcon.d.ts +4 -0
  135. package/dist/icons/DotIcon.js +23 -0
  136. package/dist/icons/QuestionIcon.d.ts +4 -0
  137. package/dist/icons/QuestionIcon.js +30 -0
  138. package/dist/icons/RadioOffIcon.d.ts +4 -0
  139. package/dist/icons/RadioOffIcon.js +22 -0
  140. package/dist/icons/RadioOnIcon.d.ts +4 -0
  141. package/dist/icons/RadioOnIcon.js +42 -0
  142. package/dist/icons/types.d.ts +6 -0
  143. package/dist/icons/types.js +0 -0
  144. package/dist/index.d.ts +5 -0
  145. package/dist/index.js +4 -0
  146. package/dist/provider/ThemeContext.d.ts +3 -0
  147. package/dist/provider/ThemeContext.js +15 -0
  148. package/dist/provider/ThemeProvider.d.ts +10 -0
  149. package/dist/provider/ThemeProvider.js +31 -0
  150. package/dist/provider/index.d.ts +2 -0
  151. package/dist/provider/index.js +2 -0
  152. package/dist/theme/colors.d.ts +6 -0
  153. package/dist/theme/colors.js +17 -0
  154. package/dist/theme/index.d.ts +7 -0
  155. package/dist/theme/index.js +16 -0
  156. package/dist/theme/opacity.d.ts +2 -0
  157. package/dist/theme/opacity.js +3 -0
  158. package/dist/theme/radius.d.ts +3 -0
  159. package/dist/theme/radius.js +10 -0
  160. package/dist/theme/spacing.d.ts +3 -0
  161. package/dist/theme/spacing.js +10 -0
  162. package/dist/types/index.d.ts +1 -0
  163. package/dist/types/index.js +0 -0
  164. package/dist/types/theme.d.ts +17 -0
  165. package/dist/types/theme.js +0 -0
  166. package/dist/utils/triggerHapticFeedback.d.ts +5 -0
  167. package/dist/utils/triggerHapticFeedback.js +16 -0
  168. package/package.json +110 -0
@@ -0,0 +1,138 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
3
+ import { TextInput } from "react-native";
4
+ import { HStack, Text, VStack } from "../index.js";
5
+ import { useColors } from "../../hooks/index.js";
6
+ import { useStyles } from "./styles.js";
7
+ const UXInput = /*#__PURE__*/ forwardRef((props, ref)=>{
8
+ const { containerStyle, wrapperStyle, inputStyle, value: controlledValue, defaultValue, errorMessage, startContent, endContent, isReadOnly, isDisabled, isRequired, isInvalid: isInvalidProp, autoErrorMessage, label, onChangeText, onValueChange, onFocus, onBlur, ...restProps } = props;
9
+ const { getColor } = useColors();
10
+ const inputRef = useRef(null);
11
+ const [internalValue, setInternalValue] = useState(defaultValue);
12
+ const [isFocused, setIsFocused] = useState(false);
13
+ const [isInvalid, setIsInvalid] = useState(isInvalidProp);
14
+ useImperativeHandle(ref, ()=>({
15
+ blur: ()=>{
16
+ inputRef.current?.blur();
17
+ },
18
+ focus: ()=>{
19
+ inputRef.current?.focus();
20
+ }
21
+ }));
22
+ useEffect(()=>{
23
+ setIsInvalid(isInvalidProp);
24
+ }, [
25
+ isInvalidProp
26
+ ]);
27
+ useEffect(()=>{
28
+ if (!internalValue && isRequired) setIsInvalid(true);
29
+ }, []);
30
+ const styles = useStyles({
31
+ ...props,
32
+ isInvalid,
33
+ isFocused
34
+ });
35
+ useEffect(()=>{
36
+ if (void 0 !== controlledValue) setInternalValue(controlledValue);
37
+ else if (void 0 !== defaultValue) setInternalValue(defaultValue);
38
+ }, [
39
+ defaultValue,
40
+ controlledValue
41
+ ]);
42
+ const handleFocus = useCallback((e)=>{
43
+ setIsFocused(true);
44
+ onFocus?.(e);
45
+ }, [
46
+ onFocus
47
+ ]);
48
+ const handleBlur = useCallback((e)=>{
49
+ setIsFocused(false);
50
+ onBlur?.(e);
51
+ }, [
52
+ onBlur
53
+ ]);
54
+ const validationResult = useMemo(()=>{
55
+ if (!internalValue && isRequired) {
56
+ setIsInvalid(true);
57
+ return {
58
+ isValid: false,
59
+ errorMessage: 'This field is required'
60
+ };
61
+ }
62
+ setIsInvalid(false);
63
+ return {
64
+ isValid: true
65
+ };
66
+ }, [
67
+ internalValue,
68
+ isRequired
69
+ ]);
70
+ const renderError = useMemo(async ()=>{
71
+ if (isInvalidProp && errorMessage) {
72
+ setIsInvalid(true);
73
+ return errorMessage;
74
+ }
75
+ if (!validationResult.isValid) return autoErrorMessage ? validationResult.errorMessage : null;
76
+ return null;
77
+ }, [
78
+ validationResult,
79
+ errorMessage,
80
+ isInvalidProp,
81
+ autoErrorMessage
82
+ ]);
83
+ const renderContent = async (content)=>{
84
+ if (!content) return null;
85
+ if ('object' == typeof content) return content;
86
+ return /*#__PURE__*/ jsx(Text, {
87
+ color: "tertiary",
88
+ children: content
89
+ });
90
+ };
91
+ return /*#__PURE__*/ jsxs(VStack, {
92
+ gap: 4,
93
+ style: containerStyle,
94
+ children: [
95
+ label ? /*#__PURE__*/ jsx(Text, {
96
+ children: label
97
+ }) : null,
98
+ /*#__PURE__*/ jsxs(HStack, {
99
+ borderStyle: "solid",
100
+ gap: 6,
101
+ ph: 12,
102
+ style: [
103
+ styles.container,
104
+ wrapperStyle
105
+ ],
106
+ children: [
107
+ renderContent(startContent),
108
+ /*#__PURE__*/ jsx(TextInput, {
109
+ ref: inputRef,
110
+ editable: !isDisabled && !isReadOnly,
111
+ placeholderTextColor: getColor('tertiary'),
112
+ selectionColor: isInvalid ? `${styles.container.borderColor}80` : styles.container.borderColor,
113
+ style: [
114
+ styles.input,
115
+ inputStyle
116
+ ],
117
+ value: internalValue,
118
+ onBlur: handleBlur,
119
+ onChangeText: (v)=>{
120
+ setInternalValue(v);
121
+ onChangeText?.(v);
122
+ onValueChange?.(v);
123
+ },
124
+ onFocus: handleFocus,
125
+ ...restProps
126
+ }),
127
+ renderContent(endContent)
128
+ ]
129
+ }),
130
+ !!renderError && /*#__PURE__*/ jsx(Text, {
131
+ color: "danger",
132
+ children: renderError
133
+ })
134
+ ]
135
+ });
136
+ });
137
+ UXInput.displayName = 'UXInput';
138
+ export { UXInput };
@@ -0,0 +1,3 @@
1
+ import React from 'react';
2
+ import type { UXInputRef, UXNumberInputProps } from './types';
3
+ export declare const UXNumberInput: React.ForwardRefExoticComponent<UXNumberInputProps & React.RefAttributes<UXInputRef>>;
@@ -0,0 +1,231 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
3
+ import { Platform, TextInput } from "react-native";
4
+ import { HStack, Text, VStack } from "../index.js";
5
+ import { useColors } from "../../hooks/index.js";
6
+ import { useStyles } from "./styles.js";
7
+ const UXNumberInput = /*#__PURE__*/ forwardRef((props, ref)=>{
8
+ const { containerStyle, wrapperStyle, inputStyle, value: controlledValue, defaultValue, errorMessage, minValue, maxValue, formatOptions, startContent, endContent, isRequired, isReadOnly, isDisabled, isInvalid: isInvalidProp, autoErrorMessage, allowNegative, label, onChangeText, onValueChange, onFocus, onBlur, ...restProps } = props;
9
+ const { getColor } = useColors();
10
+ const inputRef = useRef(null);
11
+ const [internalValue, setInternalValue] = useState(defaultValue ?? NaN);
12
+ const [displayText, setDisplayText] = useState(defaultValue?.toString() ?? '');
13
+ const [isFocused, setIsFocused] = useState(false);
14
+ const [isInvalid, setIsInvalid] = useState(isInvalidProp);
15
+ useImperativeHandle(ref, ()=>({
16
+ blur: ()=>{
17
+ inputRef.current?.blur();
18
+ },
19
+ focus: ()=>{
20
+ inputRef.current?.focus();
21
+ }
22
+ }));
23
+ useEffect(()=>{
24
+ setIsInvalid(isInvalidProp);
25
+ }, [
26
+ isInvalidProp
27
+ ]);
28
+ useEffect(()=>{
29
+ if (isNaN(internalValue) && isRequired) setIsInvalid(true);
30
+ if (void 0 !== minValue && internalValue < minValue) setIsInvalid(true);
31
+ if (void 0 !== maxValue && internalValue > maxValue) setIsInvalid(true);
32
+ }, []);
33
+ const styles = useStyles({
34
+ ...props,
35
+ isInvalid,
36
+ isFocused
37
+ });
38
+ useEffect(()=>{
39
+ if (void 0 !== controlledValue) {
40
+ setInternalValue(controlledValue);
41
+ setDisplayText(isNaN(controlledValue) ? '' : controlledValue.toString());
42
+ } else if (void 0 !== defaultValue) {
43
+ setInternalValue(defaultValue);
44
+ setDisplayText(isNaN(defaultValue) ? '' : defaultValue.toString());
45
+ }
46
+ }, [
47
+ defaultValue,
48
+ controlledValue
49
+ ]);
50
+ const numberFormatter = useMemo(()=>{
51
+ if (formatOptions) return new Intl.NumberFormat(void 0, formatOptions);
52
+ return null;
53
+ }, [
54
+ formatOptions
55
+ ]);
56
+ const validationResult = useMemo(()=>{
57
+ if (isNaN(internalValue) && isRequired) return {
58
+ isValid: false,
59
+ errorMessage: 'This field is required'
60
+ };
61
+ if (void 0 !== minValue && internalValue < minValue) return {
62
+ isValid: false,
63
+ errorMessage: `Value must be at least ${minValue}`
64
+ };
65
+ if (void 0 !== maxValue && internalValue > maxValue) return {
66
+ isValid: false,
67
+ errorMessage: `Value must be at most ${maxValue}`
68
+ };
69
+ setIsInvalid(false);
70
+ return {
71
+ isValid: true
72
+ };
73
+ }, [
74
+ internalValue,
75
+ isRequired,
76
+ minValue,
77
+ maxValue
78
+ ]);
79
+ const adjustValueToRange = useCallback((num)=>{
80
+ const numValue = isNaN(num) ? 0 : num;
81
+ if (void 0 !== minValue && numValue < minValue) return minValue;
82
+ if (void 0 !== maxValue && numValue > maxValue) return maxValue;
83
+ return numValue;
84
+ }, [
85
+ minValue,
86
+ maxValue
87
+ ]);
88
+ const adjustValueToFractionDigits = useCallback((numValue)=>{
89
+ if (formatOptions?.minimumFractionDigits !== void 0 || formatOptions?.maximumFractionDigits !== void 0) return Number(numberFormatter?.format(numValue).replaceAll(',', ''));
90
+ return numValue;
91
+ }, [
92
+ formatOptions,
93
+ numberFormatter
94
+ ]);
95
+ const handleChangeText = useCallback((text)=>{
96
+ const cleanedText = text.replace(/[^0-9.-]/gu, '');
97
+ const parts = cleanedText.split('.');
98
+ if (parts.length > 2) return;
99
+ if ((cleanedText.match(/-/gu) || []).length > 1) return;
100
+ if (cleanedText.includes('-') && !cleanedText.startsWith('-')) return;
101
+ setDisplayText(cleanedText);
102
+ onChangeText?.(cleanedText);
103
+ const numValue = parseFloat(cleanedText);
104
+ if (isNaN(numValue)) {
105
+ setInternalValue(NaN);
106
+ onValueChange?.(NaN);
107
+ } else {
108
+ setInternalValue(numValue);
109
+ onValueChange?.(numValue);
110
+ }
111
+ }, [
112
+ onChangeText,
113
+ onValueChange
114
+ ]);
115
+ const handleFocus = useCallback((e)=>{
116
+ setIsFocused(true);
117
+ onFocus?.(e);
118
+ }, [
119
+ onFocus
120
+ ]);
121
+ const handleBlur = useCallback((e)=>{
122
+ setIsFocused(false);
123
+ const adjustedValue = adjustValueToFractionDigits(adjustValueToRange(internalValue));
124
+ if (adjustedValue !== internalValue) {
125
+ const adjustedText = adjustedValue.toString();
126
+ setDisplayText(adjustedText);
127
+ setInternalValue(adjustedValue);
128
+ onChangeText?.(adjustedText);
129
+ onValueChange?.(adjustedValue);
130
+ }
131
+ onBlur?.(e);
132
+ }, [
133
+ internalValue,
134
+ onChangeText,
135
+ onValueChange,
136
+ adjustValueToRange,
137
+ adjustValueToFractionDigits,
138
+ onBlur
139
+ ]);
140
+ const displayValue = useMemo(()=>{
141
+ if (isFocused) return displayText;
142
+ if (isNaN(internalValue)) return '';
143
+ if (numberFormatter) {
144
+ const formattedValue = numberFormatter.format(internalValue);
145
+ if (formatOptions?.signDisplay === 'exceptZero' || formatOptions?.signDisplay === 'always') {
146
+ if (internalValue > 0) return `+${formattedValue}`;
147
+ else if (internalValue < 0) ;
148
+ else if ('always' === formatOptions.signDisplay) return `+${formattedValue}`;
149
+ }
150
+ return formattedValue;
151
+ }
152
+ return internalValue.toString();
153
+ }, [
154
+ internalValue,
155
+ displayText,
156
+ numberFormatter,
157
+ isFocused,
158
+ formatOptions
159
+ ]);
160
+ const renderError = useMemo(async ()=>{
161
+ if (isInvalidProp && errorMessage) {
162
+ setIsInvalid(true);
163
+ return errorMessage;
164
+ }
165
+ if (!validationResult.isValid) return autoErrorMessage ? validationResult.errorMessage : null;
166
+ return null;
167
+ }, [
168
+ validationResult,
169
+ errorMessage,
170
+ isInvalidProp,
171
+ autoErrorMessage
172
+ ]);
173
+ const keyboardType = useMemo(()=>{
174
+ if (allowNegative) return 'ios' === Platform.OS ? 'numbers-and-punctuation' : 'default';
175
+ return 'numeric';
176
+ }, [
177
+ allowNegative
178
+ ]);
179
+ const renderContent = async (content)=>{
180
+ if (!content) return null;
181
+ if ('object' == typeof content) return content;
182
+ return /*#__PURE__*/ jsx(Text, {
183
+ color: "tertiary",
184
+ children: content
185
+ });
186
+ };
187
+ return /*#__PURE__*/ jsxs(VStack, {
188
+ gap: 4,
189
+ style: containerStyle,
190
+ children: [
191
+ label ? /*#__PURE__*/ jsx(Text, {
192
+ children: label
193
+ }) : null,
194
+ /*#__PURE__*/ jsxs(HStack, {
195
+ borderStyle: "solid",
196
+ gap: 6,
197
+ ph: 12,
198
+ style: [
199
+ styles.container,
200
+ wrapperStyle
201
+ ],
202
+ children: [
203
+ renderContent(startContent),
204
+ /*#__PURE__*/ jsx(TextInput, {
205
+ ref: inputRef,
206
+ editable: !isDisabled && !isReadOnly,
207
+ keyboardType: keyboardType,
208
+ placeholderTextColor: getColor('tertiary'),
209
+ selectionColor: isInvalid ? `${styles.container.borderColor}80` : styles.container.borderColor,
210
+ style: [
211
+ styles.input,
212
+ inputStyle
213
+ ],
214
+ value: displayValue,
215
+ onBlur: handleBlur,
216
+ onChangeText: handleChangeText,
217
+ onFocus: handleFocus,
218
+ ...restProps
219
+ }),
220
+ renderContent(endContent)
221
+ ]
222
+ }),
223
+ !!renderError && /*#__PURE__*/ jsx(Text, {
224
+ color: "danger",
225
+ children: renderError
226
+ })
227
+ ]
228
+ });
229
+ });
230
+ UXNumberInput.displayName = 'UXNumberInput';
231
+ export { UXNumberInput };
@@ -0,0 +1,31 @@
1
+ import type { UXInputCommonProps } from './types';
2
+ type UseStylesProps = UXInputCommonProps & {
3
+ isFocused?: boolean;
4
+ };
5
+ export declare const useStyles: ({ isInvalid, isDisabled, fullWidth, isFocused, color, size, variant, radius, width: widthProp, textAlign, }: UseStylesProps) => {
6
+ container: {
7
+ width: number | "auto" | `${number}%` | import("react-native").Animated.AnimatedNode;
8
+ height: number;
9
+ borderRadius: number | undefined;
10
+ borderColor: string | undefined;
11
+ backgroundColor: string | undefined;
12
+ borderWidth: number;
13
+ opacity: number;
14
+ };
15
+ input: {
16
+ flex: number;
17
+ paddingTop: number;
18
+ paddingBottom: number;
19
+ paddingLeft: number;
20
+ paddingRight: number;
21
+ margin: number;
22
+ fontSize: number;
23
+ color: string | undefined;
24
+ fontWeight: "500";
25
+ textAlign: "left" | "center" | "right";
26
+ };
27
+ clearButton: {
28
+ padding: number;
29
+ };
30
+ };
31
+ export {};
@@ -0,0 +1,102 @@
1
+ import { useMemo } from "react";
2
+ import { StyleSheet } from "react-native";
3
+ import { ms } from "react-native-size-matters";
4
+ import { sizeMap } from "@particle-network/ui-shared";
5
+ import { useColors, useRadius } from "../../hooks/index.js";
6
+ import { disabledOpacity } from "../../theme/index.js";
7
+ const fontSizeMap = {
8
+ sm: ms(12),
9
+ md: ms(12),
10
+ lg: ms(14)
11
+ };
12
+ const radiusMap = {
13
+ sm: 'sm',
14
+ md: 'sm',
15
+ lg: 'md'
16
+ };
17
+ const useStyles = ({ isInvalid, isDisabled, fullWidth, isFocused, color = 'primary', size = 'md', variant = 'flat', radius, width: widthProp, textAlign = 'left' })=>{
18
+ const { getColor } = useColors();
19
+ const { getRadius } = useRadius();
20
+ const width = useMemo(()=>{
21
+ if (fullWidth) return '100%';
22
+ if (widthProp) return widthProp;
23
+ return 'auto';
24
+ }, [
25
+ fullWidth,
26
+ widthProp
27
+ ]);
28
+ const height = useMemo(()=>ms(sizeMap[size]), [
29
+ size
30
+ ]);
31
+ const fontSize = useMemo(()=>fontSizeMap[size], [
32
+ size
33
+ ]);
34
+ const borderRadius = useMemo(()=>getRadius(radius ?? radiusMap[size]), [
35
+ radius,
36
+ size
37
+ ]);
38
+ const borderColor = useMemo(()=>{
39
+ if (isInvalid) return getColor('danger');
40
+ if (isFocused) return getColor(color);
41
+ if ('bordered' === variant) return getColor(color);
42
+ return 'transparent';
43
+ }, [
44
+ color,
45
+ getColor,
46
+ variant,
47
+ isFocused,
48
+ isInvalid
49
+ ]);
50
+ const inputTextColor = useMemo(()=>{
51
+ if (isInvalid) return getColor('danger');
52
+ return getColor('foreground');
53
+ }, [
54
+ isInvalid,
55
+ getColor
56
+ ]);
57
+ const backgroundColor = useMemo(()=>{
58
+ if (isInvalid) return `${getColor('danger')}50`;
59
+ return getColor('bg-200');
60
+ }, [
61
+ isInvalid,
62
+ getColor
63
+ ]);
64
+ const styles = useMemo(()=>StyleSheet.create({
65
+ container: {
66
+ width,
67
+ height,
68
+ borderRadius,
69
+ borderColor,
70
+ backgroundColor,
71
+ borderWidth: 1,
72
+ opacity: isDisabled ? disabledOpacity : 1
73
+ },
74
+ input: {
75
+ flex: 1,
76
+ paddingTop: 0,
77
+ paddingBottom: 0,
78
+ paddingLeft: 0,
79
+ paddingRight: 0,
80
+ margin: 0,
81
+ fontSize,
82
+ color: inputTextColor,
83
+ fontWeight: '500',
84
+ textAlign
85
+ },
86
+ clearButton: {
87
+ padding: ms(4)
88
+ }
89
+ }), [
90
+ width,
91
+ height,
92
+ borderRadius,
93
+ borderColor,
94
+ isDisabled,
95
+ fontSize,
96
+ inputTextColor,
97
+ textAlign,
98
+ backgroundColor
99
+ ]);
100
+ return styles;
101
+ };
102
+ export { useStyles };
@@ -0,0 +1,61 @@
1
+ import type { ReactNode } from 'react';
2
+ import type { StyleProp, TextInputProps, TextStyle, ViewStyle } from 'react-native';
3
+ import type { UXForegroundColor, UXRadius, UXSize } from '@particle-network/ui-shared';
4
+ export interface UXInputRef {
5
+ blur: () => void;
6
+ focus: () => void;
7
+ }
8
+ export interface ValidationResult {
9
+ isValid: boolean;
10
+ errorMessage?: string;
11
+ }
12
+ export interface UXInputCommonProps extends Omit<TextInputProps, 'value' | 'defaultValue'> {
13
+ /**
14
+ * 最外层容器,包括 label 和 error
15
+ */
16
+ containerStyle?: StyleProp<ViewStyle>;
17
+ /**
18
+ * 输入框容器
19
+ */
20
+ wrapperStyle?: StyleProp<ViewStyle>;
21
+ /**
22
+ * 输入框样式
23
+ */
24
+ inputStyle?: StyleProp<TextStyle>;
25
+ color?: UXForegroundColor;
26
+ size?: UXSize;
27
+ variant?: 'bordered' | 'flat';
28
+ radius?: UXRadius;
29
+ width?: ViewStyle['width'];
30
+ errorMessage?: ReactNode;
31
+ startContent?: ReactNode;
32
+ endContent?: ReactNode;
33
+ fullWidth?: boolean;
34
+ isClearable?: boolean;
35
+ isRequired?: boolean;
36
+ isReadOnly?: boolean;
37
+ isDisabled?: boolean;
38
+ isInvalid?: boolean;
39
+ label?: string;
40
+ textAlign?: 'left' | 'center' | 'right';
41
+ autoErrorMessage?: boolean;
42
+ }
43
+ export interface UXInputProps extends UXInputCommonProps {
44
+ value?: string;
45
+ defaultValue?: string;
46
+ onValueChange?: (value: string) => void;
47
+ }
48
+ export interface UXNumberInputProps extends UXInputCommonProps {
49
+ value?: number;
50
+ defaultValue?: number;
51
+ minValue?: number;
52
+ maxValue?: number;
53
+ formatOptions?: Intl.NumberFormatOptions;
54
+ step?: number;
55
+ showStepper?: boolean;
56
+ /**
57
+ * 启用带符号的键盘
58
+ */
59
+ allowNegative?: boolean;
60
+ onValueChange?: (value: number) => void;
61
+ }
File without changes
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import { View, type ViewProps } from 'react-native';
3
+ import type { UseBoxProps } from './useBox.type';
4
+ export interface BoxProps extends ViewProps, UseBoxProps {
5
+ /**
6
+ * Child to render
7
+ */
8
+ as?: React.ReactElement<{
9
+ style?: unknown;
10
+ }>;
11
+ }
12
+ export declare const Box: React.ForwardRefExoticComponent<BoxProps & React.RefAttributes<View>>;
@@ -0,0 +1,89 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import react, { forwardRef } from "react";
3
+ import { View } from "react-native";
4
+ import { useBoxStyle } from "./useBox.style.js";
5
+ const Box = /*#__PURE__*/ forwardRef((props, ref)=>{
6
+ const { as, style, fullWidth, fullHeight, h, minH, maxH, w, minW, maxW, m, mt, mr, mb, ml, ms, me, mh, mv, p, pt, pr, pb, pl, ps, pe, ph, pv, borderStyle, border, borderTop, borderRight, borderBottom, borderLeft, borderStart, borderEnd, borderColor, borderTopColor, borderRightColor, borderBottomColor, borderLeftColor, borderStartColor, borderEndColor, radius, topLeftRadius, topRightRadius, bottomLeftRadius, bottomRightRadius, topStartRadius, topEndRadius, bottomStartRadius, bottomEndRadius, position, top, right, bottom, left, start, end, bg, bgOpacity, opacity, zIndex, overflow, ...restProps } = props;
7
+ const boxStyle = useBoxStyle({
8
+ fullWidth,
9
+ fullHeight,
10
+ h,
11
+ minH,
12
+ maxH,
13
+ w,
14
+ minW,
15
+ maxW,
16
+ m,
17
+ mt,
18
+ mr,
19
+ mb,
20
+ ml,
21
+ ms,
22
+ me,
23
+ mh,
24
+ mv,
25
+ p,
26
+ pt,
27
+ pr,
28
+ pb,
29
+ pl,
30
+ ps,
31
+ pe,
32
+ ph,
33
+ pv,
34
+ borderStyle,
35
+ border,
36
+ borderTop,
37
+ borderRight,
38
+ borderBottom,
39
+ borderLeft,
40
+ borderStart,
41
+ borderEnd,
42
+ borderColor,
43
+ borderTopColor,
44
+ borderRightColor,
45
+ borderBottomColor,
46
+ borderLeftColor,
47
+ borderStartColor,
48
+ borderEndColor,
49
+ radius,
50
+ topLeftRadius,
51
+ topRightRadius,
52
+ bottomLeftRadius,
53
+ bottomRightRadius,
54
+ topStartRadius,
55
+ topEndRadius,
56
+ bottomStartRadius,
57
+ bottomEndRadius,
58
+ position,
59
+ top,
60
+ right,
61
+ bottom,
62
+ left,
63
+ start,
64
+ end,
65
+ bg,
66
+ bgOpacity,
67
+ opacity,
68
+ zIndex,
69
+ overflow
70
+ });
71
+ if (as) return /*#__PURE__*/ react.cloneElement(as, {
72
+ ...restProps,
73
+ style: [
74
+ boxStyle,
75
+ style,
76
+ as.props.style
77
+ ]
78
+ });
79
+ return /*#__PURE__*/ jsx(View, {
80
+ ref: ref,
81
+ style: [
82
+ boxStyle,
83
+ style
84
+ ],
85
+ ...restProps
86
+ });
87
+ });
88
+ Box.displayName = 'UXBox';
89
+ export { Box };
@@ -0,0 +1,3 @@
1
+ export * from './box';
2
+ export * from './useBox.style';
3
+ export type * from './useBox.type';
@@ -0,0 +1,2 @@
1
+ export * from "./box.js";
2
+ export * from "./useBox.style.js";
@@ -0,0 +1,3 @@
1
+ import type { ViewStyle } from 'react-native';
2
+ import type { UseBoxProps } from './useBox.type';
3
+ export declare const useBoxStyle: (props: UseBoxProps) => ViewStyle;