廓形仪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.

296 lines
7.6 KiB

  1. 'use client';
  2. import React from 'react';
  3. import { createAlertDialog } from '@gluestack-ui/alert-dialog';
  4. import { tva } from '@gluestack-ui/nativewind-utils/tva';
  5. import {
  6. withStyleContext,
  7. useStyleContext,
  8. } from '@gluestack-ui/nativewind-utils/withStyleContext';
  9. import { cssInterop } from 'nativewind';
  10. import type { VariantProps } from '@gluestack-ui/nativewind-utils';
  11. import {
  12. Motion,
  13. AnimatePresence,
  14. createMotionAnimatedComponent,
  15. MotionComponentProps,
  16. } from '@legendapp/motion';
  17. import { View, Pressable, ScrollView, ViewStyle } from 'react-native';
  18. const SCOPE = 'ALERT_DIALOG';
  19. const RootComponent = withStyleContext(View, SCOPE);
  20. type IMotionViewProps = React.ComponentProps<typeof View> &
  21. MotionComponentProps<typeof View, ViewStyle, unknown, unknown, unknown>;
  22. const MotionView = Motion.View as React.ComponentType<IMotionViewProps>;
  23. type IAnimatedPressableProps = React.ComponentProps<typeof Pressable> &
  24. MotionComponentProps<typeof Pressable, ViewStyle, unknown, unknown, unknown>;
  25. const AnimatedPressable = createMotionAnimatedComponent(
  26. Pressable
  27. ) as React.ComponentType<IAnimatedPressableProps>;
  28. const UIAccessibleAlertDialog = createAlertDialog({
  29. Root: RootComponent,
  30. Body: ScrollView,
  31. Content: MotionView,
  32. CloseButton: Pressable,
  33. Header: View,
  34. Footer: View,
  35. Backdrop: AnimatedPressable,
  36. AnimatePresence: AnimatePresence,
  37. });
  38. cssInterop(MotionView, { className: 'style' });
  39. cssInterop(AnimatedPressable, { className: 'style' });
  40. const alertDialogStyle = tva({
  41. base: 'group/modal w-full h-full justify-center items-center web:pointer-events-none',
  42. parentVariants: {
  43. size: {
  44. xs: '',
  45. sm: '',
  46. md: '',
  47. lg: '',
  48. full: '',
  49. },
  50. },
  51. });
  52. const alertDialogContentStyle = tva({
  53. base: 'bg-background-0 rounded-lg overflow-hidden border border-outline-100 p-6',
  54. parentVariants: {
  55. size: {
  56. xs: 'w-[60%] max-w-[360px]',
  57. sm: 'w-[70%] max-w-[420px]',
  58. md: 'w-[80%] max-w-[510px]',
  59. lg: 'w-[90%] max-w-[640px]',
  60. full: 'w-full',
  61. },
  62. },
  63. });
  64. const alertDialogCloseButtonStyle = tva({
  65. base: 'group/alert-dialog-close-button z-10 rounded-sm p-2 data-[focus-visible=true]:bg-background-100 web:cursor-pointer outline-0',
  66. });
  67. const alertDialogHeaderStyle = tva({
  68. base: 'justify-between items-center flex-row',
  69. });
  70. const alertDialogFooterStyle = tva({
  71. base: 'flex-row justify-end items-center gap-3',
  72. });
  73. const alertDialogBodyStyle = tva({ base: '' });
  74. const alertDialogBackdropStyle = tva({
  75. base: 'absolute left-0 top-0 right-0 bottom-0 bg-background-dark web:cursor-default',
  76. });
  77. type IAlertDialogProps = React.ComponentPropsWithoutRef<
  78. typeof UIAccessibleAlertDialog
  79. > &
  80. VariantProps<typeof alertDialogStyle>;
  81. type IAlertDialogContentProps = React.ComponentPropsWithoutRef<
  82. typeof UIAccessibleAlertDialog.Content
  83. > &
  84. VariantProps<typeof alertDialogContentStyle> & { className?: string };
  85. type IAlertDialogCloseButtonProps = React.ComponentPropsWithoutRef<
  86. typeof UIAccessibleAlertDialog.CloseButton
  87. > &
  88. VariantProps<typeof alertDialogCloseButtonStyle>;
  89. type IAlertDialogHeaderProps = React.ComponentPropsWithoutRef<
  90. typeof UIAccessibleAlertDialog.Header
  91. > &
  92. VariantProps<typeof alertDialogHeaderStyle>;
  93. type IAlertDialogFooterProps = React.ComponentPropsWithoutRef<
  94. typeof UIAccessibleAlertDialog.Footer
  95. > &
  96. VariantProps<typeof alertDialogFooterStyle>;
  97. type IAlertDialogBodyProps = React.ComponentPropsWithoutRef<
  98. typeof UIAccessibleAlertDialog.Body
  99. > &
  100. VariantProps<typeof alertDialogBodyStyle>;
  101. type IAlertDialogBackdropProps = React.ComponentPropsWithoutRef<
  102. typeof UIAccessibleAlertDialog.Backdrop
  103. > &
  104. VariantProps<typeof alertDialogBackdropStyle> & { className?: string };
  105. const AlertDialog = React.forwardRef<
  106. React.ComponentRef<typeof UIAccessibleAlertDialog>,
  107. IAlertDialogProps
  108. >(function AlertDialog({ className, size = 'md', ...props }, ref) {
  109. return (
  110. <UIAccessibleAlertDialog
  111. ref={ref}
  112. {...props}
  113. className={alertDialogStyle({ class: className })}
  114. context={{ size }}
  115. pointerEvents="box-none"
  116. />
  117. );
  118. });
  119. const AlertDialogContent = React.forwardRef<
  120. React.ComponentRef<typeof UIAccessibleAlertDialog.Content>,
  121. IAlertDialogContentProps
  122. >(function AlertDialogContent({ className, size, ...props }, ref) {
  123. const { size: parentSize } = useStyleContext(SCOPE);
  124. return (
  125. <UIAccessibleAlertDialog.Content
  126. pointerEvents="auto"
  127. ref={ref}
  128. initial={{
  129. scale: 0.9,
  130. opacity: 0,
  131. }}
  132. animate={{
  133. scale: 1,
  134. opacity: 1,
  135. }}
  136. exit={{
  137. scale: 0.9,
  138. opacity: 0,
  139. }}
  140. transition={{
  141. type: 'spring',
  142. damping: 18,
  143. stiffness: 250,
  144. opacity: {
  145. type: 'timing',
  146. duration: 250,
  147. },
  148. }}
  149. {...props}
  150. className={alertDialogContentStyle({
  151. parentVariants: {
  152. size: parentSize,
  153. },
  154. size,
  155. class: className,
  156. })}
  157. />
  158. );
  159. });
  160. const AlertDialogCloseButton = React.forwardRef<
  161. React.ComponentRef<typeof UIAccessibleAlertDialog.CloseButton>,
  162. IAlertDialogCloseButtonProps
  163. >(function AlertDialogCloseButton({ className, ...props }, ref) {
  164. return (
  165. <UIAccessibleAlertDialog.CloseButton
  166. ref={ref}
  167. {...props}
  168. className={alertDialogCloseButtonStyle({
  169. class: className,
  170. })}
  171. />
  172. );
  173. });
  174. const AlertDialogHeader = React.forwardRef<
  175. React.ComponentRef<typeof UIAccessibleAlertDialog.Header>,
  176. IAlertDialogHeaderProps
  177. >(function AlertDialogHeader({ className, ...props }, ref) {
  178. return (
  179. <UIAccessibleAlertDialog.Header
  180. ref={ref}
  181. {...props}
  182. className={alertDialogHeaderStyle({
  183. class: className,
  184. })}
  185. />
  186. );
  187. });
  188. const AlertDialogFooter = React.forwardRef<
  189. React.ComponentRef<typeof UIAccessibleAlertDialog.Footer>,
  190. IAlertDialogFooterProps
  191. >(function AlertDialogFooter({ className, ...props }, ref) {
  192. return (
  193. <UIAccessibleAlertDialog.Footer
  194. ref={ref}
  195. {...props}
  196. className={alertDialogFooterStyle({
  197. class: className,
  198. })}
  199. />
  200. );
  201. });
  202. const AlertDialogBody = React.forwardRef<
  203. React.ComponentRef<typeof UIAccessibleAlertDialog.Body>,
  204. IAlertDialogBodyProps
  205. >(function AlertDialogBody({ className, ...props }, ref) {
  206. return (
  207. <UIAccessibleAlertDialog.Body
  208. ref={ref}
  209. {...props}
  210. className={alertDialogBodyStyle({
  211. class: className,
  212. })}
  213. />
  214. );
  215. });
  216. const AlertDialogBackdrop = React.forwardRef<
  217. React.ComponentRef<typeof UIAccessibleAlertDialog.Backdrop>,
  218. IAlertDialogBackdropProps
  219. >(function AlertDialogBackdrop({ className, ...props }, ref) {
  220. return (
  221. <UIAccessibleAlertDialog.Backdrop
  222. ref={ref}
  223. initial={{
  224. opacity: 0,
  225. }}
  226. animate={{
  227. opacity: 0.5,
  228. }}
  229. exit={{
  230. opacity: 0,
  231. }}
  232. transition={{
  233. type: 'spring',
  234. damping: 18,
  235. stiffness: 250,
  236. opacity: {
  237. type: 'timing',
  238. duration: 250,
  239. },
  240. }}
  241. {...props}
  242. className={alertDialogBackdropStyle({
  243. class: className,
  244. })}
  245. />
  246. );
  247. });
  248. AlertDialog.displayName = 'AlertDialog';
  249. AlertDialogContent.displayName = 'AlertDialogContent';
  250. AlertDialogCloseButton.displayName = 'AlertDialogCloseButton';
  251. AlertDialogHeader.displayName = 'AlertDialogHeader';
  252. AlertDialogFooter.displayName = 'AlertDialogFooter';
  253. AlertDialogBody.displayName = 'AlertDialogBody';
  254. AlertDialogBackdrop.displayName = 'AlertDialogBackdrop';
  255. export {
  256. AlertDialog,
  257. AlertDialogContent,
  258. AlertDialogCloseButton,
  259. AlertDialogHeader,
  260. AlertDialogFooter,
  261. AlertDialogBody,
  262. AlertDialogBackdrop,
  263. };