@edv4h/usketch-plugin-presence-activity 0.2.0
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/LICENSE +21 -0
- package/dist/activity-overlay.d.ts +35 -0
- package/dist/activity-overlay.d.ts.map +1 -0
- package/dist/activity-overlay.js +98 -0
- package/dist/activity-overlay.js.map +1 -0
- package/dist/activity.d.ts +27 -0
- package/dist/activity.d.ts.map +1 -0
- package/dist/activity.js +2 -0
- package/dist/activity.js.map +1 -0
- package/dist/ai-activity-store.d.ts +24 -0
- package/dist/ai-activity-store.d.ts.map +1 -0
- package/dist/ai-activity-store.js +22 -0
- package/dist/ai-activity-store.js.map +1 -0
- package/dist/geometry.d.ts +7 -0
- package/dist/geometry.d.ts.map +1 -0
- package/dist/geometry.js +40 -0
- package/dist/geometry.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.d.ts +19 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +74 -0
- package/dist/plugin.js.map +1 -0
- package/package.json +49 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 EdV4H
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { BoardStore, BoundingBox, ShapeRegistry, Viewport } from "@edv4h/usketch-shared";
|
|
2
|
+
import type { WsProviderHandle } from "@edv4h/usketch-sync";
|
|
3
|
+
import type { AiActivityStore } from "./ai-activity-store.js";
|
|
4
|
+
type Awareness = WsProviderHandle["awareness"];
|
|
5
|
+
interface Participant {
|
|
6
|
+
clientId: number;
|
|
7
|
+
name: string;
|
|
8
|
+
color: string;
|
|
9
|
+
action: "select" | "edit";
|
|
10
|
+
/** Per-shape world bounds this participant is selecting/editing. */
|
|
11
|
+
boxes: BoundingBox[];
|
|
12
|
+
/** Optional in-progress marquee rect (world coords). */
|
|
13
|
+
marquee?: BoundingBox;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Resolve every remote participant's `activity` awareness field into drawable
|
|
17
|
+
* world-space boxes. Self is skipped. Participants with no resolvable activity
|
|
18
|
+
* are dropped. Exported for testing the awareness→geometry mapping.
|
|
19
|
+
*/
|
|
20
|
+
export declare function collectParticipants(awareness: Awareness, store: BoardStore, shapes: ShapeRegistry): Participant[];
|
|
21
|
+
/**
|
|
22
|
+
* Screen-space SVG overlay drawing every remote participant's selection / edit /
|
|
23
|
+
* marquee in their presence color (feature #960). Mirrors the coordinate math of
|
|
24
|
+
* `UnconfirmedOverlay`. Re-renders on awareness change (own subscription) and on
|
|
25
|
+
* viewport change (the fixed layer re-renders and passes a fresh `viewport`).
|
|
26
|
+
*/
|
|
27
|
+
export declare function ActivityOverlay({ store, shapes, viewport, awareness, aiActivityStore, }: {
|
|
28
|
+
store: BoardStore;
|
|
29
|
+
shapes: ShapeRegistry;
|
|
30
|
+
viewport: Viewport;
|
|
31
|
+
awareness: Awareness;
|
|
32
|
+
aiActivityStore: AiActivityStore;
|
|
33
|
+
}): import("react").JSX.Element | null;
|
|
34
|
+
export {};
|
|
35
|
+
//# sourceMappingURL=activity-overlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity-overlay.d.ts","sourceRoot":"","sources":["../src/activity-overlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAC9F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAG5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,KAAK,SAAS,GAAG,gBAAgB,CAAC,WAAW,CAAC,CAAC;AA6B/C,UAAU,WAAW;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC1B,oEAAoE;IACpE,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,wDAAwD;IACxD,OAAO,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAClC,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,UAAU,EACjB,MAAM,EAAE,aAAa,GACnB,WAAW,EAAE,CAqBf;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,EAC/B,KAAK,EACL,MAAM,EACN,QAAQ,EACR,SAAS,EACT,eAAe,GACf,EAAE;IACF,KAAK,EAAE,UAAU,CAAC;IAClB,MAAM,EAAE,aAAa,CAAC;IACtB,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,SAAS,CAAC;IACrB,eAAe,EAAE,eAAe,CAAC;CACjC,sCAyCA"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useReducer, useSyncExternalStore } from "react";
|
|
3
|
+
import { fallbackColor, unionBounds, worldRectToScreen } from "./geometry.js";
|
|
4
|
+
/** Identity of the local in-app AI participant (matches the MCP AI presence). */
|
|
5
|
+
const AI_LABEL = "AI 🤖";
|
|
6
|
+
const AI_COLOR = "#7c3aed";
|
|
7
|
+
/** Resolve shape ids to their world bounds (registered def, else raw x/y/w/h). */
|
|
8
|
+
function resolveBoxes(store, shapes, ids) {
|
|
9
|
+
const boxes = [];
|
|
10
|
+
for (const id of ids) {
|
|
11
|
+
const shape = store.getShape(id);
|
|
12
|
+
if (!shape)
|
|
13
|
+
continue;
|
|
14
|
+
const def = shapes.get(shape.type);
|
|
15
|
+
boxes.push(def?.getBounds(shape) ?? {
|
|
16
|
+
x: shape.x,
|
|
17
|
+
y: shape.y,
|
|
18
|
+
width: shape.width,
|
|
19
|
+
height: shape.height,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
return boxes;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Resolve every remote participant's `activity` awareness field into drawable
|
|
26
|
+
* world-space boxes. Self is skipped. Participants with no resolvable activity
|
|
27
|
+
* are dropped. Exported for testing the awareness→geometry mapping.
|
|
28
|
+
*/
|
|
29
|
+
export function collectParticipants(awareness, store, shapes) {
|
|
30
|
+
const out = [];
|
|
31
|
+
for (const [clientId, state] of awareness.getStates()) {
|
|
32
|
+
if (clientId === awareness.doc.clientID)
|
|
33
|
+
continue;
|
|
34
|
+
const activity = state.activity;
|
|
35
|
+
if (!activity)
|
|
36
|
+
continue;
|
|
37
|
+
const user = state.user;
|
|
38
|
+
const boxes = resolveBoxes(store, shapes, activity.shapeIds ?? []);
|
|
39
|
+
if (boxes.length === 0 && !activity.marquee)
|
|
40
|
+
continue;
|
|
41
|
+
out.push({
|
|
42
|
+
clientId,
|
|
43
|
+
name: activity.label || user?.name || "",
|
|
44
|
+
color: user?.color || fallbackColor(clientId),
|
|
45
|
+
action: activity.action ?? "select",
|
|
46
|
+
boxes,
|
|
47
|
+
marquee: activity.marquee,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Screen-space SVG overlay drawing every remote participant's selection / edit /
|
|
54
|
+
* marquee in their presence color (feature #960). Mirrors the coordinate math of
|
|
55
|
+
* `UnconfirmedOverlay`. Re-renders on awareness change (own subscription) and on
|
|
56
|
+
* viewport change (the fixed layer re-renders and passes a fresh `viewport`).
|
|
57
|
+
*/
|
|
58
|
+
export function ActivityOverlay({ store, shapes, viewport, awareness, aiActivityStore, }) {
|
|
59
|
+
const [, bump] = useReducer((n) => n + 1, 0);
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
awareness.on("change", bump);
|
|
62
|
+
return () => awareness.off("change", bump);
|
|
63
|
+
}, [awareness]);
|
|
64
|
+
// Local in-app AI activity (this tab only) — the agent has no awareness presence.
|
|
65
|
+
const aiActivity = useSyncExternalStore(aiActivityStore.subscribe, aiActivityStore.get);
|
|
66
|
+
const participants = collectParticipants(awareness, store, shapes);
|
|
67
|
+
if (aiActivity && aiActivity.shapeIds.length > 0) {
|
|
68
|
+
const boxes = resolveBoxes(store, shapes, aiActivity.shapeIds);
|
|
69
|
+
if (boxes.length > 0) {
|
|
70
|
+
participants.push({
|
|
71
|
+
clientId: -1,
|
|
72
|
+
name: AI_LABEL,
|
|
73
|
+
color: AI_COLOR,
|
|
74
|
+
action: "edit",
|
|
75
|
+
boxes,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (participants.length === 0)
|
|
80
|
+
return null;
|
|
81
|
+
return (_jsxs("svg", { style: {
|
|
82
|
+
position: "absolute",
|
|
83
|
+
inset: 0,
|
|
84
|
+
width: "100%",
|
|
85
|
+
height: "100%",
|
|
86
|
+
pointerEvents: "none",
|
|
87
|
+
}, children: [_jsx("title", { children: "\u53C2\u52A0\u8005\u306E\u9078\u629E\u30FB\u7DE8\u96C6" }), participants.map((p) => (_jsx(ParticipantActivity, { p: p, viewport: viewport }, p.clientId)))] }));
|
|
88
|
+
}
|
|
89
|
+
const PAD = 3; // outline inflation in screen px, so it hugs outside the shape
|
|
90
|
+
function ParticipantActivity({ p, viewport }) {
|
|
91
|
+
const editing = p.action === "edit";
|
|
92
|
+
const rects = p.boxes.map((b) => worldRectToScreen(b, viewport));
|
|
93
|
+
const union = unionBounds(p.boxes);
|
|
94
|
+
const badgeAt = union ? worldRectToScreen(union, viewport) : null;
|
|
95
|
+
const marquee = p.marquee ? worldRectToScreen(p.marquee, viewport) : null;
|
|
96
|
+
return (_jsxs("g", { children: [rects.map((r, i) => (_jsx("rect", { x: r.x - PAD, y: r.y - PAD, width: r.width + PAD * 2, height: r.height + PAD * 2, fill: "none", stroke: p.color, strokeWidth: 2, rx: 4, opacity: 0.9, children: editing && (_jsx("animate", { attributeName: "opacity", values: "0.35;0.95;0.35", dur: "1.1s", repeatCount: "indefinite" })) }, i))), marquee && (_jsx("rect", { x: marquee.x, y: marquee.y, width: marquee.width, height: marquee.height, fill: p.color, fillOpacity: 0.08, stroke: p.color, strokeWidth: 1.5, strokeDasharray: "6 4" })), badgeAt && p.name && (_jsxs("g", { transform: `translate(${badgeAt.x - PAD}, ${badgeAt.y - PAD - 18})`, children: [_jsx("rect", { width: p.name.length * 7.5 + 16, height: 16, rx: 4, fill: p.color }), _jsx("text", { x: 7, y: 12, fontSize: 11, fontWeight: 600, fill: "#fff", style: { userSelect: "none" }, children: editing ? `${p.name} ✏️` : p.name })] }))] }));
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=activity-overlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity-overlay.js","sourceRoot":"","sources":["../src/activity-overlay.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { BoundingBox } from "@edv4h/usketch-shared";
|
|
2
|
+
/**
|
|
3
|
+
* A participant's live "activity" — what they are currently selecting / editing —
|
|
4
|
+
* published on the Yjs awareness `activity` field alongside the existing
|
|
5
|
+
* `user`/`cursor` fields. It is a GENERAL multiplayer channel: every participant
|
|
6
|
+
* (human or AI) publishes it, and the overlay renders it uniformly. There is no
|
|
7
|
+
* AI discriminator — the AI is just another participant whose `user.name` is "AI".
|
|
8
|
+
*
|
|
9
|
+
* Writers (presence-cursor for humans, the MCP client for AI) set the awareness
|
|
10
|
+
* field to an object of this shape; the overlay in this package reads it.
|
|
11
|
+
*/
|
|
12
|
+
export interface PresenceActivity {
|
|
13
|
+
/** Shapes the participant currently has selected / is editing. */
|
|
14
|
+
shapeIds?: string[];
|
|
15
|
+
/** In-progress selection rectangle (world coords), while marquee-dragging. */
|
|
16
|
+
marquee?: BoundingBox;
|
|
17
|
+
/** What they're doing: `select` = passive highlight, `edit` = actively mutating (pulses). */
|
|
18
|
+
action?: "select" | "edit";
|
|
19
|
+
/** Optional label shown on the badge instead of the participant name. */
|
|
20
|
+
label?: string;
|
|
21
|
+
}
|
|
22
|
+
/** The awareness `user` field this overlay reads (a subset of what presence-cursor writes). */
|
|
23
|
+
export interface PresenceUser {
|
|
24
|
+
name?: string;
|
|
25
|
+
color?: string;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=activity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../src/activity.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEzD;;;;;;;;;GASG;AACH,MAAM,WAAW,gBAAgB;IAChC,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,6FAA6F;IAC7F,MAAM,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC3B,yEAAyE;IACzE,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,+FAA+F;AAC/F,MAAM,WAAW,YAAY;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CACf"}
|
package/dist/activity.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activity.js","sourceRoot":"","sources":["../src/activity.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local (this-tab) AI activity — the in-app AI agent (⌘K → `ai:request`) writes
|
|
3
|
+
* shapes server-side, so unlike the MCP driver it has no awareness presence of its
|
|
4
|
+
* own. Instead the plugin mirrors the agent's `ai:response`/`ai:status` events into
|
|
5
|
+
* this small store, and the overlay renders it as a synthetic "AI" participant
|
|
6
|
+
* (feature #960). Only the initiating tab sees it (the edits themselves still sync
|
|
7
|
+
* to everyone via the shape store).
|
|
8
|
+
*/
|
|
9
|
+
export interface AiActivity {
|
|
10
|
+
/** Shapes the AI just placed/edited (from `ai:response`). */
|
|
11
|
+
shapeIds: string[];
|
|
12
|
+
}
|
|
13
|
+
export interface AiActivityStore {
|
|
14
|
+
get(): AiActivity | null;
|
|
15
|
+
set(next: AiActivity | null): void;
|
|
16
|
+
subscribe(listener: () => void): () => void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Create a fresh AI-activity store. One is created per plugin `setup()` so activity
|
|
20
|
+
* is scoped to that app instance — never shared across multiple `createApp()` /
|
|
21
|
+
* Canvas instances in the same JS runtime, and a teardown can't clear another's.
|
|
22
|
+
*/
|
|
23
|
+
export declare function createAiActivityStore(): AiActivityStore;
|
|
24
|
+
//# sourceMappingURL=ai-activity-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-activity-store.d.ts","sourceRoot":"","sources":["../src/ai-activity-store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IAC1B,6DAA6D;IAC7D,QAAQ,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC/B,GAAG,IAAI,UAAU,GAAG,IAAI,CAAC;IACzB,GAAG,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,GAAG,IAAI,CAAC;IACnC,SAAS,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;CAC5C;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,IAAI,eAAe,CAcvD"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create a fresh AI-activity store. One is created per plugin `setup()` so activity
|
|
3
|
+
* is scoped to that app instance — never shared across multiple `createApp()` /
|
|
4
|
+
* Canvas instances in the same JS runtime, and a teardown can't clear another's.
|
|
5
|
+
*/
|
|
6
|
+
export function createAiActivityStore() {
|
|
7
|
+
let current = null;
|
|
8
|
+
const listeners = new Set();
|
|
9
|
+
return {
|
|
10
|
+
get: () => current,
|
|
11
|
+
set(next) {
|
|
12
|
+
current = next;
|
|
13
|
+
for (const l of listeners)
|
|
14
|
+
l();
|
|
15
|
+
},
|
|
16
|
+
subscribe(listener) {
|
|
17
|
+
listeners.add(listener);
|
|
18
|
+
return () => listeners.delete(listener);
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=ai-activity-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai-activity-store.js","sourceRoot":"","sources":["../src/ai-activity-store.ts"],"names":[],"mappings":"AAmBA;;;;GAIG;AACH,MAAM,UAAU,qBAAqB;IACpC,IAAI,OAAO,GAAsB,IAAI,CAAC;IACtC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAc,CAAC;IACxC,OAAO;QACN,GAAG,EAAE,GAAG,EAAE,CAAC,OAAO;QAClB,GAAG,CAAC,IAAI;YACP,OAAO,GAAG,IAAI,CAAC;YACf,KAAK,MAAM,CAAC,IAAI,SAAS;gBAAE,CAAC,EAAE,CAAC;QAChC,CAAC;QACD,SAAS,CAAC,QAAQ;YACjB,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACxB,OAAO,GAAG,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACzC,CAAC;KACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { BoundingBox, Viewport } from "@edv4h/usketch-shared";
|
|
2
|
+
/** World-space rect → screen-space rect (same transform the canvas applies). */
|
|
3
|
+
export declare function worldRectToScreen(b: BoundingBox, vp: Viewport): BoundingBox;
|
|
4
|
+
/** Smallest box enclosing all inputs, or `null` when empty. */
|
|
5
|
+
export declare function unionBounds(boxes: readonly BoundingBox[]): BoundingBox | null;
|
|
6
|
+
export declare function fallbackColor(clientId: number): string;
|
|
7
|
+
//# sourceMappingURL=geometry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../src/geometry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAEnE,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,WAAW,EAAE,EAAE,EAAE,QAAQ,GAAG,WAAW,CAO3E;AAED,+DAA+D;AAC/D,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,GAAG,WAAW,GAAG,IAAI,CAa7E;AAaD,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEtD"}
|
package/dist/geometry.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/** World-space rect → screen-space rect (same transform the canvas applies). */
|
|
2
|
+
export function worldRectToScreen(b, vp) {
|
|
3
|
+
return {
|
|
4
|
+
x: b.x * vp.zoom + vp.x,
|
|
5
|
+
y: b.y * vp.zoom + vp.y,
|
|
6
|
+
width: b.width * vp.zoom,
|
|
7
|
+
height: b.height * vp.zoom,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
/** Smallest box enclosing all inputs, or `null` when empty. */
|
|
11
|
+
export function unionBounds(boxes) {
|
|
12
|
+
if (boxes.length === 0)
|
|
13
|
+
return null;
|
|
14
|
+
let minX = Number.POSITIVE_INFINITY;
|
|
15
|
+
let minY = Number.POSITIVE_INFINITY;
|
|
16
|
+
let maxX = Number.NEGATIVE_INFINITY;
|
|
17
|
+
let maxY = Number.NEGATIVE_INFINITY;
|
|
18
|
+
for (const b of boxes) {
|
|
19
|
+
minX = Math.min(minX, b.x);
|
|
20
|
+
minY = Math.min(minY, b.y);
|
|
21
|
+
maxX = Math.max(maxX, b.x + b.width);
|
|
22
|
+
maxY = Math.max(maxY, b.y + b.height);
|
|
23
|
+
}
|
|
24
|
+
return { x: minX, y: minY, width: maxX - minX, height: maxY - minY };
|
|
25
|
+
}
|
|
26
|
+
/** Deterministic fallback color for a participant with no `user.color`. */
|
|
27
|
+
const PALETTE = [
|
|
28
|
+
"#e74c3c",
|
|
29
|
+
"#3498db",
|
|
30
|
+
"#2ecc71",
|
|
31
|
+
"#f39c12",
|
|
32
|
+
"#9b59b6",
|
|
33
|
+
"#1abc9c",
|
|
34
|
+
"#e67e22",
|
|
35
|
+
"#e84393",
|
|
36
|
+
];
|
|
37
|
+
export function fallbackColor(clientId) {
|
|
38
|
+
return PALETTE[Math.abs(clientId) % PALETTE.length];
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=geometry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geometry.js","sourceRoot":"","sources":["../src/geometry.ts"],"names":[],"mappings":"AAEA,gFAAgF;AAChF,MAAM,UAAU,iBAAiB,CAAC,CAAc,EAAE,EAAY;IAC7D,OAAO;QACN,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;QACvB,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC;QACvB,KAAK,EAAE,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI;QACxB,MAAM,EAAE,CAAC,CAAC,MAAM,GAAG,EAAE,CAAC,IAAI;KAC1B,CAAC;AACH,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,WAAW,CAAC,KAA6B;IACxD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,IAAI,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACpC,IAAI,IAAI,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACpC,IAAI,IAAI,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACpC,IAAI,IAAI,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACpC,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACvB,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3B,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3B,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IACD,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,GAAG,IAAI,EAAE,MAAM,EAAE,IAAI,GAAG,IAAI,EAAE,CAAC;AACtE,CAAC;AAED,2EAA2E;AAC3E,MAAM,OAAO,GAAG;IACf,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;IACT,SAAS;CACT,CAAC;AACF,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC7C,OAAO,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AACrD,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type { PresenceActivity, PresenceUser } from "./activity.js";
|
|
2
|
+
export { collectParticipants } from "./activity-overlay.js";
|
|
3
|
+
export { type AiActivity, type AiActivityStore, createAiActivityStore, } from "./ai-activity-store.js";
|
|
4
|
+
export { createPresenceActivityPlugin, type PresenceActivityOptions } from "./plugin.js";
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EACN,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,qBAAqB,GACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,4BAA4B,EAAE,KAAK,uBAAuB,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAGN,qBAAqB,GACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,4BAA4B,EAAgC,MAAM,aAAa,CAAC"}
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { UsketchPlugin } from "@edv4h/usketch-shared";
|
|
2
|
+
import type { WsProviderHandle } from "@edv4h/usketch-sync";
|
|
3
|
+
export interface PresenceActivityOptions {
|
|
4
|
+
wsProvider: WsProviderHandle;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Renders every OTHER participant's live selection / edit / marquee on the canvas
|
|
8
|
+
* (feature #960) by reading the Yjs awareness `activity` field. This is a general
|
|
9
|
+
* multiplayer capability — humans and the AI participant are drawn identically;
|
|
10
|
+
* "AI" is just a participant whose `user.name` is "AI". Cursors + the Members
|
|
11
|
+
* list already come free from `presence-cursor` / `presence-store`; this only
|
|
12
|
+
* adds the selection/edit outlines.
|
|
13
|
+
*
|
|
14
|
+
* It also drives the LOCAL in-app AI: the ⌘K agent writes shapes server-side with
|
|
15
|
+
* no awareness presence, so its `ai:response` is mirrored into `aiActivityStore`
|
|
16
|
+
* and drawn as a synthetic "AI" participant on this tab.
|
|
17
|
+
*/
|
|
18
|
+
export declare function createPresenceActivityPlugin(options: PresenceActivityOptions): UsketchPlugin;
|
|
19
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAiB,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAgB5D,MAAM,WAAW,uBAAuB;IACvC,UAAU,EAAE,gBAAgB,CAAC;CAC7B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,uBAAuB,GAAG,aAAa,CAiE5F"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { ActivityOverlay } from "./activity-overlay.js";
|
|
3
|
+
import { createAiActivityStore } from "./ai-activity-store.js";
|
|
4
|
+
const LAYER_ID = "usketch-presence-activity";
|
|
5
|
+
/** How long the in-app AI highlight lingers after `ai:response` before clearing. */
|
|
6
|
+
const AI_HOLD_MS = 1600;
|
|
7
|
+
/**
|
|
8
|
+
* Renders every OTHER participant's live selection / edit / marquee on the canvas
|
|
9
|
+
* (feature #960) by reading the Yjs awareness `activity` field. This is a general
|
|
10
|
+
* multiplayer capability — humans and the AI participant are drawn identically;
|
|
11
|
+
* "AI" is just a participant whose `user.name` is "AI". Cursors + the Members
|
|
12
|
+
* list already come free from `presence-cursor` / `presence-store`; this only
|
|
13
|
+
* adds the selection/edit outlines.
|
|
14
|
+
*
|
|
15
|
+
* It also drives the LOCAL in-app AI: the ⌘K agent writes shapes server-side with
|
|
16
|
+
* no awareness presence, so its `ai:response` is mirrored into `aiActivityStore`
|
|
17
|
+
* and drawn as a synthetic "AI" participant on this tab.
|
|
18
|
+
*/
|
|
19
|
+
export function createPresenceActivityPlugin(options) {
|
|
20
|
+
const { wsProvider } = options;
|
|
21
|
+
return {
|
|
22
|
+
id: "usketch-plugin-presence-activity",
|
|
23
|
+
name: "参加者アクティビティ",
|
|
24
|
+
setup(ctx) {
|
|
25
|
+
// Per-instance (not a module singleton) so activity never leaks between
|
|
26
|
+
// multiple apps/canvases in the same runtime.
|
|
27
|
+
const aiActivityStore = createAiActivityStore();
|
|
28
|
+
// Above terrain/base/shapes, alongside the sync divergence overlay (250).
|
|
29
|
+
ctx.layers.register({
|
|
30
|
+
id: LAYER_ID,
|
|
31
|
+
order: 248,
|
|
32
|
+
fixed: true,
|
|
33
|
+
render: (renderCtx) => (_jsx(ActivityOverlay, { store: ctx.store, shapes: ctx.shapes, viewport: renderCtx.viewport, awareness: wsProvider.awareness, aiActivityStore: aiActivityStore })),
|
|
34
|
+
});
|
|
35
|
+
// ── In-app AI driver (feature #960) ──
|
|
36
|
+
// The ⌘K AI agent writes shapes server-side and has no awareness presence
|
|
37
|
+
// of its own, so mirror its `ai:response` (shapes it placed) into the local
|
|
38
|
+
// aiActivityStore — the overlay draws it as a synthetic "AI" participant on
|
|
39
|
+
// this tab. Auto-clear after a short hold; drop on error.
|
|
40
|
+
let clearTimer = null;
|
|
41
|
+
const cancelTimer = () => {
|
|
42
|
+
if (clearTimer) {
|
|
43
|
+
clearTimeout(clearTimer);
|
|
44
|
+
clearTimer = null;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
const offResponse = ctx.events.on("ai:response", (e) => {
|
|
48
|
+
const ids = (Array.isArray(e.shapes) ? e.shapes : []).map((s) => s.id).filter(Boolean);
|
|
49
|
+
if (ids.length === 0)
|
|
50
|
+
return;
|
|
51
|
+
aiActivityStore.set({ shapeIds: ids });
|
|
52
|
+
cancelTimer();
|
|
53
|
+
clearTimer = setTimeout(() => {
|
|
54
|
+
aiActivityStore.set(null);
|
|
55
|
+
clearTimer = null;
|
|
56
|
+
}, AI_HOLD_MS);
|
|
57
|
+
});
|
|
58
|
+
const offStatus = ctx.events.on("ai:status", (e) => {
|
|
59
|
+
if (e.status === "error") {
|
|
60
|
+
cancelTimer();
|
|
61
|
+
aiActivityStore.set(null);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
return () => {
|
|
65
|
+
cancelTimer();
|
|
66
|
+
aiActivityStore.set(null);
|
|
67
|
+
offResponse();
|
|
68
|
+
offStatus();
|
|
69
|
+
ctx.layers.unregister(LAYER_ID);
|
|
70
|
+
};
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.tsx"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@edv4h/usketch-plugin-presence-activity",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/index.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"source": "./src/index.ts",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@edv4h/usketch-shared": "4.11.0",
|
|
16
|
+
"@edv4h/usketch-sync": "1.3.0"
|
|
17
|
+
},
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"react": ">=19"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/react": "19.2.18",
|
|
23
|
+
"typescript": "7.0.2",
|
|
24
|
+
"vitest": "4.1.10"
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"README.md"
|
|
32
|
+
],
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "git+https://github.com/EdV4H/usketch.git",
|
|
37
|
+
"directory": "plugins/usketch-plugin-presence-activity"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://github.com/EdV4H/usketch#readme",
|
|
40
|
+
"bugs": {
|
|
41
|
+
"url": "https://github.com/EdV4H/usketch/issues"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "tsc -p tsconfig.json",
|
|
45
|
+
"typecheck": "tsc --noEmit",
|
|
46
|
+
"test": "vitest run --passWithNoTests",
|
|
47
|
+
"clean": "rm -rf dist"
|
|
48
|
+
}
|
|
49
|
+
}
|