@umriss-ui/schedule 0.2.0 → 0.3.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 CHANGED
@@ -15,6 +15,73 @@ moves from here under the rule above.
15
15
 
16
16
  ---
17
17
 
18
+ ## 0.3.0 – Dependencies and blocked time (Sep. 2026)
19
+
20
+ Needs `@umriss-ui/core` 0.11 and `@umriss-ui/charts` 0.8: it reads the renamed wording keys, the new ones for blocked time, and the charts' working-time functions; the peer ranges move to `^0.11.0` and `^0.8.0`.
21
+
22
+ ### Added
23
+
24
+ - **Blocked time per lane.** `<BlockedTimes data={…} />` takes a list of
25
+ `BlockedTime` — `{ id, lane, from, to, label? }`, plain data keyed by lane
26
+ like a subtask — for leave, maintenance and any other time a lane is not
27
+ available. It is drawn hatched behind all the work on the lane, in forced
28
+ colours too, wherever the layer is declared.
29
+ - **A finding: a subtask in blocked time.** `inBlockedTime(subtasks, blocked)`
30
+ returns every subtask that covers blocked time on its lane (lead-in and
31
+ lead-out included) as `InBlockedTime` — `{ subtask, blocked, lane, from, to }`.
32
+ `findings()` takes the blocked time as an optional third argument, and
33
+ `Findings` has the field `inBlockedTime`. The schedule marks the covered time
34
+ like an overlap; the tooltip and the keys' readout name it ("In blocked time
35
+ (Leave)"), and the plot's description counts it where there is any.
36
+ `ScheduleTooltipTarget` of kind `"subtask"` carries `blocked`, the blocked
37
+ times the subtask covers.
38
+ - **Blocked time is part of where a subtask may go.** A drag — inside the plot
39
+ or from outside — does not put work into blocked time it did not already
40
+ cover: the ghost stays where it was allowed, the cursor says no, a line ties
41
+ the ghost to the pointer, and its label says "Blocked time" (`data-blocked`
42
+ on the ghost label). Alt with an arrow key steps over blocked time instead of
43
+ into it; Alt+Shift does not stretch into it. Work the data already put there
44
+ is never locked in.
45
+ - A demo page, *Blocked time*.
46
+
47
+ ### Changed
48
+
49
+ - **Neutral names for the schedule's terms** (ADR-0035). The schedule is for
50
+ any plan of work on lanes, and its names said "plant": a transport is now a
51
+ **dependency** with a **lag**, setup and teardown are **lead-in** and
52
+ **lead-out**, and a late transport is a **violated dependency** — with every
53
+ name built on them. One hard cut, no deprecated aliases. What the terms do is
54
+ unchanged: a dependency still joins two subtasks of one task, from an end to
55
+ a start, and its anchors decide whether it is violated. `]`/`[` and `t`/Shift+T
56
+ still walk along it. The tooltip, the ghost, the readout and the summary say
57
+ "Lead-in", "Lead-out", "Dependency" and "Violated dependency" (German
58
+ "Vorlauf", "Nachlauf", "Abhängigkeit", "Abhängigkeit verletzt").
59
+
60
+ | Before | Now |
61
+ |---|---|
62
+ | `Subtask.setup` | `Subtask.leadIn` |
63
+ | `Subtask.teardown` | `Subtask.leadOut` |
64
+ | `PlaceIntent.setup`, `.teardown` | `PlaceIntent.leadIn`, `.leadOut` |
65
+ | `PlacingItem.setup`, `.teardown` | `PlacingItem.leadIn`, `.leadOut` |
66
+ | `SetupIntent` (`kind: "setup"`, field `setup`) | `LeadInIntent` (`kind: "leadIn"`, field `leadIn`) |
67
+ | `TeardownIntent` (`kind: "teardown"`, field `teardown`) | `LeadOutIntent` (`kind: "leadOut"`, field `leadOut`) |
68
+ | `"setup"`, `"teardown"` in `intents` | `"leadIn"`, `"leadOut"` |
69
+ | `Transport` | `Dependency` |
70
+ | `Transport.duration` | `Dependency.lag` |
71
+ | `leaves: "teardown"` (the default) | `leaves: "leadOut"` |
72
+ | `arrives: "setup"` (the default) | `arrives: "leadIn"` |
73
+ | `TransportRoute`, `TransportAttachment`, `TransportEnds` | `DependencyRoute`, `DependencyAttachment`, `DependencyEnds` |
74
+ | `<Transports>`, `TransportsProps` | `<Dependencies>`, `DependenciesProps` |
75
+ | `LateTransport` (field `transport`) | `ViolatedDependency` (field `dependency`) |
76
+ | `lateTransports()` | `violatedDependencies()` |
77
+ | `Findings.lateTransports` | `Findings.violatedDependencies` |
78
+ | `ScheduleTooltipTarget`: `kind: "transport"`, `transport`, `late`; `lateTransports` | `kind: "dependency"`, `dependency`, `violated`; `violatedDependencies` |
79
+ | `ScheduleHit`: `kind: "transport"`, `transport`; `part: "setup" \| "teardown"` | `kind: "dependency"`, `dependency`; `part: "leadIn" \| "leadOut"` |
80
+ | ghost `data-findings` value `late-transport` | `violated-dependency` |
81
+ | grip `data-grip` values `setup`, `teardown` | `leadIn`, `leadOut` |
82
+
83
+ ---
84
+
18
85
  ## 0.2.0 – By keyboard and screen reader (Sep. 2026)
