@umriss-ui/schedule 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.
@@ -0,0 +1,2015 @@
1
+ import "./schedule.css";
2
+ var He = Object.defineProperty;
3
+ var Ye = (n, t, e) => t in n ? He(n, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : n[t] = e;
4
+ var f = (n, t, e) => Ye(n, typeof t != "symbol" ? t + "" : t, e);
5
+ import { jsxs as H, Fragment as zt, jsx as w } from "react/jsx-runtime";
6
+ import { useContext as fe, createContext as pe, useRef as $, useEffect as B, forwardRef as Xe, useState as it, useId as Ke, useLayoutEffect as vt, useImperativeHandle as We, useSyncExternalStore as Ue, useMemo as q } from "react";
7
+ import { toOperatingTimeClamped as Y, resolveColours as ze, removedIntervals as qe, MINUTE as U, calendarFrom as et, toWallClock as X, DAY as st, timeStep as je, operatingTimeTicks as Ve, HOUR as Tt, LinearScale as Ze, subscribeTheme as Je } from "@umriss-ui/charts";
8
+ import { useFormats as me, useWording as ge } from "@umriss-ui/core";
9
+ const ke = pe(null), we = pe(null);
10
+ function ve() {
11
+ return fe(we);
12
+ }
13
+ function Qe(n) {
14
+ const t = fe(ke);
15
+ if (t === null)
16
+ throw new Error(`@umriss-ui/schedule: <${n}> must be used inside a <Schedule>.`);
17
+ return t;
18
+ }
19
+ function Ct(n, t, e, s, o) {
20
+ const i = Qe(n), r = $(null);
21
+ B(() => (r.current = e(i, t), () => {
22
+ r.current !== null && o(i, r.current), r.current = null;
23
+ }), [i]), B(() => {
24
+ r.current !== null && s(i, r.current, t);
25
+ });
26
+ }
27
+ function ts(n) {
28
+ Ct("Lane", n, (t, e) => t.registerLane(e), (t, e, s) => t.updateLane(e, s), (t, e) => t.unregisterLane(e));
29
+ }
30
+ function es(n) {
31
+ Ct("LaneGroup", n, (t, e) => t.registerGroup(e), (t, e, s) => t.updateGroup(e, s), (t, e) => t.unregisterGroup(e));
32
+ }
33
+ function ye(n, t) {
34
+ Ct(n, t, (e, s) => e.registerLayer(s), (e, s, o) => e.updateLayer(s, o), (e, s) => e.unregisterLayer(s));
35
+ }
36
+ function ht(n) {
37
+ let t = !1, e = !1, s = !1, o = !1;
38
+ for (const i of n ?? [])
39
+ i === "provisional" ? (t = !0, e = !1) : i === "fixed" ? (e = !0, t = !1) : i === "muted" ? s = !0 : i === "open" && (o = !0);
40
+ return { dashed: t, hatched: e, muted: s, open: o };
41
+ }
42
+ const ss = 24, ns = 4, os = 3, yt = 4;
43
+ function qt(n) {
44
+ const { lanes: t, groups: e, collapsed: s, laneHeight: o } = n, i = new Map(e.map((m) => [m.id, m])), r = (m) => m !== void 0 && i.has(m) ? m : void 0, a = /* @__PURE__ */ new Map(), u = (m) => {
45
+ const C = [];
46
+ let L = r(m.parent);
47
+ const E = /* @__PURE__ */ new Set();
48
+ for (; L !== void 0 && !E.has(L); )
49
+ E.add(L), C.unshift(L), L = r(i.get(L).parent);
50
+ return C;
51
+ }, c = /* @__PURE__ */ new Map();
52
+ for (const m of t) {
53
+ const C = u(m);
54
+ c.set(m.id, C);
55
+ for (const L of C) {
56
+ const E = a.get(L) ?? [];
57
+ E.push(m.id), a.set(L, E);
58
+ }
59
+ }
60
+ const l = [], d = /* @__PURE__ */ new Map();
61
+ let p = [], g = null, b = 0;
62
+ const A = (m) => (l.push({ ...m, top: b }), b += m.height, l.length - 1), _ = (m) => m.find((C) => s.has(C)), S = () => {
63
+ if (g === null) return;
64
+ const { row: m, lanes: C } = g, L = l[m], E = Math.max(L.height, C.length * ns + 2 * yt);
65
+ l[m] = { ...L, height: E }, b += E - L.height;
66
+ const F = E - 2 * yt, G = Math.max(os, Math.floor(F / C.length));
67
+ C.forEach((j, ot) => {
68
+ const z = c.get(j) ?? [];
69
+ d.set(j, {
70
+ top: L.top + yt + ot * G,
71
+ height: G,
72
+ miniature: !0,
73
+ group: z[z.length - 1]
74
+ });
75
+ }), g = null;
76
+ };
77
+ for (const m of t) {
78
+ const C = (c.get(m.id) ?? []).filter((F) => (a.get(F) ?? []).length > 0), L = _(C);
79
+ if (g !== null && L === g.group) {
80
+ g.lanes.push(m.id);
81
+ continue;
82
+ }
83
+ S();
84
+ const E = C.filter((F, G) => p[G] === F).length;
85
+ p = p.slice(0, E);
86
+ for (const F of C.slice(E)) {
87
+ if (p.push(F), F === L) break;
88
+ A({
89
+ kind: "groupHead",
90
+ lane: void 0,
91
+ group: F,
92
+ depth: p.length - 1,
93
+ within: [...p],
94
+ lanes: (a.get(F) ?? []).length,
95
+ height: ss
96
+ });
97
+ }
98
+ if (L !== void 0) {
99
+ const F = C.indexOf(L), G = A({
100
+ kind: "miniature",
101
+ lane: void 0,
102
+ group: L,
103
+ depth: F,
104
+ within: C.slice(0, F + 1),
105
+ lanes: (a.get(L) ?? []).length,
106
+ height: o
107
+ });
108
+ g = { group: L, row: G, lanes: [m.id] };
109
+ continue;
110
+ }
111
+ A({ kind: "lane", lane: m.id, group: C[C.length - 1], depth: C.length, within: C, lanes: 1, height: o }), d.set(m.id, {
112
+ top: l[l.length - 1].top,
113
+ height: o,
114
+ miniature: !1,
115
+ group: C[C.length - 1]
116
+ });
117
+ }
118
+ return S(), { rows: l, slots: d, height: b };
119
+ }
120
+ function is(n, t) {
121
+ if (t.size === 0) return n;
122
+ const e = /* @__PURE__ */ new Set();
123
+ for (const s of n) t.has(s) || e.add(s);
124
+ return e;
125
+ }
126
+ function nt(n, t) {
127
+ if (t < 0 || t >= n.height) return null;
128
+ let e = 0, s = n.rows.length - 1;
129
+ for (; e <= s; ) {
130
+ const o = e + s >> 1, i = n.rows[o];
131
+ if (t < i.top) s = o - 1;
132
+ else if (t >= i.top + i.height) e = o + 1;
133
+ else return i;
134
+ }
135
+ return null;
136
+ }
137
+ function Lt(n, t) {
138
+ return n.slots.get(t) ?? null;
139
+ }
140
+ function rs(n, t) {
141
+ const e = nt(n, t);
142
+ if (e === null) return null;
143
+ if (e.kind === "lane") return e.lane ?? null;
144
+ if (e.kind === "groupHead") return null;
145
+ for (const [s, o] of n.slots)
146
+ if (o.miniature && t >= o.top && t < o.top + o.height) return s;
147
+ return null;
148
+ }
149
+ function ut(n) {
150
+ return { from: n.from - (n.setup ?? 0), to: n.to + (n.teardown ?? 0) };
151
+ }
152
+ function St(n, t) {
153
+ return (n.leaves ?? "teardown") === "main" ? t.to : t.to + (t.teardown ?? 0);
154
+ }
155
+ function At(n, t) {
156
+ return (n.arrives ?? "setup") === "main" ? t.from : t.from - (t.setup ?? 0);
157
+ }
158
+ function jt(n, t) {
159
+ if (t.kind === "place" || t.subtask !== n.id) return n;
160
+ switch (t.kind) {
161
+ case "move":
162
+ case "stretch":
163
+ return { ...n, from: t.from, to: t.to };
164
+ case "setup":
165
+ return { ...n, setup: t.setup };
166
+ case "teardown":
167
+ return { ...n, teardown: t.teardown };
168
+ case "lane":
169
+ return { ...n, lane: t.lane };
170
+ }
171
+ }
172
+ function In(n, t) {
173
+ return {
174
+ id: t,
175
+ task: n.task,
176
+ lane: n.lane,
177
+ from: n.from,
178
+ to: n.to,
179
+ ...n.setup === void 0 ? {} : { setup: n.setup },
180
+ ...n.teardown === void 0 ? {} : { teardown: n.teardown }
181
+ };
182
+ }
183
+ const as = 6, be = 3, tt = 2, Vt = 3, Zt = 3;
184
+ function P(n, t) {
185
+ return Math.round(n.scale.toPx(Y(t, n.calendar)));
186
+ }
187
+ function ct(n, t) {
188
+ const e = Lt(n.rows, t);
189
+ return e === null ? null : { ...e, top: e.top - n.scrollY };
190
+ }
191
+ function Jt(n, t) {
192
+ return rs(n.rows, t + n.scrollY);
193
+ }
194
+ function Me(n, t, e, s, o) {
195
+ const i = s.miniature ? 0 : as, r = s.miniature ? 0 : Zt * Vt, a = Math.max(s.miniature ? 1 : 4, s.height - 2 * i - r), u = s.top - n.scrollY + Math.floor((s.height - a) / 2), c = ut(t);
196
+ return {
197
+ subtask: t,
198
+ lane: e,
199
+ miniature: s.miniature,
200
+ depth: o,
201
+ y: u + (s.miniature ? 0 : Math.min(o, Zt) * Vt),
202
+ height: a,
203
+ outerFrom: P(n, c.from),
204
+ mainFrom: P(n, t.from),
205
+ mainTo: P(n, t.to),
206
+ outerTo: P(n, c.to)
207
+ };
208
+ }
209
+ function Te(n, t, e) {
210
+ if (e < n.y || e > n.y + n.height) return null;
211
+ const s = Math.max(0, (6 - (n.outerTo - n.outerFrom)) / 2);
212
+ return t < n.outerFrom - s || t > n.outerTo + s ? null : t < n.mainFrom ? "setup" : t > n.mainTo ? "teardown" : "main";
213
+ }
214
+ function ls(n, t, e, s = 5) {
215
+ if (e < n.y || e > n.y + n.height) return null;
216
+ const o = Math.abs(t - n.mainFrom), i = Math.abs(t - n.mainTo);
217
+ return Math.min(o, i) > s ? null : o <= i ? "from" : "to";
218
+ }
219
+ function Ce(n, t, e) {
220
+ return n.outerTo >= 0 && n.outerFrom <= t && n.y + n.height >= 0 && n.y <= e;
221
+ }
222
+ const hs = 64;
223
+ function us(n, t) {
224
+ if (n.miniature) return null;
225
+ const e = ht(n.subtask.appearance).hatched ? tt + be + 1 : 0, s = Math.max(n.mainFrom + e, 0), o = Math.min(n.mainTo - e, t) - s;
226
+ return o < hs ? null : { x: s, width: o, y: n.y, height: n.height };
227
+ }
228
+ const cs = 10;
229
+ function Qt(n, t, e) {
230
+ const s = Math.round(t.y + t.height / 2);
231
+ return n === "centre" || e.y === t.y ? s : Math.round(e.y > t.y ? t.y + t.height - 1 : t.y + 1);
232
+ }
233
+ function bt(n, t, e, s, o) {
234
+ const i = t.route ?? o.route, r = t.attach ?? o.attach, a = t.ends ?? o.ends, u = P(n, St(t, e.subtask)), c = P(n, At(t, s.subtask)), l = Qt(r, e, s), d = Qt(r, s, e);
235
+ if (i === "straight")
236
+ return { transport: t, kind: i, ends: a, x1: u, y1: l, x2: c, y2: d, c1x: u, c2x: c, points: [u, l, c, d] };
237
+ if (i === "orthogonal") {
238
+ const _ = u + cs, S = l === d ? _ : Math.round((_ + c) / 2);
239
+ return { transport: t, kind: i, ends: a, x1: u, y1: l, x2: c, y2: d, c1x: u, c2x: c, points: l === d ? [u, l, c, d] : [u, l, S, l, S, d, c, d] };
240
+ }
241
+ const p = Math.max(14, Math.abs(c - u) / 2), g = u + p, b = c - p, A = [];
242
+ for (let _ = 0; _ <= 16; _++) {
243
+ const S = _ / 16, m = 1 - S;
244
+ A.push(
245
+ m * m * m * u + 3 * m * m * S * g + 3 * m * S * S * b + S * S * S * c,
246
+ m * m * m * l + 3 * m * m * S * l + 3 * m * S * S * d + S * S * S * d
247
+ );
248
+ }
249
+ return { transport: t, kind: "curve", ends: a, x1: u, y1: l, x2: c, y2: d, c1x: g, c2x: b, points: A };
250
+ }
251
+ function ds(n, t, e) {
252
+ let s = 1 / 0;
253
+ const o = n.points;
254
+ for (let i = 0; i + 3 < o.length; i += 2) {
255
+ const r = o[i], a = o[i + 1], u = o[i + 2], c = o[i + 3], l = u - r, d = c - a, p = l * l + d * d, g = p === 0 ? 0 : Math.max(0, Math.min(1, ((t - r) * l + (e - a) * d) / p));
256
+ s = Math.min(s, Math.hypot(t - (r + g * l), e - (a + g * d)));
257
+ }
258
+ return s;
259
+ }
260
+ function It(n) {
261
+ const t = [], e = /* @__PURE__ */ new Map();
262
+ n.forEach((s, o) => {
263
+ const { from: i, to: r } = ut(s);
264
+ if (!(i < r)) return;
265
+ const a = e.get(s.lane) ?? [];
266
+ a.push({ subtask: s, index: o, from: i, to: r }), e.set(s.lane, a);
267
+ });
268
+ for (const [s, o] of e) {
269
+ o.sort((i, r) => i.from - r.from || i.index - r.index);
270
+ for (let i = 0; i < o.length; i++) {
271
+ const r = o[i];
272
+ for (let a = i + 1; a < o.length; a++) {
273
+ const u = o[a];
274
+ if (u.from >= r.to) break;
275
+ t.push({ lane: s, first: r.subtask.id, second: u.subtask.id, from: u.from, to: Math.min(r.to, u.to) });
276
+ }
277
+ }
278
+ }
279
+ return t;
280
+ }
281
+ function fs(n) {
282
+ const t = /* @__PURE__ */ new Map(), e = /* @__PURE__ */ new Map();
283
+ for (const s of n) {
284
+ const o = ut(s), i = e.get(s.lane) ?? [];
285
+ let r = 0;
286
+ if (o.from < o.to) {
287
+ for (const a of i) o.from < a.to && a.from < o.to && r++;
288
+ i.push(o);
289
+ }
290
+ e.set(s.lane, i), t.set(s.id, r);
291
+ }
292
+ return t;
293
+ }
294
+ function _t(n, t) {
295
+ const e = new Map(n.map((o) => [o.id, o])), s = [];
296
+ for (const o of t) {
297
+ const i = e.get(o.from), r = e.get(o.to);
298
+ if (i === void 0 || r === void 0) continue;
299
+ const a = St(o, i), u = At(o, r), c = a + o.duration - u;
300
+ c > 0 && s.push({ transport: o.id, departure: a, arrival: u, shortBy: c });
301
+ }
302
+ return s;
303
+ }
304
+ function _n(n, t) {
305
+ return { overlaps: It(n), lateTransports: _t(n, t) };
306
+ }
307
+ class ps {
308
+ /** `changed` is called after every registration change. */
309
+ constructor(t) {
310
+ f(this, "nextId", 1);
311
+ f(this, "laneEntries", /* @__PURE__ */ new Map());
312
+ f(this, "groupEntries", /* @__PURE__ */ new Map());
313
+ f(this, "layerEntries", /* @__PURE__ */ new Map());
314
+ f(this, "dirty", !0);
315
+ f(this, "lanes", []);
316
+ /** The groups in registration order. */
317
+ f(this, "groups", []);
318
+ f(this, "laneIndex", /* @__PURE__ */ new Map());
319
+ /** The layers in registration order - the drawing order. */
320
+ f(this, "layers", []);
321
+ f(this, "subtasks", []);
322
+ f(this, "subtaskById", /* @__PURE__ */ new Map());
323
+ f(this, "transports", []);
324
+ f(this, "tasks", /* @__PURE__ */ new Map());
325
+ f(this, "overlaps", []);
326
+ f(this, "lateById", /* @__PURE__ */ new Map());
327
+ f(this, "depth", /* @__PURE__ */ new Map());
328
+ this.changed = t;
329
+ }
330
+ registerLane(t) {
331
+ const e = this.nextId++;
332
+ return this.laneEntries.set(e, t), this.touch(), e;
333
+ }
334
+ updateLane(t, e) {
335
+ this.laneEntries.get(t) !== e && (this.laneEntries.set(t, e), this.touch());
336
+ }
337
+ unregisterLane(t) {
338
+ this.laneEntries.delete(t), this.touch();
339
+ }
340
+ registerGroup(t) {
341
+ const e = this.nextId++;
342
+ return this.groupEntries.set(e, t), this.touch(), e;
343
+ }
344
+ updateGroup(t, e) {
345
+ this.groupEntries.get(t) !== e && (this.groupEntries.set(t, e), this.touch());
346
+ }
347
+ unregisterGroup(t) {
348
+ this.groupEntries.delete(t), this.touch();
349
+ }
350
+ registerLayer(t) {
351
+ const e = this.nextId++;
352
+ return this.layerEntries.set(e, t), this.touch(), e;
353
+ }
354
+ updateLayer(t, e) {
355
+ this.layerEntries.get(t) !== e && (this.layerEntries.set(t, e), this.touch());
356
+ }
357
+ unregisterLayer(t) {
358
+ this.layerEntries.delete(t), this.touch();
359
+ }
360
+ touch() {
361
+ this.dirty = !0, this.changed();
362
+ }
363
+ /** Derives anew if a registration changed since the last call; says whether
364
+ it did. */
365
+ rebuild() {
366
+ if (!this.dirty) return !1;
367
+ this.dirty = !1;
368
+ const t = (e) => [...e.keys()].sort((s, o) => s - o).map((s) => e.get(s));
369
+ this.lanes = t(this.laneEntries), this.groups = t(this.groupEntries), this.laneIndex = new Map(this.lanes.map((e, s) => [e.id, s])), this.layers = t(this.layerEntries), this.subtasks = [], this.transports = [], this.tasks = /* @__PURE__ */ new Map();
370
+ for (const e of this.layers)
371
+ if (e.kind === "subtasks") {
372
+ this.subtasks.push(...e.data);
373
+ for (const s of e.tasks) this.tasks.set(s.id, s);
374
+ } else
375
+ this.transports.push(...e.data);
376
+ return this.subtaskById = new Map(this.subtasks.map((e) => [e.id, e])), this.overlaps = It(this.subtasks), this.lateById = new Map(_t(this.subtasks, this.transports).map((e) => [e.transport, e])), this.depth = fs(this.subtasks), !0;
377
+ }
378
+ /** The task a transport belongs to: its departing subtask's. */
379
+ taskOfTransport(t) {
380
+ var e;
381
+ return ((e = this.subtaskById.get(t.from)) == null ? void 0 : e.task) ?? null;
382
+ }
383
+ /** What a tooltip is about: the hovered subtask or transport with what this
384
+ data knows about it - its task, and the findings it stands in. */
385
+ tooltipTargetFor(t) {
386
+ if (t.kind === "subtask") {
387
+ const o = t.subtask.id, i = this.overlaps.filter((a) => a.first === o || a.second === o).map((a) => this.subtaskById.get(a.first === o ? a.second : a.first)).filter((a) => a !== void 0), r = this.transports.filter((a) => a.from === o || a.to === o).map((a) => this.lateById.get(a.id)).filter((a) => a !== void 0);
388
+ return { kind: "subtask", subtask: t.subtask, task: this.tasks.get(t.subtask.task), overlapping: i, lateTransports: r };
389
+ }
390
+ if (t.kind !== "transport") return null;
391
+ const e = t.transport, s = this.taskOfTransport(e);
392
+ return {
393
+ kind: "transport",
394
+ transport: e,
395
+ task: s !== null ? this.tasks.get(s) : void 0,
396
+ from: this.subtaskById.get(e.from),
397
+ to: this.subtaskById.get(e.to),
398
+ late: this.lateById.get(e.id)
399
+ };
400
+ }
401
+ }
402
+ const ms = {
403
+ line: "var(--u-hairline)",
404
+ lineStrong: "var(--u-hairline-strong)",
405
+ text: "var(--u-color-text)",
406
+ muted: "var(--u-color-text-muted)",
407
+ alarm: "var(--u-color-danger)",
408
+ surface: "var(--u-color-surface)",
409
+ accent: "var(--u-color-accent)",
410
+ /* What text and marks take ON a filled bar - the same token the bar labels
411
+ use in CSS, so a cap and the label beside it are one colour. */
412
+ onAccent: "var(--u-color-on-accent)"
413
+ };
414
+ function gs(n, t) {
415
+ const e = {};
416
+ for (const i of t.tasks.values()) e[`task:${i.id}`] = i.color;
417
+ const s = ze(n, { ...ms, ...e }), o = /* @__PURE__ */ new Map();
418
+ for (const i of t.tasks.values()) o.set(i.id, s[`task:${i.id}`] ?? i.color);
419
+ return {
420
+ line: s.line,
421
+ lineStrong: s.lineStrong,
422
+ text: s.text,
423
+ muted: s.muted,
424
+ alarm: s.alarm,
425
+ surface: s.surface,
426
+ accent: s.accent,
427
+ onAccent: s.onAccent,
428
+ tasks: o
429
+ };
430
+ }
431
+ function at(n) {
432
+ const t = n.match(/[\d.]+/g);
433
+ return t === null || t.length < 3 ? null : [Number(t[0]), Number(t[1]), Number(t[2])];
434
+ }
435
+ function te(n) {
436
+ const t = at(n);
437
+ if (t === null) return 0;
438
+ const [e, s, o] = t.map((i) => {
439
+ const r = i / 255;
440
+ return r <= 0.04045 ? r / 12.92 : ((r + 0.055) / 1.055) ** 2.4;
441
+ });
442
+ return 0.2126 * e + 0.7152 * s + 0.0722 * o;
443
+ }
444
+ function ee(n, t) {
445
+ const e = te(n), s = te(t);
446
+ return (Math.max(e, s) + 0.05) / (Math.min(e, s) + 0.05);
447
+ }
448
+ function se(n, t, e) {
449
+ if (n === null) return null;
450
+ const s = typeof window > "u" ? 1 : window.devicePixelRatio || 1, o = Math.round(t * s), i = Math.round(e * s);
451
+ n.width !== o && (n.width = o), n.height !== i && (n.height = i);
452
+ const r = n.getContext("2d");
453
+ return r === null ? null : (r.setTransform(s, 0, 0, s, 0, 0), r.clearRect(0, 0, t, e), r);
454
+ }
455
+ function ks(n, t) {
456
+ const { data: e, view: s } = t, o = s.viewport();
457
+ bs(n, t, o), Ms(n, t);
458
+ for (const i of e.layers) {
459
+ const r = new Set(i.data);
460
+ if (i.kind === "transports")
461
+ for (const a of s.paths) r.has(a.transport) && Mt(n, t, a, !1);
462
+ else
463
+ for (const a of s.boxes) r.has(a.subtask) && Se(n, t, a, 1);
464
+ }
465
+ for (const i of e.overlaps) Ae(n, t, o, i);
466
+ Es(n, t, o), Ps(n, t);
467
+ }
468
+ function ws(n, t) {
469
+ const { view: e, hover: s } = t, o = e.viewport();
470
+ if (t.ghost === null) {
471
+ if (s.kind === "subtask") {
472
+ const l = e.boxById.get(s.subtask.id);
473
+ l !== void 0 && Ds(n, t, l);
474
+ } else if (s.kind === "transport") {
475
+ const l = e.paths.find((d) => d.transport === s.transport);
476
+ l !== void 0 && Mt(n, t, l, !0);
477
+ }
478
+ return;
479
+ }
480
+ const { ghost: i, overlaps: r, late: a } = t.ghost;
481
+ vs(n, t, o, t.ghost.refusedLanes);
482
+ const u = Le(o, i);
483
+ if (u === null) return;
484
+ for (const l of r) Ae(n, t, o, l);
485
+ const c = new Set(a.map((l) => l.transport));
486
+ for (const l of t.data.transports) {
487
+ if (l.from !== i.id && l.to !== i.id) continue;
488
+ const d = e.boxById.get(l.from === i.id ? l.to : l.from);
489
+ if (d === void 0) continue;
490
+ const p = l.from === i.id ? bt(o, l, u, d, e.options) : bt(o, l, d, u, e.options);
491
+ Mt(n, t, p, !0, c.has(l.id));
492
+ }
493
+ Se(n, t, u, 0.55), n.strokeStyle = t.colours.text, n.lineWidth = 1, n.setLineDash([3, 2]), n.strokeRect(u.outerFrom + 0.5, u.y + 0.5, Math.max(1, u.outerTo - u.outerFrom - 1), u.height - 1), n.setLineDash([]), t.ghost.tether !== null && ys(n, t, u, t.ghost.tether);
494
+ }
495
+ function vs(n, t, e, s) {
496
+ if (s.size === 0) return;
497
+ const { width: o, height: i } = t.view;
498
+ for (const r of s) {
499
+ const a = ct(e, r);
500
+ if (a === null) continue;
501
+ const { top: u, height: c } = a;
502
+ u + c < 0 || u > i || (n.globalAlpha = 0.6, n.fillStyle = t.colours.surface, n.fillRect(0, u, o, c), n.globalAlpha = 1, _s(n, 0, u, o, c, t.colours.muted, 0.7, As, 1));
503
+ }
504
+ }
505
+ function ys(n, t, e, s) {
506
+ const o = Math.max(e.outerFrom, Math.min(e.outerTo, s.x)), i = Math.max(e.y, Math.min(e.y + e.height, s.y));
507
+ Math.hypot(s.x - o, s.y - i) < 2 || (n.strokeStyle = t.colours.text, n.lineWidth = 1, n.setLineDash([2, 3]), n.beginPath(), n.moveTo(o + 0.5, i + 0.5), n.lineTo(s.x + 0.5, s.y + 0.5), n.stroke(), n.setLineDash([]));
508
+ }
509
+ function Le(n, t) {
510
+ const e = Lt(n.rows, t.lane);
511
+ return e === null ? null : Me(n, t, t.lane, e, 0);
512
+ }
513
+ function bs(n, t, e) {
514
+ const { view: s, colours: o, bands: i } = t, { width: r, height: a } = s;
515
+ n.lineWidth = 1, n.strokeStyle = o.line, n.beginPath();
516
+ for (const l of i.ticks)
517
+ n.moveTo(l.x + 0.5, 0), n.lineTo(l.x + 0.5, a);
518
+ for (const l of e.rows.rows) {
519
+ const d = l.top + l.height - e.scrollY - 0.5;
520
+ d < 0 || d > a || (n.moveTo(0, d), n.lineTo(r, d));
521
+ }
522
+ const u = [...e.rows.slots.values()].filter((l) => l.miniature).sort((l, d) => l.top - d.top);
523
+ u.forEach((l, d) => {
524
+ const p = u[d + 1];
525
+ if (p === void 0 || p.top !== l.top + l.height || p.group === l.group) return;
526
+ const g = l.top + l.height - e.scrollY - 0.5;
527
+ g < 0 || g > a || (n.moveTo(0, g), n.lineTo(r, g));
528
+ }), n.stroke(), n.strokeStyle = o.lineStrong, n.beginPath();
529
+ for (const l of i.days)
530
+ n.moveTo(l.x + 0.5, 0), n.lineTo(l.x + 0.5, a);
531
+ n.stroke();
532
+ const c = qe(s.options.calendar);
533
+ if (c.length > 0) {
534
+ n.strokeStyle = o.muted, n.setLineDash([2, 3]), n.beginPath();
535
+ for (const l of c) {
536
+ const d = Math.round(e.scale.toPx(l.operatingTime)) + 0.5;
537
+ d < 0 || d > r || (n.moveTo(d, 0), n.lineTo(d, a));
538
+ }
539
+ n.stroke(), n.setLineDash([]);
540
+ }
541
+ }
542
+ function Ms(n, t) {
543
+ const e = t.view.nowX();
544
+ e !== null && (n.fillStyle = t.colours.accent, n.fillRect(e, 0, 2, t.view.height));
545
+ }
546
+ function Ts(n, t, e, s) {
547
+ const o = t.colours.tasks.get(e.subtask.task) ?? t.colours.muted;
548
+ n.fillStyle = o;
549
+ for (const [i, r] of [
550
+ [e.outerFrom, e.mainFrom],
551
+ [e.mainTo, e.outerTo]
552
+ ])
553
+ r <= i || (n.globalAlpha = 0.28 * s, n.fillRect(i, e.y, r - i, e.height));
554
+ n.globalAlpha = s, n.fillRect(e.mainFrom, e.y, Math.max(1, e.mainTo - e.mainFrom), e.height), n.globalAlpha = 1;
555
+ }
556
+ function Ft(n, t, e) {
557
+ if (n.dashed) return { fill: null, onDark: !1 };
558
+ const s = n.muted ? Cs(t, e.surface, 0.5) : t;
559
+ return { fill: s, onDark: ee(s, e.onAccent) > ee(s, e.text) };
560
+ }
561
+ function Cs(n, t, e) {
562
+ const s = at(n), o = at(t);
563
+ if (s === null || o === null) return n;
564
+ const i = (r) => Math.round(s[r] + (o[r] - s[r]) * e);
565
+ return `rgb(${i(0)}, ${i(1)}, ${i(2)})`;
566
+ }
567
+ const Ls = 2;
568
+ function Se(n, t, e, s) {
569
+ const { view: o, colours: i } = t;
570
+ if (!Ce(e, o.width, o.height)) return;
571
+ if (e.miniature) {
572
+ Ts(n, t, e, s);
573
+ return;
574
+ }
575
+ const r = ht(e.subtask.appearance), a = i.tasks.get(e.subtask.task) ?? i.muted, u = Ft(r, a, i), c = e.y, l = e.height, d = Math.max(1, e.mainTo - e.mainFrom), p = u.onDark ? i.onAccent : i.text;
576
+ n.lineWidth = 1, n.fillStyle = a, n.strokeStyle = a;
577
+ for (const [b, A] of [
578
+ [e.outerFrom, e.mainFrom],
579
+ [e.mainTo, e.outerTo]
580
+ ])
581
+ A <= b || (n.globalAlpha = 0.28 * s, n.fillRect(b, c, A - b, l), n.globalAlpha = s, n.strokeRect(b + 0.5, c + 0.5, A - b - 1, l - 1));
582
+ u.fill !== null && (n.globalAlpha = s, n.fillStyle = u.fill, n.fillRect(e.mainFrom, c, d, l));
583
+ const g = e.subtask.progress;
584
+ if (g !== void 0) {
585
+ const b = Math.min(4, Math.max(2, Math.round(l / 6))), A = c + l - b - Ls, _ = Math.round(d * Math.max(0, Math.min(1, g)));
586
+ n.fillStyle = u.fill === null ? a : p, n.globalAlpha = 0.3 * s, n.fillRect(e.mainFrom, A, d, b), n.globalAlpha = s, _ > 0 && n.fillRect(e.mainFrom, A, _, b);
587
+ }
588
+ if (r.hatched) {
589
+ const b = Math.max(1, Math.min(be, Math.floor((d - 2 * tt) / 3))), A = d >= 4 * b ? tt : 0, _ = l >= 4 * tt ? tt : 0;
590
+ n.globalAlpha = s, n.fillStyle = p, n.fillRect(e.mainFrom + A, c + _, b, l - 2 * _), n.fillRect(e.mainTo - A - b, c + _, b, l - 2 * _);
591
+ }
592
+ r.open && Fs(n, e, c, l, i.surface, o.width), r.dashed && (n.globalAlpha = s, n.strokeStyle = a, n.setLineDash([4, 3]), n.strokeRect(e.mainFrom + 0.5, c + 0.5, d - 1, l - 1), n.setLineDash([])), n.globalAlpha = 1, e.depth > 0 && s === 1 && (n.strokeStyle = i.surface, n.strokeRect(e.outerFrom - 0.5, c - 0.5, e.outerTo - e.outerFrom + 1, l + 1));
593
+ }
594
+ const Ss = 7, As = 6, Is = 16;
595
+ function _s(n, t, e, s, o, i, r, a = Ss, u = 2) {
596
+ n.save(), n.beginPath(), n.rect(t, e, s, o), n.clip(), n.globalAlpha = 0.5 * r, n.strokeStyle = i, n.lineWidth = u, n.beginPath();
597
+ for (let c = t - o; c < t + s + o; c += a)
598
+ n.moveTo(c, e + o), n.lineTo(c + o, e);
599
+ n.stroke(), n.restore();
600
+ }
601
+ function Fs(n, t, e, s, o, i) {
602
+ const r = t.mainFrom < 0, a = t.mainTo > i, u = Math.max(1, Math.min(t.mainTo, i) - Math.max(t.mainFrom, 0)), c = Math.min(Is, u);
603
+ r && ne(n, 0, c, e, s, o, 1), a && ne(n, i, -c, e, s, o, 1);
604
+ }
605
+ function ne(n, t, e, s, o, i, r) {
606
+ const a = n.createLinearGradient(t, 0, t + e, 0);
607
+ a.addColorStop(0, oe(i, r)), a.addColorStop(1, oe(i, 0)), n.globalAlpha = 1, n.fillStyle = a, n.fillRect(Math.min(t, t + e), s, Math.abs(e), o);
608
+ }
609
+ function oe(n, t) {
610
+ const e = at(n);
611
+ return e === null ? n : `rgba(${e[0]}, ${e[1]}, ${e[2]}, ${t})`;
612
+ }
613
+ function Mt(n, t, e, s, o) {
614
+ const { data: i, colours: r } = t, a = i.taskOfTransport(e.transport), u = o ?? i.lateById.has(e.transport.id), c = a !== null && a === t.selectedTask, l = u ? r.alarm : (a !== null ? r.tasks.get(a) : void 0) ?? r.muted;
615
+ if (n.strokeStyle = l, n.fillStyle = l, n.lineWidth = s || c ? 2 : 1.25, n.setLineDash(u ? [4, 3] : []), n.beginPath(), n.moveTo(e.x1, e.y1), e.kind === "curve")
616
+ n.bezierCurveTo(e.c1x, e.y1, e.c2x, e.y2, e.x2, e.y2);
617
+ else
618
+ for (let d = 2; d + 1 < e.points.length; d += 2) n.lineTo(e.points[d], e.points[d + 1]);
619
+ if (n.stroke(), n.setLineDash([]), e.ends === "dot")
620
+ for (const [d, p] of [
621
+ [e.x1, e.y1],
622
+ [e.x2, e.y2]
623
+ ])
624
+ n.beginPath(), n.arc(d, p, u ? 3 : 2.5, 0, Math.PI * 2), n.fill();
625
+ }
626
+ function Es(n, t, e) {
627
+ const { data: s } = t;
628
+ if (s.lateById.size !== 0) {
629
+ n.fillStyle = t.colours.alarm;
630
+ for (const o of s.lateById.values()) {
631
+ const i = s.transports.find((d) => d.id === o.transport), r = i === void 0 ? void 0 : s.subtaskById.get(i.to);
632
+ if (r === void 0) continue;
633
+ const a = ct(e, r.lane);
634
+ if (a === null || !a.miniature) continue;
635
+ const u = nt(e.rows, a.top + e.scrollY);
636
+ if (u === null) continue;
637
+ const c = P(e, o.arrival), l = Math.max(c + 2, P(e, o.arrival + o.shortBy));
638
+ n.fillRect(c, u.top - e.scrollY + 1, l - c, 3);
639
+ }
640
+ }
641
+ }
642
+ function Ae(n, t, e, s) {
643
+ const o = ct(e, s.lane);
644
+ if (o === null) return;
645
+ const i = P(e, s.from), r = Math.max(i + 2, P(e, s.to));
646
+ if (n.fillStyle = t.colours.alarm, n.globalAlpha = 0.14, n.fillRect(i, o.top + 1, r - i, Math.max(1, o.height - 2)), n.globalAlpha = 1, n.fillRect(i, o.top + 1, r - i, Math.min(3, Math.max(1, o.height - 1))), o.miniature) {
647
+ const a = nt(e.rows, o.top + e.scrollY);
648
+ a !== null && n.fillRect(i, a.top - e.scrollY + 1, r - i, 3);
649
+ }
650
+ }
651
+ function Ds(n, t, e) {
652
+ const { colours: s } = t, o = ht(e.subtask.appearance), i = Ft(o, s.tasks.get(e.subtask.task) ?? s.muted, s);
653
+ n.globalAlpha = xs, n.fillStyle = i.onDark ? s.onAccent : s.text, n.fillRect(e.outerFrom, e.y, Math.max(1, e.outerTo - e.outerFrom), e.height), n.globalAlpha = 1;
654
+ }
655
+ const xs = 0.2;
656
+ function Ps(n, t) {
657
+ const e = t.selectedTask;
658
+ if (e !== null) {
659
+ n.strokeStyle = t.colours.text;
660
+ for (const s of t.view.boxes) {
661
+ if (s.subtask.task !== e) continue;
662
+ const o = s.subtask.id === t.selectedSubtask;
663
+ n.lineWidth = o ? 2 : 1;
664
+ const i = o ? 1 : 0.5;
665
+ n.strokeRect(s.outerFrom - i, s.y - i, s.outerTo - s.outerFrom + 2 * i, s.height + 2 * i);
666
+ }
667
+ }
668
+ }
669
+ const rt = 32, Ns = 18;
670
+ function ie(n, t) {
671
+ if (!(t > 2 * rt)) return 0;
672
+ const e = rt - n, s = n - (t - rt), o = Math.max(e, s);
673
+ if (o <= 0) return 0;
674
+ const i = Math.min(1, o / rt), r = Ns * i * i;
675
+ return e > 0 ? -r : r;
676
+ }
677
+ function Gs(n, t, e, s) {
678
+ const o = /* @__PURE__ */ new Set();
679
+ if (s === void 0) return o;
680
+ for (const i of n)
681
+ i !== e && (s(t, i) || o.add(i));
682
+ return o;
683
+ }
684
+ function Ie(n) {
685
+ return new Date(n).getTimezoneOffset() * U;
686
+ }
687
+ function Rs(n, t) {
688
+ const { step: e, offset: s } = typeof t == "number" ? { step: t, offset: 0 } : t;
689
+ if (!(e > 0) || !Number.isFinite(n)) return n;
690
+ const o = Ie(n) + s;
691
+ return o + Math.round((n - o) / e) * e;
692
+ }
693
+ const re = "\0placing", ae = /* @__PURE__ */ new Set();
694
+ function le(n) {
695
+ switch (n.kind) {
696
+ case "subtask":
697
+ return `subtask:${n.subtask.id}:${n.part}`;
698
+ case "transport":
699
+ return `transport:${n.transport.id}`;
700
+ case "lane":
701
+ return `lane:${n.lane}`;
702
+ default:
703
+ return "nothing";
704
+ }
705
+ }
706
+ const he = 3, $s = 600;
707
+ class Bs {
708
+ constructor(t) {
709
+ f(this, "gesture", { kind: "none" });
710
+ f(this, "touches", /* @__PURE__ */ new Map());
711
+ f(this, "hoverKey", "nothing");
712
+ /** The last pointer of a drag, in client coordinates, and the frame that
713
+ pans along while it is near an edge. */
714
+ f(this, "lastClient", { x: 0, y: 0 });
715
+ f(this, "panFrame", 0);
716
+ /** Whether the pointer last stood over a lane the dragged work may not go
717
+ to. It is a fact about the pointer and not about the ghost, which stayed
718
+ where it was allowed. */
719
+ f(this, "refused", !1);
720
+ /** Where the pointer stands on the plot while a drag is in flight - what the
721
+ tether is drawn to, since the ghost is not following it. */
722
+ f(this, "dragPoint", { x: 0, y: 0 });
723
+ /** The folded group the pointer is resting over, and the timer that will
724
+ open it for this gesture. */
725
+ f(this, "resting", null);
726
+ f(this, "hover", { kind: "nothing" });
727
+ /** Where the pointer rests on the plot while nothing is being dragged. */
728
+ f(this, "hoverPoint", { x: 0, y: 0 });
729
+ f(this, "cursor", "default");
730
+ this.host = t;
731
+ }
732
+ /* ---------------------------------------------------------------- */
733
+ /* What the scene reads */
734
+ /* ---------------------------------------------------------------- */
735
+ get editing() {
736
+ return this.gesture.kind === "edit" || this.gesture.kind === "place";
737
+ }
738
+ /** No press, pan, pinch or drag in flight. */
739
+ get idle() {
740
+ return this.gesture.kind === "none";
741
+ }
742
+ ghostDrawing() {
743
+ const t = this.gesture;
744
+ if (t.kind !== "edit" && t.kind !== "place") return null;
745
+ const e = this.ghostFindings(t.ghost, this.ghostHome(t));
746
+ return {
747
+ ghost: t.ghost,
748
+ overlaps: e.overlaps,
749
+ late: e.late,
750
+ refusedLanes: t.refused,
751
+ /* The tether is drawn only while the pointer really stands on a refused
752
+ lane: the marked lanes say where the work may not go, the tether says
753
+ that the ghost is held on purpose right now. */
754
+ tether: this.refused ? this.dragPoint : null
755
+ };
756
+ }
757
+ ghostSummary() {
758
+ const t = this.gesture;
759
+ if (t.kind !== "edit" && t.kind !== "place") return null;
760
+ const e = Le(this.host.view.viewport(), t.ghost);
761
+ if (e === null) return null;
762
+ const s = this.ghostFindings(t.ghost, this.ghostHome(t)), o = t.kind === "edit" && (t.mode === "setup" || t.mode === "teardown"), i = o ? ut(t.ghost) : t.ghost;
763
+ return {
764
+ refused: this.refused,
765
+ refusedLanes: [...t.refused],
766
+ x: o ? e.outerFrom : e.mainFrom,
767
+ y: e.y,
768
+ height: e.height,
769
+ from: i.from,
770
+ to: i.to,
771
+ overlap: s.overlaps.length > 0,
772
+ late: s.late.length > 0
773
+ };
774
+ }
775
+ /* ---------------------------------------------------------------- */
776
+ /* Pointer */
777
+ /* ---------------------------------------------------------------- */
778
+ local(t, e) {
779
+ var o;
780
+ const s = (o = this.host.plotElement()) == null ? void 0 : o.getBoundingClientRect();
781
+ return { x: t - ((s == null ? void 0 : s.left) ?? 0), y: e - ((s == null ? void 0 : s.top) ?? 0) };
782
+ }
783
+ report(t, e, s, o, i, r) {
784
+ var u, c;
785
+ const a = this.host.view;
786
+ (c = (u = this.host.handlers()).onInteraction) == null || c.call(u, { type: t, hit: e, clientX: s, clientY: o, time: a.timeAt(i), lane: a.laneIdAt(r) });
787
+ }
788
+ pointerDown(t) {
789
+ var a, u, c, l, d;
790
+ const { x: e, y: s } = this.local(t.clientX, t.clientY);
791
+ if (t.pointerType === "touch" && (this.touches.set(t.pointerId, { x: e, y: s }), this.touches.size === 2)) {
792
+ this.cancelEdit(), this.gesture = { kind: "pinch", distance: this.touchDistance() };
793
+ return;
794
+ }
795
+ if (t.button !== 0) return;
796
+ const o = (c = (u = (a = t.target) == null ? void 0 : a.closest) == null ? void 0 : u.call(a, "[data-grip]")) == null ? void 0 : c.getAttribute("data-grip"), i = this.host.selectedSubtask(), r = i !== null ? this.host.data.subtaskById.get(i) ?? null : null;
797
+ t.pointerType === "touch" ? this.gesture = { kind: "pending", pointerId: t.pointerId, x0: e, y0: s, mode: "pan", subtask: null } : (o === "setup" || o === "teardown") && r !== null ? this.gesture = { kind: "pending", pointerId: t.pointerId, x0: e, y0: s, mode: o, subtask: r } : this.gesture = { kind: "pending", pointerId: t.pointerId, x0: e, y0: s, ...this.modeAt(e, s) }, (d = (l = this.host.plotElement()) == null ? void 0 : l.setPointerCapture) == null || d.call(l, t.pointerId);
798
+ }
799
+ /** A drag over a folded group: resting on one opens it for the GESTURE.
800
+
801
+ Crossing one on the way somewhere else must not open it, so the timer
802
+ starts when the pointer arrives and is thrown away when it leaves. What
803
+ opens is a set the scene holds for the gesture; the caller's list is
804
+ never written to and no change is reported, because the application did
805
+ not fold anything (ADR-0025). */
806
+ restOver(t) {
807
+ var o;
808
+ const e = this.host.view, s = e.foldedGroupAt(t);
809
+ s !== ((o = this.resting) == null ? void 0 : o.group) && (this.stopResting(), s !== null && (this.resting = {
810
+ group: s,
811
+ timer: setTimeout(() => {
812
+ this.resting = null, e.openForGesture = /* @__PURE__ */ new Set([...e.openForGesture, s]), this.host.viewChanged();
813
+ }, $s)
814
+ }));
815
+ }
816
+ stopResting() {
817
+ this.resting !== null && clearTimeout(this.resting.timer), this.resting = null;
818
+ }
819
+ /** The end of a gesture: whatever it held open, it lets go of. */
820
+ closeGestureFolds() {
821
+ this.stopResting();
822
+ const t = this.host.view;
823
+ t.openForGesture.size !== 0 && (t.openForGesture = /* @__PURE__ */ new Set(), this.host.viewChanged());
824
+ }
825
+ /** The lane a drop at this y would land on, with the y held inside the rows -
826
+ a drag carried past the last lane still aims at the last lane. */
827
+ onLane(t) {
828
+ const e = this.host.view;
829
+ return e.dropLaneIdAt(Math.max(0, Math.min(e.lanesBottom(), t)));
830
+ }
831
+ /** May this subtask go to this lane? Without a rule from the caller, every
832
+ lane is open. Asked at a drop, where the answer has to be current; while
833
+ a drag runs, the held set answers instead. */
834
+ allowed(t, e) {
835
+ var s, o;
836
+ return ((o = (s = this.host.handlers()).canMoveTo) == null ? void 0 : o.call(s, t, e)) ?? !0;
837
+ }
838
+ /** The lanes this work may not go to, for the gesture that is beginning. A
839
+ gesture that cannot change a lane at all asks nothing: the intents the
840
+ caller handles decide whether the question exists. */
841
+ askRefused(t, e) {
842
+ if (!this.host.view.options.intents.includes(e === null ? "place" : "lane")) return ae;
843
+ const s = this.host.data.lanes.map((o) => o.id);
844
+ return Gs(s, t, e, this.host.handlers().canMoveTo);
845
+ }
846
+ /** What a press at a point would start, given the intents the caller handles. */
847
+ modeAt(t, e) {
848
+ const s = this.host.view, o = s.options.intents;
849
+ for (let i = s.boxes.length - 1; i >= 0; i--) {
850
+ const r = s.boxes[i];
851
+ if (o.includes("stretch")) {
852
+ const a = ls(r, t, e);
853
+ if (a !== null) return { mode: a === "from" ? "stretch-from" : "stretch-to", subtask: r.subtask };
854
+ }
855
+ if (Te(r, t, e) !== null)
856
+ return o.includes("move") || o.includes("lane") ? { mode: "move", subtask: r.subtask } : { mode: "pan", subtask: r.subtask };
857
+ }
858
+ return { mode: "pan", subtask: null };
859
+ }
860
+ pointerMove(t) {
861
+ const { x: e, y: s } = this.local(t.clientX, t.clientY);
862
+ if (t.pointerType === "touch" && this.touches.has(t.pointerId) && (this.touches.set(t.pointerId, { x: e, y: s }), this.gesture.kind === "pinch")) {
863
+ const r = this.touchDistance();
864
+ r > 0 && this.gesture.distance > 0 && this.host.view.zoomAt(this.touchCentre(), this.gesture.distance / r) && this.host.viewMoved(!0), this.gesture = { kind: "pinch", distance: r };
865
+ return;
866
+ }
867
+ const o = this.gesture;
868
+ if (o.kind === "pending" && o.pointerId === t.pointerId) {
869
+ if (Math.hypot(e - o.x0, s - o.y0) < he) return;
870
+ if (o.mode === "pan" || o.subtask === null)
871
+ this.gesture = { kind: "pan", pointerId: o.pointerId, lastX: o.x0, lastY: o.y0 }, this.setCursor("grabbing");
872
+ else {
873
+ const r = this.host.view.viewport().scale.fromPx(o.x0);
874
+ this.gesture = {
875
+ kind: "edit",
876
+ pointerId: o.pointerId,
877
+ mode: o.mode,
878
+ subtask: o.subtask,
879
+ t0: r,
880
+ ghost: o.subtask,
881
+ /* Asked here, once, and drawn from the first frame of the drag: the
882
+ lanes that are closed are marked before the pointer reaches one. */
883
+ refused: o.mode === "move" ? this.askRefused(o.subtask, o.subtask.lane) : ae
884
+ }, this.setCursor(o.mode === "move" ? "grabbing" : "ew-resize");
885
+ }
886
+ }
887
+ const i = this.gesture;
888
+ if (i.kind === "pan" && i.pointerId === t.pointerId) {
889
+ const r = this.host.view.pan(i.lastX - e, i.lastY - s);
890
+ r.moved && this.host.viewMoved(r.time), this.gesture = { ...i, lastX: e, lastY: s };
891
+ return;
892
+ }
893
+ if (i.kind === "edit" && i.pointerId === t.pointerId) {
894
+ this.lastClient = { x: t.clientX, y: t.clientY }, this.dragPoint = { x: e, y: s }, this.restOver(s), this.gesture = { ...i, ghost: this.ghostFor(i, e, s) }, this.setCursor(this.refused ? "not-allowed" : i.mode === "move" ? "grabbing" : "ew-resize"), this.host.interactionChanged(), this.autoPan();
895
+ return;
896
+ }
897
+ i.kind === "none" && this.hoverAt(t.clientX, t.clientY, e, s);
898
+ }
899
+ pointerUp(t) {
900
+ var i, r;
901
+ if (t.pointerType === "touch" && (this.touches.delete(t.pointerId), this.gesture.kind === "pinch")) {
902
+ this.touches.size < 2 && (this.gesture = { kind: "none" });
903
+ return;
904
+ }
905
+ const e = this.gesture, { x: s, y: o } = this.local(t.clientX, t.clientY);
906
+ if (e.kind === "pending" && e.pointerId === t.pointerId)
907
+ this.gesture = { kind: "none" }, this.click(t.clientX, t.clientY, s, o);
908
+ else if (e.kind === "pan" && e.pointerId === t.pointerId)
909
+ this.gesture = { kind: "none" }, this.setCursor("default"), this.hoverAt(t.clientX, t.clientY, s, o);
910
+ else if (e.kind === "edit" && e.pointerId === t.pointerId) {
911
+ this.stopAutoPan(), this.closeGestureFolds(), this.gesture = { kind: "none" };
912
+ const a = e.ghost.lane === e.subtask.lane || this.allowed(e.subtask, e.ghost.lane), u = this.intentsOf(e.subtask, e.ghost, e.mode).filter(
913
+ (c) => a || c.kind !== "lane"
914
+ );
915
+ this.refused = !1, this.cursor = "default", this.host.interactionChanged();
916
+ for (const c of u) (r = (i = this.host.handlers()).onIntent) == null || r.call(i, c);
917
+ }
918
+ }
919
+ /** While a drag is in flight near an edge, pans along once per frame and
920
+ moves the ghost with the view. Stops by itself when the drag ends or the
921
+ pointer leaves the zone. */
922
+ autoPan() {
923
+ if (this.panFrame !== 0 || typeof requestAnimationFrame != "function") return;
924
+ const t = () => {
925
+ this.panFrame = 0;
926
+ const e = this.gesture;
927
+ if (e.kind !== "edit" && e.kind !== "place") return;
928
+ const s = this.host.view, { x: o, y: i } = this.local(this.lastClient.x, this.lastClient.y), r = ie(o, s.width), a = ie(i, s.height);
929
+ if (r === 0 && a === 0) return;
930
+ const u = s.pan(r, a);
931
+ if (u.moved) {
932
+ if (this.dragPoint = { x: o, y: i }, e.kind === "edit")
933
+ this.gesture = { ...e, ghost: this.ghostFor(e, o, i) };
934
+ else {
935
+ const c = this.placeGhost(e.item, o, i, e.refused);
936
+ this.refused = c.refused, this.gesture = { ...e, ghost: c.ghost ?? e.ghost };
937
+ }
938
+ this.host.viewMoved(u.time), this.panFrame = requestAnimationFrame(t);
939
+ }
940
+ };
941
+ this.panFrame = requestAnimationFrame(t);
942
+ }
943
+ stopAutoPan() {
944
+ this.panFrame !== 0 && cancelAnimationFrame(this.panFrame), this.panFrame = 0;
945
+ }
946
+ pointerCancel(t) {
947
+ this.touches.delete(t.pointerId), this.closeGestureFolds(), this.cancelEdit(), this.gesture = { kind: "none" };
948
+ }
949
+ /** Reads the hover anew where the pointer already is - after the data
950
+ changed under it. A drop that moves a subtask changes what lies under the
951
+ pointer without the pointer moving, and a tooltip still naming the old
952
+ times would be a lie. Nothing is reported: no interaction happened. */
953
+ refreshHover() {
954
+ if (!this.idle || this.hoverKey === "nothing") return;
955
+ const { x: t, y: e } = this.hoverPoint, s = this.host.view.hitAt(t, e);
956
+ this.hover = s, this.hoverKey = le(s);
957
+ }
958
+ pointerLeave() {
959
+ this.gesture.kind === "none" && this.setHover({ kind: "nothing" }, "nothing");
960
+ }
961
+ /** Escape while a drag is in flight: the ghost goes, and nothing is reported.
962
+ It ends a drag from outside as it ends one inside. */
963
+ cancelEdit() {
964
+ return this.gesture.kind !== "edit" && this.gesture.kind !== "place" ? !1 : (this.stopAutoPan(), this.closeGestureFolds(), this.gesture = { kind: "none" }, this.refused = !1, this.cursor = "default", this.host.interactionChanged(), !0);
965
+ }
966
+ contextMenu(t) {
967
+ if (this.host.handlers().onInteraction === void 0) return;
968
+ t.preventDefault();
969
+ const { x: e, y: s } = this.local(t.clientX, t.clientY);
970
+ this.report("contextmenu", this.host.view.hitAt(e, s), t.clientX, t.clientY, e, s);
971
+ }
972
+ /** The wheel, as every scrolling area has it (schedule-refinement 02):
973
+ vertical scrolls the lanes, and lets the page scroll on once they are at
974
+ their end; Ctrl or ⌘ zooms - a trackpad pinch arrives as a wheel with
975
+ Ctrl -; horizontal or Shift pans through time. */
976
+ wheel(t) {
977
+ const e = this.host.view, { x: s } = this.local(t.clientX, t.clientY), o = t.deltaMode === 1 ? 16 : t.deltaMode === 2 ? e.height : 1, i = t.deltaX * o, r = t.deltaY * o;
978
+ if (t.ctrlKey || t.metaKey) {
979
+ t.preventDefault();
980
+ const c = Math.abs(r) < 50 ? 0.01 : 15e-4;
981
+ e.zoomAt(s, Math.exp(r * c)) && this.host.viewMoved(!0);
982
+ return;
983
+ }
984
+ if (Math.abs(i) > Math.abs(r) || t.shiftKey) {
985
+ t.preventDefault();
986
+ const c = e.pan(t.shiftKey && i === 0 ? r : i, 0);
987
+ c.moved && this.host.viewMoved(c.time);
988
+ return;
989
+ }
990
+ const a = r > 0 ? e.maxScroll() - e.scrollY : e.scrollY;
991
+ if (r === 0 || a <= 0) return;
992
+ t.preventDefault();
993
+ const u = e.pan(0, r);
994
+ u.moved && this.host.viewMoved(u.time);
995
+ }
996
+ click(t, e, s, o) {
997
+ const i = this.host.view.hitAt(s, o), r = i.kind === "subtask" ? i.subtask.task : i.kind === "transport" ? this.host.data.taskOfTransport(i.transport) : null;
998
+ this.host.select(r, i.kind === "subtask" ? i.subtask.id : null), this.report("click", i, t, e, s, o);
999
+ }
1000
+ hoverAt(t, e, s, o) {
1001
+ const i = this.host.view.hitAt(s, o), r = le(i), { mode: a } = this.modeAt(s, o);
1002
+ if (this.setCursor(a === "move" ? "grab" : a === "stretch-from" || a === "stretch-to" ? "ew-resize" : "default"), this.hoverPoint = { x: s, y: o }, r === this.hoverKey) {
1003
+ (i.kind === "subtask" || i.kind === "transport") && this.host.interactionChanged();
1004
+ return;
1005
+ }
1006
+ this.setHover(i, r), this.report("hover", i, t, e, s, o);
1007
+ }
1008
+ setHover(t, e) {
1009
+ e !== this.hoverKey && (this.hoverKey = e, this.hover = t, this.host.interactionChanged());
1010
+ }
1011
+ setCursor(t) {
1012
+ t !== this.cursor && (this.cursor = t, this.host.interactionChanged());
1013
+ }
1014
+ touchDistance() {
1015
+ const [t, e] = [...this.touches.values()];
1016
+ return t && e ? Math.hypot(t.x - e.x, t.y - e.y) : 0;
1017
+ }
1018
+ touchCentre() {
1019
+ const [t, e] = [...this.touches.values()];
1020
+ return t && e ? (t.x + e.x) / 2 : 0;
1021
+ }
1022
+ /* ---------------------------------------------------------------- */
1023
+ /* Dragging work in from outside */
1024
+ /* ---------------------------------------------------------------- */
1025
+ /** An HTML drag over the plot. While the caller has declared what it is
1026
+ dragging and handles the place intent, the drop is accepted and a ghost
1027
+ shows where the work would land. */
1028
+ dragOver(t, e) {
1029
+ const s = this.host.view;
1030
+ if (e === null || !s.options.intents.includes("place")) return;
1031
+ const { x: o, y: i } = this.local(t.clientX, t.clientY);
1032
+ if (s.laneIdAt(i) === null && s.foldedGroupAt(i) === null) {
1033
+ this.clearPlacing();
1034
+ return;
1035
+ }
1036
+ t.preventDefault(), this.restOver(i);
1037
+ const r = this.gesture.kind === "place" ? this.gesture.refused : (
1038
+ /* Work dragged in sits on no lane until it is dropped. Where the
1039
+ pointer is not over one either, the rule is asked about an item
1040
+ whose own lane is empty - which is the truth of it: `canMoveTo`
1041
+ is asked ABOUT a lane, and the one this item is on is none. */
1042
+ this.askRefused(this.askedFor(e, this.onLane(i) ?? "", o), null)
1043
+ ), a = this.placeGhost(e, o, i, r);
1044
+ this.refused = a.refused, this.setCursor(a.refused ? "not-allowed" : "default");
1045
+ const u = this.gesture.kind === "place" ? this.gesture.ghost : null, c = a.ghost ?? (a.refused ? u : null);
1046
+ t.dataTransfer !== null && (t.dataTransfer.dropEffect = c === null ? "none" : "copy"), c !== null && (this.lastClient = { x: t.clientX, y: t.clientY }, this.dragPoint = { x: o, y: i }, this.gesture = { kind: "place", ghost: c, item: e, refused: r }, this.host.interactionChanged(), this.autoPan());
1047
+ }
1048
+ /** The ghost of a drag from outside at a point on the plot: none off the
1049
+ lanes, and none where the caller refuses that lane - which the answer
1050
+ says apart, because the two mean different things to the drag. */
1051
+ placeGhost(t, e, s, o) {
1052
+ const i = this.onLane(s);
1053
+ return i === null ? { ghost: null, refused: !1 } : o.has(i) ? { ghost: null, refused: !0 } : { ghost: { ...this.askedFor(t, i, e), id: re }, refused: !1 };
1054
+ }
1055
+ /** The dragged item as a subtask, under the caller's key for it - not the
1056
+ internal sentinel: the rule is asked about the thing the application says
1057
+ it is dragging, and the ghost only afterwards takes the sentinel. */
1058
+ askedFor(t, e, s) {
1059
+ const o = this.snapInside(this.host.view.timeAt(s), this.snapStep());
1060
+ return {
1061
+ id: t.item,
1062
+ task: t.task,
1063
+ lane: e,
1064
+ from: o,
1065
+ to: o + t.duration,
1066
+ ...t.setup === void 0 ? {} : { setup: t.setup },
1067
+ ...t.teardown === void 0 ? {} : { teardown: t.teardown }
1068
+ };
1069
+ }
1070
+ /** The drop: the place intent, and the ghost goes. Off every lane, or with
1071
+ nothing declared, nothing is reported. */
1072
+ drop(t) {
1073
+ var r, a;
1074
+ const e = this.gesture;
1075
+ if (e.kind !== "place") return;
1076
+ t.preventDefault();
1077
+ const { ghost: s, item: o } = e;
1078
+ if (this.stopAutoPan(), this.closeGestureFolds(), this.gesture = { kind: "none" }, this.refused = !1, this.cursor = "default", this.host.interactionChanged(), !this.allowed({ ...s, id: o.item }, s.lane)) return;
1079
+ const i = {
1080
+ kind: "place",
1081
+ item: o.item,
1082
+ task: s.task,
1083
+ lane: s.lane,
1084
+ from: s.from,
1085
+ to: s.to,
1086
+ ...s.setup === void 0 ? {} : { setup: s.setup },
1087
+ ...s.teardown === void 0 ? {} : { teardown: s.teardown }
1088
+ };
1089
+ (a = (r = this.host.handlers()).onIntent) == null || a.call(r, i);
1090
+ }
1091
+ /** The drag left the plot, or the application stopped dragging - which is
1092
+ also how Escape arrives: the browser ends its own drag and sends a leave
1093
+ and a `dragend`, since it delivers no key events while a native drag
1094
+ runs. */
1095
+ clearPlacing() {
1096
+ this.refused = !1, this.cursor = "default", this.closeGestureFolds(), this.gesture.kind === "place" && (this.stopAutoPan(), this.gesture = { kind: "none" }, this.host.interactionChanged());
1097
+ }
1098
+ /* ---------------------------------------------------------------- */
1099
+ /* Ghost and intents */
1100
+ /* ---------------------------------------------------------------- */
1101
+ snapStep() {
1102
+ const t = this.host.view.options.snap;
1103
+ return t === "ticks" ? { step: this.host.view.step(), offset: 0 } : t === !1 ? { step: 0, offset: 0 } : typeof t == "number" ? { step: t, offset: 0 } : t;
1104
+ }
1105
+ ghostFor(t, e, s) {
1106
+ const o = this.host.view, i = t.subtask, r = this.snapStep(), a = o.options.intents, u = this.snapInside(o.timeAt(e), r);
1107
+ switch (t.mode) {
1108
+ case "move": {
1109
+ let c = i.from;
1110
+ const l = o.viewport().scale, d = l.fromPx(e) - t.t0;
1111
+ if (a.includes("move") && Math.abs(d * l.m) >= he) {
1112
+ const g = et(o.options.calendar), b = Y(i.from, g) + d, A = g.intervals.length === 0 ? b : X(Math.max(0, Math.min(g.total, b)), g);
1113
+ c = this.snapInside(A, r);
1114
+ }
1115
+ let p = t.ghost.lane;
1116
+ if (a.includes("lane")) {
1117
+ const g = this.onLane(s) ?? p;
1118
+ this.refused = t.refused.has(g), this.refused || (p = g);
1119
+ } else
1120
+ this.refused = !1;
1121
+ return { ...i, from: c, to: c + (i.to - i.from), lane: p };
1122
+ }
1123
+ case "stretch-from":
1124
+ return { ...i, from: Math.min(u, i.to - Math.max(r.step, U)) };
1125
+ case "stretch-to":
1126
+ return { ...i, to: Math.max(u, i.from + Math.max(r.step, U)) };
1127
+ case "setup":
1128
+ return { ...i, setup: Math.max(0, i.from - u) };
1129
+ case "teardown":
1130
+ return { ...i, teardown: Math.max(0, u - i.to) };
1131
+ }
1132
+ }
1133
+ /** Snapped - and, where the raster lands in time the calendar removes, moved
1134
+ on to the seam, where time counts again. An intent never asks for a time
1135
+ the plant does not run. */
1136
+ snapInside(t, e) {
1137
+ const s = Rs(t, e), o = et(this.host.view.options.calendar);
1138
+ return o.intervals.length === 0 ? s : X(Y(s, o), o);
1139
+ }
1140
+ intentsOf(t, e, s) {
1141
+ const o = [], i = this.host.view.options.intents, r = t.id;
1142
+ return s === "move" ? (e.from !== t.from && i.includes("move") && o.push({ kind: "move", subtask: r, from: e.from, to: e.to }), e.lane !== t.lane && i.includes("lane") && o.push({ kind: "lane", subtask: r, lane: e.lane })) : s === "stretch-from" || s === "stretch-to" ? (e.from !== t.from || e.to !== t.to) && o.push({ kind: "stretch", subtask: r, from: e.from, to: e.to }) : s === "setup" ? (e.setup ?? 0) !== (t.setup ?? 0) && o.push({ kind: "setup", subtask: r, setup: e.setup ?? 0 }) : (e.teardown ?? 0) !== (t.teardown ?? 0) && o.push({ kind: "teardown", subtask: r, teardown: e.teardown ?? 0 }), o;
1143
+ }
1144
+ /** The lane the ghost came from - the only other lane a drag can touch. */
1145
+ ghostHome(t) {
1146
+ return t.kind === "edit" ? t.subtask.lane : t.ghost.lane;
1147
+ }
1148
+ /** The findings the ghost would create, assessed as if it were data - the
1149
+ ghost of a drag from outside is added to the data, the ghost of a drag
1150
+ inside it replaces the subtask it came from.
1151
+
1152
+ Only the two lanes a drag can touch are assessed, the one the ghost is
1153
+ over and the one it came from: an overlap is a finding of one lane, and
1154
+ every other lane's overlaps are the ones already assessed. That is what
1155
+ keeps a plan of hundreds of tasks fluid while a drag runs, since this is
1156
+ computed on every pointer movement. */
1157
+ ghostFindings(t, e) {
1158
+ const s = this.host.data, o = (l) => l.lane === t.lane || l.lane === e, r = [...s.subtasks.filter((l) => l.id !== t.id && o(l)), t], a = (l) => l.first === t.id || l.second === t.id, u = s.transports.filter((l) => l.from === t.id || l.to === t.id), c = t.id === re ? s.subtasks : s.subtasks.map((l) => l.id === t.id ? t : l);
1159
+ return { overlaps: It(r).filter(a), late: _t(c, u) };
1160
+ }
1161
+ }
1162
+ const _e = [], Os = 56;
1163
+ function Hs(n, t = Os) {
1164
+ return n > 0 ? Math.min(st, Math.max(15 * U, je(n * t, 1))) : 15 * U;
1165
+ }
1166
+ function Ys(n, t, e = _e) {
1167
+ const [s, o] = Fe(n, e);
1168
+ return Ve(e, s, o, t, Ie(s)).filter(
1169
+ (i) => i.operatingTime >= n[0] && i.operatingTime <= n[1]
1170
+ );
1171
+ }
1172
+ function Xs(n, t = _e) {
1173
+ const [e, s] = Fe(n, t), o = [], i = new Date(e);
1174
+ for (i.setHours(0, 0, 0, 0); i.getTime() < s && o.length < 400; ) {
1175
+ const r = i.getTime();
1176
+ i.setDate(i.getDate() + 1);
1177
+ const a = i.getTime();
1178
+ o.push({
1179
+ start: r,
1180
+ end: a,
1181
+ from: Y(r, t),
1182
+ to: Y(a, t)
1183
+ });
1184
+ }
1185
+ return o;
1186
+ }
1187
+ function Ks(n, t, e, s) {
1188
+ const o = n[1] - n[0];
1189
+ if (!(o > 0)) return [n[0], n[1]];
1190
+ const i = Math.min(s.max, Math.max(s.min, o * e)), r = (t - n[0]) / o, a = t - r * i;
1191
+ return [a, a + i];
1192
+ }
1193
+ function Ws(n, t) {
1194
+ return [n[0] + t, n[1] + t];
1195
+ }
1196
+ function Fe(n, t) {
1197
+ const e = et(t);
1198
+ if (e.intervals.length === 0) return [n[0], n[1]];
1199
+ const s = (o) => Math.max(0, Math.min(e.total, o));
1200
+ return [X(s(n[0]), e), X(s(n[1]), e)];
1201
+ }
1202
+ const lt = 44;
1203
+ class Us {
1204
+ constructor(t) {
1205
+ f(this, "options", {
1206
+ laneHeight: lt,
1207
+ calendar: [],
1208
+ zoomLimits: { min: Tt, max: 28 * st },
1209
+ snap: "ticks",
1210
+ intents: [],
1211
+ now: null,
1212
+ route: "curve",
1213
+ attach: "centre",
1214
+ ends: "dot"
1215
+ });
1216
+ f(this, "domain", [0, st]);
1217
+ f(this, "scrollY", 0);
1218
+ f(this, "width", 0);
1219
+ f(this, "height", 0);
1220
+ /* What is laid out from top to bottom (`rows.ts`). It is derived here and
1221
+ not in the data, because a row's height comes from a view option; every y
1222
+ in the package reads it. */
1223
+ f(this, "rows", qt({ lanes: [], groups: [], collapsed: /* @__PURE__ */ new Set(), laneHeight: lt }));
1224
+ /** The folded groups, as the scene holds them. */
1225
+ f(this, "collapsed", /* @__PURE__ */ new Set());
1226
+ /** The groups a gesture in flight holds open. Dropped when it ends; the
1227
+ caller's list never learns of it. */
1228
+ f(this, "openForGesture", /* @__PURE__ */ new Set());
1229
+ f(this, "boxes", []);
1230
+ f(this, "boxById", /* @__PURE__ */ new Map());
1231
+ f(this, "paths", []);
1232
+ this.data = t;
1233
+ }
1234
+ /** Takes new options; an initial domain in wall-clock time puts the view
1235
+ there, and a new calendar keeps the wall-clock span in view. */
1236
+ setOptions(t, e) {
1237
+ const s = t.calendar !== this.options.calendar, o = this.options.calendar;
1238
+ if (this.options = t, e !== null || s) {
1239
+ const i = e ?? [X(this.domain[0], o), X(this.domain[1], o)];
1240
+ this.domain = [Y(i[0], t.calendar), Y(i[1], t.calendar)];
1241
+ }
1242
+ }
1243
+ viewport() {
1244
+ return {
1245
+ scale: new Ze(this.domain, [0, this.width]),
1246
+ calendar: this.options.calendar,
1247
+ laneHeight: this.options.laneHeight,
1248
+ scrollY: this.scrollY,
1249
+ rows: this.rows
1250
+ };
1251
+ }
1252
+ maxScroll() {
1253
+ return Math.max(0, this.rows.height - this.height);
1254
+ }
1255
+ /** The lowest y that still lies on a lane. */
1256
+ lanesBottom() {
1257
+ return this.rows.height - this.scrollY - 1;
1258
+ }
1259
+ /** The fine band's step at the current zoom. */
1260
+ step() {
1261
+ const t = this.domain[1] - this.domain[0];
1262
+ return Hs(this.width > 0 ? t / this.width : t);
1263
+ }
1264
+ /** Lays the rows out, clamps the scroll, and lays the data out anew. */
1265
+ layout() {
1266
+ this.rows = qt({
1267
+ lanes: this.data.lanes,
1268
+ groups: this.data.groups,
1269
+ collapsed: is(this.collapsed, this.openForGesture),
1270
+ laneHeight: this.options.laneHeight
1271
+ }), this.scrollY = Math.max(0, Math.min(this.maxScroll(), this.scrollY));
1272
+ const t = this.viewport();
1273
+ this.boxes = [], this.boxById = /* @__PURE__ */ new Map();
1274
+ for (const e of this.data.subtasks) {
1275
+ const s = Lt(this.rows, e.lane);
1276
+ if (s === null) continue;
1277
+ const o = Me(t, e, e.lane, s, this.data.depth.get(e.id) ?? 0);
1278
+ this.boxes.push(o), this.boxById.set(e.id, o);
1279
+ }
1280
+ this.paths = [];
1281
+ for (const e of this.data.transports) {
1282
+ const s = this.boxById.get(e.from), o = this.boxById.get(e.to);
1283
+ s === void 0 || o === void 0 || this.paths.push(bt(t, e, s, o, this.options));
1284
+ }
1285
+ }
1286
+ /** The days of the coarse band and the ticks of the fine band, in pixels. */
1287
+ bands() {
1288
+ const t = this.step();
1289
+ if (this.width <= 0) return { days: [], ticks: [], step: t };
1290
+ const e = this.viewport().scale, s = this.options.calendar;
1291
+ return {
1292
+ days: Xs(this.domain, s).map((o) => {
1293
+ const i = Math.round(e.toPx(o.from));
1294
+ return { start: o.start, x: i, width: Math.round(e.toPx(o.to)) - i };
1295
+ }),
1296
+ ticks: Ys(this.domain, t, s).map((o) => ({ wallClock: o.wallClock, x: Math.round(e.toPx(o.operatingTime)) })),
1297
+ step: t
1298
+ };
1299
+ }
1300
+ /** The now line's x, or null where there is none or it lies outside the plot. */
1301
+ nowX() {
1302
+ const t = this.options.now;
1303
+ if (t === null || this.width <= 0) return null;
1304
+ const e = Math.round(this.viewport().scale.toPx(Y(t, this.options.calendar)));
1305
+ return e >= 0 && e <= this.width ? e : null;
1306
+ }
1307
+ hitAt(t, e) {
1308
+ for (let r = this.boxes.length - 1; r >= 0; r--) {
1309
+ const a = this.boxes[r], u = Te(a, t, e);
1310
+ if (u !== null) return { kind: "subtask", subtask: a.subtask, part: u };
1311
+ }
1312
+ let s = null, o = 4;
1313
+ for (const r of this.paths) {
1314
+ const a = ds(r, t, e);
1315
+ a <= o && (o = a, s = r);
1316
+ }
1317
+ if (s !== null) return { kind: "transport", transport: s.transport };
1318
+ const i = Jt(this.viewport(), e);
1319
+ return i !== null ? { kind: "lane", lane: i } : { kind: "nothing" };
1320
+ }
1321
+ /** The wall-clock time at a plot x; within the calendar's extent. */
1322
+ timeAt(t) {
1323
+ const e = this.viewport().scale.fromPx(t), s = et(this.options.calendar);
1324
+ return s.intervals.length === 0 ? e : X(Math.max(0, Math.min(s.total, e)), s);
1325
+ }
1326
+ /** The lane at a y, strips included: what the pointer is ON.
1327
+
1328
+ One line, and it stays a line of its own: it is one of the three
1329
+ questions this object answers about a y - this one, `dropLaneIdAt` and
1330
+ `foldedGroupAt` - and a caller that reached through `viewport()` for it
1331
+ would be depending on the layout rather than asking the view. */
1332
+ laneIdAt(t) {
1333
+ return Jt(this.viewport(), t);
1334
+ }
1335
+ /** The lane a DROP at this y would land on.
1336
+
1337
+ A **Miniature** is no drop target. A strip is three pixels of a machine's
1338
+ whole day, and a drop aimed at one would be a guess; resting over the
1339
+ group opens it for the gesture instead, and then there is a real lane to
1340
+ aim at. Hover, the tooltip and selection do read a strip - they cost
1341
+ nothing if they are a pixel out. */
1342
+ dropLaneIdAt(t) {
1343
+ const e = nt(this.rows, t + this.scrollY);
1344
+ return e === null || e.kind !== "lane" ? null : e.lane ?? null;
1345
+ }
1346
+ /** The folded group a y lies over, or null. */
1347
+ foldedGroupAt(t) {
1348
+ const e = nt(this.rows, t + this.scrollY);
1349
+ return e !== null && e.kind === "miniature" ? e.group ?? null : null;
1350
+ }
1351
+ /** Pans by pixels. Says what moved: the span through time, the lanes, or
1352
+ neither - a scroll through the lanes is no news about the time. */
1353
+ pan(t, e) {
1354
+ const s = this.domain[0], o = this.scrollY, i = this.domain[1] - s;
1355
+ this.width > 0 && t !== 0 && (this.domain = Ws(this.domain, t / this.width * i)), this.scrollY = Math.max(0, Math.min(this.maxScroll(), this.scrollY + e));
1356
+ const r = this.domain[0] !== s;
1357
+ return { moved: r || this.scrollY !== o, time: r };
1358
+ }
1359
+ /** Zooms around a plot x; says whether the span changed. */
1360
+ zoomAt(t, e) {
1361
+ if (this.width <= 0 || !Number.isFinite(e)) return !1;
1362
+ const s = this.domain, o = this.viewport().scale.fromPx(t);
1363
+ return this.domain = Ks(this.domain, o, e, this.options.zoomLimits), s[0] !== this.domain[0] || s[1] !== this.domain[1];
1364
+ }
1365
+ }
1366
+ const ue = {
1367
+ width: 0,
1368
+ height: 0,
1369
+ laneHeight: lt,
1370
+ scrollY: 0,
1371
+ headers: [],
1372
+ days: [],
1373
+ ticks: [],
1374
+ step: Tt,
1375
+ ghost: null,
1376
+ grips: [],
1377
+ cursor: "default",
1378
+ tooltip: null,
1379
+ now: null,
1380
+ bars: []
1381
+ };
1382
+ class zs {
1383
+ constructor() {
1384
+ f(this, "data", new ps(() => this.viewChanged()));
1385
+ f(this, "view", new Us(this.data));
1386
+ f(this, "gestures");
1387
+ f(this, "handlersNow", {});
1388
+ f(this, "placing", null);
1389
+ f(this, "controlledTask");
1390
+ f(this, "ownTask", null);
1391
+ f(this, "selected", null);
1392
+ /** Which **Lane group**s are folded. Controlled where the caller passes a
1393
+ list, kept here otherwise - the shape `selectedTask` has. Folding changes
1394
+ the view and not the plan, so it is no **Intent** (ADR-0025). */
1395
+ f(this, "controlledCollapsed");
1396
+ f(this, "ownCollapsed", []);
1397
+ f(this, "root", null);
1398
+ f(this, "plot", null);
1399
+ f(this, "dataCanvas", null);
1400
+ f(this, "overlayCanvas", null);
1401
+ f(this, "colours", null);
1402
+ f(this, "frame", 0);
1403
+ f(this, "domainFrame", 0);
1404
+ f(this, "unsubscribeTheme", null);
1405
+ f(this, "snapshot", ue);
1406
+ f(this, "listeners", /* @__PURE__ */ new Set());
1407
+ /* ---------------------------------------------------------------- */
1408
+ /* Registration and options */
1409
+ /* ---------------------------------------------------------------- */
1410
+ f(this, "registerLane", (t) => this.data.registerLane(t));
1411
+ f(this, "updateLane", (t, e) => this.data.updateLane(t, e));
1412
+ f(this, "unregisterLane", (t) => this.data.unregisterLane(t));
1413
+ f(this, "registerGroup", (t) => this.data.registerGroup(t));
1414
+ f(this, "updateGroup", (t, e) => this.data.updateGroup(t, e));
1415
+ f(this, "unregisterGroup", (t) => this.data.unregisterGroup(t));
1416
+ f(this, "registerLayer", (t) => this.data.registerLayer(t));
1417
+ f(this, "updateLayer", (t, e) => this.data.updateLayer(t, e));
1418
+ f(this, "unregisterLayer", (t) => this.data.unregisterLayer(t));
1419
+ f(this, "subscribe", (t) => (this.listeners.add(t), () => {
1420
+ this.listeners.delete(t);
1421
+ }));
1422
+ f(this, "getSnapshot", () => this.snapshot);
1423
+ f(this, "getServerSnapshot", () => ue);
1424
+ /* ---------------------------------------------------------------- */
1425
+ /* Gestures, as the component hands them in */
1426
+ /* ---------------------------------------------------------------- */
1427
+ f(this, "pointerDown", (t) => this.gestures.pointerDown(t));
1428
+ f(this, "pointerMove", (t) => this.gestures.pointerMove(t));
1429
+ f(this, "pointerUp", (t) => this.gestures.pointerUp(t));
1430
+ f(this, "pointerCancel", (t) => this.gestures.pointerCancel(t));
1431
+ f(this, "pointerLeave", () => this.gestures.pointerLeave());
1432
+ f(this, "contextMenu", (t) => this.gestures.contextMenu(t));
1433
+ f(this, "wheel", (t) => this.gestures.wheel(t));
1434
+ f(this, "dragOver", (t) => this.gestures.dragOver(t, this.placing));
1435
+ f(this, "drop", (t) => this.gestures.drop(t));
1436
+ f(this, "dragLeave", () => this.gestures.clearPlacing());
1437
+ f(this, "cancelEdit", () => this.gestures.cancelEdit());
1438
+ this.gestures = new Bs({
1439
+ data: this.data,
1440
+ view: this.view,
1441
+ plotElement: () => this.plot,
1442
+ handlers: () => this.handlersNow,
1443
+ selectedSubtask: () => this.selected,
1444
+ select: (t, e) => this.select(t, e),
1445
+ viewChanged: () => this.viewChanged(),
1446
+ viewMoved: (t) => {
1447
+ this.viewChanged(), t && this.reportDomain();
1448
+ },
1449
+ interactionChanged: () => this.interactionChanged()
1450
+ });
1451
+ }
1452
+ setOptions(t, e) {
1453
+ this.view.setOptions(t, e), this.viewChanged();
1454
+ }
1455
+ setHandlers(t) {
1456
+ this.handlersNow = t;
1457
+ }
1458
+ /** What the application says it is dragging in, while it drags it. */
1459
+ setPlacing(t) {
1460
+ this.placing = t, t === null && this.gestures.clearPlacing();
1461
+ }
1462
+ /** `undefined`: the scene keeps the folded groups itself. */
1463
+ setCollapsedGroups(t) {
1464
+ t !== this.controlledCollapsed && (this.controlledCollapsed = t, this.viewChanged());
1465
+ }
1466
+ /** The uncontrolled starting point, taken once. */
1467
+ setDefaultCollapsedGroups(t) {
1468
+ this.ownCollapsed = t, this.viewChanged();
1469
+ }
1470
+ get collapsedGroups() {
1471
+ return this.controlledCollapsed ?? this.ownCollapsed;
1472
+ }
1473
+ /** Folds or unfolds one group. The caller's list is never written to: where
1474
+ the state is controlled, only the report goes out. */
1475
+ toggleGroup(t) {
1476
+ var o, i;
1477
+ const e = this.collapsedGroups, s = e.includes(t) ? e.filter((r) => r !== t) : [...e, t];
1478
+ this.controlledCollapsed === void 0 && (this.ownCollapsed = s), (i = (o = this.handlersNow).onCollapsedGroupsChange) == null || i.call(o, s), this.viewChanged();
1479
+ }
1480
+ /** `undefined`: the scene keeps the selection itself. */
1481
+ setControlledTask(t) {
1482
+ t !== this.controlledTask && (this.controlledTask = t, this.interactionChanged());
1483
+ }
1484
+ get selectedTask() {
1485
+ return this.controlledTask !== void 0 ? this.controlledTask : this.ownTask;
1486
+ }
1487
+ select(t, e) {
1488
+ var o, i;
1489
+ const s = t !== this.selectedTask || e !== this.selected;
1490
+ this.selected = e, t !== this.selectedTask && this.controlledTask === void 0 && (this.ownTask = t), s && ((i = (o = this.handlersNow).onSelectedTaskChange) == null || i.call(o, t, e)), this.interactionChanged();
1491
+ }
1492
+ /* ---------------------------------------------------------------- */
1493
+ /* DOM binding */
1494
+ /* ---------------------------------------------------------------- */
1495
+ bind(t, e, s, o) {
1496
+ this.root = t, this.plot = e, this.dataCanvas = s, this.overlayCanvas = o, this.unsubscribeTheme = Je(() => {
1497
+ this.colours = null, this.requestDraw();
1498
+ }), this.viewChanged();
1499
+ }
1500
+ unbind() {
1501
+ var t;
1502
+ (t = this.unsubscribeTheme) == null || t.call(this), this.unsubscribeTheme = null, this.frame !== 0 && cancelAnimationFrame(this.frame), this.domainFrame !== 0 && cancelAnimationFrame(this.domainFrame), this.frame = this.domainFrame = 0, this.root = this.plot = this.dataCanvas = this.overlayCanvas = null;
1503
+ }
1504
+ resize(t, e) {
1505
+ const s = Math.max(0, Math.round(t)), o = Math.max(0, Math.round(e));
1506
+ s === this.view.width && o === this.view.height || (this.view.width = s, this.view.height = o, this.viewChanged());
1507
+ }
1508
+ /* ---------------------------------------------------------------- */
1509
+ /* Changes */
1510
+ /* ---------------------------------------------------------------- */
1511
+ viewChanged() {
1512
+ this.view.collapsed = new Set(this.collapsedGroups), this.data.rebuild() && (this.colours = null, this.selected !== null && !this.data.subtaskById.has(this.selected) && (this.selected = null)), this.view.layout(), this.gestures.refreshHover(), this.interactionChanged();
1513
+ }
1514
+ interactionChanged() {
1515
+ this.publish(), this.requestDraw();
1516
+ }
1517
+ publish() {
1518
+ const t = this.view, e = this.selected !== null ? t.boxById.get(this.selected) : void 0, s = [];
1519
+ e !== void 0 && !e.miniature && !this.gestures.editing && e.subtask.task === this.selectedTask && (t.options.intents.includes("setup") && s.push({ kind: "setup", x: e.outerFrom, y: e.y, height: e.height }), t.options.intents.includes("teardown") && s.push({ kind: "teardown", x: e.outerTo, y: e.y, height: e.height })), this.snapshot = {
1520
+ width: t.width,
1521
+ height: t.height,
1522
+ laneHeight: t.options.laneHeight,
1523
+ scrollY: t.scrollY,
1524
+ headers: this.headers(),
1525
+ ...t.bands(),
1526
+ ghost: this.gestures.ghostSummary(),
1527
+ grips: s,
1528
+ cursor: this.gestures.cursor,
1529
+ tooltip: this.tooltip(),
1530
+ now: t.nowX(),
1531
+ bars: this.bars()
1532
+ };
1533
+ for (const o of this.listeners) o();
1534
+ }
1535
+ /** One header per row, with what it says and where it sits. The scroll is
1536
+ not taken off here: the header column is moved as a whole, as it always
1537
+ was, so that a header and its row cannot drift apart by a rounding. */
1538
+ headers() {
1539
+ const t = new Map(this.data.lanes.map((o) => [o.id, o.label])), e = new Map(this.data.groups.map((o) => [o.id, o.label])), s = new Set(this.collapsedGroups);
1540
+ return this.view.rows.rows.map((o) => ({
1541
+ key: o.lane ?? o.group ?? "",
1542
+ kind: o.kind,
1543
+ lane: o.lane,
1544
+ group: o.group,
1545
+ label: (o.lane !== void 0 ? t.get(o.lane) : e.get(o.group ?? "")) ?? o.lane ?? o.group ?? "",
1546
+ depth: o.depth,
1547
+ within: o.within,
1548
+ lanes: o.lanes,
1549
+ collapsed: o.group === void 0 ? void 0 : s.has(o.group),
1550
+ top: o.top,
1551
+ height: o.height
1552
+ }));
1553
+ }
1554
+ /** The bars a label could stand in: the visible part of every main time,
1555
+ with the contrast its colour calls for. Computed on every publish, which
1556
+ is what lets a label follow a bar while the plot pans. */
1557
+ bars() {
1558
+ const t = this.view;
1559
+ if (t.width <= 0) return [];
1560
+ const e = this.colours;
1561
+ return t.boxes.flatMap((s) => {
1562
+ if (!Ce(s, t.width, t.height)) return [];
1563
+ const o = us(s, t.width);
1564
+ if (o === null) return [];
1565
+ const i = e === null ? void 0 : e.tasks.get(s.subtask.task), r = i === void 0 || e === null ? !0 : Ft(ht(s.subtask.appearance), i, e).onDark;
1566
+ return [{ subtask: s.subtask, ...o, dark: r }];
1567
+ });
1568
+ }
1569
+ tooltip() {
1570
+ const t = this.gestures.hover;
1571
+ if (!this.gestures.idle) return null;
1572
+ const e = this.data.tooltipTargetFor(t);
1573
+ if (e === null) return null;
1574
+ const { x: s, y: o } = this.gestures.hoverPoint;
1575
+ return { target: e, x: s, y: o };
1576
+ }
1577
+ /** The visible span, as two wall-clock instants. */
1578
+ visibleDomain() {
1579
+ const t = et(this.view.options.calendar), e = (s) => t.intervals.length === 0 ? s : X(Math.max(0, Math.min(t.total, s)), t);
1580
+ return [e(this.view.domain[0]), e(this.view.domain[1])];
1581
+ }
1582
+ /** Reported once per frame, however many wheel steps a planner turns - and
1583
+ only for their gestures: a span handed in from outside is not news to the
1584
+ caller who handed it in, and reporting it would let two schedules
1585
+ synchronised with each other feed one another for ever. */
1586
+ reportDomain() {
1587
+ var t, e;
1588
+ if (typeof requestAnimationFrame != "function") {
1589
+ (e = (t = this.handlersNow).onDomainChange) == null || e.call(t, this.visibleDomain());
1590
+ return;
1591
+ }
1592
+ this.domainFrame === 0 && (this.domainFrame = requestAnimationFrame(() => {
1593
+ var s, o;
1594
+ this.domainFrame = 0, (o = (s = this.handlersNow).onDomainChange) == null || o.call(s, this.visibleDomain());
1595
+ }));
1596
+ }
1597
+ /** The time and the lane at a client point, or null outside the plot. */
1598
+ positionAt(t, e) {
1599
+ var r;
1600
+ const s = (r = this.plot) == null ? void 0 : r.getBoundingClientRect();
1601
+ if (s === void 0) return null;
1602
+ const o = t - s.left, i = e - s.top;
1603
+ return o < 0 || i < 0 || o > s.width || i > s.height ? null : { time: this.view.timeAt(o), lane: this.view.laneIdAt(i) };
1604
+ }
1605
+ /** The client point of a time, on a lane's middle where one is named, or
1606
+ null while the schedule is not on screen. */
1607
+ clientPointOf(t, e) {
1608
+ var a;
1609
+ const s = (a = this.plot) == null ? void 0 : a.getBoundingClientRect();
1610
+ if (s === void 0) return null;
1611
+ const o = this.view.viewport(), i = e === void 0 ? null : ct(o, e), r = i === null ? 0 : i.top + i.height / 2;
1612
+ return { x: s.left + P(o, t), y: s.top + r };
1613
+ }
1614
+ requestDraw() {
1615
+ this.frame !== 0 || this.dataCanvas === null || typeof requestAnimationFrame != "function" || (this.frame = requestAnimationFrame(() => {
1616
+ this.frame = 0, this.draw();
1617
+ }));
1618
+ }
1619
+ draw() {
1620
+ if (this.root === null) return;
1621
+ this.colours === null && (this.colours = gs(this.root, this.data), this.publish());
1622
+ const { width: t, height: e } = this.view, s = se(this.dataCanvas, t, e), o = se(this.overlayCanvas, t, e);
1623
+ if (s === null || o === null || t === 0) return;
1624
+ const i = {
1625
+ data: this.data,
1626
+ view: this.view,
1627
+ colours: this.colours,
1628
+ bands: this.snapshot,
1629
+ selectedTask: this.selectedTask,
1630
+ selectedSubtask: this.selected,
1631
+ hover: this.gestures.hover,
1632
+ ghost: this.gestures.ghostDrawing()
1633
+ };
1634
+ ks(s, i), ws(o, i);
1635
+ }
1636
+ }
1637
+ const qs = "_root_ekx9o_4 _text_18b86_23", js = "_corner_ekx9o_18", Vs = "_dayBand_ekx9o_22", Zs = "_tickBand_ekx9o_23", Js = "_day_ekx9o_22", Qs = "_dayLabel_ekx9o_46", tn = "_tick_ekx9o_23", en = "_tickLabel_ekx9o_64", sn = "_headers_ekx9o_72", nn = "_header_ekx9o_72", on = "_headerLabel_ekx9o_90", rn = "_headerCount_ekx9o_103", an = "_chevron_ekx9o_112", ln = "_plot_ekx9o_160", hn = "_layer_ekx9o_166", un = "_grip_ekx9o_175", cn = "_ghostLabel_ekx9o_185", dn = "_finding_ekx9o_198", fn = "_refusal_ekx9o_206", pn = "_tooltip_ekx9o_210", mn = "_tooltipHead_ekx9o_228", gn = "_tooltipTimes_ekx9o_233", kn = "_now_ekx9o_242", wn = "_barLabel_ekx9o_256", vn = "_barLabelText_ekx9o_269", v = {
1638
+ root: qs,
1639
+ corner: js,
1640
+ dayBand: Vs,
1641
+ tickBand: Zs,
1642
+ day: Js,
1643
+ dayLabel: Qs,
1644
+ tick: tn,
1645
+ tickLabel: en,
1646
+ headers: sn,
1647
+ header: nn,
1648
+ headerLabel: on,
1649
+ headerCount: rn,
1650
+ chevron: an,
1651
+ plot: ln,
1652
+ layer: hn,
1653
+ grip: un,
1654
+ ghostLabel: cn,
1655
+ finding: dn,
1656
+ refusal: fn,
1657
+ tooltip: pn,
1658
+ tooltipHead: mn,
1659
+ tooltipTimes: gn,
1660
+ now: kn,
1661
+ barLabel: wn,
1662
+ barLabelText: vn
1663
+ };
1664
+ function yn({ target: n }) {
1665
+ const t = me(), e = ge(), s = (l) => t.time(new Date(l), !1), o = (l) => {
1666
+ const d = Math.round(l / U), p = Math.floor(d / 60), g = d % 60;
1667
+ return [p > 0 ? e.hoursShort(p) : "", g > 0 || p === 0 ? e.minutesShort(g) : ""].filter(Boolean).join(" ");
1668
+ };
1669
+ if (n.kind === "subtask") {
1670
+ const { subtask: l, task: d } = n;
1671
+ return /* @__PURE__ */ H(zt, { children: [
1672
+ /* @__PURE__ */ w("span", { className: v.tooltipHead, children: (d == null ? void 0 : d.name) ?? l.task }),
1673
+ /* @__PURE__ */ w("span", { children: l.name ?? l.id }),
1674
+ /* @__PURE__ */ w("span", { className: v.tooltipTimes, children: e.scheduleGhostTimes(s(l.from), s(l.to)) }),
1675
+ (l.setup ?? 0) > 0 && /* @__PURE__ */ w("span", { children: `${e.scheduleSetup} ${o(l.setup)}` }),
1676
+ (l.teardown ?? 0) > 0 && /* @__PURE__ */ w("span", { children: `${e.scheduleTeardown} ${o(l.teardown)}` }),
1677
+ n.overlapping.map((p) => /* @__PURE__ */ w("span", { className: v.finding, children: e.scheduleOverlapWith(p.name ?? p.id) }, p.id)),
1678
+ n.lateTransports.map((p) => /* @__PURE__ */ w("span", { className: v.finding, children: e.scheduleLateBy(o(p.shortBy)) }, p.transport))
1679
+ ] });
1680
+ }
1681
+ const { transport: i, task: r, from: a, to: u, late: c } = n;
1682
+ return /* @__PURE__ */ H(zt, { children: [
1683
+ /* @__PURE__ */ w("span", { className: v.tooltipHead, children: (r == null ? void 0 : r.name) ?? (r == null ? void 0 : r.id) ?? i.id }),
1684
+ /* @__PURE__ */ w("span", { children: e.scheduleRoute((a == null ? void 0 : a.name) ?? i.from, (u == null ? void 0 : u.name) ?? i.to) }),
1685
+ /* @__PURE__ */ w("span", { children: `${e.scheduleTransport} ${o(i.duration)}` }),
1686
+ c !== void 0 && /* @__PURE__ */ w("span", { className: v.finding, children: e.scheduleLateBy(o(c.shortBy)) })
1687
+ ] });
1688
+ }
1689
+ const bn = [], ce = { min: Tt, max: 28 * st }, Mn = [], de = 20, Fn = Xe(function(t, e) {
1690
+ const {
1691
+ ariaLabel: s,
1692
+ initialDomain: o,
1693
+ height: i = 400,
1694
+ laneHeight: r = lt,
1695
+ headerWidth: a = 160,
1696
+ calendar: u = Mn,
1697
+ zoomLimits: c,
1698
+ snap: l = "ticks",
1699
+ intents: d = bn,
1700
+ onIntent: p,
1701
+ canMoveTo: g,
1702
+ onInteraction: b,
1703
+ selectedTask: A,
1704
+ onSelectedTaskChange: _,
1705
+ collapsedGroups: S,
1706
+ defaultCollapsedGroups: m,
1707
+ onCollapsedGroupsChange: C,
1708
+ onDomainChange: L,
1709
+ placing: E,
1710
+ route: F = "curve",
1711
+ attach: G = "centre",
1712
+ ends: j = "dot",
1713
+ label: ot,
1714
+ tooltip: z,
1715
+ now: V,
1716
+ className: Et,
1717
+ style: Ee,
1718
+ children: De
1719
+ } = t, [k] = it(() => new zs()), Dt = Ke(), xt = $(null), Pt = $(null), Nt = $(null), Gt = $(null), K = me(), W = ge(), [dt, ft] = o, Rt = (c == null ? void 0 : c.min) ?? ce.min, $t = (c == null ? void 0 : c.max) ?? ce.max, Bt = $(null), Ot = typeof l == "object" ? l.step : null, Ht = typeof l == "object" ? l.offset : null, Yt = typeof l == "object" ? null : l, [xe, Pe] = it(() => Date.now());
1720
+ B(() => {
1721
+ if (V !== !0) return;
1722
+ const h = setInterval(() => Pe(Date.now()), U);
1723
+ return () => clearInterval(h);
1724
+ }, [V]);
1725
+ const Xt = V === !0 ? xe : typeof V == "number" ? V : null;
1726
+ vt(() => {
1727
+ const h = `${dt}|${ft}`, y = Bt.current !== h;
1728
+ Bt.current = h;
1729
+ const I = Yt ?? { step: Ot ?? 0, offset: Ht ?? 0 };
1730
+ k.setOptions(
1731
+ { laneHeight: r, calendar: u, zoomLimits: { min: Rt, max: $t }, snap: I, intents: d, now: Xt, route: F, attach: G, ends: j },
1732
+ y ? [dt, ft] : null
1733
+ );
1734
+ }, [k, dt, ft, r, u, Rt, $t, Yt, Ot, Ht, d, Xt, F, G, j]), B(() => {
1735
+ k.setHandlers({ onIntent: p, canMoveTo: g, onInteraction: b, onSelectedTaskChange: _, onCollapsedGroupsChange: C, onDomainChange: L });
1736
+ }, [k, p, g, b, _, C, L]);
1737
+ const Ne = $(m);
1738
+ B(() => {
1739
+ const h = Ne.current;
1740
+ h !== void 0 && k.setDefaultCollapsedGroups(h);
1741
+ }, [k]), B(() => {
1742
+ k.setCollapsedGroups(S);
1743
+ }, [k, S]), We(
1744
+ e,
1745
+ () => ({
1746
+ positionAt: (h, y) => k.positionAt(h, y),
1747
+ clientPointOf: (h, y) => k.clientPointOf(h, y),
1748
+ visibleDomain: () => k.visibleDomain()
1749
+ }),
1750
+ [k]
1751
+ ), B(() => {
1752
+ k.setControlledTask(A);
1753
+ }, [k, A]), B(() => {
1754
+ k.setPlacing(E ?? null);
1755
+ }, [k, E]), B(() => {
1756
+ const h = xt.current, y = Pt.current, I = Nt.current, R = Gt.current;
1757
+ if (!h || !y || !I || !R) return;
1758
+ k.bind(h, y, I, R);
1759
+ const D = y.getBoundingClientRect();
1760
+ k.resize(D.width, D.height);
1761
+ const x = new ResizeObserver((N) => {
1762
+ var Ut;
1763
+ const Q = (Ut = N[N.length - 1]) == null ? void 0 : Ut.contentRect;
1764
+ Q !== void 0 && k.resize(Q.width, Q.height);
1765
+ });
1766
+ x.observe(y);
1767
+ const Z = (N) => k.wheel(N);
1768
+ y.addEventListener("wheel", Z, { passive: !1 });
1769
+ const J = (N) => {
1770
+ N.key === "Escape" && k.cancelEdit() && N.preventDefault();
1771
+ };
1772
+ return window.addEventListener("keydown", J), () => {
1773
+ window.removeEventListener("keydown", J), y.removeEventListener("wheel", Z), x.disconnect(), k.unbind();
1774
+ };
1775
+ }, [k]);
1776
+ const T = Ue(k.subscribe, k.getSnapshot, k.getServerSnapshot), Ge = (h, y) => {
1777
+ const I = new Date(h);
1778
+ return y >= 200 ? K.dateLong(I) : y >= 84 ? K.date(I) : y >= 44 ? K.dateShort(I) : "";
1779
+ }, M = T.ghost, pt = (h) => `${Dt}-row-${h.key}`, Re = q(() => {
1780
+ const h = /* @__PURE__ */ new Map();
1781
+ for (const y of T.headers)
1782
+ for (const I of y.within)
1783
+ y.kind === "groupHead" && I === y.group || h.set(I, [...h.get(I) ?? [], pt(y)]);
1784
+ return h;
1785
+ }, [T.headers, Dt]), $e = q(() => new Set((M == null ? void 0 : M.refusedLanes) ?? []), [M == null ? void 0 : M.refusedLanes]), Kt = $(null), [mt, Be] = it({ x: 0, y: 0, at: "" }), gt = M === null ? "" : `${M.x}:${M.y}:${M.from}:${M.to}:${M.overlap}:${M.late}`;
1786
+ vt(() => {
1787
+ const h = Kt.current;
1788
+ if (M === null || h === null) return;
1789
+ const y = 4, I = M.y - h.offsetHeight - y, R = M.y + M.height + y, D = {
1790
+ x: Math.max(2, Math.min(M.x, T.width - h.offsetWidth - 2)),
1791
+ y: I >= 2 ? I : Math.min(R, T.height - h.offsetHeight - 2),
1792
+ at: gt
1793
+ };
1794
+ Be((x) => x.x === D.x && x.y === D.y && x.at === D.at ? x : D);
1795
+ }, [M, gt, T.width, T.height]);
1796
+ const Wt = $(null), [kt, Oe] = it({ x: 0, y: 0, at: "" }), O = T.tooltip, wt = O === null ? "" : `${O.x}:${O.y}:${O.target.kind}`;
1797
+ return vt(() => {
1798
+ const h = Wt.current;
1799
+ if (O === null || h === null) return;
1800
+ const y = 12, I = (D, x, Z) => {
1801
+ const J = D + y, N = D - y - x, Q = J + x <= Z - 4 || N < 4 ? J : N;
1802
+ return Math.max(4, Math.min(Q, Z - x - 4));
1803
+ }, R = {
1804
+ x: I(O.x, h.offsetWidth, T.width),
1805
+ y: I(O.y, h.offsetHeight, T.height),
1806
+ at: wt
1807
+ };
1808
+ Oe((D) => D.x === R.x && D.y === R.y && D.at === R.at ? D : R);
1809
+ }, [O, wt, T.width, T.height]), /* @__PURE__ */ H(ke.Provider, { value: k, children: [
1810
+ /* @__PURE__ */ H(
1811
+ "div",
1812
+ {
1813
+ ref: xt,
1814
+ role: "figure",
1815
+ "aria-label": s,
1816
+ className: Et ? `${v.root} ${Et}` : v.root,
1817
+ style: { height: `${i}px`, gridTemplateColumns: `${a}px minmax(0, 1fr)`, ...Ee },
1818
+ children: [
1819
+ /* @__PURE__ */ w("div", { className: v.corner }),
1820
+ /* @__PURE__ */ w("div", { className: v.dayBand, "aria-hidden": "true", "data-schedule-days": "", "data-schedule-clip": "day band", children: T.days.map((h) => {
1821
+ const y = Math.max(0, -h.x), I = Math.min(h.x + h.width, T.width) - Math.max(h.x, 0);
1822
+ return /* @__PURE__ */ w("span", { className: v.day, style: { left: `${h.x}px`, width: `${h.width}px` }, children: /* @__PURE__ */ w("span", { className: v.dayLabel, "data-schedule-overlay": "day label", style: { marginLeft: `${y}px` }, children: Ge(h.start, I) }) }, h.start);
1823
+ }) }),
1824
+ /* @__PURE__ */ w("div", { className: v.headers, "data-schedule-headers": "", children: /* @__PURE__ */ w("div", { className: v.headerRun, style: { transform: `translateY(${-T.scrollY}px)` }, children: T.headers.map((h) => /* @__PURE__ */ H(
1825
+ "div",
1826
+ {
1827
+ id: pt(h),
1828
+ className: v.header,
1829
+ style: { height: `${h.height}px`, paddingLeft: `calc(var(--u-space-3) + ${h.depth} * var(--u-space-3))` },
1830
+ "data-lane": h.lane,
1831
+ "data-group": h.group,
1832
+ "data-row": h.kind,
1833
+ "data-schedule-clip": `header ${h.kind}`,
1834
+ "data-refused": h.lane !== void 0 && $e.has(h.lane) ? "" : void 0,
1835
+ children: [
1836
+ h.kind !== "lane" && h.group !== void 0 && /* @__PURE__ */ w(
1837
+ "button",
1838
+ {
1839
+ type: "button",
1840
+ className: v.chevron,
1841
+ "data-schedule-overlay": "fold control",
1842
+ "aria-expanded": h.collapsed === !1,
1843
+ "aria-controls": (Re.get(h.group) ?? [pt(h)]).join(" "),
1844
+ "aria-label": `${h.collapsed === !0 ? W.scheduleUnfoldGroup : W.scheduleFoldGroup}: ${typeof h.label == "string" ? h.label : h.group}`,
1845
+ onClick: () => k.toggleGroup(h.group),
1846
+ children: /* @__PURE__ */ w("svg", { viewBox: "0 0 10 10", width: "9", height: "9", "aria-hidden": "true", "data-open": h.collapsed === !1 ? "" : void 0, children: /* @__PURE__ */ w("path", { d: "M3.5 1.5 7 5l-3.5 3.5", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
1847
+ }
1848
+ ),
1849
+ /* @__PURE__ */ w("span", { className: v.headerLabel, "data-schedule-overlay": "header label", children: h.label }),
1850
+ h.kind !== "lane" && /* @__PURE__ */ w("span", { className: v.headerCount, "data-schedule-overlay": "lane count", "data-lane-count": h.lanes, children: W.scheduleLaneCount(h.lanes) })
1851
+ ]
1852
+ },
1853
+ h.key
1854
+ )) }) }),
1855
+ /* @__PURE__ */ H(
1856
+ "div",
1857
+ {
1858
+ ref: Pt,
1859
+ className: v.plot,
1860
+ "data-schedule-plot": "",
1861
+ "data-schedule-clip": "plot",
1862
+ style: { cursor: T.cursor },
1863
+ onPointerDown: (h) => k.pointerDown(h.nativeEvent),
1864
+ onPointerMove: (h) => k.pointerMove(h.nativeEvent),
1865
+ onPointerUp: (h) => k.pointerUp(h.nativeEvent),
1866
+ onPointerCancel: (h) => k.pointerCancel(h.nativeEvent),
1867
+ onPointerLeave: () => k.pointerLeave(),
1868
+ onContextMenu: (h) => k.contextMenu(h.nativeEvent),
1869
+ onDragOver: (h) => k.dragOver(h.nativeEvent),
1870
+ onDrop: (h) => k.drop(h.nativeEvent),
1871
+ onDragLeave: (h) => {
1872
+ const y = h.nativeEvent.relatedTarget;
1873
+ (!(y instanceof Node) || !h.currentTarget.contains(y)) && k.dragLeave();
1874
+ },
1875
+ children: [
1876
+ /* @__PURE__ */ w("canvas", { ref: Nt, className: v.layer, "aria-hidden": "true" }),
1877
+ /* @__PURE__ */ w("canvas", { ref: Gt, className: v.layer, "aria-hidden": "true" }),
1878
+ T.grips.map((h) => /* @__PURE__ */ w(
1879
+ "span",
1880
+ {
1881
+ "data-grip": h.kind,
1882
+ "data-schedule-overlay": `${h.kind} grip`,
1883
+ "aria-hidden": "true",
1884
+ className: v.grip,
1885
+ style: { left: `${h.x}px`, top: `${h.y}px`, height: `${h.height}px` }
1886
+ },
1887
+ h.kind
1888
+ )),
1889
+ ot !== void 0 && T.bars.map((h) => /* @__PURE__ */ w(
1890
+ "span",
1891
+ {
1892
+ className: v.barLabel,
1893
+ "data-bar-label": h.subtask.id,
1894
+ "data-schedule-overlay": "bar label",
1895
+ "data-schedule-may-cover": "",
1896
+ "data-on": h.dark ? "dark" : "light",
1897
+ style: { left: `${h.x}px`, top: `${h.y}px`, width: `${h.width}px`, height: `${h.height}px` },
1898
+ children: /* @__PURE__ */ w("span", { className: v.barLabelText, children: ot(h.subtask) })
1899
+ },
1900
+ h.subtask.id
1901
+ )),
1902
+ z !== !1 && T.tooltip !== null && /* @__PURE__ */ w(
1903
+ "span",
1904
+ {
1905
+ ref: Wt,
1906
+ role: "tooltip",
1907
+ className: v.tooltip,
1908
+ "data-schedule-tooltip": "",
1909
+ "data-schedule-overlay": "tooltip",
1910
+ style: {
1911
+ left: `${kt.x}px`,
1912
+ top: `${kt.y}px`,
1913
+ visibility: kt.at === wt ? void 0 : "hidden"
1914
+ },
1915
+ children: typeof z == "function" ? z(T.tooltip.target) : /* @__PURE__ */ w(yn, { target: T.tooltip.target })
1916
+ }
1917
+ ),
1918
+ M !== null && /* @__PURE__ */ H(
1919
+ "span",
1920
+ {
1921
+ ref: Kt,
1922
+ className: v.ghostLabel,
1923
+ "data-ghost": "",
1924
+ "data-schedule-overlay": "ghost label",
1925
+ "data-findings": [M.overlap ? "overlap" : "", M.late ? "late-transport" : ""].filter(Boolean).join(" "),
1926
+ "data-refused": M.refused ? "" : void 0,
1927
+ style: {
1928
+ left: `${mt.x}px`,
1929
+ top: `${mt.y}px`,
1930
+ visibility: mt.at === gt ? void 0 : "hidden"
1931
+ },
1932
+ children: [
1933
+ W.scheduleGhostTimes(K.time(new Date(M.from), !1), K.time(new Date(M.to), !1)),
1934
+ M.refused && /* @__PURE__ */ w("span", { className: v.refusal, children: W.scheduleLaneRefused }),
1935
+ M.overlap && /* @__PURE__ */ w("span", { className: v.finding, children: W.scheduleOverlap }),
1936
+ M.late && /* @__PURE__ */ w("span", { className: v.finding, children: W.scheduleLateTransport })
1937
+ ]
1938
+ }
1939
+ )
1940
+ ]
1941
+ }
1942
+ ),
1943
+ /* @__PURE__ */ w("div", { className: v.corner }),
1944
+ /* @__PURE__ */ H("div", { className: v.tickBand, "aria-hidden": "true", "data-schedule-ticks": "", "data-schedule-clip": "time band", children: [
1945
+ T.now !== null && /* @__PURE__ */ w("span", { className: v.now, "data-now": "", "data-schedule-overlay": "now mark", style: { left: `${T.now}px` } }),
1946
+ T.ticks.map((h) => /* @__PURE__ */ w("span", { className: v.tick, style: { left: `${h.x}px` }, children: h.x >= de && h.x <= T.width - de && /* @__PURE__ */ w("span", { className: v.tickLabel, "data-schedule-overlay": "time label", children: T.step >= st ? K.dateShort(new Date(h.wallClock)) : K.time(new Date(h.wallClock), !1) }) }, h.wallClock))
1947
+ ] })
1948
+ ]
1949
+ }
1950
+ ),
1951
+ De
1952
+ ] });
1953
+ });
1954
+ function En({ id: n, label: t }) {
1955
+ const e = ve(), s = q(() => ({ id: n, label: t ?? n, ...e === null ? {} : { parent: e } }), [n, t, e]);
1956
+ return ts(s), null;
1957
+ }
1958
+ function Dn({ id: n, label: t, children: e }) {
1959
+ const s = ve(), o = q(() => ({ id: n, label: t ?? n, ...s === null ? {} : { parent: s } }), [n, t, s]);
1960
+ return es(o), /* @__PURE__ */ w(we.Provider, { value: n, children: e });
1961
+ }
1962
+ function xn({ data: n, tasks: t }) {
1963
+ const e = q(() => ({ kind: "subtasks", data: n, tasks: t }), [n, t]);
1964
+ return ye("Subtasks", e), null;
1965
+ }
1966
+ function Pn({ data: n }) {
1967
+ const t = q(() => ({ kind: "transports", data: n }), [n]);
1968
+ return ye("Transports", t), null;
1969
+ }
1970
+ function Nn(n, t, e) {
1971
+ if (e.kind === "place") return [];
1972
+ const s = new Map(n.map((u) => [u.id, jt(u, e)])), o = /* @__PURE__ */ new Map();
1973
+ for (const u of t) {
1974
+ const c = o.get(u.from) ?? [];
1975
+ c.push(u), o.set(u.from, c);
1976
+ }
1977
+ const i = /* @__PURE__ */ new Map(), r = [e.subtask];
1978
+ let a = (n.length + 1) * (t.length + 1);
1979
+ for (; r.length > 0 && a-- > 0; ) {
1980
+ const u = r.shift(), c = s.get(u);
1981
+ if (c !== void 0)
1982
+ for (const l of o.get(u) ?? []) {
1983
+ if (l.to === e.subtask) continue;
1984
+ const d = s.get(l.to);
1985
+ if (d === void 0) continue;
1986
+ const p = St(l, c) + l.duration - At(l, d);
1987
+ if (!(p > 0)) continue;
1988
+ const g = { kind: "move", subtask: d.id, from: d.from + p, to: d.to + p };
1989
+ s.set(d.id, jt(d, g)), i.set(d.id, g), r.push(d.id);
1990
+ }
1991
+ }
1992
+ return [...i.values()];
1993
+ }
1994
+ function Gn(n, t, e) {
1995
+ return e === 0 || !Number.isFinite(e) ? [] : n.filter((s) => s.task === t).map((s) => ({ kind: "move", subtask: s.id, from: s.from + e, to: s.to + e }));
1996
+ }
1997
+ export {
1998
+ En as Lane,
1999
+ Dn as LaneGroup,
2000
+ Fn as Schedule,
2001
+ xn as Subtasks,
2002
+ Pn as Transports,
2003
+ jt as applyIntent,
2004
+ At as arrival,
2005
+ St as departure,
2006
+ _n as findings,
2007
+ _t as lateTransports,
2008
+ ut as occupied,
2009
+ It as overlaps,
2010
+ ht as resolveAppearance,
2011
+ Nn as ripple,
2012
+ Gn as shiftTask,
2013
+ Rs as snapTime,
2014
+ In as subtaskFromPlace
2015
+ };