廓形仪rn版本-技术调研
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

277 lines
7.6 KiB

  1. 'use client';
  2. import React from 'react';
  3. import { tva } from '@gluestack-ui/nativewind-utils/tva';
  4. import { PrimitiveIcon, UIIcon } from '@gluestack-ui/icon';
  5. import {
  6. withStyleContext,
  7. useStyleContext,
  8. } from '@gluestack-ui/nativewind-utils/withStyleContext';
  9. import type { VariantProps } from '@gluestack-ui/nativewind-utils';
  10. import { createSelect } from '@gluestack-ui/select';
  11. import { cssInterop } from 'nativewind';
  12. import {
  13. Actionsheet,
  14. ActionsheetContent,
  15. ActionsheetItem,
  16. ActionsheetItemText,
  17. ActionsheetDragIndicator,
  18. ActionsheetDragIndicatorWrapper,
  19. ActionsheetBackdrop,
  20. ActionsheetScrollView,
  21. ActionsheetVirtualizedList,
  22. ActionsheetFlatList,
  23. ActionsheetSectionList,
  24. ActionsheetSectionHeaderText,
  25. } from './select-actionsheet';
  26. import { Pressable, View, TextInput } from 'react-native';
  27. const SelectTriggerWrapper = React.forwardRef<
  28. React.ComponentRef<typeof Pressable>,
  29. React.ComponentProps<typeof Pressable>
  30. >(function SelectTriggerWrapper({ ...props }, ref) {
  31. return <Pressable {...props} ref={ref} />;
  32. });
  33. const selectIconStyle = tva({
  34. base: 'text-background-500 fill-none',
  35. parentVariants: {
  36. size: {
  37. '2xs': 'h-3 w-3',
  38. 'xs': 'h-3.5 w-3.5',
  39. 'sm': 'h-4 w-4',
  40. 'md': 'h-[18px] w-[18px]',
  41. 'lg': 'h-5 w-5',
  42. 'xl': 'h-6 w-6',
  43. },
  44. },
  45. });
  46. const selectStyle = tva({
  47. base: '',
  48. });
  49. const selectTriggerStyle = tva({
  50. base: 'border border-background-300 rounded flex-row items-center overflow-hidden data-[hover=true]:border-outline-400 data-[focus=true]:border-primary-700 data-[disabled=true]:opacity-40 data-[disabled=true]:data-[hover=true]:border-background-300',
  51. variants: {
  52. size: {
  53. xl: 'h-12',
  54. lg: 'h-11',
  55. md: 'h-10',
  56. sm: 'h-9',
  57. },
  58. variant: {
  59. underlined:
  60. 'border-0 border-b rounded-none data-[hover=true]:border-primary-700 data-[focus=true]:border-primary-700 data-[focus=true]:web:shadow-[inset_0_-1px_0_0] data-[focus=true]:web:shadow-primary-700 data-[invalid=true]:border-error-700 data-[invalid=true]:web:shadow-error-700',
  61. outline:
  62. 'data-[focus=true]:border-primary-700 data-[focus=true]:web:shadow-[inset_0_0_0_1px] data-[focus=true]:data-[hover=true]:web:shadow-primary-600 data-[invalid=true]:web:shadow-[inset_0_0_0_1px] data-[invalid=true]:border-error-700 data-[invalid=true]:web:shadow-error-700 data-[invalid=true]:data-[hover=true]:border-error-700',
  63. rounded:
  64. 'rounded-full data-[focus=true]:border-primary-700 data-[focus=true]:web:shadow-[inset_0_0_0_1px] data-[focus=true]:web:shadow-primary-700 data-[invalid=true]:border-error-700 data-[invalid=true]:web:shadow-error-700',
  65. },
  66. },
  67. });
  68. const selectInputStyle = tva({
  69. base: 'py-auto px-3 placeholder:text-typography-500 web:w-full h-full text-typography-900 pointer-events-none web:outline-none ios:leading-[0px]',
  70. parentVariants: {
  71. size: {
  72. xl: 'text-xl',
  73. lg: 'text-lg',
  74. md: 'text-base',
  75. sm: 'text-sm',
  76. },
  77. variant: {
  78. underlined: 'px-0',
  79. outline: '',
  80. rounded: 'px-4',
  81. },
  82. },
  83. });
  84. const UISelect = createSelect(
  85. {
  86. Root: View,
  87. Trigger: withStyleContext(SelectTriggerWrapper),
  88. Input: TextInput,
  89. Icon: UIIcon,
  90. },
  91. {
  92. Portal: Actionsheet,
  93. Backdrop: ActionsheetBackdrop,
  94. Content: ActionsheetContent,
  95. DragIndicator: ActionsheetDragIndicator,
  96. DragIndicatorWrapper: ActionsheetDragIndicatorWrapper,
  97. Item: ActionsheetItem,
  98. ItemText: ActionsheetItemText,
  99. ScrollView: ActionsheetScrollView,
  100. VirtualizedList: ActionsheetVirtualizedList,
  101. FlatList: ActionsheetFlatList,
  102. SectionList: ActionsheetSectionList,
  103. SectionHeaderText: ActionsheetSectionHeaderText,
  104. }
  105. );
  106. cssInterop(UISelect, { className: 'style' });
  107. cssInterop(UISelect.Input, {
  108. className: { target: 'style', nativeStyleToProp: { textAlign: true } },
  109. });
  110. cssInterop(SelectTriggerWrapper, { className: 'style' });
  111. cssInterop(PrimitiveIcon, {
  112. className: {
  113. target: 'style',
  114. nativeStyleToProp: {
  115. height: true,
  116. width: true,
  117. fill: true,
  118. color: 'classNameColor',
  119. stroke: true,
  120. },
  121. },
  122. });
  123. type ISelectProps = VariantProps<typeof selectStyle> &
  124. React.ComponentProps<typeof UISelect> & { className?: string };
  125. const Select = React.forwardRef<
  126. React.ComponentRef<typeof UISelect>,
  127. ISelectProps
  128. >(function Select({ className, ...props }, ref) {
  129. return (
  130. <UISelect
  131. className={selectStyle({
  132. class: className,
  133. })}
  134. ref={ref}
  135. {...props}
  136. />
  137. );
  138. });
  139. type ISelectTriggerProps = VariantProps<typeof selectTriggerStyle> &
  140. React.ComponentProps<typeof UISelect.Trigger> & { className?: string };
  141. const SelectTrigger = React.forwardRef<
  142. React.ComponentRef<typeof UISelect.Trigger>,
  143. ISelectTriggerProps
  144. >(function SelectTrigger(
  145. { className, size = 'md', variant = 'outline', ...props },
  146. ref
  147. ) {
  148. return (
  149. <UISelect.Trigger
  150. className={selectTriggerStyle({
  151. class: className,
  152. size,
  153. variant,
  154. })}
  155. ref={ref}
  156. context={{ size, variant }}
  157. {...props}
  158. />
  159. );
  160. });
  161. type ISelectInputProps = VariantProps<typeof selectInputStyle> &
  162. React.ComponentProps<typeof UISelect.Input> & { className?: string };
  163. const SelectInput = React.forwardRef<
  164. React.ComponentRef<typeof UISelect.Input>,
  165. ISelectInputProps
  166. >(function SelectInput({ className, ...props }, ref) {
  167. const { size: parentSize, variant: parentVariant } = useStyleContext();
  168. return (
  169. <UISelect.Input
  170. className={selectInputStyle({
  171. class: className,
  172. parentVariants: {
  173. size: parentSize,
  174. variant: parentVariant,
  175. },
  176. })}
  177. ref={ref}
  178. {...props}
  179. />
  180. );
  181. });
  182. type ISelectIcon = VariantProps<typeof selectIconStyle> &
  183. React.ComponentProps<typeof UISelect.Icon> & { className?: string };
  184. const SelectIcon = React.forwardRef<
  185. React.ComponentRef<typeof UISelect.Icon>,
  186. ISelectIcon
  187. >(function SelectIcon({ className, size, ...props }, ref) {
  188. const { size: parentSize } = useStyleContext();
  189. if (typeof size === 'number') {
  190. return (
  191. <UISelect.Icon
  192. ref={ref}
  193. {...props}
  194. className={selectIconStyle({ class: className })}
  195. size={size}
  196. />
  197. );
  198. } else if (
  199. //@ts-expect-error : web only
  200. (props?.height !== undefined || props?.width !== undefined) &&
  201. size === undefined
  202. ) {
  203. return (
  204. <UISelect.Icon
  205. ref={ref}
  206. {...props}
  207. className={selectIconStyle({ class: className })}
  208. />
  209. );
  210. }
  211. return (
  212. <UISelect.Icon
  213. className={selectIconStyle({
  214. class: className,
  215. size,
  216. parentVariants: {
  217. size: parentSize,
  218. },
  219. })}
  220. ref={ref}
  221. {...props}
  222. />
  223. );
  224. });
  225. Select.displayName = 'Select';
  226. SelectTrigger.displayName = 'SelectTrigger';
  227. SelectInput.displayName = 'SelectInput';
  228. SelectIcon.displayName = 'SelectIcon';
  229. // Actionsheet Components
  230. const SelectPortal = UISelect.Portal;
  231. const SelectBackdrop = UISelect.Backdrop;
  232. const SelectContent = UISelect.Content;
  233. const SelectDragIndicator = UISelect.DragIndicator;
  234. const SelectDragIndicatorWrapper = UISelect.DragIndicatorWrapper;
  235. const SelectItem = UISelect.Item;
  236. const SelectScrollView = UISelect.ScrollView;
  237. const SelectVirtualizedList = UISelect.VirtualizedList;
  238. const SelectFlatList = UISelect.FlatList;
  239. const SelectSectionList = UISelect.SectionList;
  240. const SelectSectionHeaderText = UISelect.SectionHeaderText;
  241. export {
  242. Select,
  243. SelectTrigger,
  244. SelectInput,
  245. SelectIcon,
  246. SelectPortal,
  247. SelectBackdrop,
  248. SelectContent,
  249. SelectDragIndicator,
  250. SelectDragIndicatorWrapper,
  251. SelectItem,
  252. SelectScrollView,
  253. SelectVirtualizedList,
  254. SelectFlatList,
  255. SelectSectionList,
  256. SelectSectionHeaderText,
  257. };