19
86
 
20
87
  Needs `@umriss-ui/core` 0.10 and `@umriss-ui/charts` 0.7: it reads the schedule's wording keys; the peer ranges move to `^0.10.0` and `^0.7.0`.
package/README.md CHANGED
@@ -1,11 +1,12 @@
1
1
  # @umriss-ui/schedule
2
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
3
+ Work planned over time: **subtasks** on **lanes** — people, vehicles, rooms or
4
+ machines. One task runs across several lanes in a fixed order, each stop has a
5
+ main time with a lead-in before it and a lead-out after it, between the stops
6
+ lie **dependencies** with lags of their own, and a lane can be **blocked** for
7
+ leave or maintenance. The schedule draws all of it, marks what cannot work —
8
+ two subtasks on one lane at once, a dependency whose lag does not fit, work in
9
+ blocked time — and lets a planner move things by hand without ever changing
9
10
  the plan underneath them.
10
11
 
11
12
  ## Install
@@ -17,30 +18,30 @@ pnpm add @umriss-ui/schedule @umriss-ui/core @umriss-ui/charts
17
18
  Both `@umriss-ui/core` and `@umriss-ui/charts` are **peer dependencies**
18
19
  (ADR-0022): the schedule takes its styling regime, provider, formats and
19
20
  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
+ the working calendar, the canvas colour resolution — from charts. React 18 or
21
22
  19 as a peer as well.
22
23
 
23
24
  ## The smallest schedule that runs
24
25
 
25
26
  ```tsx
26
- import { Lane, Schedule, Subtasks, Transports } from "@umriss-ui/schedule";
27
- import type { Subtask, Task, Transport } from "@umriss-ui/schedule";
27
+ import { Lane, Schedule, Subtasks, Dependencies } from "@umriss-ui/schedule";
28
+ import type { Subtask, Task, Dependency } from "@umriss-ui/schedule";
28
29
 
29
30
  const at = (h: number, m = 0) => new Date(2026, 2, 17, h, m).getTime();
30
31
 
31
32
  const tasks: Task[] = [{ id: "a-2041", color: "#2563eb" }];
32
33
  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 },
34
+ { id: "cut", task: "a-2041", lane: "saw", from: at(6), to: at(7), leadOut: 10 * 60_000 },
35
+ { id: "mill", task: "a-2041", lane: "mill", from: at(8), to: at(10), leadIn: 30 * 60_000 },
35
36
  ];
36
- const transports: Transport[] = [{ id: "move", from: "cut", to: "mill", duration: 15 * 60_000 }];
37
+ const dependencies: Dependency[] = [{ id: "move", from: "cut", to: "mill", lag: 15 * 60_000 }];
37
38
 
38
39
  export function Plan() {
39
40
  return (
40
41
  <Schedule ariaLabel="Plan of Tuesday" initialDomain={[at(5), at(12)]}>
41
42
  <Lane id="saw" label="Saw" />
42
43
  <Lane id="mill" label="Mill" />
43
- <Transports data={transports} />
44
+ <Dependencies data={dependencies} />
44
45
  <Subtasks data={subtasks} tasks={tasks} />
45
46
  </Schedule>
46
47
  );
@@ -51,7 +52,7 @@ export function Plan() {
51
52
 
52
53
  The schedule draws the data it is given and changes none of it (ADR-0023). A
53
54
  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
+ **intent** — move, lane, stretch, lead-in, lead-out — reported to the caller:
55
56
 
56
57
  ```tsx
57
58
  <Schedule
@@ -65,12 +66,12 @@ drag shows a **ghost** with the findings the drop would create, and ends in an
65
66
  read-only. `canMoveTo(subtask, lane)` narrows it: a drag across a lane the
66
67
  subtask may not go to leaves the ghost where it was allowed and shows a
67
68
  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
+ takes the tick raster, a step, or a step with an offset - handovers at 06:00,
69
70
  14:00 and 22:00 are eight hours offset by six.
70
71
 
71
72
  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
