u
This commit is contained in:
1 parent
1903861354
commit
1b1a54f7dd
35 files changed
+1185
-535
No files matched your search
@@ -39,14 +39,9 @@ const Button: React.FC<CustomButtonProps> = ({
|
||||
const isDisabled = disabled || loading
|
||||
const hasChildren = !!children
|
||||
|
||||
const renderIcon = (
|
||||
icon?: IconProp,
|
||||
position: 'left' | 'right' = 'left',
|
||||
) => {
|
||||
if (!icon)
|
||||
return null
|
||||
|
||||
if (loading && position === 'left') {
|
||||
const renderLeftIcon = () => {
|
||||
// 左侧 loading
|
||||
if (loading) {
|
||||
const spinnerColor = variant === 'outline'
|
||||
? 'rgba(0,0,0,0.6)'
|
||||
: 'rgba(255,255,255,0.9)'
|
||||
@@ -57,17 +52,25 @@ const Button: React.FC<CustomButtonProps> = ({
|
||||
)
|
||||
}
|
||||
|
||||
const node = typeof icon === 'function'
|
||||
? icon()
|
||||
: icon
|
||||
// 左侧 icon
|
||||
if (!leftIcon)
|
||||
return null
|
||||
|
||||
const node = typeof leftIcon === 'function' ? leftIcon() : leftIcon
|
||||
|
||||
return (
|
||||
<View className={hasChildren
|
||||
? position === 'left'
|
||||
? 'mr-2'
|
||||
: 'ml-2'
|
||||
: undefined}
|
||||
>
|
||||
<View className={hasChildren ? 'mr-1' : undefined}>
|
||||
{node}
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
const renderRightIcon = () => {
|
||||
if (!rightIcon)
|
||||
return null
|
||||
const node = typeof rightIcon === 'function' ? rightIcon() : rightIcon
|
||||
return (
|
||||
<View className={hasChildren ? 'ml-1' : undefined}>
|
||||
{node}
|
||||
</View>
|
||||
)
|
||||
@@ -83,9 +86,9 @@ const Button: React.FC<CustomButtonProps> = ({
|
||||
variant={variant}
|
||||
size={size}
|
||||
>
|
||||
{renderIcon(leftIcon, 'left')}
|
||||
{renderLeftIcon()}
|
||||
{children && <ButtonText>{children}</ButtonText>}
|
||||
{renderIcon(rightIcon, 'right')}
|
||||
{renderRightIcon()}
|
||||
</NativeButton>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import type { ViewStyle } from 'react-native'
|
||||
import { useState } from 'react'
|
||||
import { Text } from 'react-native'
|
||||
import { Heading } from '@/components/ui/heading'
|
||||
import { CloseIcon, Icon } from '@/components/ui/icon'
|
||||
|
||||
import {
|
||||
Modal,
|
||||
ModalBackdrop,
|
||||
@@ -19,7 +20,7 @@ interface AModalProps {
|
||||
body?: string | React.ReactNode
|
||||
footer?: React.ReactNode
|
||||
onClose?: () => void
|
||||
onConfirm?: () => void
|
||||
onConfirm?: () => Promise<void> | void
|
||||
onCancel?: () => void
|
||||
showBackdrop?: boolean
|
||||
showCloseIcon?: boolean
|
||||
@@ -41,6 +42,29 @@ export default function AModal({
|
||||
className,
|
||||
style,
|
||||
}: AModalProps) {
|
||||
const [innerLoading, setInnerLoading] = useState(false)
|
||||
|
||||
const handleConfirm = () => {
|
||||
if (!onConfirm || innerLoading)
|
||||
return
|
||||
|
||||
try {
|
||||
const result = onConfirm()
|
||||
|
||||
// 只有当返回的是 Promise 才开启 loading
|
||||
if (result && typeof (result as Promise<void>).then === 'function') {
|
||||
setInnerLoading(true)
|
||||
|
||||
result.finally(() => {
|
||||
setInnerLoading(false)
|
||||
})
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
@@ -55,7 +79,7 @@ export default function AModal({
|
||||
}}
|
||||
>
|
||||
<ModalHeader>
|
||||
{title && (typeof title === 'string' ? <Text>{title}</Text> : title)}
|
||||
{title && (typeof title === 'string' ? <Heading>{title}</Heading> : title)}
|
||||
{
|
||||
showCloseIcon && (
|
||||
<ModalCloseButton>
|
||||
@@ -76,11 +100,14 @@ export default function AModal({
|
||||
action="secondary"
|
||||
className="mr-3"
|
||||
onPress={onClose}
|
||||
size="sm"
|
||||
>
|
||||
取消
|
||||
</AButton>
|
||||
<AButton
|
||||
onPress={onConfirm}
|
||||
onPress={handleConfirm}
|
||||
size="sm"
|
||||
loading={innerLoading}
|
||||
>
|
||||
确认
|
||||
</AButton>
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { config } from './config';
|
||||
import { View, ViewProps } from 'react-native';
|
||||
import { OverlayProvider } from '@gluestack-ui/core/overlay/creator';
|
||||
import { ToastProvider } from '@gluestack-ui/core/toast/creator';
|
||||
import { useColorScheme } from 'nativewind';
|
||||
import type { ViewProps } from 'react-native'
|
||||
import { OverlayProvider } from '@gluestack-ui/core/overlay/creator'
|
||||
import { ToastProvider } from '@gluestack-ui/core/toast/creator'
|
||||
import { useColorScheme } from 'nativewind'
|
||||
import React, { useEffect } from 'react'
|
||||
import { View } from 'react-native'
|
||||
import { Toaster } from 'sonner-native'
|
||||
import { config } from './config'
|
||||
|
||||
export type ModeType = 'light' | 'dark' | 'system';
|
||||
export type ModeType = 'light' | 'dark' | 'system'
|
||||
|
||||
export function GluestackUIProvider({
|
||||
mode = 'light',
|
||||
...props
|
||||
}: {
|
||||
mode?: ModeType;
|
||||
children?: React.ReactNode;
|
||||
style?: ViewProps['style'];
|
||||
mode?: ModeType
|
||||
children?: React.ReactNode
|
||||
style?: ViewProps['style']
|
||||
}) {
|
||||
const { colorScheme, setColorScheme } = useColorScheme();
|
||||
const { colorScheme, setColorScheme } = useColorScheme()
|
||||
|
||||
useEffect(() => {
|
||||
setColorScheme(mode);
|
||||
setColorScheme(mode)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [mode]);
|
||||
}, [mode])
|
||||
|
||||
return (
|
||||
<View
|
||||
@@ -34,5 +36,5 @@ export function GluestackUIProvider({
|
||||
<ToastProvider>{props.children}</ToastProvider>
|
||||
</OverlayProvider>
|
||||
</View>
|
||||
);
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user