This commit is contained in:
oneao committed 2026-01-25 22:18:27 +08:00
1 parent 500fab7a80
commit 8f3f6982db
54 files changed
+2076 -1877

No files matched your search

@@ -1,15 +1,13 @@
import type { icons } from 'lucide-react-native'
import type { ViewStyle } from 'react-native'
import type { LucideIconProps } from './LucideIcon'
import React from 'react'
import { View } from 'react-native'
import {
ButtonSpinner,
ButtonText,
Button as NativeButton,
} from '@/components/ui/button'
import LucideIcon from './LucideIcon'
type IconProp = (LucideIconProps & { icon: keyof typeof icons }) | React.ReactNode
type IconProp = React.ReactNode | (() => React.ReactNode)
interface CustomButtonProps {
children?: React.ReactNode
@@ -21,7 +19,6 @@ interface CustomButtonProps {
action?: 'primary' | 'secondary' | 'positive' | 'negative' | 'default'
variant?: 'solid' | 'outline' | 'link'
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl'
leftIcon?: IconProp
rightIcon?: IconProp
}
@@ -41,31 +38,39 @@ const Button: React.FC<CustomButtonProps> = ({
}) => {
const isDisabled = disabled || loading
const hasChildren = !!children
const renderLeftIcon = () => {
if (loading)
return <ButtonSpinner color="#fff" className={hasChildren ? 'mr-2' : ''} />
if (!leftIcon)
const renderIcon = (
icon?: IconProp,
position: 'left' | 'right' = 'left',
) => {
if (!icon)
return null
if (React.isValidElement(leftIcon)) {
return <span className={hasChildren ? 'mr-2' : ''}>{leftIcon}</span>
if (loading && position === 'left') {
const spinnerColor = variant === 'outline'
? 'rgba(0,0,0,0.6)'
: 'rgba(255,255,255,0.9)'
return (
<View className={hasChildren ? 'mr-2' : undefined}>
<ButtonSpinner color={spinnerColor} />
</View>
)
}
const { icon, ...props } = leftIcon as LucideIconProps & { icon: keyof typeof icons }
return <LucideIcon icon={icon} className={hasChildren ? 'mr-2' : ''} {...props} />
}
const node = typeof icon === 'function'
? icon()
: icon
const renderRightIcon = () => {
if (!rightIcon)
return null
if (React.isValidElement(rightIcon)) {
return <span className={hasChildren ? 'ml-2' : ''}>{rightIcon}</span>
}
const { icon, ...props } = rightIcon as LucideIconProps & { icon: keyof typeof icons }
return <LucideIcon icon={icon} className={hasChildren ? 'ml-2' : ''} {...props} />
return (
<View className={hasChildren
? position === 'left'
? 'mr-2'
: 'ml-2'
: undefined}
>
{node}
</View>
)
}
return (
@@ -78,13 +83,9 @@ const Button: React.FC<CustomButtonProps> = ({
variant={variant}
size={size}
>
{renderLeftIcon()}
{
children && (
<ButtonText>{children}</ButtonText>
)
}
{renderRightIcon()}
{renderIcon(leftIcon, 'left')}
{children && <ButtonText>{children}</ButtonText>}
{renderIcon(rightIcon, 'right')}
</NativeButton>
)
}
@@ -11,33 +11,36 @@ import { CheckIcon } from '@/components/ui/icon'
interface CustomCheckboxProps {
value?: string
isChecked: boolean
onChange: (checked: boolean) => void
label: React.ReactNode
checked?: boolean
onChange?: (checked: boolean) => void
label?: React.ReactNode
className?: string
style?: ViewStyle
disabled?: boolean
icon?: React.ElementType
size?: 'sm' | 'md' | 'lg'
}
const Checkbox: React.FC<CustomCheckboxProps> = ({
value,
isChecked,
checked,
onChange,
label,
className,
style,
disabled,
icon,
size,
}) => {
return (
<NativeCheckbox
value={value ?? ''} // 避免 undefined
isChecked={isChecked}
value={value ?? ''}
isChecked={checked}
onChange={onChange}
className={className}
style={style}
isDisabled={disabled}
size={size}
>
<CheckboxIndicator>
<CheckboxIcon as={icon ?? CheckIcon} />
@@ -1,24 +1,21 @@
'use client';
import React from 'react';
import { createAvatar } from '@gluestack-ui/core/avatar/creator';
'use client'
import type { VariantProps } from '@gluestack-ui/utils/nativewind-utils'
import { createAvatar } from '@gluestack-ui/core/avatar/creator'
import { View, Text, Image, Platform } from 'react-native';
import { tva, useStyleContext, withStyleContext } from '@gluestack-ui/utils/nativewind-utils'
import { tva } from '@gluestack-ui/utils/nativewind-utils';
import {
withStyleContext,
useStyleContext,
} from '@gluestack-ui/utils/nativewind-utils';
const SCOPE = 'AVATAR';
import type { VariantProps } from '@gluestack-ui/utils/nativewind-utils';
import React from 'react'
import { Image, Platform, Text, View } from 'react-native'
const SCOPE = 'AVATAR'
const UIAvatar = createAvatar({
Root: withStyleContext(View, SCOPE),
Badge: View,
Group: View,
Image: Image,
Image,
FallbackText: Text,
});
})
const avatarStyle = tva({
base: 'rounded-full justify-center items-center relative bg-primary-600 group-[.avatar-group]/avatar-group:-ml-2.5',
@@ -32,7 +29,7 @@ const avatarStyle = tva({
'2xl': 'w-32 h-32',
},
},
});
})
const avatarFallbackTextStyle = tva({
base: 'text-typography-0 font-semibold overflow-hidden text-transform:uppercase web:cursor-default',
@@ -47,11 +44,11 @@ const avatarFallbackTextStyle = tva({
'2xl': 'text-5xl',
},
},
});
})
const avatarGroupStyle = tva({
base: 'group/avatar-group flex-row-reverse relative avatar-group',
});
})
const avatarBadgeStyle = tva({
base: 'w-5 h-5 bg-success-500 rounded-full absolute right-0 bottom-0 border-background-0 border-2',
@@ -65,22 +62,22 @@ const avatarBadgeStyle = tva({
'2xl': 'w-8 h-8',
},
},
});
})
const avatarImageStyle = tva({
base: 'h-full w-full rounded-full absolute',
});
})
type IAvatarProps = Omit<
React.ComponentPropsWithoutRef<typeof UIAvatar>,
'context'
> &
VariantProps<typeof avatarStyle>;
>
& VariantProps<typeof avatarStyle>
const Avatar = React.forwardRef<
React.ComponentRef<typeof UIAvatar>,
IAvatarProps
>(function Avatar({ className, size = 'md', ...props }, ref) {
>(({ className, size = 'md', ...props }, ref) => {
return (
<UIAvatar
ref={ref}
@@ -88,17 +85,17 @@ const Avatar = React.forwardRef<
className={avatarStyle({ size, class: className })}
context={{ size }}
/>
);
});
)
})
type IAvatarBadgeProps = React.ComponentPropsWithoutRef<typeof UIAvatar.Badge> &
VariantProps<typeof avatarBadgeStyle>;
type IAvatarBadgeProps = React.ComponentPropsWithoutRef<typeof UIAvatar.Badge>
& VariantProps<typeof avatarBadgeStyle>
const AvatarBadge = React.forwardRef<
React.ComponentRef<typeof UIAvatar.Badge>,
IAvatarBadgeProps
>(function AvatarBadge({ className, size, ...props }, ref) {
const { size: parentSize } = useStyleContext(SCOPE);
>(({ className, size, ...props }, ref) => {
const { size: parentSize } = useStyleContext(SCOPE)
return (
<UIAvatar.Badge
@@ -112,18 +109,18 @@ const AvatarBadge = React.forwardRef<
class: className,
})}
/>
);
});
)
})
type IAvatarFallbackTextProps = React.ComponentPropsWithoutRef<
typeof UIAvatar.FallbackText
> &
VariantProps<typeof avatarFallbackTextStyle>;
>
& VariantProps<typeof avatarFallbackTextStyle>
const AvatarFallbackText = React.forwardRef<
React.ComponentRef<typeof UIAvatar.FallbackText>,
IAvatarFallbackTextProps
>(function AvatarFallbackText({ className, size, ...props }, ref) {
const { size: parentSize } = useStyleContext(SCOPE);
>(({ className, size, ...props }, ref) => {
const { size: parentSize } = useStyleContext(SCOPE)
return (
<UIAvatar.FallbackText
@@ -137,16 +134,16 @@ const AvatarFallbackText = React.forwardRef<
class: className,
})}
/>
);
});
)
})
type IAvatarImageProps = React.ComponentPropsWithoutRef<typeof UIAvatar.Image> &
VariantProps<typeof avatarImageStyle>;
type IAvatarImageProps = React.ComponentPropsWithoutRef<typeof UIAvatar.Image>
& VariantProps<typeof avatarImageStyle>
const AvatarImage = React.forwardRef<
React.ComponentRef<typeof UIAvatar.Image>,
IAvatarImageProps
>(function AvatarImage({ className, ...props }, ref) {
>(({ className, ...props }, ref) => {
return (
<UIAvatar.Image
ref={ref}
@@ -161,16 +158,16 @@ const AvatarImage = React.forwardRef<
: undefined
}
/>
);
});
)
})
type IAvatarGroupProps = React.ComponentPropsWithoutRef<typeof UIAvatar.Group> &
VariantProps<typeof avatarGroupStyle>;
type IAvatarGroupProps = React.ComponentPropsWithoutRef<typeof UIAvatar.Group>
& VariantProps<typeof avatarGroupStyle>
const AvatarGroup = React.forwardRef<
React.ComponentRef<typeof UIAvatar.Group>,
IAvatarGroupProps
>(function AvatarGroup({ className, ...props }, ref) {
>(({ className, ...props }, ref) => {
return (
<UIAvatar.Group
ref={ref}
@@ -179,7 +176,7 @@ const AvatarGroup = React.forwardRef<
class: className,
})}
/>
);
});
)
})
export { Avatar, AvatarBadge, AvatarFallbackText, AvatarImage, AvatarGroup };
export { Avatar, AvatarBadge, AvatarFallbackText, AvatarGroup, AvatarImage }