73
+ the application to apply, or not, and `shiftTask` the moves of a whole task.
74
+ `findings`, `overlaps` and `violatedDependencies` return what the schedule draws as
74
75
  data.
75
76
 
76
77
  Work that is not on the plan is dragged in from any list of the application,
@@ -84,7 +85,7 @@ subtask under the application's own id.
84
85
  left out where nothing would be readable. `appearance` adds what a colour
85
86
  cannot say - `"provisional"`, `"fixed"`, `"muted"`, `"open"` - and `progress`
86
87
  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
+ `ends` decide how a dependency is drawn, per schedule or per dependency, without
88
89
  touching what a finding says.
89
90
 
90
91
  Each appearance owns exactly **one** property of the drawing, so several on one
@@ -92,12 +93,12 @@ bar stay several statements: `"provisional"` the fill (none at all, the surface
92
93
  shows through), `"fixed"` the ends (a cap inside each), `"muted"` the
93
94
  saturation (the task colour half mixed into the surface, at full height), and
94
95
  `"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.
96
+ rail inside the main time. The faint, outlined fill belongs to a lead-in and a
97
+ lead-out and to nothing else.
97
98
 
98
99
  ## Lanes that fold
99
100
 
100
- `<LaneGroup>` puts halls, lines and machine groups over the lanes, to any
101
+ `<LaneGroup>` puts teams, depots or regions over the lanes, to any
101
102
  depth. A group is structure and never a lane: nothing sits on it, no finding is
102
103
  reported for it, and no intent names it (ADR-0025).
103
104
 
@@ -112,7 +113,7 @@ reported for it, and no intent names it (ADR-0025).
112
113
  ```
113
114
 
114
115
  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
+ thin strip, the real work smaller. Dependencies still arrive at the right strip,
116
117
  findings are still marked, and a strip can still be hovered and selected:
117
118
  folding costs a planner detail and never access. `collapsedGroups`,
118
119
  `defaultCollapsedGroups` and `onCollapsedGroupsChange` put the state in the
@@ -120,8 +121,8 @@ application's hands; it is a view state, never an intent.
120
121
 
121
122
  ## Reading and moving
122
123
 
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
124
+ A tooltip on a hovered subtask or dependency names the order, the times, lead-in
125
+ and lead-out and the findings; `tooltip` replaces its content or switches it
125
126
  off. `now` draws the present across the lanes. The wheel over the schedule,
126
127
  lane headers included, scrolls the lanes and releases the page at their end,
127
128
  Ctrl or ⌘ and a pinch zoom, Shift pans; on a touch screen one finger pans and a
@@ -130,6 +131,26 @@ phone the plot keeps the larger part;
130
131
  `onDomainChange` reports the visible span, and a ref handle turns a client
131
132
  point into a time and a lane and back.
132
133
 
134
+ ## Blocked time
135
+
136
+ `<BlockedTimes data={…} />` takes the time a lane is not available — leave,
137
+ maintenance — as plain data, `{ id, lane, from, to, label? }`. It is drawn
138
+ hatched behind the work; a subtask that covers some of it is a finding
139
+ (`inBlockedTime`, and the third argument of `findings`), and a drag does not
140
+ put work into it.
141
+
142
+ ## Not yet
143
+
144
+ What the schedule does not do today, and waits for a caller who needs it (what
145
+ it never does stands in ADR-0032):
146
+
147
+ * **Milestones** — a point in time on a lane, drawn as a mark rather than a bar.
148
+ * **Stacked overlap** — overlapping subtasks packed into sub-lanes on request;
149
+ today an overlap is always drawn offset, as the finding it is.
150
+ * **Dependencies across tasks** — a dependency joins two subtasks of one task.
151
+
152
+ Done from this list: **blocked time** per lane.
153
+
133
154
  ## Where to read on
134
155
 
135
156
  * The demo: <https://romanhaendler.github.io/umriss-ui/schedule/>, or locally
@@ -141,8 +162,8 @@ point into a time and a lane and back.
141
162
  with its examples' source, its props tables and why it is built as it is,
142
163
  and the declaration of every other export. Online, for the latest version:
143
164
  <https://romanhaendler.github.io/umriss-ui/schedule/llms.txt>.
144
- * The vocabulary — **Task**, **Subtask**, **Setup**, **Teardown**,
145
- **Transport**, **Late transport**, **Lane header**, **Lane group**,
165
+ * The vocabulary — **Task**, **Subtask**, **Lead-in**, **Lead-out**,
166
+ **Dependency**, **Violated dependency**, **Blocked time**, **Lane header**, **Lane group**,
146
167
  **Miniature**, **Intent**, **Ghost** — stands in the workspace's
147
168
  `CONTEXT.md`, section "The schedule".
148
169
  * [`../../docs/design-language.md`](../../docs/design-language.md) — the design