macos update
Publish npm package / publish (push) Canceled after 0s

This commit is contained in:
2026-10-07 14:02:19 +02:00
parent 7fb87fbb96
commit c7e7e615c2
17 changed files with 284 additions and 130 deletions
@@ -36,7 +36,11 @@
"imageWidth": 76
}
}
]
],
"expo-font",
"expo-image",
"expo-status-bar",
"expo-web-browser"
],
"experiments": {
"typedRoutes": true,
@@ -3,32 +3,32 @@
"main": "expo-router/entry",
"version": "1.0.0",
"dependencies": {
"@expo/ui": "~56.0.14",
"@<@var(context.project.name)>/rpc": "workspace:*",
"expo": "~56.0.5",
"expo-constants": "~56.0.16",
"expo-crypto": "~56.0.4",
"expo-dev-client": "~56.0.18",
"expo-device": "~56.0.4",
"expo-font": "~56.0.5",
"expo-glass-effect": "~56.0.4",
"expo-image": "~56.0.9",
"expo-linking": "~56.0.12",
"expo-router": "~56.2.7",
"expo-splash-screen": "~56.0.10",
"expo-status-bar": "~56.0.4",
"expo-symbols": "~56.0.5",
"expo-system-ui": "~56.0.5",
"expo-web-browser": "~56.0.5",
"@expo/ui": "~57.0.22",
"expo": "~57.0.27",
"expo-constants": "~57.0.21",
"expo-crypto": "~57.0.3",
"expo-dev-client": "~57.0.19",
"expo-device": "~57.0.2",
"expo-font": "~57.0.4",
"expo-glass-effect": "~57.0.4",
"expo-image": "~57.0.5",
"expo-linking": "~57.0.12",
"expo-router": "~57.0.25",
"expo-splash-screen": "~57.0.9",
"expo-status-bar": "~57.0.1",
"expo-symbols": "~57.0.3",
"expo-system-ui": "~57.0.4",
"expo-web-browser": "~57.0.3",
"react": "19.2.3",
"react-dom": "19.2.3",
"react-native": "0.85.3",
"react-native-gesture-handler": "~2.31.1",
"react-native-reanimated": "4.3.1",
"react-native": "0.86.3",
"react-native-gesture-handler": "~2.32.0",
"react-native-reanimated": "4.5.1",
"react-native-safe-area-context": "~5.7.0",
"react-native-screens": "4.25.2",
"react-native-screens": "~4.26.0",
"react-native-web": "~0.21.0",
"react-native-worklets": "0.8.3"
"react-native-worklets": "0.10.1"
},
"devDependencies": {
"@types/react": "~19.2.2",
@@ -1,13 +1,47 @@
import { createRouter, Todo } from "@<@var(context.project.name)>/rpc"
import { useEffect, useState } from "react"
import { ScrollView, Button, Checkbox, Host, Column, TextInput, Text, useNativeState, Row, Icon } from "@expo/ui";
import { Platform, PlatformColor, ScrollView, useColorScheme } from "react-native"
import Animated, { FadeIn, FadeOut, LinearTransition } from "react-native-reanimated"
import { SafeAreaView } from "react-native-safe-area-context"
import { Button, Checkbox, Host, Column, TextInput, Text, useNativeState, Row, Icon } from "@expo/ui";
import * as Crypto from "expo-crypto"
import { colorInvert, controlSize } from "@expo/ui/swift-ui/modifiers";
import { fillMaxWidth, padding, width } from "@expo/ui/jetpack-compose/modifiers";
import { background, colorInvert, controlSize, padding as iosPadding, shapes } from "@expo/ui/swift-ui/modifiers";
// No numeric width() on Android: @expo/ui 57 can't convert it natively and crashes.
import { fillMaxWidth, padding, weight } from "@expo/ui/jetpack-compose/modifiers";
// The Android emulator reaches the host via 10.0.2.2; the iOS simulator shares the host's network.
const apiUrl = Platform.OS === "android" ? "http://10.0.2.2:8080" : "http://127.0.0.1:8080"
// SwiftUI clips a border to its corner radius, cutting off the corners, so on iOS the
// border is an outer rounded fill showing 1pt around an inner one.
const iosInputBorder = Platform.OS === "ios" ? [
iosPadding({ all: 10 }),
background(PlatformColor("secondarySystemGroupedBackground"), shapes.roundedRectangle({ cornerRadius: 9, roundedCornerStyle: "continuous" })),
iosPadding({ all: 1 }),
background(PlatformColor("separator"), shapes.roundedRectangle({ cornerRadius: 10, roundedCornerStyle: "continuous" })),
] : []
// Animates its position when the list re-sorts. The Host's measured height goes through state:
// on Android a layout transition ignores the size matchContents sets natively, collapsing the row.
function AnimatedRow({ children }: { children: React.ReactNode }) {
const [height, setHeight] = useState<number>()
return (
<Animated.View layout={LinearTransition.springify()} entering={FadeIn} exiting={FadeOut}>
<Host
matchContents={{ vertical: true }}
style={height ? { height } : undefined}
onLayoutContent={(e) => setHeight(e.nativeEvent.height)}
>
{children}
</Host>
</Animated.View>
)
}
export default function Index() {
const router = createRouter("http://10.0.2.2:8080")
const router = createRouter(apiUrl)
const [todos, setTodos] = useState<Array<Todo>>([])
const todoToCreateTask = useNativeState<string>("")
const colorScheme = useColorScheme()
const fetchTodos = () => {
router.todos.listTodos({}).then((r) => {
setTodos(r.todos)
@@ -15,19 +49,17 @@ export default function Index() {
}
useEffect(() => {
fetchTodos();
})
}, [])
const setTodoDone = (id: string, task: string) => {
return (done: boolean) => {
router.todos.updateTodo({ todo: { id, task, done } })
fetchTodos()
router.todos.updateTodo({ todo: { id, task, done } }).then(fetchTodos)
}
}
const deleteTodo = (id: string) => {
return () => {
router.todos.deleteTodo({ todo: { id } })
fetchTodos()
router.todos.deleteTodo({ todo: { id } }).then(fetchTodos)
}
}
@@ -45,29 +77,43 @@ export default function Index() {
}
return (
<Host style={{ flex: 1 }}>
<Column alignment="center" modifiers={[fillMaxWidth()]}>
<Text textStyle={{fontSize:30}}> Create Todo </Text>
<TextInput value={todoToCreateTask} onChangeText={updateTodoToCreateTask} />
<Button modifiers={[controlSize('regular')]} label="create Todo" onPress={createTodo} />
<ScrollView modifiers={[fillMaxWidth()]}>
{
todos.map((todo) => (
<SafeAreaView style={{ flex: 1 }}>
<Host matchContents={{ vertical: true }}>
<Column alignment="center" modifiers={[fillMaxWidth()]}>
<Text textStyle={{fontSize:30}}> Create Todo </Text>
<TextInput
value={todoToCreateTask}
onChangeText={updateTodoToCreateTask}
placeholder="What needs to be done?"
style={Platform.OS === "ios"
? { width: 280 }
// Android draws the border as a fill behind the background, so the background must be opaque.
: { padding: 10, borderWidth: 1, borderColor: "#8E8E93", borderRadius: 8, backgroundColor: colorScheme === "dark" ? "#1C1B1F" : "#FFFFFF" }}
modifiers={Platform.OS === "ios" ? iosInputBorder : [fillMaxWidth(0.75)]}
/>
<Button modifiers={[controlSize('regular')]} label="create Todo" onPress={createTodo} />
</Column>
</Host>
<ScrollView>
{
todos.map((todo) => (
// Keyed by id so native toggles follow their todo.
<AnimatedRow key={todo.id}>
<Row alignment="center" modifiers={[fillMaxWidth(),padding(20,0,20,0)]}>
<Column alignment="start" modifiers={[width(200)]}>
<Text> {todo.task} </Text>
<Column alignment="start" modifiers={[weight(1)]}>
<Text>{todo.task}</Text>
</Column>
<Column alignment="center">
<Checkbox value={todo.done || false} onValueChange={setTodoDone(todo.id || "", todo.task)} />
</Column>
<Column alignment="end" modifiers={[fillMaxWidth()]}>
<Column alignment="end">
<Button modifiers={[controlSize('regular')]} label="delete" onPress={deleteTodo(todo.id || "")}/>
</Column>
</Row>
))
}
</ScrollView>
</Column>
</Host>
</AnimatedRow>
))
}
</ScrollView>
</SafeAreaView>
)
}