mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-20 06:43:36 +02:00
- Add uload project with apps/web structure
- Reorganize from flat to monorepo structure
- Remove PocketBase binary and local data
- Update to pnpm and @uload/web namespace
- Add picture project to monorepo
- Remove embedded git repository
- Unify all package names to @{project}/{app} schema:
- @maerchenzauber/* (was @storyteller/*)
- @manacore/* (was manacore-*, manacore)
- @manadeck/* (was web, backend, manadeck)
- @memoro/* (was memoro-web, landing, memoro)
- @picture/* (already unified)
- @uload/web
- Add convenient dev scripts for all apps:
- pnpm dev:{project}:web
- pnpm dev:{project}:landing
- pnpm dev:{project}:mobile
- pnpm dev:{project}:backend
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
87 lines
2 KiB
TypeScript
87 lines
2 KiB
TypeScript
import { Pressable } from 'react-native';
|
|
import { Ionicons } from '@expo/vector-icons';
|
|
import { BlurView } from 'expo-blur';
|
|
import Animated, {
|
|
useAnimatedStyle,
|
|
withSpring,
|
|
useSharedValue,
|
|
} from 'react-native-reanimated';
|
|
import { useTheme } from '~/contexts/ThemeContext';
|
|
|
|
type FABProps = {
|
|
icon: keyof typeof Ionicons.glyphMap;
|
|
onPress: () => void;
|
|
bottom?: number;
|
|
right?: number;
|
|
left?: number;
|
|
color?: string;
|
|
};
|
|
|
|
export function FAB({ icon, onPress, bottom = 100, right, left, color }: FABProps) {
|
|
const { theme } = useTheme();
|
|
const fabColor = color || theme.colors.primary.default;
|
|
const iconColor = color === theme.colors.surface ? theme.colors.text.primary : 'white';
|
|
const pressScale = useSharedValue(1);
|
|
|
|
const animatedStyle = useAnimatedStyle(() => {
|
|
return {
|
|
transform: [
|
|
{ scale: pressScale.value },
|
|
],
|
|
};
|
|
});
|
|
|
|
const handlePressIn = () => {
|
|
pressScale.value = withSpring(0.9, {
|
|
damping: 10,
|
|
stiffness: 400,
|
|
});
|
|
};
|
|
|
|
const handlePressOut = () => {
|
|
pressScale.value = withSpring(1, {
|
|
damping: 10,
|
|
stiffness: 400,
|
|
});
|
|
};
|
|
|
|
return (
|
|
<Animated.View
|
|
style={[
|
|
{
|
|
position: 'absolute',
|
|
...(left !== undefined ? { left } : { right: right ?? 16 }),
|
|
bottom: bottom,
|
|
zIndex: 10,
|
|
},
|
|
animatedStyle,
|
|
]}
|
|
>
|
|
<Pressable
|
|
onPress={onPress}
|
|
onPressIn={handlePressIn}
|
|
onPressOut={handlePressOut}
|
|
className="rounded-full shadow-2xl overflow-hidden"
|
|
style={{
|
|
shadowColor: fabColor,
|
|
shadowOffset: { width: 0, height: 4 },
|
|
shadowOpacity: 0.4,
|
|
shadowRadius: 8,
|
|
elevation: 8,
|
|
}}
|
|
>
|
|
<BlurView
|
|
intensity={80}
|
|
tint="systemChromeMaterialDark"
|
|
className="p-4"
|
|
>
|
|
<Ionicons
|
|
name={icon}
|
|
size={24}
|
|
color={iconColor}
|
|
/>
|
|
</BlurView>
|
|
</Pressable>
|
|
</Animated.View>
|
|
);
|
|
}
|