@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/CHANGELOG.md
ADDED
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# Changes to `@umriss-ui/schedule`
|
|
2
|
+
|
|
3
|
+
This document describes what changes for **callers** of the package: exports,
|
|
4
|
+
props, behaviour. What was worked on in the repository stands in the
|
|
5
|
+
repository's journal (`docs/journal.md`) and in the specs under `.scratch/`.
|
|
6
|
+
|
|
7
|
+
**The numbers.** The middle digit rises when something is added; the last one
|
|
8
|
+
when something is repaired. As long as the first digit is `0`, no number
|
|
9
|
+
promises compatibility — which is why whatever changes existing behaviour stands
|
|
10
|
+
under a heading "Changed" of its own, no matter which digit rose.
|
|
11
|
+
|
|
12
|
+
**Release candidates.** The package started as a release candidate under the
|
|
13
|
+
tag `next`. With `0.1.0` it is released: the tag is gone, and the interface
|
|
14
|
+
moves from here under the rule above.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## 0.1.0 – The first release (Sep. 2026)
|
|
19
|
+
|
|
20
|
+
No longer a release candidate: the tag `next` is gone, `pnpm add
|
|
21
|
+
@umriss-ui/schedule` is the whole install line, and `@umriss-ui/core` and
|
|
22
|
+
`@umriss-ui/charts` are released versions too. What the candidate `0.1.0-rc.0`
|
|
23
|
+
was is still here; three deliveries stand on top of it, newest first, each with
|
|
24
|
+
its own report below.
|
|
25
|
+
|
|
26
|
+
The numbers keep their meaning from here: the middle digit rises when something
|
|
27
|
+
is added, the last one when something is repaired, and whatever changes
|
|
28
|
+
existing behaviour stands under a heading "Changed" of its own. As long as the
|
|
29
|
+
first digit is `0`, no number promises compatibility.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Lanes that fold, and one language for the bars (Sep. 2026)
|
|
34
|
+
|
|
35
|
+
Delivery report for `.scratch/schedule-lane-groups/spec.md`, tickets 01–11.
|
|
36
|
+
|
|
37
|
+
### Added
|
|
38
|
+
|
|
39
|
+
- **`<LaneGroup id label>`** puts structure over the lanes — halls, lines,
|
|
40
|
+
machine groups, to any depth. It is declared by composition, so a group reads
|
|
41
|
+
in JSX as it reads in the plant, and a lane never names its group.
|
|
42
|
+
|
|
43
|
+
A group is **never a lane** (ADR-0025). Nothing sits on it: a subtask names a
|
|
44
|
+
machine, a finding belongs to a machine, `canMoveTo` is asked about a machine
|
|
45
|
+
and every intent names one. Folding a group changes none of it.
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
<Schedule …>
|
|
49
|
+
<LaneGroup id="hall-a" label="Hall A">
|
|
50
|
+
<LaneGroup id="turning" label="Turning line">
|
|
51
|
+
<Lane id="lathe-1" label="Lathe 1" />
|
|
52
|
+
<Lane id="lathe-2" label="Lathe 2" />
|
|
53
|
+
</LaneGroup>
|
|
54
|
+
<Lane id="press-1" label="Press 1" />
|
|
55
|
+
</LaneGroup>
|
|
56
|
+
<Lane id="paint" label="Paint shop" />
|
|
57
|
+
</Schedule>
|
|
58
|
+
```
|
|
59
|
+
- **`collapsedGroups`, `defaultCollapsedGroups` and `onCollapsedGroupsChange`**
|
|
60
|
+
say which groups are folded — controlled, with an uncontrolled default: the
|
|
61
|
+
shape `selectedTask` has. It is **not an intent**. Folding says what is on
|
|
62
|
+
screen and nothing about the plan, so a caller that applies every intent it
|
|
63
|
+
receives will never find a fold among them.
|
|
64
|
+
- **A folded group shows a miniature**: every lane in it as a thin strip, at a
|
|
65
|
+
smaller scale, with its work in the tasks' own colours. Transports arrive at
|
|
66
|
+
a strip, a finding inside a fold is marked on the strip and on the row, and a
|
|
67
|
+
strip can be hovered, tooltipped and selected. A strip carries no appearance,
|
|
68
|
+
no bar label, no progress rail and no grips — that is what unfolding is for.
|
|
69
|
+
- **The header of a group** carries a chevron button with `aria-expanded` and
|
|
70
|
+
`aria-controls`, the group's label and how many lanes it holds; children
|
|
71
|
+
indent one step per level. It is the first thing the schedule puts into the
|
|
72
|
+
tab order, and it has a focus ring of its own. Two wording entries in English
|
|
73
|
+
and in `@umriss-ui/core/wording/de`, plus the lane count.
|
|
74
|
+
- **A drag held over a folded group opens it** after a moment, so work can be
|
|
75
|
+
moved into a group without preparing the view first. It closes again when the
|
|
76
|
+
drag ends, and the caller's list is never written to — the application did
|
|
77
|
+
not fold anything, and hears nothing.
|
|
78
|
+
|
|
79
|
+
### Changed
|
|
80
|
+
|
|
81
|
+
- **Every appearance is drawn differently.** The words a caller writes are
|
|
82
|
+
unchanged and so is `resolveAppearance`; the picture is not. Each statement
|
|
83
|
+
now owns exactly one property of the drawing, so that several on one bar stay
|
|
84
|
+
several statements:
|
|
85
|
+
- `"provisional"` is **hollow** - no fill at all, the surface shows through,
|
|
86
|
+
with its dashed outline in the task colour at full weight. It used to be a
|
|
87
|
+
45-per-cent fill, which read as a setup; empty is not faint.
|
|
88
|
+
- `"fixed"` carries a **cap at each end** of the main time, three pixels, in
|
|
89
|
+
the colour the bar's label takes, set just inside the end. The hatch across
|
|
90
|
+
its face is gone: it lay under the label, and it was the loudest mark in
|
|
91
|
+
the picture for the calmest statement.
|
|
92
|
+
- `"muted"` is at **full height** in the task colour mixed half into the
|
|
93
|
+
surface, opaque and without an outline. It used to be drawn at half height,
|
|
94
|
+
which read as a different kind of thing and cost it its label.
|
|
95
|
+
- `"open"` **fades at whichever edge of the view** the bar passes, left as
|
|
96
|
+
well as right. A bar that began before the view used to say nothing at all.
|
|
97
|
+
- **A `progress` rail** lies within the main time and above the bar's lower
|
|
98
|
+
edge. It measures the work, so it stops where the main time does.
|
|
99
|
+
- **A hatch now means one thing only**: a lane a drag may not put its work on.
|
|
100
|
+
It is no longer a mark on any bar.
|
|
101
|
+
- **A refused lane is visible before it is met.** The lanes `canMoveTo` turns
|
|
102
|
+
down are marked from the first frame of a drag - drawn back and hatched, and
|
|
103
|
+
their headers with them (`[data-lane][data-refused]`, to style beside the
|
|
104
|
+
schedule). Over one of them the cursor says no and a hairline ties the ghost
|
|
105
|
+
to the pointer it is not following.
|
|
106
|
+
- **A refused lane no longer costs the whole gesture.** A drop after one still
|
|
107
|
+
reports the move in time; only the lane change is dropped. `canMoveTo` is
|
|
108
|
+
asked once per lane when a drag takes hold, and again at the drop.
|
|
109
|
+
- **`ScheduleHandle` answers for a folded lane** with its strip:
|
|
110
|
+
`clientPointOf` and `positionAt` read the place a lane is actually drawn, so
|
|
111
|
+
a caller's own marks keep pointing at the work when a group folds.
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## A plan one can read (Sep. 2026)
|
|
116
|
+
|
|
117
|
+
Delivery report for `.scratch/schedule-legibility/spec.md`, tickets 01–06.
|
|
118
|
+
The formats of `@umriss-ui/core` became English in the same delivery
|
|
119
|
+
(ADR-0024), which is what the dates and numbers of a schedule follow.
|
|
120
|
+
|
|
121
|
+
### Added
|
|
122
|
+
|
|
123
|
+
- **`label`** writes a line into every bar: the order, the article, whatever a
|
|
124
|
+
planner reads first. It is real DOM text, cut off with an ellipsis where the
|
|
125
|
+
bar is too narrow, left out where nothing would be readable, and held at the
|
|
126
|
+
view's edge for a bar that began before it. Its colour follows the brightness
|
|
127
|
+
of the bar's.
|
|
128
|
+
- **`route`, `anchor` and `ends`** decide how a transport is drawn: a curve, a
|
|
129
|
+
straight line or orthogonal segments; from the middle of a bar or from the
|
|
130
|
+
edge facing the other stop; with or without a dot at each end. All three are
|
|
131
|
+
options of the schedule and all three are overridable per transport. They
|
|
132
|
+
change the picture and never a finding - `leaves` and `arrives` alone decide
|
|
133
|
+
whether a transport is late.
|
|
134
|
+
- **`appearance` and `progress` on a subtask:** `"provisional"` (a dashed
|
|
135
|
+
outline), `"fixed"` (a hatch), `"muted"` (drawn slim), `"open"` (fading where
|
|
136
|
+
it continues past the view), and a share of the work that is done, drawn as a
|
|
137
|
+
rail along the bar. Each is a pattern or an outline and not only a colour, and
|
|
138
|
+
none of them uses the faint fill that means a setup or a teardown.
|
|
139
|
+
- **`canMoveTo(subtask, lane)`** narrows where a drag may land. The ghost stays
|
|
140
|
+
on the last lane that was allowed and says "Not this lane"; a refused drop
|
|
141
|
+
reports nothing. It is asked for work dragged in from outside as well. Two
|
|
142
|
+
wording entries come with it.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## The schedule in daily use (Sep. 2026)
|
|
147
|
+
|
|
148
|
+
Delivery report for `.scratch/schedule-refinement/spec.md`, tickets 01–09.
|
|
149
|
+
Read **Changed** first: the wheel does something else now.
|
|
150
|
+
|
|
151
|
+
### Changed
|
|
152
|
+
|
|
153
|
+
- **The wheel scrolls the lanes** and lets the page scroll on once they are at
|
|
154
|
+
their end. **Ctrl or ⌘ with the wheel, and a pinch, zoom**; a horizontal
|
|
155
|
+
wheel or Shift with a vertical one pans through time. Before this, every
|
|
156
|
+
wheel movement zoomed, which trapped the wheel on a long page and left
|
|
157
|
+
twenty lanes unreachable by it.
|
|
158
|
+
- **`onSelectedTaskChange` carries the clicked subtask** as a second argument
|
|
159
|
+
(null for a click on a transport or on nothing), and is called again when
|
|
160
|
+
another subtask of the same task is clicked. A caller that reads only the
|
|
161
|
+
first argument is unaffected.
|
|
162
|
+
|
|
163
|
+
### Added
|
|
164
|
+
|
|
165
|
+
- **A tooltip** on a hovered subtask or transport: the order, the stop, its
|
|
166
|
+
times, setup and teardown, the transport's route and duration, and the
|
|
167
|
+
findings on it. `tooltip={false}` switches it off; a function replaces its
|
|
168
|
+
content and receives a `ScheduleTooltipTarget` with the findings.
|
|
169
|
+
- **`now`** draws a line across the lanes at the present: `true` follows the
|
|
170
|
+
clock by the minute, an instant fixes it there. Off by default.
|
|
171
|
+
- **A drag near the edge of the plot pans the plot along**, faster the closer
|
|
172
|
+
to the edge, so a subtask reaches a time that was not in view in one
|
|
173
|
+
gesture.
|
|
174
|
+
- **`snap` takes a raster with an offset** (`{ step, offset }`): shifts at
|
|
175
|
+
06:00, 14:00 and 22:00 are eight hours offset by six. A snapped time that
|
|
176
|
+
would land in time an operating calendar removes moves on to the seam, so an
|
|
177
|
+
intent never asks for a time the plant does not run.
|
|
178
|
+
- **`shiftTask(subtasks, task, by)`** returns one move intent per stop of a
|
|
179
|
+
task - the whole order moved, distances kept.
|
|
180
|
+
- **The place intent and `placing`:** work that is not on the plan can be
|
|
181
|
+
dragged in from any list, with the platform's drag and drop. The application
|
|
182
|
+
declares what it is dragging in `placing` while it drags; a drop on a lane
|
|
183
|
+
reports `{ kind: "place", item, task, lane, from, to, setup, teardown }`.
|
|
184
|
+
`subtaskFromPlace(intent, id)` builds the subtask, `applyIntent` leaves the
|
|
185
|
+
data alone for it, and `ripple` pushes nothing until the subtask exists.
|
|
186
|
+
Without `"place"` in `intents` no drop is accepted.
|
|
187
|
+
- **`onDomainChange`** reports the visible span after the planner pans or
|
|
188
|
+
zooms - for keeping a second schedule, or a chart's time axis, in step. A
|
|
189
|
+
span handed in through `initialDomain` is not reported back.
|
|
190
|
+
- **A ref handle** (`ScheduleHandle`): `positionAt(clientX, clientY)`,
|
|
191
|
+
`clientPointOf(time, lane?)`, `visibleDomain()`.
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
## 0.1.0-rc.0 – The schedule (Sep. 2026)
|
|
196
|
+
|
|
197
|
+
Delivery report for `.scratch/schedule/spec.md` (ADR-0022, ADR-0023). Not yet
|
|
198
|
+
published.
|
|
199
|
+
|
|
200
|
+
### Added
|
|
201
|
+
|
|
202
|
+
- **`Schedule`** with **`Lane`**, **`Subtasks`** and **`Transports`** declared
|
|
203
|
+
as children. Lane headers at the left as text, a day band above the plot and a
|
|
204
|
+
time band below it that steps from the day down to the quarter hour with the
|
|
205
|
+
zoom. Subtasks drawn with main time, setup and teardown in their task's colour;
|
|
206
|
+
transports as lines from an end to a start, anchored per transport
|
|
207
|
+
(`leaves`, `arrives`). Canvas colours follow `color-scheme`.
|
|
208
|
+
- **Findings drawn and never resolved:** an overlap on a lane — setup and
|
|
209
|
+
teardown included — offset and marked; a late transport dashed in the finding
|
|
210
|
+
colour.
|
|
211
|
+
- **Pan and zoom:** drag the background in both directions, the wheel and a
|
|
212
|
+
pinch zoom around the pointer, a horizontal wheel pans; `zoomLimits`. An
|
|
213
|
+
operating calendar (`calendar`) cuts removed time out of the axis.
|
|
214
|
+
- **Interaction:** `onInteraction` reports click, context menu and hover with
|
|
215
|
+
the hit (subtask and part, transport, lane, nothing), the client point, the
|
|
216
|
+
time and the lane. A click selects the whole task; `selectedTask` and
|
|
217
|
+
`onSelectedTaskChange` control it.
|
|
218
|
+
- **Controlled editing:** `intents` and `onIntent` — move, lane, stretch at the
|
|
219
|
+
edges, setup and teardown grips on the selected subtask — with a ghost that
|
|
220
|
+
shows its times and findings while the drag is in flight; Escape cancels.
|
|
221
|
+
`snap`: the tick raster by default, a step, or `false`.
|
|
222
|
+
- **The arithmetic:** `findings`, `overlaps`, `lateTransports`, `ripple`,
|
|
223
|
+
`applyIntent`, `snapTime`, `occupied`, `departure`, `arrival`, and the types
|
|
224
|
+
`Task`, `Subtask`, `Transport`, `Intent` and its five kinds.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Roman Händler
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
# @umriss-ui/schedule
|
|
2
|
+
|
|
3
|
+
The schedule of a plant: **subtasks** on **lanes** over time. One task runs
|
|
4
|
+
across several machines in a fixed order, each stop has a main time with a
|
|
5
|
+
setup before it and a teardown after it, and between the stops lie
|
|
6
|
+
**transports** with durations of their own. The schedule draws all of it, marks
|
|
7
|
+
what cannot work — two subtasks on one machine at once, a transport that cannot
|
|
8
|
+
arrive in time — and lets a planner move things by hand without ever changing
|
|
9
|
+
the plan underneath them.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pnpm add @umriss-ui/schedule @umriss-ui/core @umriss-ui/charts
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Both `@umriss-ui/core` and `@umriss-ui/charts` are **peer dependencies**
|
|
18
|
+
(ADR-0022): the schedule takes its styling regime, provider, formats and
|
|
19
|
+
wording from core, and its time arithmetic — the affine scale, the time steps,
|
|
20
|
+
the operating calendar, the canvas colour resolution — from charts. React 18 or
|
|
21
|
+
19 as a peer as well.
|
|
22
|
+
|
|
23
|
+
## The smallest schedule that runs
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
import { Lane, Schedule, Subtasks, Transports } from "@umriss-ui/schedule";
|
|
27
|
+
import type { Subtask, Task, Transport } from "@umriss-ui/schedule";
|
|
28
|
+
|
|
29
|
+
const at = (h: number, m = 0) => new Date(2026, 2, 17, h, m).getTime();
|
|
30
|
+
|
|
31
|
+
const tasks: Task[] = [{ id: "a-2041", color: "#2563eb" }];
|
|
32
|
+
const subtasks: Subtask[] = [
|
|
33
|
+
{ id: "cut", task: "a-2041", lane: "saw", from: at(6), to: at(7), teardown: 10 * 60_000 },
|
|
34
|
+
{ id: "mill", task: "a-2041", lane: "mill", from: at(8), to: at(10), setup: 30 * 60_000 },
|
|
35
|
+
];
|
|
36
|
+
const transports: Transport[] = [{ id: "move", from: "cut", to: "mill", duration: 15 * 60_000 }];
|
|
37
|
+
|
|
38
|
+
export function Plan() {
|
|
39
|
+
return (
|
|
40
|
+
<Schedule ariaLabel="Plan of Tuesday" initialDomain={[at(5), at(12)]}>
|
|
41
|
+
<Lane id="saw" label="Saw" />
|
|
42
|
+
<Lane id="mill" label="Mill" />
|
|
43
|
+
<Transports data={transports} />
|
|
44
|
+
<Subtasks data={subtasks} tasks={tasks} />
|
|
45
|
+
</Schedule>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Editing is controlled
|
|
51
|
+
|
|
52
|
+
The schedule draws the data it is given and changes none of it (ADR-0023). A
|
|
53
|
+
drag shows a **ghost** with the findings the drop would create, and ends in an
|
|
54
|
+
**intent** — move, lane, stretch, setup, teardown — reported to the caller:
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
<Schedule
|
|
58
|
+
intents={["move", "lane"]}
|
|
59
|
+
onIntent={(intent) => setSubtasks((all) => all.map((s) => applyIntent(s, intent)))}
|
|
60
|
+
…
|
|
61
|
+
>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`intents` lists what the application handles; without it the schedule is
|
|
65
|
+
read-only. `canMoveTo(subtask, lane)` narrows it: a drag across a lane the
|
|
66
|
+
subtask may not go to leaves the ghost where it was allowed and shows a
|
|
67
|
+
refusal, and a refused drop reports nothing. A drag near the edge of the plot pans the plot along, and `snap`
|
|
68
|
+
takes the tick raster, a step, or a step with an offset - shifts at 06:00,
|
|
69
|
+
14:00 and 22:00 are eight hours offset by six.
|
|
70
|
+
|
|
71
|
+
Dependent subtasks never move by themselves: `ripple` computes the cascade for
|
|
72
|
+
the application to apply, or not, and `shiftTask` the moves of a whole order.
|
|
73
|
+
`findings`, `overlaps` and `lateTransports` return what the schedule draws as
|
|
74
|
+
data.
|
|
75
|
+
|
|
76
|
+
Work that is not on the plan is dragged in from any list of the application,
|
|
77
|
+
with the platform's drag and drop: the application says what it is dragging in
|
|
78
|
+
`placing`, the drop reports a `place` intent, and `subtaskFromPlace` builds the
|
|
79
|
+
subtask under the application's own id.
|
|
80
|
+
|
|
81
|
+
## What a bar says
|
|
82
|
+
|
|
83
|
+
`label` writes a line into every bar, cut off where the bar is too narrow and
|
|
84
|
+
left out where nothing would be readable. `appearance` adds what a colour
|
|
85
|
+
cannot say - `"provisional"`, `"fixed"`, `"muted"`, `"open"` - and `progress`
|
|
86
|
+
draws the share that is done as a rail along the bar. `route`, `anchor` and
|
|
87
|
+
`ends` decide how a transport is drawn, per schedule or per transport, without
|
|
88
|
+
touching what a finding says.
|
|
89
|
+
|
|
90
|
+
Each appearance owns exactly **one** property of the drawing, so several on one
|
|
91
|
+
bar stay several statements: `"provisional"` the fill (none at all, the surface
|
|
92
|
+
shows through), `"fixed"` the ends (a cap inside each), `"muted"` the
|
|
93
|
+
saturation (the task colour half mixed into the surface, at full height), and
|
|
94
|
+
`"open"` a fade at whichever edge of the view the bar passes. `progress` owns a
|
|
95
|
+
rail inside the main time. The faint, outlined fill belongs to a setup and a
|
|
96
|
+
teardown and to nothing else.
|
|
97
|
+
|
|
98
|
+
## Lanes that fold
|
|
99
|
+
|
|
100
|
+
`<LaneGroup>` puts halls, lines and machine groups over the lanes, to any
|
|
101
|
+
depth. A group is structure and never a lane: nothing sits on it, no finding is
|
|
102
|
+
reported for it, and no intent names it (ADR-0025).
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
<LaneGroup id="hall-a" label="Hall A">
|
|
106
|
+
<LaneGroup id="turning" label="Turning line">
|
|
107
|
+
<Lane id="lathe-1" label="Lathe 1" />
|
|
108
|
+
<Lane id="lathe-2" label="Lathe 2" />
|
|
109
|
+
</LaneGroup>
|
|
110
|
+
<Lane id="press-1" label="Press 1" />
|
|
111
|
+
</LaneGroup>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
Folded, a group becomes one row showing a **miniature** — every lane in it as a
|
|
115
|
+
thin strip, the real work smaller. Transports still arrive at the right strip,
|
|
116
|
+
findings are still marked, and a strip can still be hovered and selected:
|
|
117
|
+
folding costs a planner detail and never access. `collapsedGroups`,
|
|
118
|
+
`defaultCollapsedGroups` and `onCollapsedGroupsChange` put the state in the
|
|
119
|
+
application's hands; it is a view state, never an intent.
|
|
120
|
+
|
|
121
|
+
## Reading and moving
|
|
122
|
+
|
|
123
|
+
A tooltip on a hovered subtask or transport names the order, the times, setup
|
|
124
|
+
and teardown and the findings; `tooltip` replaces its content or switches it
|
|
125
|
+
off. `now` draws the present across the lanes. The wheel scrolls the lanes and
|
|
126
|
+
releases the page at their end, Ctrl or ⌘ and a pinch zoom, Shift pans;
|
|
127
|
+
`onDomainChange` reports the visible span, and a ref handle turns a client
|
|
128
|
+
point into a time and a lane and back.
|
|
129
|
+
|
|
130
|
+
## Where to read on
|
|
131
|
+
|
|
132
|
+
* The demo — `pnpm dev:schedule` (port 4176) — is the documentation: every page
|
|
133
|
+
shows running examples with their source and the props generated from `src/`.
|
|
134
|
+
* [`CHANGELOG.md`](CHANGELOG.md) — what changes for a caller.
|
|
135
|
+
* The vocabulary — **Task**, **Subtask**, **Setup**, **Teardown**,
|
|
136
|
+
**Transport**, **Late transport**, **Lane header**, **Lane group**,
|
|
137
|
+
**Miniature**, **Intent**, **Ghost** — stands in the workspace's
|
|
138
|
+
`CONTEXT.md`, section "The schedule".
|