paseo-kanban 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/README.zh-CN.md +3 -1
- package/client/kanban-drag.ts +24 -12
- package/client/kanban-overlay.tsx +2 -1
- package/client/use-projects.ts +4 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ A lightweight, responsive Kanban board plugin for [Paseo](https://paseo.sh) work
|
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
29
|
-
## Installation
|
|
29
|
+
## Installation
|
|
30
30
|
|
|
31
31
|
### Quick Install (Recommended)
|
|
32
32
|
|
|
@@ -116,7 +116,7 @@ npm run check
|
|
|
116
116
|
npm run format
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
-
|
|
119
|
+
Maintainers can publish a new GitHub Release and npm package in one run of the **Release to GitHub and npm** GitHub Action: select `patch`, `minor`, or `major`. Configure `NPM_TOKEN` and repository write permissions first. For setup, recovery, and manual host acceptance, see the [Development & Acceptance Guide](./docs/development.md#24-一键发布github-actions).
|
|
120
120
|
|
|
121
121
|
---
|
|
122
122
|
|
package/README.zh-CN.md
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
29
|
-
##
|
|
29
|
+
## 安装
|
|
30
30
|
|
|
31
31
|
### 快速安装(推荐)
|
|
32
32
|
|
|
@@ -116,6 +116,8 @@ npm run check
|
|
|
116
116
|
npm run format
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
+
维护者可在 GitHub Actions 的 **Release to GitHub and npm** 工作流中选择 `patch` / `minor` / `major` 一键发布 GitHub Release 与 npm 包;首次使用需配置 `NPM_TOKEN` 和仓库写入权限。操作及失败重试说明见 [开发与宿主验收指南](./docs/development.md#24-一键发布github-actions)。
|
|
120
|
+
|
|
119
121
|
详细开发贡献流程、发布前检查机制与真实宿主环境手工验收指南,请参阅 [开发与宿主验收指南](./docs/development.md)。
|
|
120
122
|
|
|
121
123
|
---
|
package/client/kanban-drag.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { useRef, useSyncExternalStore, useEffect } from "react";
|
|
2
|
+
import type {
|
|
3
|
+
GestureResponderHandlers,
|
|
4
|
+
PanResponderCallbacks,
|
|
5
|
+
PanResponderInstance,
|
|
6
|
+
} from "react-native";
|
|
2
7
|
import type { KanbanTask } from "../shared/kanban";
|
|
3
8
|
|
|
4
9
|
export interface Rect {
|
|
@@ -98,16 +103,17 @@ export interface ContainerRefTarget {
|
|
|
98
103
|
measureInWindow?: (
|
|
99
104
|
callback: (x: number, y: number, width: number, height: number) => void,
|
|
100
105
|
) => void;
|
|
106
|
+
scrollTo?: (options: { x: number; animated: boolean }) => void;
|
|
101
107
|
}
|
|
102
108
|
|
|
103
109
|
export interface PanResponderFactory {
|
|
104
|
-
create: (config:
|
|
110
|
+
create: (config: PanResponderCallbacks) => PanResponderInstance;
|
|
105
111
|
}
|
|
106
112
|
|
|
107
113
|
export interface CardDragBinding {
|
|
108
114
|
readonly isDragging: boolean;
|
|
109
|
-
readonly cardPanHandlers
|
|
110
|
-
readonly handlePanHandlers
|
|
115
|
+
readonly cardPanHandlers?: GestureResponderHandlers;
|
|
116
|
+
readonly handlePanHandlers?: GestureResponderHandlers;
|
|
111
117
|
readonly onLayout: (rect: Rect) => void;
|
|
112
118
|
readonly onUnmount: () => void;
|
|
113
119
|
}
|
|
@@ -193,7 +199,10 @@ export class KanbanDragController {
|
|
|
193
199
|
private cancelHandler?: () => void;
|
|
194
200
|
private panResponderFactory: PanResponderFactory | null = null;
|
|
195
201
|
private cardCallbacks: Map<string, () => void> = new Map();
|
|
196
|
-
private cardResponders: Map<
|
|
202
|
+
private cardResponders: Map<
|
|
203
|
+
string,
|
|
204
|
+
{ body: PanResponderInstance; handle: PanResponderInstance }
|
|
205
|
+
> = new Map();
|
|
197
206
|
private pendingInputKind: "mouse" | "touch" = "mouse";
|
|
198
207
|
private operationSeq: number = 0;
|
|
199
208
|
private currentOperationId: string | null = null;
|
|
@@ -428,7 +437,7 @@ export class KanbanDragController {
|
|
|
428
437
|
const body = factory.create({
|
|
429
438
|
onStartShouldSetPanResponder: () => true,
|
|
430
439
|
onMoveShouldSetPanResponder: () => true,
|
|
431
|
-
onPanResponderGrant: (_e
|
|
440
|
+
onPanResponderGrant: (_e, gs) => {
|
|
432
441
|
const cb = this.cardCallbacks.get(key);
|
|
433
442
|
this.handlePointerDown(
|
|
434
443
|
{ taskId, laneId, onPress: cb },
|
|
@@ -436,7 +445,7 @@ export class KanbanDragController {
|
|
|
436
445
|
"body",
|
|
437
446
|
);
|
|
438
447
|
},
|
|
439
|
-
onPanResponderMove: (_e
|
|
448
|
+
onPanResponderMove: (_e, gs) => {
|
|
440
449
|
this.handlePointerMove({ x: gs.moveX, y: gs.moveY });
|
|
441
450
|
},
|
|
442
451
|
onPanResponderRelease: () => this.handlePointerUp(),
|
|
@@ -449,7 +458,7 @@ export class KanbanDragController {
|
|
|
449
458
|
const handle = factory.create({
|
|
450
459
|
onStartShouldSetPanResponder: () => true,
|
|
451
460
|
onMoveShouldSetPanResponder: () => true,
|
|
452
|
-
onPanResponderGrant: (_e
|
|
461
|
+
onPanResponderGrant: (_e, gs) => {
|
|
453
462
|
const cb = this.cardCallbacks.get(key);
|
|
454
463
|
this.handlePointerDown(
|
|
455
464
|
{ taskId, laneId, onPress: cb },
|
|
@@ -457,7 +466,7 @@ export class KanbanDragController {
|
|
|
457
466
|
"handle",
|
|
458
467
|
);
|
|
459
468
|
},
|
|
460
|
-
onPanResponderMove: (_e
|
|
469
|
+
onPanResponderMove: (_e, gs) => {
|
|
461
470
|
this.handlePointerMove({ x: gs.moveX, y: gs.moveY });
|
|
462
471
|
},
|
|
463
472
|
onPanResponderRelease: () => this.handlePointerUp(),
|
|
@@ -1358,7 +1367,7 @@ export interface UseKanbanDragReturn {
|
|
|
1358
1367
|
getTaskPreview?: (taskId: string) => TaskPreviewItem | null;
|
|
1359
1368
|
setGetTaskPreview?: (fn?: (taskId: string) => TaskPreviewItem | null) => void;
|
|
1360
1369
|
bindLane: (laneId: string) => LaneDragBinding;
|
|
1361
|
-
bindContainerRef: (instance:
|
|
1370
|
+
bindContainerRef: (instance: ContainerRefTarget | null) => void;
|
|
1362
1371
|
handleContainerLayout: (layout: Rect) => void;
|
|
1363
1372
|
handleContainerScroll: (scrollX: number) => void;
|
|
1364
1373
|
getContainerBounds: () => Rect | null;
|
|
@@ -1427,7 +1436,7 @@ export function useKanbanDrag(
|
|
|
1427
1436
|
controller.getDroppingState,
|
|
1428
1437
|
);
|
|
1429
1438
|
|
|
1430
|
-
const containerScrollRef = useRef<
|
|
1439
|
+
const containerScrollRef = useRef<ContainerRefTarget | null>(null);
|
|
1431
1440
|
const currentScrollX = useRef(0);
|
|
1432
1441
|
|
|
1433
1442
|
useEffect(() => {
|
|
@@ -1448,7 +1457,10 @@ export function useKanbanDrag(
|
|
|
1448
1457
|
if (!curVelocity || !liveFeedback.isDragging) return;
|
|
1449
1458
|
const nextOffset = Math.max(0, currentScrollX.current + curVelocity * 14);
|
|
1450
1459
|
currentScrollX.current = nextOffset;
|
|
1451
|
-
containerScrollRef.current?.scrollTo({
|
|
1460
|
+
containerScrollRef.current?.scrollTo?.({
|
|
1461
|
+
x: nextOffset,
|
|
1462
|
+
animated: false,
|
|
1463
|
+
});
|
|
1452
1464
|
}, 16);
|
|
1453
1465
|
|
|
1454
1466
|
return () => clearInterval(timer);
|
|
@@ -1463,7 +1475,7 @@ export function useKanbanDrag(
|
|
|
1463
1475
|
controller.handleScroll(scrollX);
|
|
1464
1476
|
};
|
|
1465
1477
|
|
|
1466
|
-
const bindContainerRef = (instance:
|
|
1478
|
+
const bindContainerRef = (instance: ContainerRefTarget | null) => {
|
|
1467
1479
|
containerScrollRef.current = instance;
|
|
1468
1480
|
controller.bindContainerRef(instance);
|
|
1469
1481
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useEffect, useRef, useSyncExternalStore, memo } from "react";
|
|
2
2
|
import { Animated, View, StyleSheet } from "react-native";
|
|
3
|
+
import type { ViewStyle } from "react-native";
|
|
3
4
|
import type { PluginSurfaceProps } from "@getpaseo/plugin/client";
|
|
4
5
|
import type { KanbanTask } from "../shared/kanban";
|
|
5
6
|
import { KanbanCardPreview } from "./kanban-card";
|
|
@@ -151,7 +152,7 @@ function KanbanDragOverlayInner({
|
|
|
151
152
|
const containerY = containerBounds?.y ?? 0;
|
|
152
153
|
const cardHalfWidth = layout.compact ? 125 : 140;
|
|
153
154
|
|
|
154
|
-
let overlayStyle:
|
|
155
|
+
let overlayStyle: Animated.WithAnimatedValue<ViewStyle>;
|
|
155
156
|
if (curDropping && animPos && animRotate && animScale) {
|
|
156
157
|
overlayStyle = {
|
|
157
158
|
left: animPos.x,
|
package/client/use-projects.ts
CHANGED
|
@@ -48,7 +48,9 @@ export function fetchProjectsWithOrderControl(
|
|
|
48
48
|
let isDestroyed = false;
|
|
49
49
|
|
|
50
50
|
return {
|
|
51
|
-
execute: async (
|
|
51
|
+
execute: async (
|
|
52
|
+
fetchFn: () => Promise<{ projects?: ProjectItem[] | null } | null>,
|
|
53
|
+
): Promise<void> => {
|
|
52
54
|
const requestId = ++latestRequestId;
|
|
53
55
|
try {
|
|
54
56
|
const result = await fetchFn();
|
|
@@ -56,7 +58,7 @@ export function fetchProjectsWithOrderControl(
|
|
|
56
58
|
return;
|
|
57
59
|
}
|
|
58
60
|
onUpdate({
|
|
59
|
-
projects:
|
|
61
|
+
projects: result?.projects ?? [],
|
|
60
62
|
error: null,
|
|
61
63
|
isLoading: false,
|
|
62
64
|
});
|