@charcuterie/ui 4.10.2 → 4.11.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/dist/LaneTimeline/LaneTimeline.d.ts +8 -1
- package/dist/LaneTimeline/LaneTimeline.d.ts.map +1 -1
- package/dist/LaneTimeline/LaneTimeline.js +26 -3
- package/dist/LaneTimeline/LaneTimeline.js.map +1 -1
- package/dist/LaneTimeline/LaneTimelineBar.d.ts +9 -2
- package/dist/LaneTimeline/LaneTimelineBar.d.ts.map +1 -1
- package/dist/LaneTimeline/LaneTimelineBar.js +14 -7
- package/dist/LaneTimeline/LaneTimelineBar.js.map +1 -1
- package/dist/LaneTimeline/LaneTimelineLane.d.ts +8 -2
- package/dist/LaneTimeline/LaneTimelineLane.d.ts.map +1 -1
- package/dist/LaneTimeline/LaneTimelineLane.js +2 -2
- package/dist/LaneTimeline/LaneTimelineLane.js.map +1 -1
- package/dist/LaneTimeline/laneTimelineGeometry.d.ts +31 -0
- package/dist/LaneTimeline/laneTimelineGeometry.d.ts.map +1 -1
- package/dist/LaneTimeline/laneTimelineGeometry.js +15 -0
- package/dist/LaneTimeline/laneTimelineGeometry.js.map +1 -1
- package/package.json +1 -1
- package/src/LaneTimeline/LaneTimeline.mdx +14 -0
- package/src/LaneTimeline/LaneTimeline.test.tsx +33 -0
- package/src/LaneTimeline/LaneTimeline.tsx +35 -0
- package/src/LaneTimeline/LaneTimelineBar.tsx +44 -12
- package/src/LaneTimeline/LaneTimelineLane.tsx +12 -1
- package/src/LaneTimeline/laneTimelineGeometry.test.ts +35 -0
- package/src/LaneTimeline/laneTimelineGeometry.ts +43 -0
|
@@ -48,6 +48,13 @@ export type LaneTimelineProps = {
|
|
|
48
48
|
* `2026-04-06` to `2026-04-12`, which is seven columns, not eight.
|
|
49
49
|
*/
|
|
50
50
|
range: TimelineSpan;
|
|
51
|
+
/**
|
|
52
|
+
* The narrowest a day column may be before a bar's title wraps
|
|
53
|
+
* onto up to three lines instead of clipping to one, as a
|
|
54
|
+
* multiple of the timeline's **own font size**. Default 6. In em
|
|
55
|
+
* for the reason `minColumnSize` is.
|
|
56
|
+
*/
|
|
57
|
+
wrapColumnSize?: number;
|
|
51
58
|
};
|
|
52
59
|
/**
|
|
53
60
|
* One horizontal lane per group, across a date axis, with anything
|
|
@@ -128,5 +135,5 @@ export type LaneTimelineProps = {
|
|
|
128
135
|
* can drag is a write operation, which is a different component with
|
|
129
136
|
* a different decision behind it.
|
|
130
137
|
*/
|
|
131
|
-
export declare const LaneTimeline: ({ className, emptyState, headingLevel, label, lanes, locale, maxRowCount, minColumnSize, range, }: LaneTimelineProps) => ReactNode;
|
|
138
|
+
export declare const LaneTimeline: ({ className, emptyState, headingLevel, label, lanes, locale, maxRowCount, minColumnSize, range, wrapColumnSize, }: LaneTimelineProps) => ReactNode;
|
|
132
139
|
//# sourceMappingURL=LaneTimeline.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LaneTimeline.d.ts","sourceRoot":"","sources":["../../src/LaneTimeline/LaneTimeline.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAKtC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAE1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;
|
|
1
|
+
{"version":3,"file":"LaneTimeline.d.ts","sourceRoot":"","sources":["../../src/LaneTimeline/LaneTimeline.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAKtC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAE1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAkE7D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,SAAS,CAAA;IACtB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC5B,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,SAAS,YAAY,EAAE,CAAA;IAC9B;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,mDAAmD;IACnD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;;OAIG;IACH,KAAK,EAAE,YAAY,CAAA;IACnB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8EG;AACH,eAAO,MAAM,YAAY,GAAI,mHAW1B,iBAAiB,KAAG,SAoMtB,CAAA"}
|
|
@@ -3,7 +3,7 @@ import { getPlainDateFromDayNumber } from "../DatePicker/plainDate.js";
|
|
|
3
3
|
import { EmptyState } from "../EmptyState/EmptyState.js";
|
|
4
4
|
import { toClassName } from "../toClassName.js";
|
|
5
5
|
import { LaneTimelineLane } from "./LaneTimelineLane.js";
|
|
6
|
-
import { chooseAxisTickStep, formatAxisDate, getIsAxisReadable, toTimelineAxis, } from "./laneTimelineGeometry.js";
|
|
6
|
+
import { chooseAxisTickStep, chooseTitleLayout, formatAxisDate, getIsAxisReadable, toTimelineAxis, } from "./laneTimelineGeometry.js";
|
|
7
7
|
import { useTrackMeasurements } from "./useTrackMeasurements.js";
|
|
8
8
|
/**
|
|
9
9
|
* Room one tick label needs, as a multiple of the timeline's own
|
|
@@ -40,6 +40,23 @@ const DEFAULT_MIN_COLUMN_SIZE = 1.75;
|
|
|
40
40
|
* than drawn. Six is roughly a screen's worth of one lane.
|
|
41
41
|
*/
|
|
42
42
|
const DEFAULT_MAX_ROW_COUNT = 6;
|
|
43
|
+
/**
|
|
44
|
+
* The narrowest a day column may be before a bar's title WRAPS
|
|
45
|
+
* rather than clips, in em.
|
|
46
|
+
*
|
|
47
|
+
* A one-line title with an ellipsis is right for a narrow column
|
|
48
|
+
* and wrong for a wide one, and the fold threshold above cannot
|
|
49
|
+
* tell the two apart: `minColumnSize` is where the axis stops
|
|
50
|
+
* being worth drawing, not where a title becomes readable. A
|
|
51
|
+
* seven-day week across a 64rem page gives every column 7em, and
|
|
52
|
+
* a single-day bar in it still printed `Regional Rob…` — the
|
|
53
|
+
* owner's verdict on that picture was *"I can't really read this
|
|
54
|
+
* text"*. Six em is about eight characters of the bar's own type,
|
|
55
|
+
* which is the narrowest box in which a wrapped word is a word and
|
|
56
|
+
* not a column of letters. A four-week range on the same page is
|
|
57
|
+
* under it and keeps the ellipsis.
|
|
58
|
+
*/
|
|
59
|
+
const DEFAULT_WRAP_COLUMN_SIZE = 6;
|
|
43
60
|
/**
|
|
44
61
|
* One horizontal lane per group, across a date axis, with anything
|
|
45
62
|
* that lasts more than a day drawn as a **bar**.
|
|
@@ -119,7 +136,7 @@ const DEFAULT_MAX_ROW_COUNT = 6;
|
|
|
119
136
|
* can drag is a write operation, which is a different component with
|
|
120
137
|
* a different decision behind it.
|
|
121
138
|
*/
|
|
122
|
-
export const LaneTimeline = ({ className, emptyState, headingLevel = 3, label, lanes, locale, maxRowCount = DEFAULT_MAX_ROW_COUNT, minColumnSize = DEFAULT_MIN_COLUMN_SIZE, range, }) => {
|
|
139
|
+
export const LaneTimeline = ({ className, emptyState, headingLevel = 3, label, lanes, locale, maxRowCount = DEFAULT_MAX_ROW_COUNT, minColumnSize = DEFAULT_MIN_COLUMN_SIZE, range, wrapColumnSize = DEFAULT_WRAP_COLUMN_SIZE, }) => {
|
|
123
140
|
const { fontSize, inlineSize, isMeasured, trackRef } = useTrackMeasurements();
|
|
124
141
|
const axis = toTimelineAxis(range);
|
|
125
142
|
const columnCount = axis?.columnCount ?? 0;
|
|
@@ -134,6 +151,12 @@ export const LaneTimeline = ({ className, emptyState, headingLevel = 3, label, l
|
|
|
134
151
|
inlineSize,
|
|
135
152
|
minTickInlineSize: TICK_LABEL_SIZE * fontSize,
|
|
136
153
|
});
|
|
154
|
+
const titleLayout = chooseTitleLayout({
|
|
155
|
+
columnCount,
|
|
156
|
+
inlineSize,
|
|
157
|
+
isMeasured,
|
|
158
|
+
wrapColumnInlineSize: wrapColumnSize * fontSize,
|
|
159
|
+
});
|
|
137
160
|
/*
|
|
138
161
|
* An inline style, not a class. Tailwind scans source text for
|
|
139
162
|
* complete class strings, so a `grid-cols-[repeat(${n},…)]` is
|
|
@@ -160,6 +183,6 @@ export const LaneTimeline = ({ className, emptyState, headingLevel = 3, label, l
|
|
|
160
183
|
}, children: formatAxisDate({
|
|
161
184
|
date: getPlainDateFromDayNumber(axis.startDay + index),
|
|
162
185
|
locale,
|
|
163
|
-
}) }, axis.startDay + index))) })] }), lanes.map((lane, position) => (_jsx(LaneTimelineLane, { axis: axis, columnTemplate: columnTemplate, headingLevel: headingLevel, lane: lane, locale: locale, maxRowCount: maxRowCount, position: position, shape: "axis", tickStep: tickStep }, lane.key)))] })) : (_jsxs(_Fragment, { children: [_jsx("p", { className: "pb-1 text-content-muted text-xs", children: rangeCaption }), lanes.map((lane, position) => (_jsx(LaneTimelineLane, { axis: axis, columnTemplate: columnTemplate, headingLevel: headingLevel, lane: lane, locale: locale, maxRowCount: maxRowCount, position: position, shape: "list", tickStep: tickStep }, lane.key)))] }))] }));
|
|
186
|
+
}) }, axis.startDay + index))) })] }), lanes.map((lane, position) => (_jsx(LaneTimelineLane, { axis: axis, columnTemplate: columnTemplate, headingLevel: headingLevel, lane: lane, locale: locale, maxRowCount: maxRowCount, position: position, shape: "axis", tickStep: tickStep, titleLayout: titleLayout }, lane.key)))] })) : (_jsxs(_Fragment, { children: [_jsx("p", { className: "pb-1 text-content-muted text-xs", children: rangeCaption }), lanes.map((lane, position) => (_jsx(LaneTimelineLane, { axis: axis, columnTemplate: columnTemplate, headingLevel: headingLevel, lane: lane, locale: locale, maxRowCount: maxRowCount, position: position, shape: "list", tickStep: tickStep }, lane.key)))] }))] }));
|
|
164
187
|
};
|
|
165
188
|
//# sourceMappingURL=LaneTimeline.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LaneTimeline.js","sourceRoot":"","sources":["../../src/LaneTimeline/LaneTimeline.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAA;AACtE,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA8B,CAAA;AACzD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAwB,CAAA;AAEzD,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,cAAc,GACf,MAAM,2BAA2B,CAAA;AAClC,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAA;AAEhE;;;;;;;;;;GAUG;AACH,MAAM,eAAe,GAAG,GAAG,CAAA;AAE3B;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,uBAAuB,GAAG,IAAI,CAAA;AAEpC;;;GAGG;AACH,MAAM,qBAAqB,GAAG,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"LaneTimeline.js","sourceRoot":"","sources":["../../src/LaneTimeline/LaneTimeline.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CategoricalIndex } from "@charcuterie/tokens";
|
|
2
2
|
import type { ReactNode } from "react";
|
|
3
|
-
import type { TimelineSpan } from "./laneTimelineGeometry.ts";
|
|
3
|
+
import type { TimelineSpan, TimelineTitleLayout } from "./laneTimelineGeometry.ts";
|
|
4
4
|
/**
|
|
5
5
|
* Who owns the item's activation — nobody, a router, or a handler.
|
|
6
6
|
*
|
|
@@ -59,6 +59,13 @@ export type LaneTimelineBarProps = {
|
|
|
59
59
|
* text and no position to carry meaning.
|
|
60
60
|
*/
|
|
61
61
|
shape: "bar" | "row";
|
|
62
|
+
/**
|
|
63
|
+
* For the `bar` shape only: `clip` prints the title on one line
|
|
64
|
+
* with an ellipsis, `wrap` lets it run onto up to three. The
|
|
65
|
+
* timeline chooses from the measured column width, so a bar
|
|
66
|
+
* never decides this for itself. Default `clip`.
|
|
67
|
+
*/
|
|
68
|
+
titleLayout?: TimelineTitleLayout;
|
|
62
69
|
};
|
|
63
70
|
/**
|
|
64
71
|
* One item, in either of the two shapes this component draws it in.
|
|
@@ -92,6 +99,6 @@ export type LaneTimelineBarProps = {
|
|
|
92
99
|
* missing corner is not something anybody perceives without the
|
|
93
100
|
* unclipped bar beside it to compare against.
|
|
94
101
|
*/
|
|
95
|
-
export declare const LaneTimelineBar: ({ className, description, hasEarlierStart, hasLaterEnd, item, laneCategorical, shape, }: LaneTimelineBarProps) => ReactNode;
|
|
102
|
+
export declare const LaneTimelineBar: ({ className, description, hasEarlierStart, hasLaterEnd, item, laneCategorical, shape, titleLayout, }: LaneTimelineBarProps) => ReactNode;
|
|
96
103
|
export {};
|
|
97
104
|
//# sourceMappingURL=LaneTimelineBar.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LaneTimelineBar.d.ts","sourceRoot":"","sources":["../../src/LaneTimeline/LaneTimelineBar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAUtC,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"LaneTimelineBar.d.ts","sourceRoot":"","sources":["../../src/LaneTimeline/LaneTimelineBar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAUtC,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACpB,MAAM,2BAA2B,CAAA;AAElC;;;;;;;;GAQG;AACH,KAAK,kBAAkB,GACnB;IACE;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,KAAK,CAAA;CACjB,GACD;IACE,IAAI,CAAC,EAAE,KAAK,CAAA;IACZ,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACtB,CAAA;AAEL,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG;IACxC;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,gBAAgB,CAAA;IAC9B,GAAG,EAAE,MAAM,CAAA;IACX;;;;;OAKG;IACH,KAAK,EAAE,MAAM,CAAA;CACd,GAAG,kBAAkB,CAAA;AAEtB,MAAM,MAAM,oBAAoB,GAAG;IACjC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,YAAY,CAAA;IAClB,sDAAsD;IACtD,eAAe,EAAE,gBAAgB,CAAA;IACjC,iEAAiE;IACjE,WAAW,EAAE,MAAM,CAAA;IACnB,kEAAkE;IAClE,eAAe,EAAE,OAAO,CAAA;IACxB,0DAA0D;IAC1D,WAAW,EAAE,OAAO,CAAA;IACpB;;;;OAIG;IACH,KAAK,EAAE,KAAK,GAAG,KAAK,CAAA;IACpB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,mBAAmB,CAAA;CAClC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,eAAe,GAAI,sGAS7B,oBAAoB,KAAG,SA4IzB,CAAA"}
|
|
@@ -36,12 +36,14 @@ import { VisuallyHidden } from "../VisuallyHidden/VisuallyHidden.js";
|
|
|
36
36
|
* missing corner is not something anybody perceives without the
|
|
37
37
|
* unclipped bar beside it to compare against.
|
|
38
38
|
*/
|
|
39
|
-
export const LaneTimelineBar = ({ className, description, hasEarlierStart, hasLaterEnd, item, laneCategorical, shape, }) => {
|
|
39
|
+
export const LaneTimelineBar = ({ className, description, hasEarlierStart, hasLaterEnd, item, laneCategorical, shape, titleLayout = "clip", }) => {
|
|
40
40
|
const categorical = item.categorical ?? laneCategorical;
|
|
41
41
|
const isInteractive = Boolean(item.href ?? item.onSelect);
|
|
42
|
-
const content = (_jsxs(_Fragment, { children: [_jsx("span", { className: toClassName("min-w-0 flex-1", shape === "
|
|
43
|
-
? "
|
|
44
|
-
:
|
|
42
|
+
const content = (_jsxs(_Fragment, { children: [_jsx("span", { className: toClassName("min-w-0 flex-1 text-sm", shape === "row"
|
|
43
|
+
? "wrap-anywhere"
|
|
44
|
+
: titleLayout === "wrap"
|
|
45
|
+
? "line-clamp-3 wrap-anywhere"
|
|
46
|
+
: "truncate"), children: item.title }), shape === "row" ? (_jsx("span", { className: "text-content-muted text-xs", children: description })) : isInteractive ? null : (_jsx(VisuallyHidden, { children: description }))] }));
|
|
45
47
|
/**
|
|
46
48
|
* Only the bar shape gets one, and it carries the **title** as
|
|
47
49
|
* well as the span. The Narrow View prints both already, and a
|
|
@@ -50,9 +52,14 @@ export const LaneTimelineBar = ({ className, description, hasEarlierStart, hasLa
|
|
|
50
52
|
*/
|
|
51
53
|
const sentence = `${item.title}, ${description}`;
|
|
52
54
|
const hoverText = shape === "bar" ? sentence : undefined;
|
|
53
|
-
const shellClassName = toClassName("w-full min-w-0 border px-1.5 text-xs leading-tight",
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
const shellClassName = toClassName("w-full min-w-0 border px-1.5 text-xs leading-tight",
|
|
56
|
+
// `h-full` so every bar in one packed row is the height of the
|
|
57
|
+
// tallest: a wrapped three-line title beside a one-line one
|
|
58
|
+
// would otherwise leave the shorter bar floating above the
|
|
59
|
+
// row's baseline.
|
|
60
|
+
shape === "bar"
|
|
61
|
+
? "flex h-full min-h-5 items-center rounded-sm"
|
|
62
|
+
: "flex flex-col gap-0.5 rounded-md py-1", shape === "bar" && titleLayout === "wrap" && "py-0.5", CATEGORICAL_APPEARANCE_CLASS[categorical].soft,
|
|
56
63
|
// A square edge where the item leaves the range. `rounded-*-none`
|
|
57
64
|
// rather than a different component, so a clipped bar and a whole
|
|
58
65
|
// one are the same box with one corner rule changed.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LaneTimelineBar.js","sourceRoot":"","sources":["../../src/LaneTimeline/LaneTimelineBar.tsx"],"names":[],"mappings":";AAGA,OAAO,EACL,4BAA4B,EAC5B,uBAAuB,GACxB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,+BAAgC,CAAA;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAsC,CAAA;
|
|
1
|
+
{"version":3,"file":"LaneTimelineBar.js","sourceRoot":"","sources":["../../src/LaneTimeline/LaneTimelineBar.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { CategoricalIndex } from "@charcuterie/tokens";
|
|
2
2
|
import type { ReactNode } from "react";
|
|
3
3
|
import type { TimelineItem } from "./LaneTimelineBar.tsx";
|
|
4
|
-
import type { TimelineAxis } from "./laneTimelineGeometry.ts";
|
|
4
|
+
import type { TimelineAxis, TimelineTitleLayout } from "./laneTimelineGeometry.ts";
|
|
5
5
|
export type TimelineLane = {
|
|
6
6
|
/**
|
|
7
7
|
* Which of the ten hues this lane wears, overriding the one its
|
|
@@ -47,6 +47,12 @@ export type LaneTimelineLaneProps = {
|
|
|
47
47
|
shape: "axis" | "list";
|
|
48
48
|
/** Draw a separator every this many columns. */
|
|
49
49
|
tickStep: number;
|
|
50
|
+
/**
|
|
51
|
+
* Whether a bar's title clips to one line or wraps onto up to
|
|
52
|
+
* three. The parent measures the column and decides; the Narrow
|
|
53
|
+
* View ignores it, because a row always has room to wrap.
|
|
54
|
+
*/
|
|
55
|
+
titleLayout?: TimelineTitleLayout;
|
|
50
56
|
};
|
|
51
57
|
/**
|
|
52
58
|
* One lane: its name, how much it is carrying, and either a track of
|
|
@@ -80,5 +86,5 @@ export type LaneTimelineLaneProps = {
|
|
|
80
86
|
* month grid, where every cell is the same size no matter what is
|
|
81
87
|
* in it.
|
|
82
88
|
*/
|
|
83
|
-
export declare const LaneTimelineLane: ({ axis, columnTemplate, headingLevel, lane, locale, maxRowCount, position, shape, tickStep, }: LaneTimelineLaneProps) => ReactNode;
|
|
89
|
+
export declare const LaneTimelineLane: ({ axis, columnTemplate, headingLevel, lane, locale, maxRowCount, position, shape, tickStep, titleLayout, }: LaneTimelineLaneProps) => ReactNode;
|
|
84
90
|
//# sourceMappingURL=LaneTimelineLane.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LaneTimelineLane.d.ts","sourceRoot":"","sources":["../../src/LaneTimeline/LaneTimelineLane.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAK3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAMtC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAEzD,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"LaneTimelineLane.d.ts","sourceRoot":"","sources":["../../src/LaneTimeline/LaneTimelineLane.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAK3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAMtC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAEzD,OAAO,KAAK,EACV,YAAY,EACZ,mBAAmB,EACpB,MAAM,2BAA2B,CAAA;AAMlC,MAAM,MAAM,YAAY,GAAG;IACzB;;;;;;;;;;OAUG;IACH,WAAW,CAAC,EAAE,gBAAgB,CAAA;IAC9B;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,SAAS,YAAY,EAAE,CAAA;IAC9B,GAAG,EAAE,MAAM,CAAA;IACX;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,EAAE,YAAY,CAAA;IAClB,+DAA+D;IAC/D,cAAc,EAAE,MAAM,CAAA;IACtB,YAAY,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC3B,IAAI,EAAE,YAAY,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,4DAA4D;IAC5D,QAAQ,EAAE,MAAM,CAAA;IAChB;;;OAGG;IACH,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;IACtB,gDAAgD;IAChD,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;OAIG;IACH,WAAW,CAAC,EAAE,mBAAmB,CAAA;CAClC,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,gBAAgB,GAAI,4GAW9B,qBAAqB,KAAG,SA8N1B,CAAA"}
|
|
@@ -39,7 +39,7 @@ import { describeTimelineSpan, toPackedLane, } from "./laneTimelineGeometry.js";
|
|
|
39
39
|
* month grid, where every cell is the same size no matter what is
|
|
40
40
|
* in it.
|
|
41
41
|
*/
|
|
42
|
-
export const LaneTimelineLane = ({ axis, columnTemplate, headingLevel, lane, locale, maxRowCount, position, shape, tickStep, }) => {
|
|
42
|
+
export const LaneTimelineLane = ({ axis, columnTemplate, headingLevel, lane, locale, maxRowCount, position, shape, tickStep, titleLayout = "clip", }) => {
|
|
43
43
|
const headingId = useUniqueId();
|
|
44
44
|
/*
|
|
45
45
|
* Position, not `getCategoricalIndex(lane.key)`, and `ActionTiles`
|
|
@@ -104,6 +104,6 @@ export const LaneTimelineLane = ({ axis, columnTemplate, headingLevel, lane, loc
|
|
|
104
104
|
locale,
|
|
105
105
|
placement,
|
|
106
106
|
span: item,
|
|
107
|
-
}), hasEarlierStart: placement.hasEarlierStart, hasLaterEnd: placement.hasLaterEnd, item: item, shape: "bar" }) }, item.key)))) }), packed.hiddenCount > 0 ? (_jsx("p", { className: "pt-1 text-content-muted text-xs", children: `+ ${packed.hiddenCount} more overlapping in ${lane.label}` })) : null] })] }));
|
|
107
|
+
}), hasEarlierStart: placement.hasEarlierStart, hasLaterEnd: placement.hasLaterEnd, item: item, shape: "bar", titleLayout: titleLayout }) }, item.key)))) }), packed.hiddenCount > 0 ? (_jsx("p", { className: "pt-1 text-content-muted text-xs", children: `+ ${packed.hiddenCount} more overlapping in ${lane.label}` })) : null] })] }));
|
|
108
108
|
};
|
|
109
109
|
//# sourceMappingURL=LaneTimelineLane.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LaneTimelineLane.js","sourceRoot":"","sources":["../../src/LaneTimeline/LaneTimelineLane.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAEhD,OAAO,EACL,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,qBAAqB,CAAA;AAG5B,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAoB,CAAA;AAC1C,OAAO,EAAE,4BAA4B,EAAE,MAAM,yBAAyB,CAAA;AACtE,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAA0B,CAAA;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/C,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"LaneTimelineLane.js","sourceRoot":"","sources":["../../src/LaneTimeline/LaneTimelineLane.tsx"],"names":[],"mappings":"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"}
|
|
@@ -221,6 +221,37 @@ export declare const getIsAxisReadable: ({ columnCount, inlineSize, isMeasured,
|
|
|
221
221
|
isMeasured: boolean;
|
|
222
222
|
minColumnInlineSize: number;
|
|
223
223
|
}) => boolean;
|
|
224
|
+
/**
|
|
225
|
+
* How a bar prints its title: on one line with an ellipsis, or
|
|
226
|
+
* wrapped onto up to three.
|
|
227
|
+
*
|
|
228
|
+
* `clip` is the honest answer when a column is narrow — a wrapped
|
|
229
|
+
* title in 30px is three lines of two letters each, which is
|
|
230
|
+
* neither the word nor a shape. `wrap` is the honest answer when
|
|
231
|
+
* the column is wide, and it is the one the whole component was
|
|
232
|
+
* measured wanting: at seven columns across a 64rem page a single-
|
|
233
|
+
* day bar has 7em of room and was still printing `Regional Rob…`,
|
|
234
|
+
* because one line is one line however wide the box gets.
|
|
235
|
+
*/
|
|
236
|
+
export type TimelineTitleLayout = "clip" | "wrap";
|
|
237
|
+
/**
|
|
238
|
+
* Wrap the titles only once a day column is wide enough for a word.
|
|
239
|
+
*
|
|
240
|
+
* Measured, for the same reason `getIsAxisReadable` is: the
|
|
241
|
+
* question is the width of ONE column, which is the box divided by
|
|
242
|
+
* a number that lives in the data. Before the first measurement it
|
|
243
|
+
* clips, because that is the layout with no vertical surprise in
|
|
244
|
+
* it — a server render that wrapped would move every lane on the
|
|
245
|
+
* client's first paint.
|
|
246
|
+
*/
|
|
247
|
+
export declare const chooseTitleLayout: ({ columnCount, inlineSize, isMeasured, wrapColumnInlineSize, }: {
|
|
248
|
+
columnCount: number;
|
|
249
|
+
/** The measured inline size of the track, in CSS pixels. */
|
|
250
|
+
inlineSize: number;
|
|
251
|
+
isMeasured: boolean;
|
|
252
|
+
/** The narrowest column that wraps, in CSS pixels. */
|
|
253
|
+
wrapColumnInlineSize: number;
|
|
254
|
+
}) => TimelineTitleLayout;
|
|
224
255
|
export declare const chooseAxisTickStep: ({ columnCount, inlineSize, minTickInlineSize, }: {
|
|
225
256
|
columnCount: number;
|
|
226
257
|
inlineSize: number;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"laneTimelineGeometry.d.ts","sourceRoot":"","sources":["../../src/LaneTimeline/laneTimelineGeometry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AAO3D;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAA;IACX,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,YAAY,GAAG;IACzB,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAA;IACnB;;;;;;;;;OASG;IACH,UAAU,EAAE,MAAM,CAAA;IAClB;;;;;OAKG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB,oDAAoD;IACpD,eAAe,EAAE,OAAO,CAAA;IACxB,4DAA4D;IAC5D,WAAW,EAAE,OAAO,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,kBAAkB,CAAC,IAAI,IAAI;IACrC,IAAI,EAAE,IAAI,CAAA;IACV,SAAS,EAAE,YAAY,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,UAAU,CAAC,IAAI,IAAI;IAC7B;;;;;;;;OAQG;IACH,WAAW,EAAE,MAAM,CAAA;IACnB;;;;;;;;;;;OAWG;IACH,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,kBAAkB,CAAC,IAAI,CAAC,EAAE,EAAE,CAAA;CACnC,CAAA;AAQD;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,cAAc,GACzB,OAAO,YAAY,KAClB,IAAI,GAAG,YAgBT,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,eAAO,MAAM,cAAc,GAAI,iBAG5B;IACD,IAAI,EAAE,YAAY,CAAA;IAClB,IAAI,EAAE,YAAY,CAAA;CACnB,KAAG,IAAI,GAAG,YAgCV,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,YAAY,GACvB,IAAI,SAAS,YAAY,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EAC3C,+BAIC;IACD,IAAI,EAAE,YAAY,CAAA;IAClB,KAAK,EAAE,SAAS,IAAI,EAAE,CAAA;IACtB;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAA;CACpB,KAAG,UAAU,CAAC,IAAI,CAiDlB,CAAA;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,eAAO,MAAM,iBAAiB,GAAI,+DAK/B;IACD,WAAW,EAAE,MAAM,CAAA;IACnB,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,OAAO,CAAA;IACnB,mBAAmB,EAAE,MAAM,CAAA;CAC5B,KAAG,OAG6C,CAAA;
|
|
1
|
+
{"version":3,"file":"laneTimelineGeometry.d.ts","sourceRoot":"","sources":["../../src/LaneTimeline/laneTimelineGeometry.ts"],"names":[],"mappings":"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"}
|
|
@@ -198,6 +198,21 @@ export const toPackedLane = ({ axis, items, maxRowCount, }) => {
|
|
|
198
198
|
export const getIsAxisReadable = ({ columnCount, inlineSize, isMeasured, minColumnInlineSize, }) => !isMeasured ||
|
|
199
199
|
columnCount <= 0 ||
|
|
200
200
|
inlineSize / columnCount >= minColumnInlineSize;
|
|
201
|
+
/**
|
|
202
|
+
* Wrap the titles only once a day column is wide enough for a word.
|
|
203
|
+
*
|
|
204
|
+
* Measured, for the same reason `getIsAxisReadable` is: the
|
|
205
|
+
* question is the width of ONE column, which is the box divided by
|
|
206
|
+
* a number that lives in the data. Before the first measurement it
|
|
207
|
+
* clips, because that is the layout with no vertical surprise in
|
|
208
|
+
* it — a server render that wrapped would move every lane on the
|
|
209
|
+
* client's first paint.
|
|
210
|
+
*/
|
|
211
|
+
export const chooseTitleLayout = ({ columnCount, inlineSize, isMeasured, wrapColumnInlineSize, }) => isMeasured &&
|
|
212
|
+
columnCount > 0 &&
|
|
213
|
+
inlineSize / columnCount >= wrapColumnInlineSize
|
|
214
|
+
? "wrap"
|
|
215
|
+
: "clip";
|
|
201
216
|
/**
|
|
202
217
|
* Label every day, every week, or every four weeks.
|
|
203
218
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"laneTimelineGeometry.js","sourceRoot":"","sources":["../../src/LaneTimeline/laneTimelineGeometry.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"laneTimelineGeometry.js","sourceRoot":"","sources":["../../src/LaneTimeline/laneTimelineGeometry.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -117,6 +117,20 @@ which measures 0 again, every frame.
|
|
|
117
117
|
Which is why "has it been measured" is its own flag rather than `inlineSize > 0`: **zero is a
|
|
118
118
|
real width here**, because the track is a `minmax(0, 1fr)` column beside a fixed label rail.
|
|
119
119
|
|
|
120
|
+
## A title wraps when its column has room
|
|
121
|
+
|
|
122
|
+
A bar's title is words, and one line is one line however wide the box gets: a week across
|
|
123
|
+
a desktop page gives every day about 7em, and a single-day bar in it still printed
|
|
124
|
+
`Regional Rob…`. So the timeline measures the column and chooses. At or above
|
|
125
|
+
`wrapColumnSize` (default `6`, in em of the timeline's own type) a title wraps onto up to
|
|
126
|
+
three lines; below it, the title clips to one line with an ellipsis, because three lines
|
|
127
|
+
of two letters each is neither the word nor a shape. The full title is in the bar's
|
|
128
|
+
`title` attribute and its accessible name either way.
|
|
129
|
+
|
|
130
|
+
The threshold is the **column's** width, not the box's, which is why the same 64rem panel
|
|
131
|
+
wraps a week's titles and clips a month's. It is decided by the timeline, never by the
|
|
132
|
+
bar, so every bar in a range agrees.
|
|
133
|
+
|
|
120
134
|
## The labels thin; the type does not shrink
|
|
121
135
|
|
|
122
136
|
Type that shrinks to fit is type somebody cannot read, and the density axis already owns font
|
|
@@ -252,6 +252,39 @@ test("the same width keeps its axis for a week and loses it for a month", async
|
|
|
252
252
|
await expect(getBarCount("The month at 34rem")).toBe(0)
|
|
253
253
|
})
|
|
254
254
|
|
|
255
|
+
/**
|
|
256
|
+
* A title is words, and one line is one line however wide the box
|
|
257
|
+
* gets. So a bar in a column the timeline measured as wide enough
|
|
258
|
+
* wraps onto more lines, and the same title in a narrow column clips
|
|
259
|
+
* to one — decided from the column, never from the bar, which is why
|
|
260
|
+
* one story wraps what the other clips.
|
|
261
|
+
*/
|
|
262
|
+
test("a bar's title wraps in a wide column and clips in a narrow one", async () => {
|
|
263
|
+
const toLineCount = (element: HTMLElement) =>
|
|
264
|
+
element.getBoundingClientRect().height /
|
|
265
|
+
Number.parseFloat(getComputedStyle(element).lineHeight)
|
|
266
|
+
|
|
267
|
+
// Playground: seven columns across 64rem, so about 7em a day.
|
|
268
|
+
const { canvas: week } = await mountStory(Playground)
|
|
269
|
+
|
|
270
|
+
const wrapped = week.getByText("Mic locker inventory")
|
|
271
|
+
|
|
272
|
+
await expect(toLineCount(wrapped)).toBeGreaterThanOrEqual(
|
|
273
|
+
1.8,
|
|
274
|
+
)
|
|
275
|
+
|
|
276
|
+
// LongRange: thirty columns across 72rem, so about 2em a day.
|
|
277
|
+
const { canvas: month } = await mountStory(LongRange)
|
|
278
|
+
|
|
279
|
+
const clipped = month.getByText("Mic locker inventory")
|
|
280
|
+
|
|
281
|
+
await expect(toLineCount(clipped)).toBeLessThan(1.5)
|
|
282
|
+
|
|
283
|
+
await expect(clipped.scrollWidth).toBeGreaterThan(
|
|
284
|
+
clipped.clientWidth,
|
|
285
|
+
)
|
|
286
|
+
})
|
|
287
|
+
|
|
255
288
|
/**
|
|
256
289
|
* Thinning the labels rather than shrinking the type, because type
|
|
257
290
|
* that shrinks to fit is type somebody cannot read.
|
|
@@ -8,6 +8,7 @@ import { LaneTimelineLane } from "./LaneTimelineLane.tsx"
|
|
|
8
8
|
import type { TimelineSpan } from "./laneTimelineGeometry.ts"
|
|
9
9
|
import {
|
|
10
10
|
chooseAxisTickStep,
|
|
11
|
+
chooseTitleLayout,
|
|
11
12
|
formatAxisDate,
|
|
12
13
|
getIsAxisReadable,
|
|
13
14
|
toTimelineAxis,
|
|
@@ -52,6 +53,24 @@ const DEFAULT_MIN_COLUMN_SIZE = 1.75
|
|
|
52
53
|
*/
|
|
53
54
|
const DEFAULT_MAX_ROW_COUNT = 6
|
|
54
55
|
|
|
56
|
+
/**
|
|
57
|
+
* The narrowest a day column may be before a bar's title WRAPS
|
|
58
|
+
* rather than clips, in em.
|
|
59
|
+
*
|
|
60
|
+
* A one-line title with an ellipsis is right for a narrow column
|
|
61
|
+
* and wrong for a wide one, and the fold threshold above cannot
|
|
62
|
+
* tell the two apart: `minColumnSize` is where the axis stops
|
|
63
|
+
* being worth drawing, not where a title becomes readable. A
|
|
64
|
+
* seven-day week across a 64rem page gives every column 7em, and
|
|
65
|
+
* a single-day bar in it still printed `Regional Rob…` — the
|
|
66
|
+
* owner's verdict on that picture was *"I can't really read this
|
|
67
|
+
* text"*. Six em is about eight characters of the bar's own type,
|
|
68
|
+
* which is the narrowest box in which a wrapped word is a word and
|
|
69
|
+
* not a column of letters. A four-week range on the same page is
|
|
70
|
+
* under it and keeps the ellipsis.
|
|
71
|
+
*/
|
|
72
|
+
const DEFAULT_WRAP_COLUMN_SIZE = 6
|
|
73
|
+
|
|
55
74
|
export type LaneTimelineProps = {
|
|
56
75
|
className?: string
|
|
57
76
|
/**
|
|
@@ -99,6 +118,13 @@ export type LaneTimelineProps = {
|
|
|
99
118
|
* `2026-04-06` to `2026-04-12`, which is seven columns, not eight.
|
|
100
119
|
*/
|
|
101
120
|
range: TimelineSpan
|
|
121
|
+
/**
|
|
122
|
+
* The narrowest a day column may be before a bar's title wraps
|
|
123
|
+
* onto up to three lines instead of clipping to one, as a
|
|
124
|
+
* multiple of the timeline's **own font size**. Default 6. In em
|
|
125
|
+
* for the reason `minColumnSize` is.
|
|
126
|
+
*/
|
|
127
|
+
wrapColumnSize?: number
|
|
102
128
|
}
|
|
103
129
|
|
|
104
130
|
/**
|
|
@@ -190,6 +216,7 @@ export const LaneTimeline = ({
|
|
|
190
216
|
maxRowCount = DEFAULT_MAX_ROW_COUNT,
|
|
191
217
|
minColumnSize = DEFAULT_MIN_COLUMN_SIZE,
|
|
192
218
|
range,
|
|
219
|
+
wrapColumnSize = DEFAULT_WRAP_COLUMN_SIZE,
|
|
193
220
|
}: LaneTimelineProps): ReactNode => {
|
|
194
221
|
const { fontSize, inlineSize, isMeasured, trackRef } =
|
|
195
222
|
useTrackMeasurements()
|
|
@@ -211,6 +238,13 @@ export const LaneTimeline = ({
|
|
|
211
238
|
minTickInlineSize: TICK_LABEL_SIZE * fontSize,
|
|
212
239
|
})
|
|
213
240
|
|
|
241
|
+
const titleLayout = chooseTitleLayout({
|
|
242
|
+
columnCount,
|
|
243
|
+
inlineSize,
|
|
244
|
+
isMeasured,
|
|
245
|
+
wrapColumnInlineSize: wrapColumnSize * fontSize,
|
|
246
|
+
})
|
|
247
|
+
|
|
214
248
|
/*
|
|
215
249
|
* An inline style, not a class. Tailwind scans source text for
|
|
216
250
|
* complete class strings, so a `grid-cols-[repeat(${n},…)]` is
|
|
@@ -345,6 +379,7 @@ export const LaneTimeline = ({
|
|
|
345
379
|
position={position}
|
|
346
380
|
shape="axis"
|
|
347
381
|
tickStep={tickStep}
|
|
382
|
+
titleLayout={titleLayout}
|
|
348
383
|
/>
|
|
349
384
|
))}
|
|
350
385
|
</>
|
|
@@ -9,7 +9,10 @@ import { FOCUS_RING_CLASS } from "../intentStyles.ts"
|
|
|
9
9
|
import { UnstyledLink } from "../RouterLink/UnstyledLink.tsx"
|
|
10
10
|
import { toClassName } from "../toClassName.ts"
|
|
11
11
|
import { VisuallyHidden } from "../VisuallyHidden/VisuallyHidden.tsx"
|
|
12
|
-
import type {
|
|
12
|
+
import type {
|
|
13
|
+
TimelineSpan,
|
|
14
|
+
TimelineTitleLayout,
|
|
15
|
+
} from "./laneTimelineGeometry.ts"
|
|
13
16
|
|
|
14
17
|
/**
|
|
15
18
|
* Who owns the item's activation — nobody, a router, or a handler.
|
|
@@ -73,6 +76,13 @@ export type LaneTimelineBarProps = {
|
|
|
73
76
|
* text and no position to carry meaning.
|
|
74
77
|
*/
|
|
75
78
|
shape: "bar" | "row"
|
|
79
|
+
/**
|
|
80
|
+
* For the `bar` shape only: `clip` prints the title on one line
|
|
81
|
+
* with an ellipsis, `wrap` lets it run onto up to three. The
|
|
82
|
+
* timeline chooses from the measured column width, so a bar
|
|
83
|
+
* never decides this for itself. Default `clip`.
|
|
84
|
+
*/
|
|
85
|
+
titleLayout?: TimelineTitleLayout
|
|
76
86
|
}
|
|
77
87
|
|
|
78
88
|
/**
|
|
@@ -115,6 +125,7 @@ export const LaneTimelineBar = ({
|
|
|
115
125
|
item,
|
|
116
126
|
laneCategorical,
|
|
117
127
|
shape,
|
|
128
|
+
titleLayout = "clip",
|
|
118
129
|
}: LaneTimelineBarProps): ReactNode => {
|
|
119
130
|
const categorical = item.categorical ?? laneCategorical
|
|
120
131
|
|
|
@@ -123,19 +134,35 @@ export const LaneTimelineBar = ({
|
|
|
123
134
|
const content = (
|
|
124
135
|
<>
|
|
125
136
|
{/*
|
|
126
|
-
*
|
|
127
|
-
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
137
|
+
* A `min-w-0`, per the flex-overflow rule: the title is the
|
|
138
|
+
* flex row's text child and a single unbreakable word would
|
|
139
|
+
* otherwise become the bar's floor and push the bar past its
|
|
140
|
+
* own grid column.
|
|
141
|
+
*
|
|
142
|
+
* Then one of three treatments. A bar in a narrow column
|
|
143
|
+
* clips to one line with an ellipsis, because three lines
|
|
144
|
+
* of two letters each is neither the word nor a shape. A
|
|
145
|
+
* bar in a column the timeline measured as wide enough
|
|
146
|
+
* WRAPS, onto up to three lines — one line is one line
|
|
147
|
+
* however wide the box gets, and a week across a desktop
|
|
148
|
+
* was still printing `Regional Rob…` at 7em a column. The
|
|
149
|
+
* Narrow View's row wraps freely. The whole string is in the
|
|
150
|
+
* `title` attribute and in the hidden sentence either way,
|
|
151
|
+
* so nothing is lost to a clamp.
|
|
152
|
+
*
|
|
153
|
+
* `wrap-anywhere` on the wrapped shapes rather than
|
|
154
|
+
* `break-word`, for the reason `Main` gives: only `anywhere`
|
|
155
|
+
* also shrinks the min-content size, so a long word cannot
|
|
156
|
+
* push the bar out of its column.
|
|
132
157
|
*/}
|
|
133
158
|
<span
|
|
134
159
|
className={toClassName(
|
|
135
|
-
"min-w-0 flex-1",
|
|
136
|
-
shape === "
|
|
137
|
-
? "
|
|
138
|
-
: "wrap
|
|
160
|
+
"min-w-0 flex-1 text-sm",
|
|
161
|
+
shape === "row"
|
|
162
|
+
? "wrap-anywhere"
|
|
163
|
+
: titleLayout === "wrap"
|
|
164
|
+
? "line-clamp-3 wrap-anywhere"
|
|
165
|
+
: "truncate",
|
|
139
166
|
)}
|
|
140
167
|
>
|
|
141
168
|
{item.title}
|
|
@@ -183,9 +210,14 @@ export const LaneTimelineBar = ({
|
|
|
183
210
|
|
|
184
211
|
const shellClassName = toClassName(
|
|
185
212
|
"w-full min-w-0 border px-1.5 text-xs leading-tight",
|
|
213
|
+
// `h-full` so every bar in one packed row is the height of the
|
|
214
|
+
// tallest: a wrapped three-line title beside a one-line one
|
|
215
|
+
// would otherwise leave the shorter bar floating above the
|
|
216
|
+
// row's baseline.
|
|
186
217
|
shape === "bar"
|
|
187
|
-
? "flex min-h-5 items-center rounded-sm"
|
|
218
|
+
? "flex h-full min-h-5 items-center rounded-sm"
|
|
188
219
|
: "flex flex-col gap-0.5 rounded-md py-1",
|
|
220
|
+
shape === "bar" && titleLayout === "wrap" && "py-0.5",
|
|
189
221
|
CATEGORICAL_APPEARANCE_CLASS[categorical].soft,
|
|
190
222
|
// A square edge where the item leaves the range. `rounded-*-none`
|
|
191
223
|
// rather than a different component, so a clipped bar and a whole
|
|
@@ -12,7 +12,10 @@ import { TextLink } from "../TextLink/TextLink.tsx"
|
|
|
12
12
|
import { toClassName } from "../toClassName.ts"
|
|
13
13
|
import type { TimelineItem } from "./LaneTimelineBar.tsx"
|
|
14
14
|
import { LaneTimelineBar } from "./LaneTimelineBar.tsx"
|
|
15
|
-
import type {
|
|
15
|
+
import type {
|
|
16
|
+
TimelineAxis,
|
|
17
|
+
TimelineTitleLayout,
|
|
18
|
+
} from "./laneTimelineGeometry.ts"
|
|
16
19
|
import {
|
|
17
20
|
describeTimelineSpan,
|
|
18
21
|
toPackedLane,
|
|
@@ -64,6 +67,12 @@ export type LaneTimelineLaneProps = {
|
|
|
64
67
|
shape: "axis" | "list"
|
|
65
68
|
/** Draw a separator every this many columns. */
|
|
66
69
|
tickStep: number
|
|
70
|
+
/**
|
|
71
|
+
* Whether a bar's title clips to one line or wraps onto up to
|
|
72
|
+
* three. The parent measures the column and decides; the Narrow
|
|
73
|
+
* View ignores it, because a row always has room to wrap.
|
|
74
|
+
*/
|
|
75
|
+
titleLayout?: TimelineTitleLayout
|
|
67
76
|
}
|
|
68
77
|
|
|
69
78
|
/**
|
|
@@ -108,6 +117,7 @@ export const LaneTimelineLane = ({
|
|
|
108
117
|
position,
|
|
109
118
|
shape,
|
|
110
119
|
tickStep,
|
|
120
|
+
titleLayout = "clip",
|
|
111
121
|
}: LaneTimelineLaneProps): ReactNode => {
|
|
112
122
|
const headingId = useUniqueId()
|
|
113
123
|
|
|
@@ -315,6 +325,7 @@ export const LaneTimelineLane = ({
|
|
|
315
325
|
hasLaterEnd={placement.hasLaterEnd}
|
|
316
326
|
item={item}
|
|
317
327
|
shape="bar"
|
|
328
|
+
titleLayout={titleLayout}
|
|
318
329
|
/>
|
|
319
330
|
</li>
|
|
320
331
|
)),
|
|
@@ -17,6 +17,7 @@ import { expect, test } from "vitest"
|
|
|
17
17
|
|
|
18
18
|
import {
|
|
19
19
|
chooseAxisTickStep,
|
|
20
|
+
chooseTitleLayout,
|
|
20
21
|
describeTimelineSpan,
|
|
21
22
|
getIsAxisReadable,
|
|
22
23
|
toBarPlacement,
|
|
@@ -427,3 +428,37 @@ test("a single day says the day and nothing about a span", () => {
|
|
|
427
428
|
}),
|
|
428
429
|
).toBe("Wed 8 Apr")
|
|
429
430
|
})
|
|
431
|
+
|
|
432
|
+
/**
|
|
433
|
+
* The wrap threshold is a column width, so the same box answers
|
|
434
|
+
* differently for a week and for a month — and before a measurement
|
|
435
|
+
* it clips, so a server render has no vertical surprise in it.
|
|
436
|
+
*/
|
|
437
|
+
test("a title wraps only once a measured column is wide enough", () => {
|
|
438
|
+
expect(
|
|
439
|
+
chooseTitleLayout({
|
|
440
|
+
columnCount: 7,
|
|
441
|
+
inlineSize: 812,
|
|
442
|
+
isMeasured: true,
|
|
443
|
+
wrapColumnInlineSize: 96,
|
|
444
|
+
}),
|
|
445
|
+
).toBe("wrap")
|
|
446
|
+
|
|
447
|
+
expect(
|
|
448
|
+
chooseTitleLayout({
|
|
449
|
+
columnCount: 30,
|
|
450
|
+
inlineSize: 812,
|
|
451
|
+
isMeasured: true,
|
|
452
|
+
wrapColumnInlineSize: 96,
|
|
453
|
+
}),
|
|
454
|
+
).toBe("clip")
|
|
455
|
+
|
|
456
|
+
expect(
|
|
457
|
+
chooseTitleLayout({
|
|
458
|
+
columnCount: 7,
|
|
459
|
+
inlineSize: 0,
|
|
460
|
+
isMeasured: false,
|
|
461
|
+
wrapColumnInlineSize: 96,
|
|
462
|
+
}),
|
|
463
|
+
).toBe("clip")
|
|
464
|
+
})
|
|
@@ -357,6 +357,49 @@ export const getIsAxisReadable = ({
|
|
|
357
357
|
columnCount <= 0 ||
|
|
358
358
|
inlineSize / columnCount >= minColumnInlineSize
|
|
359
359
|
|
|
360
|
+
/**
|
|
361
|
+
* How a bar prints its title: on one line with an ellipsis, or
|
|
362
|
+
* wrapped onto up to three.
|
|
363
|
+
*
|
|
364
|
+
* `clip` is the honest answer when a column is narrow — a wrapped
|
|
365
|
+
* title in 30px is three lines of two letters each, which is
|
|
366
|
+
* neither the word nor a shape. `wrap` is the honest answer when
|
|
367
|
+
* the column is wide, and it is the one the whole component was
|
|
368
|
+
* measured wanting: at seven columns across a 64rem page a single-
|
|
369
|
+
* day bar has 7em of room and was still printing `Regional Rob…`,
|
|
370
|
+
* because one line is one line however wide the box gets.
|
|
371
|
+
*/
|
|
372
|
+
export type TimelineTitleLayout = "clip" | "wrap"
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Wrap the titles only once a day column is wide enough for a word.
|
|
376
|
+
*
|
|
377
|
+
* Measured, for the same reason `getIsAxisReadable` is: the
|
|
378
|
+
* question is the width of ONE column, which is the box divided by
|
|
379
|
+
* a number that lives in the data. Before the first measurement it
|
|
380
|
+
* clips, because that is the layout with no vertical surprise in
|
|
381
|
+
* it — a server render that wrapped would move every lane on the
|
|
382
|
+
* client's first paint.
|
|
383
|
+
*/
|
|
384
|
+
export const chooseTitleLayout = ({
|
|
385
|
+
columnCount,
|
|
386
|
+
inlineSize,
|
|
387
|
+
isMeasured,
|
|
388
|
+
wrapColumnInlineSize,
|
|
389
|
+
}: {
|
|
390
|
+
columnCount: number
|
|
391
|
+
/** The measured inline size of the track, in CSS pixels. */
|
|
392
|
+
inlineSize: number
|
|
393
|
+
isMeasured: boolean
|
|
394
|
+
/** The narrowest column that wraps, in CSS pixels. */
|
|
395
|
+
wrapColumnInlineSize: number
|
|
396
|
+
}): TimelineTitleLayout =>
|
|
397
|
+
isMeasured &&
|
|
398
|
+
columnCount > 0 &&
|
|
399
|
+
inlineSize / columnCount >= wrapColumnInlineSize
|
|
400
|
+
? "wrap"
|
|
401
|
+
: "clip"
|
|
402
|
+
|
|
360
403
|
/**
|
|
361
404
|
* Label every day, every week, or every four weeks.
|
|
362
405
|
*
|