@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.
- package/CHANGELOG.md +224 -0
- package/LICENSE +20 -0
- package/README.md +138 -0
- package/dist/index.d.ts +560 -0
- package/dist/schedule.css +1 -0
- package/dist/schedule.js +2015 -0
- package/package.json +79 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,560 @@
|
|
|
1
|
+
import { CalendarInput } from '@umriss-ui/charts';
|
|
2
|
+
import { CSSProperties } from 'react';
|
|
3
|
+
import { ForwardRefExoticComponent } from 'react';
|
|
4
|
+
import { ReactNode } from 'react';
|
|
5
|
+
import { RefAttributes } from 'react';
|
|
6
|
+
|
|
7
|
+
/** The subtask as the intent asks for it. An intent for another subtask leaves
|
|
8
|
+
it as it is. */
|
|
9
|
+
export declare function applyIntent<S extends Subtask>(subtask: S, intent: Intent): S;
|
|
10
|
+
|
|
11
|
+
/** When a transport has to have arrived at its subtask, by its anchor. */
|
|
12
|
+
export declare function arrival(transport: Transport, to: Subtask): number;
|
|
13
|
+
|
|
14
|
+
/** When a transport leaves its subtask, by its anchor. */
|
|
15
|
+
export declare function departure(transport: Transport, from: Subtask): number;
|
|
16
|
+
|
|
17
|
+
/** Both kinds of finding over the same data. */
|
|
18
|
+
export declare interface Findings {
|
|
19
|
+
readonly overlaps: readonly Overlap[];
|
|
20
|
+
readonly lateTransports: readonly LateTransport[];
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Overlaps and late transports at once. */
|
|
24
|
+
export declare function findings(subtasks: readonly Subtask[], transports: readonly Transport[]): Findings;
|
|
25
|
+
|
|
26
|
+
/** What the schedule reports when an interaction asks for a change. Every
|
|
27
|
+
intent carries the values it asks for, not a difference: two intents of one
|
|
28
|
+
drop - a move and a lane - give the same data in either order. */
|
|
29
|
+
export declare type Intent = MoveIntent | StretchIntent | SetupIntent | TeardownIntent | LaneIntent | PlaceIntent;
|
|
30
|
+
|
|
31
|
+
/** The names of the intents - the editing API of the schedule. */
|
|
32
|
+
export declare type IntentKind = Intent["kind"];
|
|
33
|
+
|
|
34
|
+
/** One lane: a machine or station. The lanes run top to bottom in the order
|
|
35
|
+
they are declared - whichever group they are declared in. */
|
|
36
|
+
export declare function Lane({ id, label }: LaneProps): null;
|
|
37
|
+
|
|
38
|
+
/** A group of lanes: structure over them, and never a lane itself.
|
|
39
|
+
|
|
40
|
+
It gives its id to its children through context, so a lane never names its
|
|
41
|
+
group and a group reads in JSX as it reads in the plant. Folded, it becomes
|
|
42
|
+
one row showing a **Miniature** of everything in it; open, it shows a slim
|
|
43
|
+
head above its lanes. Which groups are folded is `collapsedGroups` on
|
|
44
|
+
`Schedule` - a view state, never an **Intent**. */
|
|
45
|
+
export declare function LaneGroup({ id, label, children }: LaneGroupProps): ReactNode;
|
|
46
|
+
|
|
47
|
+
export declare interface LaneGroupProps {
|
|
48
|
+
/** The group's identity - what `collapsedGroups` names. It is never a lane:
|
|
49
|
+
no subtask sits on it, no finding is reported for it, and no intent names
|
|
50
|
+
it (ADR-0025). */
|
|
51
|
+
id: string;
|
|
52
|
+
/** What the group's header says - the hall, the line, the machine group.
|
|
53
|
+
Real text, read by a screen reader; without one the header shows the id. */
|
|
54
|
+
label?: ReactNode;
|
|
55
|
+
/** `Lane`s and further `LaneGroup`s, to any depth. */
|
|
56
|
+
children?: ReactNode;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** Put the subtask on another lane. */
|
|
60
|
+
export declare interface LaneIntent {
|
|
61
|
+
readonly kind: "lane";
|
|
62
|
+
/** The id of the subtask. */
|
|
63
|
+
readonly subtask: string;
|
|
64
|
+
/** The id of the new lane. */
|
|
65
|
+
readonly lane: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export declare interface LaneProps {
|
|
69
|
+
/** The identity subtasks name in their `lane`. */
|
|
70
|
+
id: string;
|
|
71
|
+
/** What the lane header says - the machine or station. Real text, read by a
|
|
72
|
+
screen reader; without one the header shows the id. */
|
|
73
|
+
label?: ReactNode;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** A transport whose duration does not fit between its anchors. */
|
|
77
|
+
export declare interface LateTransport {
|
|
78
|
+
/** The id of the transport. */
|
|
79
|
+
readonly transport: string;
|
|
80
|
+
/** When it leaves, by its anchor. */
|
|
81
|
+
readonly departure: number;
|
|
82
|
+
/** When it has to have arrived, by its anchor. */
|
|
83
|
+
readonly arrival: number;
|
|
84
|
+
/** How much time is missing: departure plus duration, minus arrival. */
|
|
85
|
+
readonly shortBy: number;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Every transport whose successor is to be reached before the predecessor's
|
|
89
|
+
departure plus the transport's duration. A transport naming a subtask that
|
|
90
|
+
is not in the data is passed over: there is nothing to judge. */
|
|
91
|
+
export declare function lateTransports(subtasks: readonly Subtask[], transports: readonly Transport[]): LateTransport[];
|
|
92
|
+
|
|
93
|
+
/** Move the subtask in time: the main time keeps its length. */
|
|
94
|
+
export declare interface MoveIntent {
|
|
95
|
+
readonly kind: "move";
|
|
96
|
+
/** The id of the subtask. */
|
|
97
|
+
readonly subtask: string;
|
|
98
|
+
/** The new start of the main time. */
|
|
99
|
+
readonly from: number;
|
|
100
|
+
/** The new end of the main time. */
|
|
101
|
+
readonly to: number;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/** The interval a subtask occupies on its lane: setup and teardown included. */
|
|
105
|
+
export declare function occupied(subtask: Subtask): {
|
|
106
|
+
from: number;
|
|
107
|
+
to: number;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/** Two subtasks covering the same time on one lane. */
|
|
111
|
+
export declare interface Overlap {
|
|
112
|
+
/** The lane both sit on. */
|
|
113
|
+
readonly lane: string;
|
|
114
|
+
/** The subtask that starts earlier (setup included); on a tie, the one that
|
|
115
|
+
stands first in the data. */
|
|
116
|
+
readonly first: string;
|
|
117
|
+
/** The other one. */
|
|
118
|
+
readonly second: string;
|
|
119
|
+
/** Where the covering begins. */
|
|
120
|
+
readonly from: number;
|
|
121
|
+
/** Where it ends. */
|
|
122
|
+
readonly to: number;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/** Every pair of subtasks that cover each other on a lane. Touching at a
|
|
126
|
+
shared edge is not covering, and a subtask that covers no time covers
|
|
127
|
+
nothing. */
|
|
128
|
+
export declare function overlaps(subtasks: readonly Subtask[]): Overlap[];
|
|
129
|
+
|
|
130
|
+
/** Put work on the plan that was not on it: the answer to a drag from outside
|
|
131
|
+
the schedule (schedule-refinement 07). It carries no subtask id - there is
|
|
132
|
+
no subtask yet; the caller creates one, with its own identity, from
|
|
133
|
+
`subtaskFromPlace`. */
|
|
134
|
+
export declare interface PlaceIntent {
|
|
135
|
+
readonly kind: "place";
|
|
136
|
+
/** The caller's key for the dragged item, as it declared it while dragging. */
|
|
137
|
+
readonly item: string;
|
|
138
|
+
/** The task the work belongs to. */
|
|
139
|
+
readonly task: string;
|
|
140
|
+
/** The lane it was dropped on. */
|
|
141
|
+
readonly lane: string;
|
|
142
|
+
/** Where its main time would start. */
|
|
143
|
+
readonly from: number;
|
|
144
|
+
/** Where its main time would end. */
|
|
145
|
+
readonly to: number;
|
|
146
|
+
/** The setup it was declared with. */
|
|
147
|
+
readonly setup?: number;
|
|
148
|
+
/** The teardown it was declared with. */
|
|
149
|
+
readonly teardown?: number;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/** What the application says it is dragging in, while it drags it
|
|
153
|
+
(schedule-refinement 07): the browser hands over the dragged data only on
|
|
154
|
+
the drop, so the ghost before the drop can only come from the caller. */
|
|
155
|
+
export declare interface PlacingItem {
|
|
156
|
+
/** The caller's key for the dragged item; it comes back in the intent. */
|
|
157
|
+
readonly item: string;
|
|
158
|
+
/** The task the work belongs to. */
|
|
159
|
+
readonly task: string;
|
|
160
|
+
/** How long its main time is. */
|
|
161
|
+
readonly duration: number;
|
|
162
|
+
/** The setup it brings. */
|
|
163
|
+
readonly setup?: number;
|
|
164
|
+
/** The teardown it brings. */
|
|
165
|
+
readonly teardown?: number;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export declare function resolveAppearance(appearance: readonly SubtaskAppearance[] | undefined): ResolvedAppearance;
|
|
169
|
+
|
|
170
|
+
/** What the drawing needs to know, with the contradiction already settled.
|
|
171
|
+
|
|
172
|
+
The four names are the ones this module was born with, and they are kept so
|
|
173
|
+
that a caller's code does not change because a picture did. Two of them are
|
|
174
|
+
now named after a drawing they no longer use, and the channel each one
|
|
175
|
+
really owns stands beside it (`sceneDraw.ts`, "ONE CHANNEL PER
|
|
176
|
+
STATEMENT"). */
|
|
177
|
+
export declare interface ResolvedAppearance {
|
|
178
|
+
/** `provisional`: the FILL - none at all, so the surface shows through, with
|
|
179
|
+
a dashed outline in the task colour. Planned, not released. */
|
|
180
|
+
readonly dashed: boolean;
|
|
181
|
+
/** `fixed`: the ENDS - a cap at each end of the main time. Not a hatch any
|
|
182
|
+
more; a hatch now says "not available" of a refused lane, and the name is
|
|
183
|
+
kept only so that this type did not change with the picture. */
|
|
184
|
+
readonly hatched: boolean;
|
|
185
|
+
/** `muted`: the SATURATION - the task colour mixed half into the surface,
|
|
186
|
+
opaque and at full height. Another shift's, another crew's. */
|
|
187
|
+
readonly muted: boolean;
|
|
188
|
+
/** `open`: the FADE, where the bar passes the edge of the view. It goes on
|
|
189
|
+
past what is drawn. */
|
|
190
|
+
readonly open: boolean;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
/** The moves that push every successor whose transport no longer fits after
|
|
194
|
+
`intent` - transitively, in the order they were first pushed. The subtask the
|
|
195
|
+
intent is about is never moved, and a cycle among the successors ends after a
|
|
196
|
+
bounded number of pushes instead of running on. */
|
|
197
|
+
export declare function ripple(subtasks: readonly Subtask[], transports: readonly Transport[], intent: Intent): MoveIntent[];
|
|
198
|
+
|
|
199
|
+
export declare const Schedule: ForwardRefExoticComponent<ScheduleProps & RefAttributes<ScheduleHandle>>;
|
|
200
|
+
|
|
201
|
+
/** What a schedule offers a caller imperatively: the arithmetic between a
|
|
202
|
+
point on the screen and a time on a lane. Everything else is props. */
|
|
203
|
+
export declare interface ScheduleHandle {
|
|
204
|
+
/** The time and the lane at a client point, or null outside the plot. */
|
|
205
|
+
positionAt: (clientX: number, clientY: number) => {
|
|
206
|
+
time: number;
|
|
207
|
+
lane: string | null;
|
|
208
|
+
} | null;
|
|
209
|
+
/** The client point of a time - on the middle of a lane where one is named -
|
|
210
|
+
or null while the schedule is not on screen. */
|
|
211
|
+
clientPointOf: (time: number, lane?: string) => {
|
|
212
|
+
x: number;
|
|
213
|
+
y: number;
|
|
214
|
+
} | null;
|
|
215
|
+
/** The visible span, as two wall-clock instants. */
|
|
216
|
+
visibleDomain: () => readonly [number, number];
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/** What a pointer is on. */
|
|
220
|
+
export declare type ScheduleHit = {
|
|
221
|
+
readonly kind: "subtask";
|
|
222
|
+
readonly subtask: Subtask;
|
|
223
|
+
readonly part: "setup" | "main" | "teardown";
|
|
224
|
+
} | {
|
|
225
|
+
readonly kind: "transport";
|
|
226
|
+
readonly transport: Transport;
|
|
227
|
+
} | {
|
|
228
|
+
readonly kind: "lane";
|
|
229
|
+
readonly lane: string;
|
|
230
|
+
} | {
|
|
231
|
+
readonly kind: "nothing";
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
/** A pointer interaction, reported with its target and its position. */
|
|
235
|
+
export declare interface ScheduleInteraction {
|
|
236
|
+
/** `"hover"` is reported when the target under the pointer changes, not on
|
|
237
|
+
every movement. */
|
|
238
|
+
readonly type: "click" | "contextmenu" | "hover";
|
|
239
|
+
/** What the pointer is on. */
|
|
240
|
+
readonly hit: ScheduleHit;
|
|
241
|
+
/** The pointer's horizontal client coordinate - where a `ContextMenu` opens. */
|
|
242
|
+
readonly clientX: number;
|
|
243
|
+
/** The pointer's vertical client coordinate. */
|
|
244
|
+
readonly clientY: number;
|
|
245
|
+
/** The wall-clock instant under the pointer. */
|
|
246
|
+
readonly time: number;
|
|
247
|
+
/** The lane under the pointer, or null below the last one. */
|
|
248
|
+
readonly lane: string | null;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
export declare interface ScheduleProps {
|
|
252
|
+
/** What the schedule shows, for a screen reader: "Plan of week 38". */
|
|
253
|
+
ariaLabel: string;
|
|
254
|
+
/** The time in view when the schedule mounts, as two wall-clock instants.
|
|
255
|
+
Pan and zoom take it from there; a new pair of values puts it back. */
|
|
256
|
+
initialDomain: readonly [number, number];
|
|
257
|
+
/** Height in CSS pixels, both bands included. The width is the host's. */
|
|
258
|
+
height?: number;
|
|
259
|
+
/** Height of one lane in pixels. */
|
|
260
|
+
laneHeight?: number;
|
|
261
|
+
/** Width of the lane headers in pixels. */
|
|
262
|
+
headerWidth?: number;
|
|
263
|
+
/** An operating calendar: the intervals in which time counts. Nights and
|
|
264
|
+
weekends outside them are cut out of the axis. Default: the wall clock. */
|
|
265
|
+
calendar?: CalendarInput;
|
|
266
|
+
/** The narrowest and widest time span zoom may reach, in milliseconds.
|
|
267
|
+
Default: one hour to 28 days. */
|
|
268
|
+
zoomLimits?: ZoomLimits;
|
|
269
|
+
/** The raster a drag lands on: `"ticks"` - the fine band's current step -, a
|
|
270
|
+
step in milliseconds from local midnight, a step with an offset (shifts at
|
|
271
|
+
06:00, 14:00 and 22:00 are eight hours offset by six), or `false` for none.
|
|
272
|
+
It shapes the ghost and the intent, never the data. */
|
|
273
|
+
snap?: "ticks" | number | SnapRaster | false;
|
|
274
|
+
/** The intents the caller handles. Each one enables its interaction; none
|
|
275
|
+
leaves a read-only schedule (ADR-0023). */
|
|
276
|
+
intents?: readonly IntentKind[];
|
|
277
|
+
/** Whether a subtask may go to a lane. Without it every lane is open; it
|
|
278
|
+
narrows `"lane"`, it does not enable it.
|
|
279
|
+
|
|
280
|
+
Asked once per lane when a drag takes hold, and asked again at the drop.
|
|
281
|
+
The lanes it turns down are marked from the first frame of the drag - a
|
|
282
|
+
planner sees the refusal before meeting it - and over one of them the
|
|
283
|
+
ghost stays on the last lane that was allowed, the cursor says no and a
|
|
284
|
+
line ties the ghost to the pointer. A refused lane costs the lane and
|
|
285
|
+
nothing else: a drop after it still reports the move in time.
|
|
286
|
+
|
|
287
|
+
It is asked for work dragged in from outside as well, with the key and
|
|
288
|
+
task the application declared in `placing`. */
|
|
289
|
+
canMoveTo?: (subtask: Subtask, lane: string) => boolean;
|
|
290
|
+
/** Called once per intent when a drag ends. The data changes only if the
|
|
291
|
+
caller changes it. */
|
|
292
|
+
onIntent?: (intent: Intent) => void;
|
|
293
|
+
/** Click, context menu and hover, with what the pointer is on and where.
|
|
294
|
+
While it is set, a right-click opens no browser menu. */
|
|
295
|
+
onInteraction?: (interaction: ScheduleInteraction) => void;
|
|
296
|
+
/** The selected task, controlled. Leave it out and the schedule keeps the
|
|
297
|
+
selection itself. */
|
|
298
|
+
selectedTask?: string | null;
|
|
299
|
+
/** Called when a click selects a task or clears the selection, with the
|
|
300
|
+
subtask that was clicked - null where the click was on a transport or on
|
|
301
|
+
nothing. It is called again when another subtask of the same task is
|
|
302
|
+
clicked. */
|
|
303
|
+
onSelectedTaskChange?: (task: string | null, subtask: string | null) => void;
|
|
304
|
+
/** The **Lane group**s that are folded, controlled. Leave it out and the
|
|
305
|
+
schedule keeps them itself, starting from `defaultCollapsedGroups`.
|
|
306
|
+
|
|
307
|
+
Folding changes the view and not the plan, which is why it is no intent:
|
|
308
|
+
a caller that applies every intent it receives must never find a fold
|
|
309
|
+
among them (ADR-0025). A folded outer group hides the inner ones without
|
|
310
|
+
their entries leaving the list, so unfolding it gives back the view that
|
|
311
|
+
was there. */
|
|
312
|
+
collapsedGroups?: readonly string[];
|
|
313
|
+
/** Which groups are folded when the schedule mounts, where the schedule
|
|
314
|
+
keeps the state itself. Ignored while `collapsedGroups` is given. */
|
|
315
|
+
defaultCollapsedGroups?: readonly string[];
|
|
316
|
+
/** Called with the whole list when the planner folds or unfolds a group. */
|
|
317
|
+
onCollapsedGroupsChange?: (groups: readonly string[]) => void;
|
|
318
|
+
/** The visible time span after the planner panned or zoomed, as two
|
|
319
|
+
wall-clock instants - for keeping a second schedule or a chart in step. A
|
|
320
|
+
span handed in through `initialDomain` is not reported back. */
|
|
321
|
+
onDomainChange?: (domain: readonly [number, number]) => void;
|
|
322
|
+
/** What the application is dragging in from outside while it drags it - its
|
|
323
|
+
key, task, the length of its main time, its setup and teardown. The
|
|
324
|
+
browser hands the dragged data over only on the drop, so the ghost before
|
|
325
|
+
it can only come from here: set it on your own `dragstart`, clear it on
|
|
326
|
+
`dragend`. Without `"place"` in `intents` no drop is accepted. */
|
|
327
|
+
placing?: PlacingItem | null;
|
|
328
|
+
/** How the transports are drawn: a `"curve"` that leaves and arrives
|
|
329
|
+
forwards, a `"straight"` line, or `"orthogonal"` segments. A transport may
|
|
330
|
+
say otherwise for itself. */
|
|
331
|
+
route?: TransportRoute;
|
|
332
|
+
/** Where a transport's ends sit on their bars: the `"centre"` of both, or the
|
|
333
|
+
`"nearest"` edge - which is the shortest line between two stops. Within
|
|
334
|
+
one lane both mean the middle. A transport may say otherwise for itself.
|
|
335
|
+
|
|
336
|
+
It changes the picture and never a finding: whether a transport is late
|
|
337
|
+
follows from its `leaves` and `arrives` alone. */
|
|
338
|
+
attach?: TransportAttachment;
|
|
339
|
+
/** Whether a transport's two ends carry a dot (`"dot"`, the default) or the
|
|
340
|
+
line stands alone (`"none"`). The dot says where the line is anchored - a
|
|
341
|
+
help while a plan is being read, and noise in a plan full of short moves.
|
|
342
|
+
A transport may say otherwise for itself. */
|
|
343
|
+
ends?: TransportEnds;
|
|
344
|
+
/** What stands written in a bar: a function from a subtask to a line of
|
|
345
|
+
text, or nothing for bars without text. The text is cut off with an
|
|
346
|
+
ellipsis where the bar is too narrow for it and left out where even that
|
|
347
|
+
would say nothing; a bar that began before the view keeps its text at the
|
|
348
|
+
view's edge. */
|
|
349
|
+
label?: (subtask: Subtask) => string;
|
|
350
|
+
/** The tooltip on a hovered subtask or transport: its order, its times, its
|
|
351
|
+
parts and its findings. `false` switches it off; a function receives
|
|
352
|
+
what the pointer rests on and returns content of the application's own. */
|
|
353
|
+
tooltip?: false | ((target: ScheduleTooltipTarget) => ReactNode);
|
|
354
|
+
/** A line marking the present across the lanes: `true` follows the clock by
|
|
355
|
+
the minute, an instant fixes it there. Off by default. */
|
|
356
|
+
now?: boolean | number;
|
|
357
|
+
/** Goes to the root element. */
|
|
358
|
+
className?: string;
|
|
359
|
+
/** Goes to the root element. */
|
|
360
|
+
style?: CSSProperties;
|
|
361
|
+
/** `Lane`, `Transports` and `Subtasks`, in the order they are to stand and
|
|
362
|
+
be drawn. */
|
|
363
|
+
children?: ReactNode;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/** What a tooltip is about: the hovered subtask or transport, with what the
|
|
367
|
+
schedule knows about it. */
|
|
368
|
+
export declare type ScheduleTooltipTarget = {
|
|
369
|
+
/** A subtask is hovered. */
|
|
370
|
+
readonly kind: "subtask";
|
|
371
|
+
/** The hovered subtask. */
|
|
372
|
+
readonly subtask: Subtask;
|
|
373
|
+
/** Its task, where the tasks name it. */
|
|
374
|
+
readonly task: Task | undefined;
|
|
375
|
+
/** The subtasks it overlaps with on its lane. */
|
|
376
|
+
readonly overlapping: readonly Subtask[];
|
|
377
|
+
/** The late transports leaving or reaching it. */
|
|
378
|
+
readonly lateTransports: readonly LateTransport[];
|
|
379
|
+
} | {
|
|
380
|
+
/** A transport is hovered. */
|
|
381
|
+
readonly kind: "transport";
|
|
382
|
+
/** The hovered transport. */
|
|
383
|
+
readonly transport: Transport;
|
|
384
|
+
/** Its task, where the tasks name it. */
|
|
385
|
+
readonly task: Task | undefined;
|
|
386
|
+
/** The subtask it leaves. */
|
|
387
|
+
readonly from: Subtask | undefined;
|
|
388
|
+
/** The subtask it reaches. */
|
|
389
|
+
readonly to: Subtask | undefined;
|
|
390
|
+
/** Its finding, where it is late. */
|
|
391
|
+
readonly late: LateTransport | undefined;
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
/** Change the setup on its own. */
|
|
395
|
+
export declare interface SetupIntent {
|
|
396
|
+
readonly kind: "setup";
|
|
397
|
+
/** The id of the subtask. */
|
|
398
|
+
readonly subtask: string;
|
|
399
|
+
/** The new duration of the setup. */
|
|
400
|
+
readonly setup: number;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
export declare function shiftTask(subtasks: readonly Subtask[], task: string, by: number): MoveIntent[];
|
|
404
|
+
|
|
405
|
+
/** A raster: a step, and where it starts after local midnight. */
|
|
406
|
+
export declare interface SnapRaster {
|
|
407
|
+
/** The distance between two lines of the raster, in milliseconds. */
|
|
408
|
+
readonly step: number;
|
|
409
|
+
/** Where the raster starts after local midnight, in milliseconds: six
|
|
410
|
+
hours for shifts that change at 06:00. */
|
|
411
|
+
readonly offset: number;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/** `time` onto the nearest line of the raster in local time - a step alone
|
|
415
|
+
starts at local midnight. A step of zero or less is no raster: the time
|
|
416
|
+
stays as it is. */
|
|
417
|
+
export declare function snapTime(time: number, raster: number | SnapRaster): number;
|
|
418
|
+
|
|
419
|
+
/** Stretch the main time at one or both of its edges. */
|
|
420
|
+
export declare interface StretchIntent {
|
|
421
|
+
readonly kind: "stretch";
|
|
422
|
+
/** The id of the subtask. */
|
|
423
|
+
readonly subtask: string;
|
|
424
|
+
/** The new start of the main time. */
|
|
425
|
+
readonly from: number;
|
|
426
|
+
/** The new end of the main time. */
|
|
427
|
+
readonly to: number;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/** The drawn interval: a main time on one lane, with an optional setup before
|
|
431
|
+
it and a teardown after it. */
|
|
432
|
+
export declare interface Subtask {
|
|
433
|
+
/** The caller's identity of the subtask. */
|
|
434
|
+
readonly id: string;
|
|
435
|
+
/** The id of the task it belongs to. */
|
|
436
|
+
readonly task: string;
|
|
437
|
+
/** The id of the lane it sits on. */
|
|
438
|
+
readonly lane: string;
|
|
439
|
+
/** Start of the main time. */
|
|
440
|
+
readonly from: number;
|
|
441
|
+
/** End of the main time. */
|
|
442
|
+
readonly to: number;
|
|
443
|
+
/** Duration of the setup before the main time; none is zero. */
|
|
444
|
+
readonly setup?: number;
|
|
445
|
+
/** Duration of the teardown after the main time; none is zero. */
|
|
446
|
+
readonly teardown?: number;
|
|
447
|
+
/** What the subtask is called, where the schedule names it. */
|
|
448
|
+
readonly name?: string;
|
|
449
|
+
/** What the bar says besides its colour: `"provisional"`, `"fixed"`,
|
|
450
|
+
`"muted"`, `"open"`. Several hold at once; `"provisional"` and `"fixed"`
|
|
451
|
+
contradict, and the later one in the list wins. */
|
|
452
|
+
readonly appearance?: readonly SubtaskAppearance[];
|
|
453
|
+
/** The share of the work that is done, from 0 to 1, drawn as a filled part
|
|
454
|
+
of the bar. Without it nothing is claimed - an empty bar and a bar at
|
|
455
|
+
zero per cent are two different statements. */
|
|
456
|
+
readonly progress?: number;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/** The appearances a caller may give a subtask. */
|
|
460
|
+
export declare type SubtaskAppearance = "provisional" | "fixed" | "muted" | "open";
|
|
461
|
+
|
|
462
|
+
/** The subtask a place intent asks for, under an id the caller chooses. */
|
|
463
|
+
export declare function subtaskFromPlace(intent: PlaceIntent, id: string): Subtask;
|
|
464
|
+
|
|
465
|
+
/** A layer of subtasks. Several layers draw in the order they are declared. */
|
|
466
|
+
export declare function Subtasks({ data, tasks }: SubtasksProps): null;
|
|
467
|
+
|
|
468
|
+
export declare interface SubtasksProps {
|
|
469
|
+
/** The subtasks, as the caller holds them. The schedule never changes one. */
|
|
470
|
+
data: readonly Subtask[];
|
|
471
|
+
/** The tasks the subtasks belong to - their identity and their colour. A
|
|
472
|
+
subtask whose task is not among them is drawn in a muted colour. */
|
|
473
|
+
tasks: readonly Task[];
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/** One whole undertaking. It is never drawn as a thing of its own: it shows as
|
|
477
|
+
the colour its subtasks share, and in selection, which takes all of it. */
|
|
478
|
+
export declare interface Task {
|
|
479
|
+
/** The caller's identity of the task. */
|
|
480
|
+
readonly id: string;
|
|
481
|
+
/** Any CSS colour - a literal, a token, `light-dark(…)`. The colour means what
|
|
482
|
+
the caller's domain needs it to mean. */
|
|
483
|
+
readonly color: string;
|
|
484
|
+
/** What the task is called, where the schedule names it. */
|
|
485
|
+
readonly name?: string;
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
/** Change the teardown on its own. */
|
|
489
|
+
export declare interface TeardownIntent {
|
|
490
|
+
readonly kind: "teardown";
|
|
491
|
+
/** The id of the subtask. */
|
|
492
|
+
readonly subtask: string;
|
|
493
|
+
/** The new duration of the teardown. */
|
|
494
|
+
readonly teardown: number;
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/** A task's move between two of its subtasks: always from an end to a start. */
|
|
498
|
+
export declare interface Transport {
|
|
499
|
+
/** The caller's identity of the transport. */
|
|
500
|
+
readonly id: string;
|
|
501
|
+
/** The id of the subtask it leaves. */
|
|
502
|
+
readonly from: string;
|
|
503
|
+
/** The id of the subtask it arrives at. */
|
|
504
|
+
readonly to: string;
|
|
505
|
+
/** How long the move takes. */
|
|
506
|
+
readonly duration: number;
|
|
507
|
+
/** Where it leaves: at the end of the main time, or after the teardown.
|
|
508
|
+
Default `"teardown"` - the part leaves once the machine is cleared. */
|
|
509
|
+
readonly leaves?: "main" | "teardown";
|
|
510
|
+
/** Where it arrives: at the start of the main time, or before the setup.
|
|
511
|
+
Default `"setup"` - the part must be there before the machine is set up. */
|
|
512
|
+
readonly arrives?: "main" | "setup";
|
|
513
|
+
/** How this one is drawn, where it is not drawn like the rest. It changes
|
|
514
|
+
the picture and never the finding: whether a transport is late follows
|
|
515
|
+
from `leaves` and `arrives` alone. */
|
|
516
|
+
readonly route?: TransportRoute;
|
|
517
|
+
/** Where on the bars this one's line attaches, where it does not attach like
|
|
518
|
+
the rest. Also picture only, and not to be confused with the two anchors
|
|
519
|
+
above: those say what the transport connects, this says where the line
|
|
520
|
+
touches. */
|
|
521
|
+
readonly attach?: TransportAttachment;
|
|
522
|
+
/** Whether this one's ends are marked with a dot, where it is not marked
|
|
523
|
+
like the rest. Also picture only. */
|
|
524
|
+
readonly ends?: TransportEnds;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
/** Where on its bars a transport's line attaches: the middle of both, or the
|
|
528
|
+
edge that faces the other stop - which is the shortest line between them.
|
|
529
|
+
|
|
530
|
+
Deliberately not called an anchor: a transport already HAS two anchors
|
|
531
|
+
(`leaves`, `arrives`), and those decide what it connects and therefore
|
|
532
|
+
whether it is late. This decides where the line touches, and nothing else.
|
|
533
|
+
The tree has an **Anchor** of its own as well (CONTEXT.md). */
|
|
534
|
+
export declare type TransportAttachment = "centre" | "nearest";
|
|
535
|
+
|
|
536
|
+
/** Whether a transport's two ends carry a dot. The dot says where the line is
|
|
537
|
+
anchored, which is worth saying while a plan is being read and is noise in a
|
|
538
|
+
plan full of short moves - so it is the caller's choice. */
|
|
539
|
+
export declare type TransportEnds = "dot" | "none";
|
|
540
|
+
|
|
541
|
+
/** How a transport is drawn between its two ends: a curve that leaves and
|
|
542
|
+
arrives forwards, a straight line, or axis-parallel segments. */
|
|
543
|
+
export declare type TransportRoute = "curve" | "straight" | "orthogonal";
|
|
544
|
+
|
|
545
|
+
/** A layer of transports. Declared before `Subtasks`, the lines run beneath the
|
|
546
|
+
bars; after them, above. */
|
|
547
|
+
export declare function Transports({ data }: TransportsProps): null;
|
|
548
|
+
|
|
549
|
+
export declare interface TransportsProps {
|
|
550
|
+
/** The transports, as the caller holds them. */
|
|
551
|
+
data: readonly Transport[];
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
/** The narrowest and the widest span zoom may reach. */
|
|
555
|
+
export declare interface ZoomLimits {
|
|
556
|
+
readonly min: number;
|
|
557
|
+
readonly max: number;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
export { }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@layer umriss.tokens,umriss.base,umriss.components;@layer umriss.base{._text_18b86_23{font-family:var(--u-font-sans);font-size:var(--u-text-md);line-height:var(--u-leading-normal);color:var(--u-color-text);-webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility}._field_18b86_34{caret-color:var(--u-color-accent)}._scroll_18b86_40{scrollbar-width:thin;scrollbar-color:color-mix(in srgb,var(--u-color-text) 25%,transparent) transparent}._scroll_18b86_40::-webkit-scrollbar{width:10px;height:10px}._scroll_18b86_40::-webkit-scrollbar-thumb{background:color-mix(in srgb,var(--u-color-text) 22%,transparent);border-radius:var(--u-radius-full);border:3px solid transparent;background-clip:content-box}._scroll_18b86_40::-webkit-scrollbar-track{background:transparent}}@layer umriss.components{._ring_18b86_65:focus-visible{outline:none;box-shadow:var(--u-focus-ring)}._field_18b86_34:-webkit-autofill,._field_18b86_34:-webkit-autofill:hover,._field_18b86_34:-webkit-autofill:focus{-webkit-box-shadow:inset 0 0 0 1000px var(--u-color-surface),0 0 0 1px var(--u-edge-color-strong);-webkit-text-fill-color:var(--u-color-text);caret-color:var(--u-color-accent)}}@layer umriss.tokens,umriss.base,umriss.components;@layer umriss.components{._root_ekx9o_4,._root_ekx9o_4:before,._root_ekx9o_4:after{box-sizing:border-box}._corner_ekx9o_18,._corner_ekx9o_18:before,._corner_ekx9o_18:after{box-sizing:border-box}._dayBand_ekx9o_22,._dayBand_ekx9o_22:before,._dayBand_ekx9o_22:after{box-sizing:border-box}._tickBand_ekx9o_23,._tickBand_ekx9o_23:before,._tickBand_ekx9o_23:after{box-sizing:border-box}._day_ekx9o_22,._day_ekx9o_22:before,._day_ekx9o_22:after{box-sizing:border-box}._dayLabel_ekx9o_46,._dayLabel_ekx9o_46:before,._dayLabel_ekx9o_46:after{box-sizing:border-box}._tick_ekx9o_23,._tick_ekx9o_23:before,._tick_ekx9o_23:after{box-sizing:border-box}._tickLabel_ekx9o_64,._tickLabel_ekx9o_64:before,._tickLabel_ekx9o_64:after{box-sizing:border-box}._headers_ekx9o_72,._headers_ekx9o_72:before,._headers_ekx9o_72:after{box-sizing:border-box}._header_ekx9o_72,._header_ekx9o_72:before,._header_ekx9o_72:after{box-sizing:border-box}._headerLabel_ekx9o_90,._headerLabel_ekx9o_90:before,._headerLabel_ekx9o_90:after{box-sizing:border-box}._headerCount_ekx9o_103,._headerCount_ekx9o_103:before,._headerCount_ekx9o_103:after{box-sizing:border-box}._chevron_ekx9o_112,._chevron_ekx9o_112:before,._chevron_ekx9o_112:after{box-sizing:border-box}._plot_ekx9o_160,._plot_ekx9o_160:before,._plot_ekx9o_160:after{box-sizing:border-box}._layer_ekx9o_166,._layer_ekx9o_166:before,._layer_ekx9o_166:after{box-sizing:border-box}._grip_ekx9o_175,._grip_ekx9o_175:before,._grip_ekx9o_175:after{box-sizing:border-box}._ghostLabel_ekx9o_185,._ghostLabel_ekx9o_185:before,._ghostLabel_ekx9o_185:after{box-sizing:border-box}._finding_ekx9o_198,._finding_ekx9o_198:before,._finding_ekx9o_198:after{box-sizing:border-box}._refusal_ekx9o_206,._refusal_ekx9o_206:before,._refusal_ekx9o_206:after{box-sizing:border-box}._tooltip_ekx9o_210,._tooltip_ekx9o_210:before,._tooltip_ekx9o_210:after{box-sizing:border-box}._tooltipHead_ekx9o_228,._tooltipHead_ekx9o_228:before,._tooltipHead_ekx9o_228:after{box-sizing:border-box}._tooltipTimes_ekx9o_233,._tooltipTimes_ekx9o_233:before,._tooltipTimes_ekx9o_233:after{box-sizing:border-box}._now_ekx9o_242,._now_ekx9o_242:before,._now_ekx9o_242:after{box-sizing:border-box}._barLabel_ekx9o_256,._barLabel_ekx9o_256:before,._barLabel_ekx9o_256:after{box-sizing:border-box}._barLabelText_ekx9o_269,._barLabelText_ekx9o_269:before,._barLabelText_ekx9o_269:after{box-sizing:border-box}._root_ekx9o_4{display:grid;grid-template-rows:28px minmax(0,1fr) 28px;width:100%;font-size:var(--u-text-sm);background:var(--u-color-surface);box-shadow:var(--u-edge);border-radius:var(--u-radius-md);corner-shape:squircle;overflow:hidden;font-variant-numeric:tabular-nums;-webkit-user-select:none;user-select:none}._corner_ekx9o_18{background:var(--u-color-surface)}._dayBand_ekx9o_22,._tickBand_ekx9o_23{position:relative;overflow:hidden;color:var(--u-color-text-muted);font-size:var(--u-text-xs)}._dayBand_ekx9o_22{border-bottom:1px solid var(--u-hairline-strong)}._tickBand_ekx9o_23{border-top:1px solid var(--u-hairline-strong)}._day_ekx9o_22{position:absolute;top:0;bottom:0;border-left:1px solid var(--u-hairline-strong);overflow:hidden}._dayLabel_ekx9o_46{position:absolute;left:var(--u-space-2);top:50%;transform:translateY(-50%);white-space:nowrap;color:var(--u-color-text);font-weight:var(--u-weight-medium)}._tick_ekx9o_23{position:absolute;top:0;bottom:0;width:1px;background:var(--u-hairline)}._tickLabel_ekx9o_64{position:absolute;top:50%;left:0;transform:translate(-50%,-50%);white-space:nowrap}._headers_ekx9o_72{position:relative;overflow:hidden;border-right:1px solid var(--u-hairline-strong)}._header_ekx9o_72{display:flex;align-items:center;gap:var(--u-space-2);padding-right:var(--u-space-3);border-bottom:1px solid var(--u-hairline);overflow:hidden;white-space:nowrap}._headerLabel_ekx9o_90{min-width:0;overflow:hidden;text-overflow:ellipsis}._header_ekx9o_72[data-row=groupHead],._header_ekx9o_72[data-row=miniature]{font-weight:var(--u-weight-medium)}._headerCount_ekx9o_103{flex:none;color:var(--u-color-text-muted);font-size:var(--u-text-xs);font-variant-numeric:tabular-nums}._chevron_ekx9o_112{flex:none;display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;padding:0;border:none;border-radius:var(--u-radius-xs);corner-shape:squircle;background:transparent;color:var(--u-color-text-secondary);cursor:pointer}._chevron_ekx9o_112:hover{color:var(--u-color-text)}._chevron_ekx9o_112:focus-visible{outline:none;box-shadow:var(--u-focus-ring);color:var(--u-color-text)}._chevron_ekx9o_112 svg{box-sizing:border-box}._chevron_ekx9o_112 svg{transition:transform var(--u-duration-fast) var(--u-ease-standard)}._chevron_ekx9o_112 svg[data-open]{box-sizing:border-box}._chevron_ekx9o_112 svg[data-open]{transform:rotate(90deg)}@media(prefers-reduced-motion:reduce){._chevron_ekx9o_112 svg{transition:none}}._header_ekx9o_72[data-refused]{color:var(--u-color-text-muted)}._plot_ekx9o_160{position:relative;overflow:hidden;touch-action:none}._layer_ekx9o_166{position:absolute;top:0;right:0;bottom:0;left:0;width:100%;height:100%;display:block;pointer-events:none}._grip_ekx9o_175{position:absolute;width:9px;margin-left:-4px;border-radius:var(--u-radius-xs);corner-shape:squircle;background:var(--u-color-surface);box-shadow:inset 0 0 0 1.5px var(--u-color-text);cursor:ew-resize}._ghostLabel_ekx9o_185{position:absolute;display:inline-flex;gap:var(--u-space-2);padding:1px var(--u-space-2);border-radius:var(--u-radius-sm);corner-shape:squircle;background:var(--u-color-text);color:var(--u-color-surface);font-size:var(--u-text-xs);white-space:nowrap;pointer-events:none}._finding_ekx9o_198{font-weight:var(--u-weight-semibold);color:var(--u-color-danger-subtle)}._refusal_ekx9o_206{font-weight:var(--u-weight-semibold)}._tooltip_ekx9o_210{position:absolute;z-index:1;display:flex;flex-direction:column;gap:1px;max-width:260px;padding:var(--u-space-2) var(--u-space-3);border-radius:var(--u-radius-sm);corner-shape:squircle;background:var(--u-color-surface);box-shadow:var(--u-shadow-overlay);color:var(--u-color-text-secondary);font-size:var(--u-text-xs);line-height:var(--u-leading-tight);pointer-events:none;white-space:nowrap}._tooltipHead_ekx9o_228{color:var(--u-color-text);font-weight:var(--u-weight-semibold)}._tooltipTimes_ekx9o_233{color:var(--u-color-text)}._tooltip_ekx9o_210 ._finding_ekx9o_198{color:var(--u-color-danger)}._now_ekx9o_242{position:absolute;top:0;width:0;height:0;margin-left:-4px;border-left:5px solid transparent;border-right:5px solid transparent;border-top:6px solid var(--u-color-accent)}._barLabel_ekx9o_256{position:absolute;display:flex;align-items:center;padding:0 var(--u-space-1);overflow:hidden;font-size:var(--u-text-xs);line-height:var(--u-leading-tight);pointer-events:none}._barLabelText_ekx9o_269{min-width:0;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}._barLabel_ekx9o_256[data-on=dark]{color:var(--u-color-on-accent)}._barLabel_ekx9o_256[data-on=light]{color:var(--u-color-text)}}
|