@edv4h/usketch-plugin-timter 0.1.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/index.d.ts +4 -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 +18 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +131 -0
- package/dist/plugin.js.map +1 -0
- package/dist/timer-model.d.ts +43 -0
- package/dist/timer-model.d.ts.map +1 -0
- package/dist/timer-model.js +63 -0
- package/dist/timer-model.js.map +1 -0
- package/dist/timer-shape.d.ts +42 -0
- package/dist/timer-shape.d.ts.map +1 -0
- package/dist/timer-shape.js +296 -0
- package/dist/timer-shape.js.map +1 -0
- package/package.json +50 -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.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { createTimterPlugin, type TimterPluginOptions } from "./plugin.js";
|
|
2
|
+
export { displayMs, formatDuration, initialCore, isDone, pause, reset, start, type TimerCore, type TimerType, } from "./timer-model.js";
|
|
3
|
+
export { TIMER_SHAPE_TYPE, type TimerShapeData } from "./timer-shape.js";
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EACN,SAAS,EACT,cAAc,EACd,WAAW,EACX,MAAM,EACN,KAAK,EACL,KAAK,EACL,KAAK,EACL,KAAK,SAAS,EACd,KAAK,SAAS,GACd,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,KAAK,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAA4B,MAAM,aAAa,CAAC;AAC3E,OAAO,EACN,SAAS,EACT,cAAc,EACd,WAAW,EACX,MAAM,EACN,KAAK,EACL,KAAK,EACL,KAAK,GAGL,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAuB,MAAM,kBAAkB,CAAC"}
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type UsketchPlugin } from "@edv4h/usketch-shared";
|
|
2
|
+
import type { ServerClock } from "@edv4h/usketch-sync";
|
|
3
|
+
export interface TimterPluginOptions {
|
|
4
|
+
/** Shared server clock so all users agree on "now". */
|
|
5
|
+
serverClock: ServerClock;
|
|
6
|
+
/** Attribution for created-by (reserved). Defaults to "local". */
|
|
7
|
+
userId?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Shared timers as **canvas shapes** (single source of truth). The `timer` shape
|
|
11
|
+
* (see `timer-shape`) is placeable/movable and syncs via the normal shapes map;
|
|
12
|
+
* this plugin additionally surfaces every timer shape in the Debug HUD's Controls
|
|
13
|
+
* dock (group "Timter") — add / per-timer toggle-reset-remove / clear-all — so
|
|
14
|
+
* timers created either way (canvas tool or Controls) appear in one list. All
|
|
15
|
+
* timing is on the shared server clock so users agree on "now".
|
|
16
|
+
*/
|
|
17
|
+
export declare function createTimterPlugin(options: TimterPluginOptions): UsketchPlugin;
|
|
18
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAIN,KAAK,aAAa,EAClB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAWvD,MAAM,WAAW,mBAAmB;IACnC,uDAAuD;IACvD,WAAW,EAAE,WAAW,CAAC;IACzB,kEAAkE;IAClE,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,aAAa,CAqI9E"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { generateId, } from "@edv4h/usketch-shared";
|
|
2
|
+
import { createAddShapeCommand } from "@edv4h/usketch-store";
|
|
3
|
+
import { displayMs, formatDuration, isDone } from "./timer-model.js";
|
|
4
|
+
import { coreOf, dispatchTimerShapeAction, makeTimerShape, registerTimerShape, TIMER_SHAPE_TYPE, } from "./timer-shape.js";
|
|
5
|
+
/**
|
|
6
|
+
* Shared timers as **canvas shapes** (single source of truth). The `timer` shape
|
|
7
|
+
* (see `timer-shape`) is placeable/movable and syncs via the normal shapes map;
|
|
8
|
+
* this plugin additionally surfaces every timer shape in the Debug HUD's Controls
|
|
9
|
+
* dock (group "Timter") — add / per-timer toggle-reset-remove / clear-all — so
|
|
10
|
+
* timers created either way (canvas tool or Controls) appear in one list. All
|
|
11
|
+
* timing is on the shared server clock so users agree on "now".
|
|
12
|
+
*/
|
|
13
|
+
export function createTimterPlugin(options) {
|
|
14
|
+
return {
|
|
15
|
+
id: "usketch-plugin-timter",
|
|
16
|
+
name: "タイマー",
|
|
17
|
+
setup(ctx) {
|
|
18
|
+
const now = () => options.serverClock.now();
|
|
19
|
+
// ── Timer shape (placeable, movable) — the source of truth ──
|
|
20
|
+
const disposeShape = registerTimerShape(ctx, options.serverClock, options.userId ?? "local");
|
|
21
|
+
const listTimers = () => [...ctx.store.getShapes().values()]
|
|
22
|
+
.filter((s) => s.type === TIMER_SHAPE_TYPE)
|
|
23
|
+
.sort((a, b) => (a.createdAt ?? 0) - (b.createdAt ?? 0) || a.id.localeCompare(b.id));
|
|
24
|
+
const addTimer = (timerType, durationMs) => {
|
|
25
|
+
// Place at the current viewport center.
|
|
26
|
+
const vp = ctx.store.getViewport();
|
|
27
|
+
const cx = (window.innerWidth / 2 - vp.x) / vp.zoom;
|
|
28
|
+
const cy = (window.innerHeight / 2 - vp.y) / vp.zoom;
|
|
29
|
+
const shape = makeTimerShape({
|
|
30
|
+
id: generateId(),
|
|
31
|
+
x: cx - 80,
|
|
32
|
+
y: cy - 60,
|
|
33
|
+
timerType,
|
|
34
|
+
durationMs,
|
|
35
|
+
serverNow: now(),
|
|
36
|
+
});
|
|
37
|
+
ctx.commands.execute(createAddShapeCommand(ctx.store, shape));
|
|
38
|
+
ctx.store.setSelection([shape.id]);
|
|
39
|
+
};
|
|
40
|
+
// ── Global actions (Controls → "Timter") ──
|
|
41
|
+
const globalOffs = [
|
|
42
|
+
ctx.actions.register({
|
|
43
|
+
id: "timter:new-countdown",
|
|
44
|
+
label: "⏳ カウントダウン追加",
|
|
45
|
+
group: "Timter",
|
|
46
|
+
order: 0,
|
|
47
|
+
params: [{ name: "minutes", type: "number", min: 1, max: 180, step: 1, default: 5 }],
|
|
48
|
+
run: ({ minutes }) => addTimer("countdown", Math.max(1, Number(minutes) || 5) * 60_000),
|
|
49
|
+
}),
|
|
50
|
+
ctx.actions.register({
|
|
51
|
+
id: "timter:new-stopwatch",
|
|
52
|
+
label: "⏱ ストップウォッチ追加",
|
|
53
|
+
group: "Timter",
|
|
54
|
+
order: 1,
|
|
55
|
+
run: () => addTimer("stopwatch"),
|
|
56
|
+
}),
|
|
57
|
+
ctx.actions.register({
|
|
58
|
+
id: "timter:clear-all",
|
|
59
|
+
label: "✕ 全タイマー削除",
|
|
60
|
+
group: "Timter",
|
|
61
|
+
order: 2,
|
|
62
|
+
isEnabled: () => listTimers().length > 0,
|
|
63
|
+
run: () => {
|
|
64
|
+
for (const t of listTimers())
|
|
65
|
+
ctx.store.deleteShape(t.id);
|
|
66
|
+
},
|
|
67
|
+
}),
|
|
68
|
+
];
|
|
69
|
+
// ── Per-timer actions, rebuilt on store change + ticked while running ──
|
|
70
|
+
let perTimerOffs = [];
|
|
71
|
+
let tick = null;
|
|
72
|
+
const clearPerTimer = () => {
|
|
73
|
+
for (const off of perTimerOffs)
|
|
74
|
+
off();
|
|
75
|
+
perTimerOffs = [];
|
|
76
|
+
};
|
|
77
|
+
const rebuild = () => {
|
|
78
|
+
clearPerTimer();
|
|
79
|
+
const timers = listTimers();
|
|
80
|
+
const serverNow = now();
|
|
81
|
+
timers.forEach((s, idx) => {
|
|
82
|
+
const n = idx + 1;
|
|
83
|
+
const icon = s.timerType === "countdown" ? "⏳" : "⏱";
|
|
84
|
+
const done = s.timerType === "countdown" && isDone(coreOf(s), serverNow);
|
|
85
|
+
const time = formatDuration(displayMs(coreOf(s), serverNow));
|
|
86
|
+
perTimerOffs.push(ctx.actions.register({
|
|
87
|
+
id: `timter:${s.id}:toggle`,
|
|
88
|
+
group: "Timter",
|
|
89
|
+
order: 10 + idx * 3,
|
|
90
|
+
label: `${s.running ? "⏸" : "▶"} ${icon} #${n} ${time}${done ? " ⏰終了" : ""}`,
|
|
91
|
+
isActive: () => ctx.store.getShape(s.id)?.running ?? false,
|
|
92
|
+
run: () => dispatchTimerShapeAction({ id: s.id, action: "toggle" }),
|
|
93
|
+
}), ctx.actions.register({
|
|
94
|
+
id: `timter:${s.id}:reset`,
|
|
95
|
+
group: "Timter",
|
|
96
|
+
order: 10 + idx * 3 + 1,
|
|
97
|
+
label: `↺ #${n} リセット`,
|
|
98
|
+
run: () => dispatchTimerShapeAction({ id: s.id, action: "reset" }),
|
|
99
|
+
}), ctx.actions.register({
|
|
100
|
+
id: `timter:${s.id}:remove`,
|
|
101
|
+
group: "Timter",
|
|
102
|
+
order: 10 + idx * 3 + 2,
|
|
103
|
+
label: `✕ #${n} 削除`,
|
|
104
|
+
run: () => ctx.store.deleteShape(s.id),
|
|
105
|
+
}));
|
|
106
|
+
});
|
|
107
|
+
const needsTick = timers.some((s) => s.running && !(s.timerType === "countdown" && isDone(coreOf(s), serverNow)));
|
|
108
|
+
if (needsTick && tick == null)
|
|
109
|
+
tick = setInterval(rebuild, 1000);
|
|
110
|
+
else if (!needsTick && tick != null) {
|
|
111
|
+
clearInterval(tick);
|
|
112
|
+
tick = null;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
const unsub = ctx.store.subscribe(rebuild);
|
|
116
|
+
rebuild();
|
|
117
|
+
return () => {
|
|
118
|
+
for (const off of globalOffs)
|
|
119
|
+
off();
|
|
120
|
+
clearPerTimer();
|
|
121
|
+
if (tick != null) {
|
|
122
|
+
clearInterval(tick);
|
|
123
|
+
tick = null;
|
|
124
|
+
}
|
|
125
|
+
unsub();
|
|
126
|
+
disposeShape();
|
|
127
|
+
};
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timer domain model — pure, framework-free, time-source agnostic (every
|
|
3
|
+
* function takes an explicit `serverNow` so the same logic runs against the
|
|
4
|
+
* shared server clock). The core timing state ({@link TimerCore}) is deliberately
|
|
5
|
+
* envelope-free so it can be embedded both in the collaborative `timters` map
|
|
6
|
+
* (as {@link TimerEntry}) and in a canvas timer shape. New timer types are added
|
|
7
|
+
* by extending {@link TimerType} + one {@link TIMER_KINDS} entry; the transitions
|
|
8
|
+
* stay type-agnostic.
|
|
9
|
+
*/
|
|
10
|
+
export type TimerType = "countdown" | "stopwatch";
|
|
11
|
+
/** The minimal timing state shared by every timer representation. */
|
|
12
|
+
export interface TimerCore {
|
|
13
|
+
type: TimerType;
|
|
14
|
+
running: boolean;
|
|
15
|
+
/** Server-epoch ms: countdown → endsAt while running; stopwatch → startedAt while running. Null when paused. */
|
|
16
|
+
anchorAt: number | null;
|
|
17
|
+
/** Paused snapshot: countdown → remaining ms; stopwatch → elapsed ms. */
|
|
18
|
+
accumMs: number;
|
|
19
|
+
/** Configured length (countdown); 0 for stopwatch. */
|
|
20
|
+
durationMs: number;
|
|
21
|
+
}
|
|
22
|
+
interface TimerKind {
|
|
23
|
+
displayMs(c: TimerCore, serverNow: number): number;
|
|
24
|
+
isDone(c: TimerCore, serverNow: number): boolean;
|
|
25
|
+
onStart(c: TimerCore, serverNow: number): Pick<TimerCore, "anchorAt" | "accumMs">;
|
|
26
|
+
onPause(c: TimerCore, serverNow: number): Pick<TimerCore, "anchorAt" | "accumMs">;
|
|
27
|
+
initial(durationMs: number): Pick<TimerCore, "anchorAt" | "accumMs" | "durationMs">;
|
|
28
|
+
}
|
|
29
|
+
export declare const TIMER_KINDS: Record<TimerType, TimerKind>;
|
|
30
|
+
/** Fresh, stopped core for a type + configured duration. */
|
|
31
|
+
export declare function initialCore(type: TimerType, durationMs: number): TimerCore;
|
|
32
|
+
export declare function displayMs(c: TimerCore, serverNow: number): number;
|
|
33
|
+
export declare function isDone(c: TimerCore, serverNow: number): boolean;
|
|
34
|
+
/** Start or resume. Returns the same core (no-op) if already running. */
|
|
35
|
+
export declare function start(c: TimerCore, serverNow: number): TimerCore;
|
|
36
|
+
/** Pause, snapshotting remaining/elapsed. No-op if already paused. */
|
|
37
|
+
export declare function pause(c: TimerCore, serverNow: number): TimerCore;
|
|
38
|
+
/** Return to the stopped, initial state for the configured duration. */
|
|
39
|
+
export declare function reset(c: TimerCore): TimerCore;
|
|
40
|
+
/** Format ms as `M:SS` (or `H:MM:SS` past an hour). Negative clamps to 0. */
|
|
41
|
+
export declare function formatDuration(ms: number): string;
|
|
42
|
+
export {};
|
|
43
|
+
//# sourceMappingURL=timer-model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timer-model.d.ts","sourceRoot":"","sources":["../src/timer-model.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC;AAElD,qEAAqE;AACrE,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,gHAAgH;IAChH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,yEAAyE;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,SAAS;IAClB,SAAS,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IACnD,MAAM,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC;IACjD,OAAO,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,UAAU,GAAG,SAAS,CAAC,CAAC;IAClF,OAAO,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,UAAU,GAAG,SAAS,CAAC,CAAC;IAClF,OAAO,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC,SAAS,EAAE,UAAU,GAAG,SAAS,GAAG,YAAY,CAAC,CAAC;CACpF;AAED,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,SAAS,EAAE,SAAS,CAepD,CAAC;AAEF,4DAA4D;AAC5D,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,GAAG,SAAS,CAE1E;AAED,wBAAgB,SAAS,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAEjE;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAE/D;AAED,yEAAyE;AACzE,wBAAgB,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,CAGhE;AAED,sEAAsE;AACtE,wBAAgB,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,GAAG,SAAS,CAGhE;AAED,wEAAwE;AACxE,wBAAgB,KAAK,CAAC,CAAC,EAAE,SAAS,GAAG,SAAS,CAE7C;AAED,6EAA6E;AAC7E,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAQjD"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Timer domain model — pure, framework-free, time-source agnostic (every
|
|
3
|
+
* function takes an explicit `serverNow` so the same logic runs against the
|
|
4
|
+
* shared server clock). The core timing state ({@link TimerCore}) is deliberately
|
|
5
|
+
* envelope-free so it can be embedded both in the collaborative `timters` map
|
|
6
|
+
* (as {@link TimerEntry}) and in a canvas timer shape. New timer types are added
|
|
7
|
+
* by extending {@link TimerType} + one {@link TIMER_KINDS} entry; the transitions
|
|
8
|
+
* stay type-agnostic.
|
|
9
|
+
*/
|
|
10
|
+
export const TIMER_KINDS = {
|
|
11
|
+
countdown: {
|
|
12
|
+
displayMs: (c, now) => (c.running ? Math.max(0, (c.anchorAt ?? now) - now) : c.accumMs),
|
|
13
|
+
isDone: (c, now) => (c.running ? (c.anchorAt ?? now) - now <= 0 : c.accumMs <= 0),
|
|
14
|
+
onStart: (c, now) => ({ anchorAt: now + c.accumMs, accumMs: c.accumMs }),
|
|
15
|
+
onPause: (c, now) => ({ anchorAt: null, accumMs: Math.max(0, (c.anchorAt ?? now) - now) }),
|
|
16
|
+
initial: (d) => ({ anchorAt: null, accumMs: d, durationMs: d }),
|
|
17
|
+
},
|
|
18
|
+
stopwatch: {
|
|
19
|
+
displayMs: (c, now) => (c.running ? now - (c.anchorAt ?? now) + c.accumMs : c.accumMs),
|
|
20
|
+
isDone: () => false,
|
|
21
|
+
onStart: (c, now) => ({ anchorAt: now, accumMs: c.accumMs }),
|
|
22
|
+
onPause: (c, now) => ({ anchorAt: null, accumMs: now - (c.anchorAt ?? now) + c.accumMs }),
|
|
23
|
+
initial: () => ({ anchorAt: null, accumMs: 0, durationMs: 0 }),
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
/** Fresh, stopped core for a type + configured duration. */
|
|
27
|
+
export function initialCore(type, durationMs) {
|
|
28
|
+
return { type, running: false, ...TIMER_KINDS[type].initial(durationMs) };
|
|
29
|
+
}
|
|
30
|
+
export function displayMs(c, serverNow) {
|
|
31
|
+
return TIMER_KINDS[c.type].displayMs(c, serverNow);
|
|
32
|
+
}
|
|
33
|
+
export function isDone(c, serverNow) {
|
|
34
|
+
return TIMER_KINDS[c.type].isDone(c, serverNow);
|
|
35
|
+
}
|
|
36
|
+
/** Start or resume. Returns the same core (no-op) if already running. */
|
|
37
|
+
export function start(c, serverNow) {
|
|
38
|
+
if (c.running)
|
|
39
|
+
return c;
|
|
40
|
+
return { ...c, ...TIMER_KINDS[c.type].onStart(c, serverNow), running: true };
|
|
41
|
+
}
|
|
42
|
+
/** Pause, snapshotting remaining/elapsed. No-op if already paused. */
|
|
43
|
+
export function pause(c, serverNow) {
|
|
44
|
+
if (!c.running)
|
|
45
|
+
return c;
|
|
46
|
+
return { ...c, ...TIMER_KINDS[c.type].onPause(c, serverNow), running: false };
|
|
47
|
+
}
|
|
48
|
+
/** Return to the stopped, initial state for the configured duration. */
|
|
49
|
+
export function reset(c) {
|
|
50
|
+
return initialCore(c.type, c.durationMs);
|
|
51
|
+
}
|
|
52
|
+
/** Format ms as `M:SS` (or `H:MM:SS` past an hour). Negative clamps to 0. */
|
|
53
|
+
export function formatDuration(ms) {
|
|
54
|
+
const total = Math.max(0, Math.round(ms / 1000));
|
|
55
|
+
const h = Math.floor(total / 3600);
|
|
56
|
+
const m = Math.floor((total % 3600) / 60);
|
|
57
|
+
const s = total % 60;
|
|
58
|
+
const ss = String(s).padStart(2, "0");
|
|
59
|
+
if (h > 0)
|
|
60
|
+
return `${h}:${String(m).padStart(2, "0")}:${ss}`;
|
|
61
|
+
return `${m}:${ss}`;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=timer-model.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timer-model.js","sourceRoot":"","sources":["../src/timer-model.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type PluginContext, type ShapeData } from "@edv4h/usketch-shared";
|
|
2
|
+
import type { ServerClock } from "@edv4h/usketch-sync";
|
|
3
|
+
import { type TimerCore, type TimerType } from "./timer-model.js";
|
|
4
|
+
export declare const TIMER_SHAPE_TYPE = "timer";
|
|
5
|
+
/** A timer as a placeable canvas shape. Timing state mirrors {@link TimerCore}. */
|
|
6
|
+
export interface TimerShapeData extends ShapeData {
|
|
7
|
+
type: typeof TIMER_SHAPE_TYPE;
|
|
8
|
+
timerType: TimerType;
|
|
9
|
+
running: boolean;
|
|
10
|
+
anchorAt: number | null;
|
|
11
|
+
accumMs: number;
|
|
12
|
+
durationMs: number;
|
|
13
|
+
}
|
|
14
|
+
export type ShapeAction = {
|
|
15
|
+
id: string;
|
|
16
|
+
action: "toggle" | "reset" | "switch-type";
|
|
17
|
+
} | {
|
|
18
|
+
id: string;
|
|
19
|
+
action: "adjust";
|
|
20
|
+
value: number;
|
|
21
|
+
};
|
|
22
|
+
export declare const coreOf: (s: TimerShapeData) => TimerCore;
|
|
23
|
+
declare function emit(detail: ShapeAction): void;
|
|
24
|
+
/** Dispatch a timer-shape action (toggle/reset/…) — used by the Controls actions too. */
|
|
25
|
+
export declare const dispatchTimerShapeAction: typeof emit;
|
|
26
|
+
/** Build a started timer shape of a given type/duration (used by Controls "add"). */
|
|
27
|
+
export declare function makeTimerShape(params: {
|
|
28
|
+
id: string;
|
|
29
|
+
x: number;
|
|
30
|
+
y: number;
|
|
31
|
+
timerType: TimerType;
|
|
32
|
+
durationMs?: number;
|
|
33
|
+
serverNow: number;
|
|
34
|
+
}): TimerShapeData;
|
|
35
|
+
/**
|
|
36
|
+
* Register the timer shape, its draw tool, and the button-action listener.
|
|
37
|
+
* `serverClock` is closed over by the renderer so every client computes the
|
|
38
|
+
* remaining/elapsed time against the shared server clock.
|
|
39
|
+
*/
|
|
40
|
+
export declare function registerTimerShape(ctx: PluginContext, serverClock: ServerClock, _userId: string): () => void;
|
|
41
|
+
export {};
|
|
42
|
+
//# sourceMappingURL=timer-shape.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timer-shape.d.ts","sourceRoot":"","sources":["../src/timer-shape.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIN,KAAK,aAAa,EAGlB,KAAK,SAAS,EAEd,MAAM,uBAAuB,CAAC;AAE/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,OAAO,EAQN,KAAK,SAAS,EACd,KAAK,SAAS,EACd,MAAM,kBAAkB,CAAC;AAE1B,eAAO,MAAM,gBAAgB,UAAU,CAAC;AAIxC,mFAAmF;AACnF,MAAM,WAAW,cAAe,SAAQ,SAAS;IAChD,IAAI,EAAE,OAAO,gBAAgB,CAAC;IAC9B,SAAS,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,WAAW,GACpB;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,GAAG,aAAa,CAAA;CAAE,GAC1D;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnD,eAAO,MAAM,MAAM,MAAO,cAAc,KAAG,SAMzC,CAAC;AAUH,iBAAS,IAAI,CAAC,MAAM,EAAE,WAAW,QAEhC;AAED,yFAAyF;AACzF,eAAO,MAAM,wBAAwB,aAAO,CAAC;AAyP7C,qFAAqF;AACrF,wBAAgB,cAAc,CAAC,MAAM,EAAE;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CAClB,GAAG,cAAc,CAMjB;AAYD;;;;GAIG;AACH,wBAAgB,kBAAkB,CACjC,GAAG,EAAE,aAAa,EAClB,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,MAAM,GACb,MAAM,IAAI,CAkGZ"}
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { generateId, } from "@edv4h/usketch-shared";
|
|
3
|
+
import { createAddShapeCommand } from "@edv4h/usketch-store";
|
|
4
|
+
import { useEffect, useReducer } from "react";
|
|
5
|
+
import { displayMs, formatDuration, initialCore, isDone, pause, reset, start, } from "./timer-model.js";
|
|
6
|
+
export const TIMER_SHAPE_TYPE = "timer";
|
|
7
|
+
const DEFAULT_MINUTES = 5;
|
|
8
|
+
const ACTION_EVENT = "usketch:timter-shape-action";
|
|
9
|
+
export const coreOf = (s) => ({
|
|
10
|
+
type: s.timerType,
|
|
11
|
+
running: s.running,
|
|
12
|
+
anchorAt: s.anchorAt,
|
|
13
|
+
accumMs: s.accumMs,
|
|
14
|
+
durationMs: s.durationMs,
|
|
15
|
+
});
|
|
16
|
+
const corePatch = (c) => ({
|
|
17
|
+
timerType: c.type,
|
|
18
|
+
running: c.running,
|
|
19
|
+
anchorAt: c.anchorAt,
|
|
20
|
+
accumMs: c.accumMs,
|
|
21
|
+
durationMs: c.durationMs,
|
|
22
|
+
});
|
|
23
|
+
function emit(detail) {
|
|
24
|
+
window.dispatchEvent(new CustomEvent(ACTION_EVENT, { detail }));
|
|
25
|
+
}
|
|
26
|
+
/** Dispatch a timer-shape action (toggle/reset/…) — used by the Controls actions too. */
|
|
27
|
+
export const dispatchTimerShapeAction = emit;
|
|
28
|
+
// ── View ──
|
|
29
|
+
const btn = {
|
|
30
|
+
border: "1px solid #d1d5db",
|
|
31
|
+
borderRadius: 6,
|
|
32
|
+
background: "#f5f5f5",
|
|
33
|
+
color: "#333",
|
|
34
|
+
cursor: "pointer",
|
|
35
|
+
fontSize: 14,
|
|
36
|
+
lineHeight: 1,
|
|
37
|
+
padding: "4px 8px",
|
|
38
|
+
};
|
|
39
|
+
function TimerShapeView({ shape, serverClock, }) {
|
|
40
|
+
const [, force] = useReducer((n) => n + 1, 0);
|
|
41
|
+
const running = shape.running;
|
|
42
|
+
// Self-tick while running so the display counts without writing to the store.
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
if (!running)
|
|
45
|
+
return;
|
|
46
|
+
const id = setInterval(force, 250);
|
|
47
|
+
return () => clearInterval(id);
|
|
48
|
+
}, [running]);
|
|
49
|
+
const core = coreOf(shape);
|
|
50
|
+
const serverNow = serverClock.now();
|
|
51
|
+
const done = shape.timerType === "countdown" && isDone(core, serverNow);
|
|
52
|
+
const icon = shape.timerType === "countdown" ? "⏳" : "⏱";
|
|
53
|
+
const stop = (e) => e.stopPropagation();
|
|
54
|
+
return (_jsxs("div", { style: {
|
|
55
|
+
width: "100%",
|
|
56
|
+
height: "100%",
|
|
57
|
+
boxSizing: "border-box",
|
|
58
|
+
display: "flex",
|
|
59
|
+
flexDirection: "column",
|
|
60
|
+
alignItems: "center",
|
|
61
|
+
justifyContent: "center",
|
|
62
|
+
gap: 6,
|
|
63
|
+
padding: 8,
|
|
64
|
+
background: done ? "#fee2e2" : shape.style.fill,
|
|
65
|
+
border: `${shape.style.strokeWidth}px solid ${done ? "#ef4444" : shape.style.stroke}`,
|
|
66
|
+
borderRadius: 10,
|
|
67
|
+
fontFamily: "system-ui, sans-serif",
|
|
68
|
+
userSelect: "none",
|
|
69
|
+
}, children: [_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [!running && (_jsx("button", { type: "button", title: "\u7A2E\u5225\u3092\u5207\u66FF", style: btn, onPointerDown: stop, onClick: (e) => {
|
|
70
|
+
stop(e);
|
|
71
|
+
emit({ id: shape.id, action: "switch-type" });
|
|
72
|
+
}, children: icon })), running && _jsx("span", { style: { fontSize: 16 }, children: icon }), _jsx("span", { style: {
|
|
73
|
+
fontVariantNumeric: "tabular-nums",
|
|
74
|
+
fontSize: 30,
|
|
75
|
+
fontWeight: 700,
|
|
76
|
+
color: done ? "#b91c1c" : "#1e1e1e",
|
|
77
|
+
}, children: formatDuration(displayMs(core, serverNow)) })] }), !running && shape.timerType === "countdown" && (_jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [_jsx("button", { type: "button", title: "\u22121\u5206", style: btn, onPointerDown: stop, onClick: (e) => {
|
|
78
|
+
stop(e);
|
|
79
|
+
emit({ id: shape.id, action: "adjust", value: -1 });
|
|
80
|
+
}, children: "\u2212" }), _jsx("button", { type: "button", title: "+1\u5206", style: btn, onPointerDown: stop, onClick: (e) => {
|
|
81
|
+
stop(e);
|
|
82
|
+
emit({ id: shape.id, action: "adjust", value: 1 });
|
|
83
|
+
}, children: "\uFF0B" })] })), _jsxs("div", { style: { display: "flex", gap: 8 }, children: [_jsx("button", { type: "button", title: running ? "一時停止" : "開始", style: btn, onPointerDown: stop, onClick: (e) => {
|
|
84
|
+
stop(e);
|
|
85
|
+
emit({ id: shape.id, action: "toggle" });
|
|
86
|
+
}, children: running ? "⏸" : "▶" }), _jsx("button", { type: "button", title: "\u30EA\u30BB\u30C3\u30C8", style: btn, onPointerDown: stop, onClick: (e) => {
|
|
87
|
+
stop(e);
|
|
88
|
+
emit({ id: shape.id, action: "reset" });
|
|
89
|
+
}, children: "\u21BA" })] })] }));
|
|
90
|
+
}
|
|
91
|
+
function SimplifiedTimer({ shape }) {
|
|
92
|
+
// LOD: static time, no controls (LOD is non-interactive).
|
|
93
|
+
const s = shape;
|
|
94
|
+
const rotation = typeof s.rotation === "number" ? s.rotation : 0;
|
|
95
|
+
return (_jsxs("div", { style: {
|
|
96
|
+
position: "absolute",
|
|
97
|
+
left: s.x,
|
|
98
|
+
top: s.y,
|
|
99
|
+
width: s.width,
|
|
100
|
+
height: s.height,
|
|
101
|
+
display: "flex",
|
|
102
|
+
alignItems: "center",
|
|
103
|
+
justifyContent: "center",
|
|
104
|
+
background: s.style?.fill || "#fff",
|
|
105
|
+
border: `1px solid ${s.style?.stroke || "#999"}`,
|
|
106
|
+
borderRadius: 6,
|
|
107
|
+
fontSize: Math.max(12, Math.min(s.width, s.height) * 0.32),
|
|
108
|
+
fontWeight: 700,
|
|
109
|
+
color: "#222",
|
|
110
|
+
pointerEvents: "none",
|
|
111
|
+
overflow: "hidden",
|
|
112
|
+
transform: rotation ? `rotate(${rotation}deg)` : undefined,
|
|
113
|
+
transformOrigin: "center center",
|
|
114
|
+
}, children: [s.timerType === "countdown" ? "⏳" : "⏱", " ", formatDuration(s.accumMs)] }));
|
|
115
|
+
}
|
|
116
|
+
// ── Geometry ──
|
|
117
|
+
function getBounds(data) {
|
|
118
|
+
return { x: data.x, y: data.y, width: data.width, height: data.height };
|
|
119
|
+
}
|
|
120
|
+
function hitTest(data, point) {
|
|
121
|
+
return (point.x >= data.x &&
|
|
122
|
+
point.x <= data.x + data.width &&
|
|
123
|
+
point.y >= data.y &&
|
|
124
|
+
point.y <= data.y + data.height);
|
|
125
|
+
}
|
|
126
|
+
function resize(data, handle, delta) {
|
|
127
|
+
let { x, y, width, height } = data;
|
|
128
|
+
switch (handle) {
|
|
129
|
+
case "se":
|
|
130
|
+
width += delta.x;
|
|
131
|
+
height += delta.y;
|
|
132
|
+
break;
|
|
133
|
+
case "nw":
|
|
134
|
+
x += delta.x;
|
|
135
|
+
y += delta.y;
|
|
136
|
+
width -= delta.x;
|
|
137
|
+
height -= delta.y;
|
|
138
|
+
break;
|
|
139
|
+
case "ne":
|
|
140
|
+
y += delta.y;
|
|
141
|
+
width += delta.x;
|
|
142
|
+
height -= delta.y;
|
|
143
|
+
break;
|
|
144
|
+
case "sw":
|
|
145
|
+
x += delta.x;
|
|
146
|
+
width -= delta.x;
|
|
147
|
+
height += delta.y;
|
|
148
|
+
break;
|
|
149
|
+
case "e":
|
|
150
|
+
width += delta.x;
|
|
151
|
+
break;
|
|
152
|
+
case "w":
|
|
153
|
+
x += delta.x;
|
|
154
|
+
width -= delta.x;
|
|
155
|
+
break;
|
|
156
|
+
case "n":
|
|
157
|
+
y += delta.y;
|
|
158
|
+
height -= delta.y;
|
|
159
|
+
break;
|
|
160
|
+
case "s":
|
|
161
|
+
height += delta.y;
|
|
162
|
+
break;
|
|
163
|
+
}
|
|
164
|
+
return { ...data, x, y, width: Math.max(120, width), height: Math.max(90, height) };
|
|
165
|
+
}
|
|
166
|
+
function createDefault(params) {
|
|
167
|
+
return {
|
|
168
|
+
id: params.id,
|
|
169
|
+
type: TIMER_SHAPE_TYPE,
|
|
170
|
+
x: params.x,
|
|
171
|
+
y: params.y,
|
|
172
|
+
width: 160,
|
|
173
|
+
height: 120,
|
|
174
|
+
style: { fill: "#ffffff", stroke: "#1e1e1e", strokeWidth: 2, opacity: 1 },
|
|
175
|
+
timerType: "countdown",
|
|
176
|
+
running: false,
|
|
177
|
+
anchorAt: null,
|
|
178
|
+
accumMs: DEFAULT_MINUTES * 60_000,
|
|
179
|
+
durationMs: DEFAULT_MINUTES * 60_000,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/** Build a started timer shape of a given type/duration (used by Controls "add"). */
|
|
183
|
+
export function makeTimerShape(params) {
|
|
184
|
+
const base = createDefault({ id: params.id, x: params.x, y: params.y });
|
|
185
|
+
const dur = params.timerType === "countdown" ? (params.durationMs ?? DEFAULT_MINUTES * 60_000) : 0;
|
|
186
|
+
const core = start(initialCore(params.timerType, dur), params.serverNow);
|
|
187
|
+
return { ...base, ...corePatch(core) };
|
|
188
|
+
}
|
|
189
|
+
function TimerToolIcon() {
|
|
190
|
+
return (_jsxs("svg", { width: "20", height: "20", viewBox: "0 0 20 20", "aria-hidden": "true", children: [_jsx("circle", { cx: "10", cy: "11", r: "6", fill: "none", stroke: "currentColor", strokeWidth: "1.5" }), _jsx("path", { d: "M10 11V7.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }), _jsx("path", { d: "M8 2.5h4", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })] }));
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Register the timer shape, its draw tool, and the button-action listener.
|
|
194
|
+
* `serverClock` is closed over by the renderer so every client computes the
|
|
195
|
+
* remaining/elapsed time against the shared server clock.
|
|
196
|
+
*/
|
|
197
|
+
export function registerTimerShape(ctx, serverClock, _userId) {
|
|
198
|
+
const now = () => serverClock.now();
|
|
199
|
+
ctx.shapes.register(TIMER_SHAPE_TYPE, {
|
|
200
|
+
render: (shape) => _jsx(TimerShapeView, { shape: shape, serverClock: serverClock }),
|
|
201
|
+
getBounds,
|
|
202
|
+
hitTest,
|
|
203
|
+
resize,
|
|
204
|
+
createDefault,
|
|
205
|
+
renderTarget: "html",
|
|
206
|
+
minSize: { width: 120, height: 90 },
|
|
207
|
+
simplifiedComponent: SimplifiedTimer,
|
|
208
|
+
});
|
|
209
|
+
// Button actions from the rendered shape mutate the shape via updateShape
|
|
210
|
+
// (live, non-undoable — matching other interactive shapes like counter).
|
|
211
|
+
const onAction = (e) => {
|
|
212
|
+
const detail = e.detail;
|
|
213
|
+
const shape = ctx.store.getShape(detail.id);
|
|
214
|
+
if (!shape || shape.type !== TIMER_SHAPE_TYPE)
|
|
215
|
+
return;
|
|
216
|
+
const core = coreOf(shape);
|
|
217
|
+
let next;
|
|
218
|
+
switch (detail.action) {
|
|
219
|
+
case "toggle":
|
|
220
|
+
next = core.running ? pause(core, now()) : start(core, now());
|
|
221
|
+
break;
|
|
222
|
+
case "reset":
|
|
223
|
+
next = reset(core);
|
|
224
|
+
break;
|
|
225
|
+
case "switch-type": {
|
|
226
|
+
if (core.running)
|
|
227
|
+
return;
|
|
228
|
+
const nextType = core.type === "countdown" ? "stopwatch" : "countdown";
|
|
229
|
+
const dur = nextType === "countdown" ? core.durationMs || DEFAULT_MINUTES * 60_000 : 0;
|
|
230
|
+
next = initialCore(nextType, dur);
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
233
|
+
case "adjust": {
|
|
234
|
+
if (core.running || core.type !== "countdown")
|
|
235
|
+
return;
|
|
236
|
+
next = initialCore("countdown", Math.max(60_000, core.durationMs + detail.value * 60_000));
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
default:
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
ctx.store.updateShape(detail.id, corePatch(next));
|
|
243
|
+
};
|
|
244
|
+
window.addEventListener(ACTION_EVENT, onAction);
|
|
245
|
+
// ── Draw tool: drag to size, or click for default size ──
|
|
246
|
+
let drawState = null;
|
|
247
|
+
ctx.tools.register("timer-draw", {
|
|
248
|
+
icon: TimerToolIcon,
|
|
249
|
+
cursor: "crosshair",
|
|
250
|
+
order: 41,
|
|
251
|
+
onPointerDown(_toolCtx, event) {
|
|
252
|
+
const id = generateId();
|
|
253
|
+
drawState = { startX: event.worldPoint.x, startY: event.worldPoint.y, shapeId: id };
|
|
254
|
+
const shape = createDefault({ id, x: event.worldPoint.x, y: event.worldPoint.y });
|
|
255
|
+
shape.width = 0;
|
|
256
|
+
shape.height = 0;
|
|
257
|
+
_toolCtx.store.addShape(shape);
|
|
258
|
+
},
|
|
259
|
+
onPointerMove(toolCtx, event) {
|
|
260
|
+
if (!drawState)
|
|
261
|
+
return;
|
|
262
|
+
const x = Math.min(drawState.startX, event.worldPoint.x);
|
|
263
|
+
const y = Math.min(drawState.startY, event.worldPoint.y);
|
|
264
|
+
const width = Math.abs(event.worldPoint.x - drawState.startX);
|
|
265
|
+
const height = Math.abs(event.worldPoint.y - drawState.startY);
|
|
266
|
+
toolCtx.store.updateShape(drawState.shapeId, { x, y, width, height });
|
|
267
|
+
},
|
|
268
|
+
onPointerUp(toolCtx) {
|
|
269
|
+
if (!drawState)
|
|
270
|
+
return;
|
|
271
|
+
const shape = toolCtx.store.getShape(drawState.shapeId);
|
|
272
|
+
toolCtx.store.deleteShape(drawState.shapeId);
|
|
273
|
+
if (shape && shape.width > 10 && shape.height > 10) {
|
|
274
|
+
toolCtx.commands.execute(createAddShapeCommand(toolCtx.store, shape));
|
|
275
|
+
toolCtx.store.setSelection([shape.id]);
|
|
276
|
+
}
|
|
277
|
+
else {
|
|
278
|
+
const def = createDefault({
|
|
279
|
+
id: drawState.shapeId,
|
|
280
|
+
x: drawState.startX - 80,
|
|
281
|
+
y: drawState.startY - 60,
|
|
282
|
+
});
|
|
283
|
+
toolCtx.commands.execute(createAddShapeCommand(toolCtx.store, def));
|
|
284
|
+
toolCtx.store.setSelection([def.id]);
|
|
285
|
+
}
|
|
286
|
+
drawState = null;
|
|
287
|
+
toolCtx.store.resetToDefaultTool();
|
|
288
|
+
},
|
|
289
|
+
});
|
|
290
|
+
// Note: the shape/tool registries are register-only (like other shape plugins,
|
|
291
|
+
// e.g. counter), so teardown just drops the window listener.
|
|
292
|
+
return () => {
|
|
293
|
+
window.removeEventListener(ACTION_EVENT, onAction);
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
//# sourceMappingURL=timer-shape.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timer-shape.js","sourceRoot":"","sources":["../src/timer-shape.tsx"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@edv4h/usketch-plugin-timter",
|
|
3
|
+
"version": "0.1.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.5.0",
|
|
16
|
+
"@edv4h/usketch-store": "3.3.1",
|
|
17
|
+
"@edv4h/usketch-sync": "1.1.0"
|
|
18
|
+
},
|
|
19
|
+
"peerDependencies": {
|
|
20
|
+
"react": ">=19"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@types/react": "19.2.17",
|
|
24
|
+
"typescript": "7.0.2",
|
|
25
|
+
"vitest": "4.1.10"
|
|
26
|
+
},
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"README.md"
|
|
33
|
+
],
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"repository": {
|
|
36
|
+
"type": "git",
|
|
37
|
+
"url": "git+https://github.com/EdV4H/usketch.git",
|
|
38
|
+
"directory": "plugins/usketch-plugin-timter"
|
|
39
|
+
},
|
|
40
|
+
"homepage": "https://github.com/EdV4H/usketch#readme",
|
|
41
|
+
"bugs": {
|
|
42
|
+
"url": "https://github.com/EdV4H/usketch/issues"
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"build": "tsc -p tsconfig.json",
|
|
46
|
+
"typecheck": "tsc --noEmit",
|
|
47
|
+
"test": "vitest run --passWithNoTests",
|
|
48
|
+
"clean": "rm -rf dist"
|
|
49
|
+
}
|
|
50
|
+
}
|