packages/storybook/stories/example-kanban.stories.tsx (162 lines of code) (raw):
import { DebugFlags, Log, ScrollAxis, ScrollBounds } from '@canvas-ui/core'
import { Canvas, Flex, ScrollView, Text, useCanvasState } from '@canvas-ui/react'
import type { StoryObj } from '@storybook/react'
import React, { FC, useCallback, useEffect, useState } from 'react'
import { CardListSchema, CardSchema, data } from './example-kanban.data'
type BoardProps = {
data: CardListSchema[]
}
type CardListProps = {
id: string
defalutCards: CardSchema[]
width: number
}
type CardProps = {
id: string
text: string
index: number
width: number
onPointerDown: (index: number) => void
}
const Card: FC<CardProps> = props => {
const { id, text, index, width, onPointerDown } = props
const [style, setStyle] = useState({
width,
paddingLeft: 8,
paddingTop: 8,
paddingRight: 8,
paddingBottom: 8,
marginBottom: 8,
backgroundColor: '#ffffff',
borderRadius: 4,
boxShadow: '0 1px 2px rgb(0 0 0 / 10%)',
cursor: 'pointer',
})
const handlePointerOut = useCallback(
() => {
setStyle(pre => {
return {
...pre,
borderColor: undefined,
borderWidth: undefined
}
})
},
[],
)
const handlePointerOver = useCallback(
() => {
setStyle(pre => {
return {
...pre,
borderColor: '#1B9AEE',
borderWidth: 1
}
})
},
[],
)
const handlePointerDown = useCallback(
() => {
onPointerDown(index)
},
[onPointerDown, index],
)
return (
<Flex
id={id}
style={style}
onPointerOut={handlePointerOut}
onPointerOver={handlePointerOver}
onPointerDown={handlePointerDown}
>
<Text style={{ color: '#383838', fontSize: 14, maxLines: 3 }}>
{text}
</Text>
</Flex>
)
}
const CardList: FC<CardListProps> = props => {
const { id, defalutCards, width } = props
const [cards, setCards] = useState(defalutCards)
const handlePointerDown = useCallback(
(index: number) => {
const nodeId = id + '-flex' + '-' + cards.length
cards.splice(index + 1, 0, {
text: `任务 ${nodeId}`.repeat(Math.ceil(Math.random() * 20)),
id: id + '-flex' + '-' + cards.length
})
setCards([...cards])
},
[cards, id],
)
const content = cards.map((item, index) => {
return (
<Card
key={item.id}
id={item.id}
text={item.text}
index={index}
width={width}
onPointerDown={handlePointerDown}
/>
)
})
return (
<ScrollView
id={id}
style={{ width: 220, height: '100%' }}
scrollBounds={ScrollBounds.Fit}
scrollAxis={ScrollAxis.Vertical}
>
<Flex
id={id + '-flex'}
style={{ flexDirection: 'column', paddingLeft: 12, paddingTop: 12, paddingRight: 12 }}
>
{content}
</Flex>
</ScrollView>
)
}
const Board: FC<BoardProps> = props => {
const { data } = props
const { width, height } = useCanvasState()
const content = data.map(item => {
return (
<CardList key={item.id} id={item.id} defalutCards={item.cards} width={200} />
)
})
return (
<ScrollView
id='board'
style={{ width, height }}
scrollBounds={ScrollBounds.Fit}
scrollAxis={ScrollAxis.Horizontal}
>
<Flex id='list-container-wrapper' style={{ height, paddingTop: 12, paddingBottom: 12 }}>
{content}
</Flex>
</ScrollView>
)
}
export const KanbanTest: StoryObj<React.FC> = () => {
useEffect(() => {
const restore = DebugFlags.set(0)
Log.disableAll = true
return () => {
Log.disableAll = false
restore()
}
})
return (
<Canvas onReady={() => console.info('canvas ready')}>
<Board data={data} />
</Canvas>
)
}
KanbanTest.storyName = 'Kanban'
export default {
title: 'example/Kanban',
component: KanbanTest,
decorators: [(Story: React.ComponentType) => <div style={{ backgroundColor: '#efefef', width: '100%', height: '100vh' }}><Story /></div>],
}