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

185 lines
4.5 KiB

  1. 'use client';
  2. import React from 'react';
  3. import { createAvatar } from '@gluestack-ui/avatar';
  4. import { View, Text, Image, Platform } from 'react-native';
  5. import { tva } from '@gluestack-ui/nativewind-utils/tva';
  6. import {
  7. withStyleContext,
  8. useStyleContext,
  9. } from '@gluestack-ui/nativewind-utils/withStyleContext';
  10. const SCOPE = 'AVATAR';
  11. import type { VariantProps } from '@gluestack-ui/nativewind-utils';
  12. const UIAvatar = createAvatar({
  13. Root: withStyleContext(View, SCOPE),
  14. Badge: View,
  15. Group: View,
  16. Image: Image,
  17. FallbackText: Text,
  18. });
  19. const avatarStyle = tva({
  20. base: 'rounded-full justify-center items-center relative bg-primary-600 group-[.avatar-group]/avatar-group:-ml-2.5',
  21. variants: {
  22. size: {
  23. 'xs': 'w-6 h-6',
  24. 'sm': 'w-8 h-8',
  25. 'md': 'w-12 h-12',
  26. 'lg': 'w-16 h-16',
  27. 'xl': 'w-24 h-24',
  28. '2xl': 'w-32 h-32',
  29. },
  30. },
  31. });
  32. const avatarFallbackTextStyle = tva({
  33. base: 'text-typography-0 font-semibold overflow-hidden text-transform:uppercase web:cursor-default',
  34. parentVariants: {
  35. size: {
  36. 'xs': 'text-2xs',
  37. 'sm': 'text-xs',
  38. 'md': 'text-base',
  39. 'lg': 'text-xl',
  40. 'xl': 'text-3xl',
  41. '2xl': 'text-5xl',
  42. },
  43. },
  44. });
  45. const avatarGroupStyle = tva({
  46. base: 'group/avatar-group flex-row-reverse relative avatar-group',
  47. });
  48. const avatarBadgeStyle = tva({
  49. base: 'w-5 h-5 bg-success-500 rounded-full absolute right-0 bottom-0 border-background-0 border-2',
  50. parentVariants: {
  51. size: {
  52. 'xs': 'w-2 h-2',
  53. 'sm': 'w-2 h-2',
  54. 'md': 'w-3 h-3',
  55. 'lg': 'w-4 h-4',
  56. 'xl': 'w-6 h-6',
  57. '2xl': 'w-8 h-8',
  58. },
  59. },
  60. });
  61. const avatarImageStyle = tva({
  62. base: 'h-full w-full rounded-full absolute',
  63. });
  64. type IAvatarProps = Omit<
  65. React.ComponentPropsWithoutRef<typeof UIAvatar>,
  66. 'context'
  67. > &
  68. VariantProps<typeof avatarStyle>;
  69. const Avatar = React.forwardRef<
  70. React.ComponentRef<typeof UIAvatar>,
  71. IAvatarProps
  72. >(function Avatar({ className, size = 'md', ...props }, ref) {
  73. return (
  74. <UIAvatar
  75. ref={ref}
  76. {...props}
  77. className={avatarStyle({ size, class: className })}
  78. context={{ size }}
  79. />
  80. );
  81. });
  82. type IAvatarBadgeProps = React.ComponentPropsWithoutRef<typeof UIAvatar.Badge> &
  83. VariantProps<typeof avatarBadgeStyle>;
  84. const AvatarBadge = React.forwardRef<
  85. React.ComponentRef<typeof UIAvatar.Badge>,
  86. IAvatarBadgeProps
  87. >(function AvatarBadge({ className, size, ...props }, ref) {
  88. const { size: parentSize } = useStyleContext(SCOPE);
  89. return (
  90. <UIAvatar.Badge
  91. ref={ref}
  92. {...props}
  93. className={avatarBadgeStyle({
  94. parentVariants: {
  95. size: parentSize,
  96. },
  97. size,
  98. class: className,
  99. })}
  100. />
  101. );
  102. });
  103. type IAvatarFallbackTextProps = React.ComponentPropsWithoutRef<
  104. typeof UIAvatar.FallbackText
  105. > &
  106. VariantProps<typeof avatarFallbackTextStyle>;
  107. const AvatarFallbackText = React.forwardRef<
  108. React.ComponentRef<typeof UIAvatar.FallbackText>,
  109. IAvatarFallbackTextProps
  110. >(function AvatarFallbackText({ className, size, ...props }, ref) {
  111. const { size: parentSize } = useStyleContext(SCOPE);
  112. return (
  113. <UIAvatar.FallbackText
  114. ref={ref}
  115. {...props}
  116. className={avatarFallbackTextStyle({
  117. parentVariants: {
  118. size: parentSize,
  119. },
  120. size,
  121. class: className,
  122. })}
  123. />
  124. );
  125. });
  126. type IAvatarImageProps = React.ComponentPropsWithoutRef<typeof UIAvatar.Image> &
  127. VariantProps<typeof avatarImageStyle>;
  128. const AvatarImage = React.forwardRef<
  129. React.ComponentRef<typeof UIAvatar.Image>,
  130. IAvatarImageProps
  131. >(function AvatarImage({ className, ...props }, ref) {
  132. return (
  133. <UIAvatar.Image
  134. ref={ref}
  135. {...props}
  136. className={avatarImageStyle({
  137. class: className,
  138. })}
  139. // @ts-expect-error : This is a workaround to fix the issue with the image style on web.
  140. style={
  141. Platform.OS === 'web'
  142. ? { height: 'revert-layer', width: 'revert-layer' }
  143. : undefined
  144. }
  145. />
  146. );
  147. });
  148. type IAvatarGroupProps = React.ComponentPropsWithoutRef<typeof UIAvatar.Group> &
  149. VariantProps<typeof avatarGroupStyle>;
  150. const AvatarGroup = React.forwardRef<
  151. React.ComponentRef<typeof UIAvatar.Group>,
  152. IAvatarGroupProps
  153. >(function AvatarGroup({ className, ...props }, ref) {
  154. return (
  155. <UIAvatar.Group
  156. ref={ref}
  157. {...props}
  158. className={avatarGroupStyle({
  159. class: className,
  160. })}
  161. />
  162. );
  163. });
  164. export { Avatar, AvatarBadge, AvatarFallbackText, AvatarImage, AvatarGroup };