import { Button, Navigation, NavigationStack, Script, Text, ScrollView, useObservable, LazyVGrid, ReorderableForEach, RoundedRectangle, VStack, Toolbar, ToolbarItem, modifiers, Color } from "scripting"
type Item = {
id: string
color: Color
}
const colors: Color[] = [
'systemRed',
'systemBlue',
'systemGreen',
'systemPink',
'systemOrange',
'systemPurple',
]
function ItemView({
item
}: {
item: Item
}) {
return <VStack
modifiers={
modifiers()
.frame({
height: 80
})
.frame({
maxWidth: 'infinity'
})
.background(
<RoundedRectangle
cornerRadius={16}
fill={item.color}
/>
)
.contentShape({
kind: 'dragPreview',
shape: {
type: 'rect',
cornerRadius: 16
}
})
}
>
<Text
foregroundStyle="white"
font="title"
>{item.id}</Text>
</VStack>
}
function View() {
// Access dismiss function.
const dismiss = Navigation.useDismiss()
const data = useObservable<Item[]>(() => {
return new Array(30)
.fill(0)
.map((_, index) => ({
id: String(index),
color: colors[index % colors.length]
}))
})
const active = useObservable<Item | null>(null)
const onMove = (indices: number[], newOffset: number) => {
const movingItems = indices.map(index => data.value[index])
const newValue = data.value.filter((_, index) => !indices.includes(index))
newValue.splice(newOffset, 0, ...movingItems)
data.setValue(newValue)
}
return <NavigationStack>
<ScrollView
navigationTitle="ReorderableForEach demo"
toolbar={
<Toolbar>
<ToolbarItem
placement="topBarLeading"
>
<Button
title="Close"
action={dismiss}
/>
</ToolbarItem>
</Toolbar>
}
>
<LazyVGrid
columns={[
{
size: {
type: 'flexible'
}
},
{
size: {
type: 'flexible'
}
}
]}
padding={{
horizontal: true
}}
>
<ReorderableForEach
active={active}
data={data.value}
builder={(item) =>
<ItemView
item={item}
/>
}
onMove={onMove}
/>
</LazyVGrid>
</ScrollView>
</NavigationStack>
}
async function run() {
// Present view.
await Navigation.present({
element: <View />
})
// Avoiding memory leaks.
Script.exit()
}
run()